3808|1

85

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

求助:8051串口 中断接收 查询发送 数据丢失 [复制链接]

用C8051F020与PC机之间串口通讯.
单片机用中断方式接收数据,用查询方式发送数据.
我的程序是为了实现:定义5字节数据为一帧,PC机向单片机发送数据,当数据到达一帧(5个字节)的时候,单片机向PC机将这一帧数据发送出去.
我用了2个BUFF,第1个BUFF用于依次接收SBUF0中的数据,将第1个BUFF里面的数据传入第2个BUFF.当第2个BUFF的数据达到5个字节的时候,就将取数标志置位,就将BUFF2中的数从串口发出.

用串口调试助手进行调试,试验现象如下:
发送5字节数据为一帧(1包数据),例如:AA BB CC DD EE.每次当单片机复位或者重起之后,发送之后接收到的第一帧数据总是为AA CC DD EE,丢失第2字节数据;然后不复位继续发送,则正常接收AA BB CC DD EE,只要不复位或者重起,之后都是正常.
我用16进制和非16进制,都出现"首次"会第2个数据丢失的现象,之后都是正常.
而我观察BUFF2中数组inbuf2[len2]中的第2个元素,观察显示,第2个元素"BB"正常.
通俗讲,就是复位后第一次发送,第2字节数据"应该"正常接收,但就是发不出来,我也试过会不会是延迟的问题,但是我手动1个字节1个字节地发送,还是出现上述问题,就觉得不会是延迟方面问题.
这个程序是没有校验代码的,如果加上了校验,会不会改善?请问一下,如何加校验呢?
还有个小问题,如果对2个BUFF进行复位?

请大家帮我分析一下,谢谢!

其中程序如下,我略去了一些代码.

#define len 5                    //BUFF1缓冲区长度
unsigned char idata inbuf[len];
unsigned char idata *inlast=inbuf;
unsigned char idata *getlast=inbuf;

bit inbufsign;                        //BUFF1缓冲区非空标志 有=1,空=0
bit inbufful;                        //BUFF1缓冲区满标志 满=1,非满=0
bit read_flag=0;                //取数标志位
int i=0;                       
unsigned char  *str;
unsigned int  strlen;

#define len2 5                         //BUFF2缓冲区长度
unsigned char idata inbuf2[len2];
unsigned char idata c,c1;

//主函数//
void main (void)                       
{
...
...
   EA=1;                                  //中断开放       
   while(1)                                  //查询发送
          {
            if(read_flag)                  //如果取数标志置位,就将读到的数从串口发出
                {
                read_flag=0;
                sendstring(inbuf2,len2);
                }
          }
}

//串口接收中断//
void serial() interrupt 4              
          {
            if(RI0)
                {
                 RI0=0;
                 if(!inbufful)           //查询BUFF1是否满
                    {
                     *inlast=SBUF0;      //放入数据
                     inlast++;                 //放入位置加1
                     inbufsign=1;
                     if(inlast=inbuf+len)
                        inlast=inbuf;         //地址到顶部回底部                          
                     if(inlast=getlast)
                        inbufful=1;      //BUFF1置满标志
                    }       
                 c1=getbyte();           
                 inbuf2=c1;           //将BUFF1中数据依次读入到BUFF2的数组中
                 i++;
                 if(i==5)               
                   {
                    read_flag=1;
                    i=0;                 //若达到5字节时,置取数标志位,启动发送
                   }                               
                }
          }


//从缓冲区BUFF1中取一个byte//
unsigned char getbyte(void)           
  {
   while(!inbufsign);                    //BUFF1空等待
   ES0=0;
   c=*getlast;                           //取数据
   getlast++;                            //最后取走的数据位置加1
   inbufful=0;                           //BUFF1的满标志清0
   if(getlast=inbuf+len)
      getlast=inbuf;                     //地址到顶部回到底部
   if(getlast=inlast)
      inbufsign=0;                       //地址相等,BUFF1置空标志
   ES0=1;
   return(c);
  }


//向串口发送一个字符//
void sendchar(unsigned char ch)      
{
    SBUF0=ch;
        while(TI0==0);
        TI0=0;
}


