|
這兩天買了個藍(lán)牙模塊研究,發(fā)現(xiàn)串口接收到的數(shù)據(jù)沒有規(guī)律,不好檢測到底接收完了沒有。查閱了些資料發(fā)現(xiàn)了比較好的方法,為了幫助跟我一樣的萌新可以更好的學(xué)習(xí),我決定發(fā)個帖子,也算是給自己做個筆記。
1、IDLE中斷
IDLE就是串口收到一幀數(shù)據(jù)后,發(fā)生的中斷。什么是一幀數(shù)據(jù)呢?比如說給單片機(jī)一次發(fā)來1個字節(jié),或者一次發(fā)來8個字節(jié),這些一次發(fā)來的數(shù)據(jù),就稱為一幀數(shù)據(jù),也可以叫做一包數(shù)據(jù)。
如何判斷一幀數(shù)據(jù)結(jié)束,就是我們今天討論的問題。因?yàn)楹芏囗?xiàng)目中都要用到這個,因?yàn)橹挥薪邮盏揭粠瑪?shù)據(jù)以后,你才可以判斷這次收了幾個字節(jié)和每個字節(jié)的內(nèi)容是否符合協(xié)議要求。
看到這個第一反應(yīng)就是“好東西”,可惜51單片機(jī)好像沒有,所以只是做了粗略的了解,有興趣的各位可以去找些資料看看,隨便查一下資料還挺多的
2、自定義結(jié)束符
在一幀數(shù)據(jù)尾部添加一個字符,比如傳輸?shù)拿恳粠瑪?shù)據(jù)尾部都是“#”,當(dāng)單片機(jī)接收到“#”后,說明已經(jīng)接收完畢,然后立個Flag,就可以開始處理這些接收到的數(shù)據(jù)了,如下:
- u8 xdata RxLen=0; //接收計數(shù)
- u8 xdata RxFlag=0; //接收完畢標(biāo)志位
- u8 xdata Uart4_Rx_Buffer[33]; //接收到的數(shù)據(jù)
- void Uart4_Init() //藍(lán)牙串口4,選擇定時器2為波特率發(fā)生器,波特率57600
- {
- S4CON = 0x10; //8位數(shù)據(jù),可變波特率
- S4CON &= 0xBF; //串口4選擇定時器2為波特率發(fā)生器
- AUXR |= 0x04; //定時器2時鐘為Fosc,即1T
- T2L = 0x7E; //設(shè)定定時初值
- T2H = 0xFF; //設(shè)定定時初值
- AUXR |= 0x10; //啟動定時器2
-
- IE2|=0X10; //打開串口中斷4
- EA=1; //打開總中斷
- }
- void S4_Routine() interrupt 18 //串口4中斷函數(shù)
- {
- if(S4CON&0x01) //接收中斷
- {
- S4CON&=0xFE; //清除接收中斷
- Uart4_Rx_Buffer[RxLen]=S4BUF;
- if(Uart4_Rx_Buffer[RxLen] == '#') //是結(jié)束符,說明接收完畢,就可以拿著RxFlag出去搞事情了
- {
- RxFlag=1;
- }
- else //不是結(jié)束符,老實(shí)接收下一個數(shù)據(jù)
- {
- RxLen++;
- }
- }
- }
- void BLE_Allot() //數(shù)據(jù)分配
- {
- if(RxFlag)
- {
- RxFlag=0;
- RxLen=0;
- /*干一些你想干的事情*/
- }
- }
復(fù)制代碼 3、用另外一個定時器檢測
具體的思路是,因?yàn)槊恳晃粋鬏數(shù)臅r間間隔由波特率決定都是一樣,所以每一個字節(jié)的傳輸時間也是一樣的。那么我們每傳輸一個字節(jié)時,把定時器初值復(fù)位,以保證定時器不會溢出。定時器時間取傳輸一個字節(jié)的1.5倍,這樣一來,當(dāng)定時器超時時候,就意味著串口接收數(shù)據(jù)停止了。此時同樣立一個flag開始處理這些接收到的數(shù)據(jù),如下:
PS:大佬用的是滴答定時器,我發(fā)現(xiàn)51單片機(jī)還是沒有,欲哭無淚,所以只好自己做一個了
- u8 xdata RxLen=0; //接收計數(shù)
- u8 xdata RxFlag=0; //接收完畢標(biāo)志位
- u8 xdata Uart4_Rx_Buffer[33]; //接收到的數(shù)據(jù)
- void Timer1_Init() //定時器1初始化
- {
- AUXR |= 0x40; //定時器時鐘1T模式
- TMOD &= 0x0F; //設(shè)置定時器模式
- TL1 = 0x82; //設(shè)置定時初值
- TH1 = 0xE7; //設(shè)置定時初值
- TF1 = 0; //清除TF1標(biāo)志
- TR1 = 0; //這里先不開始計時,等傳輸信號的時候開始計時
-
- ET1=1;
- EA=1;
- }
- void Timer0_Rountine() interrupt 3
- {
- TR1 = 0; //定時器1停止計時
- TF1 = 0; //清除TF1標(biāo)志
- RxFlag=1; //串口接收完畢
- }
- void Uart4_Init() //藍(lán)牙串口4,選擇定時器2為波特率發(fā)生器,波特率57600
- {
- S4CON = 0x10; //8位數(shù)據(jù),可變波特率
- S4CON &= 0xBF; //串口4選擇定時器2為波特率發(fā)生器
- AUXR |= 0x04; //定時器2時鐘為Fosc,即1T
- T2L = 0x7E; //設(shè)定定時初值
- T2H = 0xFF; //設(shè)定定時初值
- AUXR |= 0x10; //啟動定時器2
-
- IE2|=0X10; //打開串口中斷4
- EA=1; //打開總中斷
- }
- void S4_Routine() interrupt 18 //串口4中斷函數(shù)
- {
- if(S4CON&0x01) //接收中斷
- {
- S4CON&=0xFE; //清除接收中斷
- Uart4_Rx_Buffer[RxLen]=S4BUF; //將數(shù)據(jù)放到數(shù)組中
- RxLen++; //下次進(jìn)來數(shù)據(jù)存放地址+1
- TR1=0; //定時器1停止計時(這里搞了好久,一定要先停止,不然會出現(xiàn)錯誤)
- TL1=0x82; //設(shè)置定時初值
- TH1=0xE7; //設(shè)置定時初值
- TR1=1; //定時器1開始計時
- }
- }
- void BLE_Allot() //數(shù)據(jù)分配
- {
- if(RxFlag)
- {
- RxFlag=0; //標(biāo)志清零
- RxLen=0; //計數(shù)清零
- /*干一些你想干的事情*/
- }
- }
復(fù)制代碼 最后,感謝大佬在網(wǎng)上發(fā)布的好資料能給我們參考,也希望大佬能進(jìn)來多討論,多給點(diǎn)意見和建議
|
評分
-
查看全部評分
|