使用Msp430的串口中斷接收一包數(shù)據(jù)
序號(hào) | 項(xiàng) 目 | 長(zhǎng)度(字節(jié)) | 說(shuō)明 |
1 | 數(shù)據(jù)包頭(STX) | 1 | 常量:0x02 |
2 | 數(shù)據(jù)單元長(zhǎng)度(Data_len) | 2 | 需傳輸?shù)臄?shù)據(jù)單元Data部分的長(zhǎng)度,高字節(jié)在前,低字節(jié)在后。 例如:0x0010表示Data部分有16個(gè)字節(jié)。 |
3 | 需傳輸?shù)臄?shù)據(jù)單元(Data) | 不定 | 長(zhǎng)度由Data_len指出,數(shù)據(jù)單元頭兩個(gè)字節(jié)是命令碼(終端發(fā)送命令到讀寫器)或狀態(tài)碼(讀寫器返回?cái)?shù)據(jù)給終端),后面是其它參數(shù)。 |
4 | 冗余檢驗(yàn)值(LRC) | 1 | Data部分?jǐn)?shù)據(jù)各字節(jié)異或值。 |
5 | 數(shù)據(jù)包尾(ETX) | 1 | 常量:0x03 |
程序?qū)崿F(xiàn)如下所示:
- #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
- //以下三行為波特率設(shè)置使用
- 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;//注意應(yīng)在初始化USCI之后,設(shè)置中斷使能,否則不起作用,即若此句放在UCA0CTL1&=~UCSWRST;之前,則不會(huì)響應(yīng)中斷
- 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;//標(biāo)志已經(jīng)接收到幀頭
- rxArray.finishFlag=0;
- rxArray.lenHighFlag=0;
- rxArray.lenLowFlag=0;
- rxArray.dataFlag=0;
- rxArray.lrcFlag=0;
- rxArray.index=0;
- rxArray.len=0;//存儲(chǔ)幀長(zhǎng)度
- rxArray.buf[rxArray.index]=num;
- rxArray.index++;
- }
- return;
- }
- if(0==rxArray.lenHighFlag)//判斷是否接收到幀長(zhǎng)度的高字節(jié)信息
- {
- rxArray.lenHighFlag=1;//標(biāo)志已經(jīng)接收到幀長(zhǎng)度的高字節(jié)
- rxArray.lenHigh=rxArray.buf[rxArray.index]=num;
- rxArray.index++;
- return;
- }
- if(0==rxArray.lenLowFlag)//判斷是否接收到幀長(zhǎng)度的低字節(jié)信息
- {
- rxArray.lenLowFlag=1;//標(biāo)志已經(jīng)接收到幀長(zhǎng)度的低字節(jié)
- rxArray.lenLow=rxArray.buf[rxArray.index]=num;
- rxArray.index++;
- rxArray.dataStartIndex=rxArray.index;
- rxArray.tempLen=rxArray.len=(rxArray.lenHigh<<8)+rxArray.lenLow;//增加一字節(jié)的幀尾
- if(rxArray.len+5>512)//如果數(shù)據(jù)長(zhǎng)度大于12,則說(shuō)明接收的數(shù)據(jù)長(zhǎng)度信息有誤,需要重新接收
- {
- rxArray.startFlag=0;
- rxArray.lenHighFlag=0;
- rxArray.lenLowFlag=0;
- }
- return;
- }
- if(0==rxArray.dataFlag)
- {
- rxArray.buf[rxArray.index]=num;//把數(shù)據(jù)存放到數(shù)組中
- rxArray.index++;
- rxArray.tempLen--;
- if(0==rxArray.tempLen)
- {
- rxArray.dataFlag=1;
- }
- return;
- }
- if(0==rxArray.lrcFlag)//接收l(shuí)rc
- {
- rxArray.buf[rxArray.index]=num;
- rxArray.index++;
- rxArray.lrcFlag=1;
- if(0!=uart_CalLrc(&rxArray.buf[rxArray.dataStartIndex],rxArray.len+1))//判斷接收數(shù)據(jù)的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)//最后一個(gè)字節(jié)不是0x03,說(shuō)明數(shù)據(jù)有誤,需要重新接收
- {
- rxArray.finishFlag=0;
- }
- if(rxArray.finishFlag)
- {
- //收到數(shù)據(jù)處理部分
- }
- }
本程序一個(gè)致命的bug就是,如果長(zhǎng)度信息那兩個(gè)字節(jié)的數(shù)據(jù)接收時(shí)出現(xiàn)錯(cuò)誤,會(huì)導(dǎo)致不能正確組成一包數(shù)據(jù),后面發(fā)送過(guò)來(lái)的數(shù)據(jù)包也不能正確接收。
如有一包數(shù)據(jù)(16進(jìn)制):02 00 02 11 11 00 03,
如果接收過(guò)程出現(xiàn)錯(cuò)誤,導(dǎo)致將長(zhǎng)度的兩個(gè)字節(jié)00 02在接收端變成了00 05,因此接收端會(huì)等待接收完5個(gè)字節(jié)的數(shù)據(jù)之后才認(rèn)為完整的接收完一包數(shù)據(jù),從而導(dǎo)致后面發(fā)送過(guò)來(lái)的完整的數(shù)據(jù)包的一部分會(huì)被拆分,周而復(fù)始的這樣惡性循環(huán)下去,暫時(shí)還沒(méi)想到好的解決辦法!
評(píng)論