序号 |
项 目 |
长度(字节) |
说明 |
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个字节的数据之后才认为完整的接收完一包数据,从而导致后面发送过来的完整的数据包的一部分会被拆分,周而复始的这样恶性循环下去,暂时还没想到好的解决办法!
上一篇:MSP430F2131读写DS1991
下一篇:MSP430可通过哪些接口进行烧写程序
推荐阅读最新更新时间:2024-03-16 15:05