使用Msp430的串口中断接收一包数据
2010-06-25 21:25
351 查看
使用Msp430的串口中断接收一包数据
假设有一数据包,数据格式如表所示:
数据包总长度为: Data_len + 5 字节,最长不能超过512字节。
程序实现如下所示:
本程序一个致命的bug就是,如果长度信息那两个字节的数据接收时出现错误,会导致不能正确组成一包数据,后面发送过来的数据包也不能正确接收。
如有一包数据(16进制):02 00 02 11 11 00 03,
如果接收过程出现错误,导致将长度的两个字节00 02在接收端变成了00 05,因此接收端会等待接收完5个字节的数据之后才认为完整的接收完一包数据,从而导致后面发送过来的完整的数据包的一部分会被拆分,周而复始的这样恶性循环下去,暂时还没想到好的解决办法!
假设有一数据包,数据格式如表所示:
序号 | 项 目 | 长度(字节) | 说明 |
1 | 数据包头(STX) | 1 | 常量:0x02 |
2 | 数据单元长度(Data_len) | 2 | 需传输的数据单元Data部分的长度,高字节在前,低字节在后。 例如:0x0010表示Data部分有16个字节。 |
3 | 需传输的数据单元(Data) | 不定 | 长度由Data_len指出,数据单元头两个字节是命令码(终端发送命令到读写器)或状态码(读写器返回数据给终端),后面是其它参数。 |
4 | 冗余检验值(LRC) | 1 | Data部分数据各字节异或值。 |
5 | 数据包尾(ETX) | 1 | 常量:0x03 |
程序实现如下所示:
#include <msp430x22x4.h> 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<len; i++ ) { lrc ^= buf[i]; } 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个字节的数据之后才认为完整的接收完一包数据,从而导致后面发送过来的完整的数据包的一部分会被拆分,周而复始的这样恶性循环下去,暂时还没想到好的解决办法!
相关文章推荐
- MSP430串口接收程序(使用中断)
- STM32串口使用IDLE中断接收不定长数据原理与源程序
- STM8S003F使用IO口模拟串口(三)使用中断方式发送和接收数据
- STM32—无需中断来实现使用DMA接收串口数据(原创)
- STM32使用串口IDLE中断的两种接收不定长数据的方式
- STM32使用DMA加串口空闲中断接收数据
- STM32—无需中断来实现使用DMA接收串口数据
- STM32—无需中断来实现使用DMA接收串口数据(原创)
- STM32F207运用串口空闲中断+DMA接收不定长数据
- Kinetis KL8x 使用eDMA模块接收串口数据
- STM32利用串口空闲中断在串口DMA配置下接收变长数据
- STM32使用串口中断发送和接受数据
- stm32 实现串口中断接收浮点型、整型数据
- SYD8801 UART使用说明【uart轮发数据代码实现】【 uart中断发数据代码实现】【RFSleep函数对串口的影响】【中断中调用串口打印函数有可能会造成死机】
- STM32F207运用串口空闲中断+DMA接收不定长数据
- Qt之串口编程--使用事件驱动来触发接收数据
- 解决使用MSComm控件进行串口数据的接收数据不完整
- STM32F4的HAL库开启串口空闲中断 不定长数据接收很好用
- Qt5自带串口调试 --使用signal接收数据,自动侦测端口列表
- 地磅称量系统之(59) 接收串口数据(串口控件的属性设置和超级终端的使用)