赞
踩
使用nordic官网的串口蓝牙时,若传输大量数据,会使单片机复位,从而蓝牙断开。
原因:在串口服务函数里发送蓝牙的数据,导致中断响应不及时,系统复位。
解决方法:串口服务函数不要发送蓝牙数据,只接受串口数据,使用定时器发送数据。
为了防止不同的数据帧粘在同一包,串口传输时定义通信协议,再使用fifo缓存将要发送的数据。fifo尽量大,5K没有问题。
定义了一个简单的协议:
Head Length Data
2字节 2字节 不定长度
0x11 0x22 0xxx
Head 数据包头
Length Data长度
Data 具体数据
具体代码如下:
- uint8_t uart_readF = 0; //命令接收标志
- uint16_t uart_len = 0; //命令总长度
- uint16_t uart_cnt = 0; //命令已接收长度
-
-
- void uart_event_handle(app_uart_evt_t * p_event)
- {
- uint8_t dat;
- switch (p_event->evt_type)
- {
- case APP_UART_DATA_READY:
- UNUSED_VARIABLE(app_uart_get(&dat));
- switch(uart_readF){
- case 0:
- if(dat == 0x11){
- uart_readF = 1;
- }
- break;
- case 1:
- if(dat == 0x22){
- uart_readF = 2;
- }
- break;
- case 2:
- uart_len = dat << 8;
- uart_readF = 3;
- break;
- case 3:
- uart_len += dat;
- if(uart_len > Fifo_Empty_Size(ffs)){
- uart_readF = 0; //fifo不足以写入本次数据帧,抛弃该数据帧
- }else{
- Fifo_Push(ffs,uart_len>>8);
- Fifo_Push(ffs,(uint8_t)uart_len);//将本次数据帧长度写入fifo
- uart_readF = 4;
- uart_cnt = 0;
- }
- break;
- case 4:
- Fifo_Push(ffs,dat); //将数据写入fifo
- if(++uart_cnt == uart_len){
- uart_readF = 0;
- }
- break;
- }
- break;
-
- case APP_UART_COMMUNICATION_ERROR:
- APP_ERROR_HANDLER(p_event->data.error_communication);
- break;
-
- case APP_UART_FIFO_ERROR:
- APP_ERROR_HANDLER(p_event->data.error_code);
- break;
-
- default:
- break;
- }
- }
在定时器每隔10ms(这个时间根据实际情况修改,测试10ms传输数据没有问题)去读取fifo里面的数据,通过蓝牙发送出去。发送数据时,一帧数据大于20个字节(蓝牙一包最多可以发送20个字节的用户数据),每一包都要发足20个字节,最后一包可以不用发足20字节。这是为了防止,写上位机软件的人员老是认为每一包数据都是有20个字节的,没有严格按照通信协议解析数据,造成通信存在问题(经常遇到这样的人,对接起来真累)。
-
- uint8_t CMDDat[250] = {0};
- uint16_t CMDLen = 0;
- uint16_t CMDOff = 0;
- static void TIME_update(void)
- {
- uint8_t dat = 0;
- uint16_t len = 0;
-
- if(CMDF==0){
- if(Fifo_GetLen(ffs) > 1){ //协议中,一帧数据的长度为两个字节
- Fifo_Pop(ffs,&dat);
- CMDLen = dat << 8;
- Fifo_Pop(ffs,&dat);
- CMDLen += dat; //获取一帧数据的长度
- CMDF = 1;
- }
- }
- if(CMDF==1){
- if(Fifo_GetLen(ffs) >= CMDLen){
- Fifo_Pop_More(ffs,CMDDat,CMDLen); //获取一帧数据
- CMDOff = 0;
- CMDF = 2;
- }
- }
- if(CMDF==2){
- len = 20 < CMDLen ? 20 : CMDLen; //长度多余20个字节,每次发送20个字节
- // uart_send(CMDDat+CMDOff,len);
- ble_nus_string_send(&m_nus, CMDDat+CMDOff, len);
- CMDLen -= len;
- CMDOff += len;
- if(CMDLen == 0){
- CMDF = 0;
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。