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