使用Msp430的串口中断接收一包数据
标签:
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 |
程序实现如下所示:
- #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[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个字节的数据之后才认为完整的接收完一包数据,从而导致后面发送过来的完整的数据包的一部分会被拆分,周而复始的这样恶性循环下去,暂时还没想到好的解决办法!

加载中…