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