加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

使用Msp430的串口中断接收一包数据

(2012-10-20 18:35:23)
标签:

msp430

串口

数据包

中断

it

分类: 单片机

使用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字节。

 

程序实现如下所示:

  1. #include    
  2.   
  3. typedef struct newStruct  
  4.            
  5.       unsigned char startFlag;  
  6.       unsigned char finishFlag;  
  7.       unsigned char lenHighFlag;  
  8.       unsigned char lenLowFlag;  
  9.       unsigned char dataFlag;  
  10.       unsigned char lrcFlag;  
  11.       unsigned char buf[512];  
  12.       unsigned char lenHigh;  
  13.       unsigned char lenLow;  
  14.       unsigned char dataStartIndex;  
  15.       unsigned short len;  
  16.       unsigned short index;  
  17.       unsigned short tempLen;  
  18. }rxstruct;  
  19. rxstruct rxArray;  
  20.   
  21. void m430_InitUart()  
  22.  
  23.       P3SEL |= BIT4|BIT5;           // P3.4, P3.5 USCI_A0 TXD/RXD   
  24.         
  25.       UCA0CTL1 |= UCSSEL_2;          // SMCLK   
  26.         
  27.       //以下三行为波特率设置使用   
  28.       UCA0BR1  0;   
  29.       UCA0BR0  104;         // 12MHz:1250->9600,625->19200,312->38400,214->56000,104->115200                
  30.       UCA0MCTL 0x02;         // Modulation UCBRSx 1   
  31.      
  32.       UCA0CTL1 &= ~UCSWRST;    // Initialize USCI state machine    
  33.       //IE2 |= UCA0RXIE UCA0TXIE;  //注意应在初始化USCI之后,设置中断使能,否则不起作用,即若此句放在UCA0CTL1 &= ~UCSWRST;之前,则不会响应中断   
  34.       IE2 |= UCA0RXIE;  
  35.  
  36.   
  37. unsigned char uart_CalLrc(unsigned char *buf, unsigned short len)  
  38.  
  39.       unsigned short i;  
  40.       unsigned char lrc;  
  41.       lrc 0x00;  
  42.         
  43.       for( i=0; i
  44.                  
  45.           lrc ^= buf[i];  
  46.        
  47.         
  48.       return lrc;  
  49.  
  50.   
  51. void main()  
  52.     
  53.       WDTCTL WDTPW WDTHOLD;  
  54.       BCSCTL1 CALBC1_12MHZ;  
  55.       DCOCTL  CALDCO_12MHZ;  
  56.         
  57.       m430_InitUart();  
  58.         
  59.       rxArray.startFlag 0;              
  60.       rxArray.finishFlag 0;  
  61.         
  62.       _EINT();                        
  63.       _BIS_SR(LPM4_bits);  
  64.       while(1)  
  65.                  
  66.        
  67.  
  68.   
  69. #pragma vector USCIAB0RX_VECTOR   
  70. __interrupt void uartRxHandle()  
  71.  
  72.       unsigned char num;        
  73.       num UCA0RXBUF;        
  74.                     
  75.       if( 0==rxArray.startFlag )//判断是否接收到帧头   
  76.        
  77.             if( 0x02==num )//判断帧头是否正确   
  78.              
  79.                 rxArray.startFlag 1;//标志已经接收到帧头   
  80.                 rxArray.finishFlag 0;  
  81.                 rxArray.lenHighFlag 0;  
  82.                 rxArray.lenLowFlag 0;  
  83.                 rxArray.dataFlag 0;  
  84.                 rxArray.lrcFlag 0;  
  85.                 rxArray.index 0;  
  86.                 rxArray.len 0;//存储帧长度   
  87.                 rxArray.buf[rxArray.index] num;  
  88.                 rxArray.index++;  
  89.              
  90.             return;  
  91.        
  92.         
  93.       if( 0==rxArray.lenHighFlag )//判断是否接收到帧长度的高字节信息   
  94.        
  95.             rxArray.lenHighFlag 1;//标志已经接收到帧长度的高字节   
  96.             rxArray.lenHigh rxArray.buf[rxArray.index] num;  
  97.             rxArray.index++;                            
  98.             return;  
  99.        
  100.         
  101.       if( 0==rxArray.lenLowFlag )//判断是否接收到帧长度的低字节信息   
  102.        
  103.             rxArray.lenLowFlag 1;//标志已经接收到帧长度的低字节   
  104.             rxArray.lenLow rxArray.buf[rxArray.index] num;  
  105.             rxArray.index++;  
  106.             rxArray.dataStartIndex rxArray.index;  
  107.               
  108.             rxArray.tempLen rxArray.len (rxArray.lenHigh<<8) rxArray.lenLow;//增加一字节的帧尾   
  109.             if( rxArray.len+5>512 )//如果数据长度大于12,则说明接收的数据长度信息有误,需要重新接收   
  110.              
  111.                 rxArray.startFlag 0;  
  112.                 rxArray.lenHighFlag 0;  
  113.                 rxArray.lenLowFlag 0;  
  114.                   
  115.             return;  
  116.        
  117.         
  118.       if( 0==rxArray.dataFlag  
  119.        
  120.             rxArray.buf[rxArray.index] num;//把数据存放到数组中   
  121.             rxArray.index++;  
  122.             rxArray.tempLen--;  
  123.             if( 0==rxArray.tempLen  
  124.              
  125.                   rxArray.dataFlag 1;  
  126.              
  127.             return;  
  128.        
  129.         
  130.       if( 0==rxArray.lrcFlag )//接收lrc   
  131.        
  132.             rxArray.buf[rxArray.index] num;  
  133.             rxArray.index++;  
  134.             rxArray.lrcFlag 1;  
  135.             if( 0!=uart_CalLrc( &rxArray.buf[rxArray.dataStartIndex], rxArray.len+1 )//判断接收数据的lrc是否正确   
  136.              
  137.                 rxArray.startFlag 0;  
  138.                 rxArray.lenHighFlag 0;  
  139.                 rxArray.lenLowFlag 0;  
  140.                 rxArray.dataFlag 0;  
  141.                 rxArray.lrcFlag 0;  
  142.              
  143.             return;  
  144.        
  145.         
  146.       rxArray.buf[rxArray.index] num;       
  147.       rxArray.finishFlag 1;  
  148.       rxArray.startFlag 0;  
  149.       rxArray.lenHighFlag 0;  
  150.       rxArray.lenLowFlag 0;  
  151.       rxArray.dataFlag 0;  
  152.       rxArray.lrcFlag 0;        
  153.       if( rxArray.buf[rxArray.index]!=0x03 )//最后一个字节不是0x03,说明数据有误,需要重新接收   
  154.                     
  155.             rxArray.finishFlag 0;               
  156.           
  157.         
  158.       if( rxArray.finishFlag  
  159.        
  160.             //收到数据处理部分                                                          
  161.        
  162.  

本程序一个致命的bug就是,如果长度信息那两个字节的数据接收时出现错误,会导致不能正确组成一包数据,后面发送过来的数据包也不能正确接收。

如有一包数据(16进制):02 00 02 11 11 00 03,

如果接收过程出现错误,导致将长度的两个字节00 02在接收端变成了00 05,因此接收端会等待接收完5个字节的数据之后才认为完整的接收完一包数据,从而导致后面发送过来的完整的数据包的一部分会被拆分,周而复始的这样恶性循环下去,暂时还没想到好的解决办法!

 

http://s11/mw690/7880d335ncc7b3622a55a&690

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有