1948|0

2781

帖子

419

TA的资源

五彩晶圆(中级)

楼主
 

使用Msp430的串口中断接收一包数据 [复制链接]

假设有一数据包,数据格式如表所示:
                                                                                                            
序号
项 目
长度(字节)
说明
1
数据包头(STX)
1
常量:0x02
2
数据单元长度(Data_len)
2
需传输的数据单元Data部分的长度,高字节在前,低字节在后。
例如:0x0010表示Data部分有16个字节。
3
需传输的数据单元(Data)
不定
长度由Data_len指出,数据单元头两个字节是命令码(终端发送命令到读写器)或状态码(读写器返回数据给终端),后面是其它参数。
4
冗余检验值(LRC)
1
Data部分数据各字节异或值。
5
数据包尾(ETX)
1
常量:0x03
数据包总长度为: Data_len + 5 字节,最长不能超过512字节。

程序实现如下所示:

  • #include
  • typedef struct newStruct
  • {
  •       unsigned char startFlag;
  •       unsigned char finishFlag;
  •       unsigned char lenHighFlag;
  •       unsigned char lenLowFlag;
  •       unsigned char dataFlag;
  •       unsigned char lrcFlag;
  •       unsigned char buf[512];
  •       unsigned char lenHigh;
  •       unsigned char lenLow;
  •       unsigned char dataStartIndex;
  •       unsigned short len;
  •       unsigned short index;
  •       unsigned short tempLen;
  • }rxstruct;
  • rxstruct rxArray;
  • void m430_InitUart()
  • {
  •       P3SEL |= BIT4|BIT5;           // P3.4, P3.5 = USCI_A0 TXD/RXD
  •       UCA0CTL1 |= UCSSEL_2;          // SMCLK
  •       //以下三行为波特率设置使用
  •       UCA0BR1  = 0;
  •       UCA0BR0  = 104;         // 12MHz:1250->9600,625->19200,312->38400,214->56000,104->115200
  •       UCA0MCTL = 0x02;         // Modulation UCBRSx = 1
  •       UCA0CTL1 &= ~UCSWRST;    // Initialize USCI state machine
  •       //IE2 |= UCA0RXIE | UCA0TXIE;  //注意应在初始化USCI之后,设置中断使能,否则不起作用,即若此句放在UCA0CTL1 &= ~UCSWRST;之前,则不会响应中断
  •       IE2 |= UCA0RXIE;
  • }
  • unsigned char uart_CalLrc(unsigned char *buf, unsigned short len)
  • {
  •       unsigned short i;
  •       unsigned char lrc;
  •       lrc = 0x00;
  •       for( i=0; i
  •       {
  •           lrc ^= buf;  
  •       }  
  •       return lrc;  
  • }  
  • void main()  
  • {     
  •       WDTCTL = WDTPW + WDTHOLD;  
  •       BCSCTL1 = CALBC1_12MHZ;  
  •       DCOCTL  = CALDCO_12MHZ;  
  •       m430_InitUart();  
  •       rxArray.startFlag = 0;              
  •       rxArray.finishFlag = 0;  
  •       _EINT();                        
  •       _BIS_SR(LPM4_bits);  
  •       while(1)  
  •       {            
  •       }  
  • }  
  • #pragma vector = USCIAB0RX_VECTOR   
  • __interrupt void uartRxHandle()  
  • {  
  •       unsigned char num;        
  •       num = UCA0RXBUF;        
  •       if( 0==rxArray.startFlag )//判断是否接收到帧头   
  •       {  
  •             if( 0x02==num )//判断帧头是否正确   
  •             {  
  •                 rxArray.startFlag = 1;//标志已经接收到帧头   
  •                 rxArray.finishFlag = 0;  
  •                 rxArray.lenHighFlag = 0;  
  •                 rxArray.lenLowFlag = 0;  
  •                 rxArray.dataFlag = 0;  
  •                 rxArray.lrcFlag = 0;  
  •                 rxArray.index = 0;  
  •                 rxArray.len = 0;//存储帧长度   
  •                 rxArray.buf[rxArray.index] = num;  
  •                 rxArray.index++;  
  •             }  
  •             return;  
  •       }  
  •       if( 0==rxArray.lenHighFlag )//判断是否接收到帧长度的高字节信息   
  •       {  
  •             rxArray.lenHighFlag = 1;//标志已经接收到帧长度的高字节   
  •             rxArray.lenHigh = rxArray.buf[rxArray.index] = num;  
  •             rxArray.index++;                           
  •             return;  
  •       }  
  •       if( 0==rxArray.lenLowFlag )//判断是否接收到帧长度的低字节信息   
  •       {  
  •             rxArray.lenLowFlag = 1;//标志已经接收到帧长度的低字节   
  •             rxArray.lenLow = rxArray.buf[rxArray.index] = num;  
  •             rxArray.index++;  
  •             rxArray.dataStartIndex = rxArray.index;  
  •             rxArray.tempLen = rxArray.len = (rxArray.lenHigh<<8) + rxArray.lenLow;//增加一字节的帧尾   
  •             if( rxArray.len+5>512 )//如果数据长度大于12,则说明接收的数据长度信息有误,需要重新接收   
  •             {  
  •                 rxArray.startFlag = 0;  
  •                 rxArray.lenHighFlag = 0;  
  •                 rxArray.lenLowFlag = 0;  
  •             }      
  •             return;  
  •       }  
  •       if( 0==rxArray.dataFlag )  
  •       {  
  •             rxArray.buf[rxArray.index] = num;//把数据存放到数组中   
  •             rxArray.index++;  
  •             rxArray.tempLen--;  
  •             if( 0==rxArray.tempLen )  
  •             {  
  •                   rxArray.dataFlag = 1;  
  •             }  
  •             return;  
  •       }  
  •       if( 0==rxArray.lrcFlag )//接收lrc   
  •       {  
  •             rxArray.buf[rxArray.index] = num;  
  •             rxArray.index++;  
  •             rxArray.lrcFlag = 1;  
  •             if( 0!=uart_CalLrc( &rxArray.buf[rxArray.dataStartIndex], rxArray.len+1 ) )//判断接收数据的lrc是否正确   
  •             {  
  •                 rxArray.startFlag = 0;  
  •                 rxArray.lenHighFlag = 0;  
  •                 rxArray.lenLowFlag = 0;  
  •                 rxArray.dataFlag = 0;  
  •                 rxArray.lrcFlag = 0;  
  •             }  
  •             return;  
  •       }  
  •       rxArray.buf[rxArray.index] = num;      
  •       rxArray.finishFlag = 1;  
  •       rxArray.startFlag = 0;  
  •       rxArray.lenHighFlag = 0;  
  •       rxArray.lenLowFlag = 0;  
  •       rxArray.dataFlag = 0;  
  •       rxArray.lrcFlag = 0;        
  •       if( rxArray.buf[rxArray.index]!=0x03 )//最后一个字节不是0x03,说明数据有误,需要重新接收   
  •       {               
  •             rxArray.finishFlag = 0;               
  •       }     
  •       if( rxArray.finishFlag )  
  •       {  
  •             //收到数据处理部分                                                         
  •       }  
  • }  


本程序一个致命的bug就是,如果长度信息那两个字节的数据接收时出现错误,会导致不能正确组成一包数据,后面发送过来的数据包也不能正确接收。
如有一包数据(16进制):02 00 02 11 11 00 03,
如果接收过程出现错误,导致将长度的两个字节00 02在接收端变成了00 05,因此接收端会等待接收完5个字节的数据之后才认为完整的接收完一包数据,从而导致后面发送过来的完整的数据包的一部分会被拆分,周而复始的这样恶性循环下去,暂时还没想到好的解决办法!

分享自:http://t.cn/zlRe0E1

 
点赞 关注(1)
个人签名

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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

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

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

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