假设有一数据包,数据格式如表所示:
序号 |
项 目 |
长度(字节) |
阐明 |
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字节。
程序完成如下所示:
[cpp]view plaincopyprint?
- #include
- typedefstructnewStruct
- {
- unsignedcharstartFlag;
- unsignedcharfinishFlag;
- unsignedcharlenHighFlag;
- unsignedcharlenLowFlag;
- unsignedchardataFlag;
- unsignedcharlrcFlag;
- unsignedcharbuf[512];
- unsignedcharlenHigh;
- unsignedcharlenLow;
- unsignedchardataStartIndex;
- unsignedshortlen;
- unsignedshortindex;
- unsignedshorttempLen;
- }rxstruct;
- rxstructrxArray;
- voidm430_InitUart()
- {
- P3SEL|=BIT4|BIT5;//P3.4,P3.5=USCI_A0TXD/RXD
- UCA0CTL1|=UCSSEL_2;//SMCLK
- //以下三行为波特率设置运用
- UCA0BR1=0;
- UCA0BR0=104;//12MHz:1250->9600,625->19200,312->38400,214->56000,104->115200
- UCA0MCTL=0x02;//ModulationUCBRSx=1
- UCA0CTL1&=~UCSWRST;//InitializeUSCIstatemachine
- //IE2|=UCA0RXIE|UCA0TXIE;//留意应在初始化USCI之后,设置中止使能,不然不起作用,即若此句放在UCA0CTL1&=~UCSWRST;之前,则不会呼应中止
- IE2|=UCA0RXIE;
- }
- unsignedcharuart_CalLrc(unsignedchar*buf,unsignedshortlen)
- {
- unsignedshorti;
- unsignedcharlrc;
- lrc=0x00;
- for(i=0;i
- {
- lrc^=buf[i];
- }
- returnlrc;
- }
- voidmain()
- {
- WDTCTL=WDTPW+WDTHOLD;
- BCSCTL1=CALBC1_12MHZ;
- DCOCTL=CALDCO_12MHZ;
- m430_InitUart();
- rxArray.startFlag=0;
- rxArray.finishFlag=0;
- _EINT();
- _BIS_SR(LPM4_bits);
- while(1)
- {
- }
- }
- #pragmavector=USCIAB0RX_VECTOR
- __interruptvoiduartRxHandle()
- {
- unsignedcharnum;
- 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个字节的数据之后才以为完好的接纳完一包数据,然后导致后边发送过来的完好的数据包的一部分会被拆分,循环往复的这样恶性循环下去,暂时还没想到好的解决办法!