OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5557|回复: 16

STM32串口接收格式为:0x20+data1+data2+0x0A的数据求救!

[复制链接]

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
发表于 2014-9-4 18:29:12 | 显示全部楼层 |阅读模式
5金钱
   我想用STM32接收蓝牙4.0传过来的RSSI数据。该数据我用串口助手观察时,十六进制显示为20 35 30 0A,十进制显示为数值50.那么该数据的发送格式是不是以0x20(空格)开头,0x0A(换行)结尾,中间两个数据?
   然后我默认数据格式如上述,自己修改了原子哥的代码。代码如下:
在串口中断接收函数中,采用u8 Res接收数据,用u8 i 计数。每次进入中断函数时 i 都++,当i=1时判断接收到的数据是否为0x20,不是的话就将i清零,退出接收中断函数。当i=2或者3时,说明i=1时接收到的数据为0x20(帧头合法),然后将数据存入数组 USART_RX_BUF[]之中。当接收到的第四位数据为0x0A时,说明接收结束,标志接收状态寄存器的最高位(USART_RX_STA|=0x8000; )。
  在主函数之中主要是各种初始化之后不断的检测接收状态寄存器的最高位是否被置高。一旦被置高则说明有数据接收到了,然后去读取数据。。如果测得的RSSI值大于设定值,则led快闪报警。
  个人觉得自己弄得小协议没问题,但是下载到单片机上时就是不行。。
  问题:1 该数据的发送格式是不是以0x20(空格)开头,0x0A(换行)结尾,中间两个数据?
             2 求各路大神帮我看看代码,指出错误。万分感激!
             3 原子哥的接收数据代码如下: USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;USART_RX_STA++;
一开始
USART_RX_STA是零,假设接收了两个数据,那么USART_RX_STA最后是1,即共 USART_RX_BUF[0], USART_RX_BUF[1]两个数据。而读取数据时,len=USART_RX_STA&0x3fff; for(t=0;t<len;t++){};len经过运算后数值应该是1,那么用 for(t=0;t<len;t++){};读取数据时岂不是丢了一位数据?应该是 for(t=0;t<len+1;t++){};吧?(不知这样理解对不对,不过还是斗胆提出来,请大神批评!)
             

Project lin01.zip

1.86 MB, 下载次数: 384

最佳答案

