解决nrf52832串口蓝牙4.0传输大量数据断开蓝牙的问题

使用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;
		}
	}
}

 

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值