//向串口发送一个字符串,strlen为该字符串长度//
void sendstring(unsigned char *str,unsigned int strlen)
{
      int k;
      for(k=0;k          {
           sendchar(*str);
           str++;
         }
      while(k }



谢谢

最新回复

#define len 5                    //BUFF1缓冲区长度 unsigned char idata inbuf[len]; unsigned char idata *inlast=inbuf; unsigned char idata *getlast=inbuf; bit inbufsign; //BUFF1缓冲区非空标志 有=1,空=0 bit inbufful; //BUFF1缓冲区满标志 满=1,非满=0 bit read_flag=0;                //取数标志位 int i=0;                      unsigned char  *str; unsigned int  strlen; #define len2 5                        //BUFF2缓冲区长度 unsigned char idata inbuf2[len2]; unsigned char idata c,c1; //主函数// void main (void)                      { ... ...   EA=1;   //中断开放   while(1)           //查询发送   {     if(read_flag)   //如果取数标志置位,就将读到的数从串口发出         { read_flag=0; sendstring(inbuf2,len2); }   } } //串口接收中断// void serial() interrupt 4                 {     if(RI0) { RI0=0; if(!inbufful)          //查询BUFF1是否满             {     *inlast=SBUF0;      //放入数据     inlast++;         //放入位置加1     inbufsign=1;     if(inlast=inbuf+len) ///////////////////////////??????????????????         inlast=inbuf; //地址到顶部回底部        if(inlast=getlast)  ///////////////////////////?????????????????? inbufful=1;      //BUFF1置满标志     }         c1=getbyte();                          inbuf2=c1;          //将BUFF1中数据依次读入到BUFF2的数组中         i++;         if(i==5)                          {             read_flag=1;     i=0;                //若达到5字节时,置取数标志位,启动发送           } }   } //从缓冲区BUFF1中取一个byte// unsigned char getbyte(void)            {   while(!inbufsign);                    //BUFF1空等待   ES0=0;   c=*getlast;                          //取数据   getlast++;                            //最后取走的数据位置加1   inbufful=0;                          //BUFF1的满标志清0   if(getlast=inbuf+len)  ///////////////////////////??????????????????       getlast=inbuf;                    //地址到顶部回到底部   if(getlast=inlast) ///////////////////////////??????????????????       inbufsign=0;                      //地址相等,BUFF1置空标志   ES0=1;   return(c);   } //向串口发送一个字符// void sendchar(unsigned char ch)       {     SBUF0=ch; while(TI0==0); TI0=0; } //向串口发送一个字符串,strlen为该字符串长度// void sendstring(unsigned char *str,unsigned int strlen) {       int k;       for(k=0;k   详情 回复 发表于 2008-8-20 10:28
点赞 关注

回复
举报

78

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
#define len 5                    //BUFF1缓冲区长度
unsigned char idata inbuf[len];
unsigned char idata *inlast=inbuf;
unsigned char idata *getlast=inbuf;

bit inbufsign; //BUFF1缓冲区非空标志 有=1,空=0
bit inbufful; //BUFF1缓冲区满标志 满=1,非满=0
bit read_flag=0;                //取数标志位
int i=0;                     
unsigned char  *str;
unsigned int  strlen;

#define len2 5                        //BUFF2缓冲区长度
unsigned char idata inbuf2[len2];
unsigned char idata c,c1;

//主函数//
void main (void)                     
{
...
...
  EA=1;   //中断开放
  while(1)           //查询发送
  {
    if(read_flag)   //如果取数标志置位,就将读到的数从串口发出
        {
read_flag=0;
sendstring(inbuf2,len2);
}
  }
}

//串口接收中断//
void serial() interrupt 4              
  {
    if(RI0)
{
RI0=0;
if(!inbufful)          //查询BUFF1是否满
            {
    *inlast=SBUF0;      //放入数据
    inlast++;         //放入位置加1
    inbufsign=1;
    if(inlast=inbuf+len) ///////////////////////////??????????????????

        inlast=inbuf; //地址到顶部回底部   
    if(inlast=getlast)  ///////////////////////////??????????????????
inbufful=1;      //BUFF1置满标志
    }
        c1=getbyte();         
                inbuf2=c1;          //将BUFF1中数据依次读入到BUFF2的数组中
        i++;
        if(i==5)               
          {
            read_flag=1;
    i=0;                //若达到5字节时,置取数标志位,启动发送
          }
}
  }


//从缓冲区BUFF1中取一个byte//
unsigned char getbyte(void)         
  {
  while(!inbufsign);                    //BUFF1空等待
  ES0=0;
  c=*getlast;                          //取数据
  getlast++;                            //最后取走的数据位置加1
  inbufful=0;                          //BUFF1的满标志清0
  if(getlast=inbuf+len)  ///////////////////////////??????????????????

      getlast=inbuf;                    //地址到顶部回到底部
  if(getlast=inlast) ///////////////////////////??????????????????
      inbufsign=0;                      //地址相等,BUFF1置空标志
  ES0=1;
  return(c);
  }


//向串口发送一个字符//
void sendchar(unsigned char ch)      
{
    SBUF0=ch;
while(TI0==0);
TI0=0;
}


//向串口发送一个字符串,strlen为该字符串长度//
void sendstring(unsigned char *str,unsigned int strlen)
{
      int k;
      for(k=0;k {
  sendchar(*str);
  str++;
}
      while(k }

 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表