查看完整内容[请看2#楼]

解决了。。将变量i定义为static u8 或者定义到中断接收函数外边去就行了。。真傻!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
 楼主| 发表于 2014-9-4 18:29:13 | 显示全部楼层
解决了。。将变量i定义为static u8 或者定义到中断接收函数外边去就行了。。真傻!
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
 楼主| 发表于 2014-9-4 18:54:45 | 显示全部楼层
[mw_shl_code=c,true]#if EN_USART1_RX // void USART1_IRQHandler(void)//接受中断函数 { u8 Res,i; #ifdef OS_TICKS_PER_SEC OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // { i++; Res =USART_ReceiveData(USART1);//读取接受到的值 if(i==1&&Res!=0x20)//如果接受到的数据不是0x20开头 { i=0;//清零 USART_RX_STA=0;//接受错误 return; } if(i==2||i==3)//执行这句语句时,说明帧头合法了 { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;//装数据 USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0; } if(i==4&&Res==0x0A)//如果第四位数据是0x0A { i=0; USART_RX_STA|=0x8000; //接受完成 } else { i=0;//否则接受错误,i 清零 USART_RX_STA=0;//重新接收 } } #ifdef OS_TICKS_PER_SEC OSIntExit(); #endif } 主函数 int main(void) { u8 len,t; //uchar 8bits 0~255 u8 receive[2]; delay_init(); NVIC_Configuration(); LED_Init(); LED_Flash(3);//LED慢闪三次表示开机 uart_init(9600); //波特率9600 while(1) { if(USART_RX_STA&0x8000)//检测串口接收标志 { USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);//关接收中断 len=USART_RX_STA&0x3fff;/读取字长 for(t=0;t<len;t++) { switch (USART_RX_BUF[t]) { case 0x30: receive[t]=0; break; case 0x31: receive[t] =1; break; case 0x32: receive[t]=2; break; case 0x33: receive[t]=3; break; case 0x34: receive[t]=4; break; case 0x35: receive[t]=5; break; case 0x36: receive[t]=6; break; case 0x37: receive[t]=7; break; case 0x38: receive[t]=8; break; case 0x39: receive[t]=9; break; } } USART_RX_STA=0;//清除串口接收状态寄存器 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开串口接收中断 if(10*receive[0]+receive[1]>55)//如果接受到的RSSI大于55 LED_Flash1(3);//快闪报警 } } } [/mw_shl_code]

回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-9-5 00:45:32 | 显示全部楼层
你可以仿真找下问题。
然后帧格式这个,你要看模块资料了,猜测就不好说了。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
 楼主| 发表于 2014-9-5 08:57:34 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
谢谢原子哥指点。。辛苦了啊,深夜还帮我回答问题
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
 楼主| 发表于 2014-9-6 00:06:58 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
明白了,帧格式是我理解错了。。班门弄斧。。多多包涵啊
回复

使用道具 举报

7

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2013-10-5
在线时间
9 小时
发表于 2014-9-7 00:24:35 | 显示全部楼层
楼主是用什么蓝牙模块?可以兼容2.0吗?
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
 楼主| 发表于 2014-9-8 10:59:04 | 显示全部楼层
回复【7楼】岁月已无声:
---------------------------------
蓝牙4.0  不知道能不能兼容啊。。貌似不能,反正我用我的手机蓝牙搜不到它。。。当然也不能连上
回复

使用道具 举报

7

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2013-10-5
在线时间
9 小时
发表于 2014-9-8 15:00:05 | 显示全部楼层
回复【8楼】Radio Amateur:
---------------------------------
楼主得到的RSSI数据稳定吗?可以用来测大概的距离吗?
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
 楼主| 发表于 2014-9-8 15:55:40 | 显示全部楼层
回复【9楼】岁月已无声:
---------------------------------
还是比较稳定的,大致测量距离没问题,不过精度肯定不高
回复

使用道具 举报

7

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2013-10-5
在线时间
9 小时
发表于 2014-9-8 15:56:17 | 显示全部楼层
回复【10楼】Radio Amateur:
---------------------------------
楼主用的是什么型号的?
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
 楼主| 发表于 2014-9-8 18:04:42 | 显示全部楼层
回复【11楼】岁月已无声:
---------------------------------
什么型号。。
回复

使用道具 举报

7

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2013-10-5
在线时间
9 小时
发表于 2014-9-8 18:52:02 | 显示全部楼层
回复【12楼】Radio Amateur:
---------------------------------
就是什么型号蓝牙?
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
 楼主| 发表于 2014-9-8 19:23:52 | 显示全部楼层
回复【13楼】岁月已无声:
---------------------------------
网蜂的产品,淘宝搜去。。忘了
回复

使用道具 举报

7

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2013-10-5
在线时间
9 小时
发表于 2014-9-9 02:53:22 | 显示全部楼层
回复【14楼】Radio Amateur:
---------------------------------
OK,谢喽。
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2014-9-19
在线时间
1 小时
发表于 2014-9-20 09:51:53 | 显示全部楼层
想了一个下午,还没搞定如果接受两个字符头 两个字符尾的处理程序。。
知识像是大海。
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2014-7-2
在线时间
0 小时
 楼主| 发表于 2014-9-22 18:12:38 | 显示全部楼层
首先我要接收的数据格式以0x20开头,0x0a结尾。中间有可能是两位数或者三位数据。(RSSI的值随距离主从模块距离而变,大的时候可以超过100)以下是接收源代码:
[mw_shl_code=c,true]#define USART_REC_LEN 10 u8 USART_RX_BUF[USART_REC_LEN];//接收数据缓冲 u16 USART_RX_STA=0; //自定义接收数据状态寄存器 u8 i;//计数变量 #if EN_USART1_RX //如果使能了接收 void USART1_IRQHandler(void) //串口中断服务函数 { u8 Res;//临时接收变量 #ifdef OS_TICKS_PER_SEC OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //检测中断标志 { Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据 switch (i) { case 0: if(Res==0x20)//如果第一次接收到的数据为0X20 { USART_RX_STA|=0x4000; //置USART_RX_STA自定义寄存器次高位,表示帧头合法。下一次可以接收有效数据 i++; } else { USART_RX_STA=0;//否则帧头不合法,USART_RX_STA自定义寄存器清零,接收从新开始 } break; case 1: if(( USART_RX_STA&0x4000)!=0)//如果帧头合法(其实如果能够执行这条语句的话,帧头肯定合法) { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;//接收第一位有效数据 USART_RX_STA++; i++; } else { USART_RX_STA=0; //接收错误,USART_RX_STA自定义寄存器清零,接收从新开始 i=0; } break; case 2: if(( USART_RX_STA&0x4000)!=0) { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;//接收第二位有效数据 USART_RX_STA++; i++; } else { USART_RX_STA=0;//接收错误,USART_RX_STA自定义寄存器清零,接收从新开始 i=0; } break; case 3: if(Res==0x0A)//如果第四次时接收到0X0A,表示接收到的RSSI值为两位数 { USART_RX_STA|=0x8000; //接收完成 i=0; } else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;//否则接收到的RSSI值为三位数,将其存储好 USART_RX_STA++; //if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收到的数据超过自定义长度,清零 i++; } break; case 4: if(Res==0x0A)//如果第五次时接收到0X0A,表示接收到的RSSI值为三位数 { USART_RX_STA|=0x8000; //接收完成 i=0; } else { USART_RX_STA=0;//接收错误,从新开始 i=0; } break; default: USART_RX_STA=0;//接收错误,从新开始 i=0; break; } } #ifdef OS_TICKS_PER_SEC OSIntExit(); #endif } #endif [/mw_shl_code]

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-1 01:51

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表