W801/W800蓝牙收发数据与控制设计(三)-实际项目:蓝牙传输温湿度数据

这是目录

  • 一、项目概述
  • 二、程序设计
  • 三、测试
  • 四、附件

本文使用环境:
主控:W801 (开发板)
兼容:W800 AIR101
蓝牙调试器:如下图

W801/W800蓝牙收发数据与控制设计(三)-实际项目:蓝牙传输温湿度数据_第1张图片
参考前文:
W801蓝牙收发数据与控制设计(一)-INDICATE
W801蓝牙收发数据与控制设计(二)-NOTIFY方式

一、项目概述

^^^^这篇文章在前两文的代码基础上完成。本文github地址

^^^^程序功能: 使用蓝牙调试器搭建界面,控制开发板的七个LED亮灭,并将开发板的电压和温度上传到蓝牙app上。

二、程序设计

1、接收程序设计
接收一字节即八位数据,分别控制七个灯,一位空闲不用。开发板接收数据格式为:

包头 原数据 校验和 包尾
0XA5 一字节(七个灯) 所有原数据的和 0X5A

代码如下:


//add by zxx start
tls_os_queue_t 	*ble_q = NULL;

//重新定义一个数据uff
//ble_data[0] 表示数据的长度,往后依次为数据
u8 ble_data[255]  = {0};

//add by zxx end
static int
gatt_svr_chr_demo_access_func(uint16_t conn_handle, uint16_t attr_handle,
                               struct ble_gatt_access_ctxt *ctxt, void *arg)
{
    int i = 0;
    struct os_mbuf *om = ctxt->om;
    
    switch (ctxt->op) {
        case BLE_GATT_ACCESS_OP_WRITE_CHR:
              while(om) {
                  if(g_ble_uart_output_fptr)
                  {
                    g_ble_uart_output_fptr((uint8_t *)om->om_data, om->om_len);
                    
                  }else
                  {
                     
					//print_bytes(om->om_data, om->om_len); 
					//add by zxx start

					if(om->om_len > 200)
					{
						printf("ble om->om_len is too long:%d  return 0 please check send data length...\r\n",om->om_len);
						return 0;
					}
					
					//有效数据需要减三
					ble_data[0] = om->om_len-3;
					//将数据转存到buff中,ble_data[0]是数据的长度,长度必须小于255-1,否者下列循环会出问题。
					//蓝牙发送过来的数据格式为:0xA5 数据(n个) 校验 0x5a,因此数据的第二位才是有效数据,同时需要将数据的前一位和后三位排除
					for (u8 i = 1; i <= om->om_len-3; i++) {
						ble_data[i] = om->om_data[i];
					}

					 if(om->om_len>0)
						{
							tls_os_queue_send(ble_q,ble_data, 0);
						}
					//add by zxx end
                  }
                  om = SLIST_NEXT(om, om_next);
              }
              return 0;
        default:
            assert(0);
            return BLE_ATT_ERR_UNLIKELY;
    }
}

2、task程序设计
^^^^和前文的区别在于本文需要发送两个float类型的数据,使用共同体对数据进行封装。数据存入adc_f,发送adc_i即可。开发板发送数据格式:

包头 原数据 校验和 包尾
0XA5 8字节(两个浮点数) 所有原数据的和 0X5A
//add by zxx start
//发送数据的长度:0x5a+data_len+校验+0xa5
//校验位是有效数据的和不包括帧头和尾部
send_data_len = 11;
typedef union ADC_DATA
{
    u8 adc_i[8];
    float adc_f[2];
}ADC_DATA;
//add by zxx end

^^^^控制LED需要单独提取每一位,具体任务函数,LED的IO分别是:B5、B25、B26、B18、B17、B16、B11。具体看代码


//add by zxx start
void my_ble_msg_task(void *sdata)
{
	//传过来的消息队列指针,这里我定义的是u8类型的
	u8 *msg;
	//蓝牙发送数据
	u8 send_data[20] = {0x00}; 
	//定义共同体
	ADC_DATA adc_data;

	demo_bt_enable();
	while(bt_adapter_state == WM_BT_STATE_OFF)
	{
		tls_os_time_delay(5000 /HZ);
	}
	tls_os_time_delay(5000 /HZ);
	demo_ble_server_on();
	printf("ble ready ok \r\n");
	
	//初始化IO口,注意对应开发板上的IO 这里使用5 25 26
	tls_gpio_cfg(WM_IO_PB_05, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
	tls_gpio_cfg(WM_IO_PB_25, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
	tls_gpio_cfg(WM_IO_PB_26, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
	tls_gpio_cfg(WM_IO_PB_18, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
	tls_gpio_cfg(WM_IO_PB_17, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
	tls_gpio_cfg(WM_IO_PB_16, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
	tls_gpio_cfg(WM_IO_PB_11, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
	
	for(;;)
	{
		//接收手机发送的数据,注意是数据是按照字节进行的接收
		tls_os_queue_receive(ble_q,&msg, 0, 0);
		//打印ble收到数据的长度
		printf("ble revice len:%d\n",msg[0]);
		//依次打印收到的ble数据,只算有效数据的长度
		for(u8 i=0;i<msg[0];i++){
			printf("0x%x   0x%x",msg[i+1],msg[i+1]&0x01);
		}printf("\n");
		
		//分别判断每一位数据,注意需要把每一位数据移到最低位进行判断,对应开关灯:00 开  其他数据 关
		if(msg[1]&0x01 != 0)
			tls_gpio_write(WM_IO_PB_05,0);
		else
			tls_gpio_write(WM_IO_PB_05,1);
		if(msg[1]>>1&0x01 != 0)
			tls_gpio_write(WM_IO_PB_25,0);
		else
			tls_gpio_write(WM_IO_PB_25,1);
		if(msg[1]>>2&0x01 != 0)
			tls_gpio_write(WM_IO_PB_26,0);
		else
			tls_gpio_write(WM_IO_PB_26,1);
		if(msg[1]>>3&0x01 != 0)
			tls_gpio_write(WM_IO_PB_18,0);
		else
			tls_gpio_write(WM_IO_PB_18,1);
		if(msg[1]>>4&0x01 != 0)
			tls_gpio_write(WM_IO_PB_17,0);
		else
			tls_gpio_write(WM_IO_PB_17,1);
		if(msg[1]>>5&0x01 != 0)
			tls_gpio_write(WM_IO_PB_16,0);
		else
			tls_gpio_write(WM_IO_PB_16,1);
		if(msg[1]>>6&0x01 != 0)
			tls_gpio_write(WM_IO_PB_11,0);
		else
			tls_gpio_write(WM_IO_PB_11,1);

		//返回打开成功信息:
		
		adc_data.adc_f[0] = (float)adc_get_interVolt()/1000.0;
		adc_data.adc_f[1] = (float)adc_temp()/1000.0;
		
		//0xa5(0) 8个数据(1-8字节) 校验(9) 0x5a(10)
		send_data[0] = 0xA5;
		send_data[send_data_len-2] = 0;
		for(u8 i=0;i<8;i++)
		{
			//转存数据到发送数组
			send_data[i+1] = adc_data.adc_i[i];
			//计算校验和
			send_data[send_data_len-2] += adc_data.adc_i[i];
		}
		/*
		send_data[1] = adc_data.adc_i[0];
		send_data[2] = adc_data.adc_i[1];
		send_data[3] = adc_data.adc_i[2];
		send_data[4] = adc_data.adc_i[3];
		send_data[5] = adc_data.adc_i[0]+adc_data.adc_i[1]+adc_data.adc_i[2]+adc_data.adc_i[3];
		*/
		send_data[send_data_len-1] = 0x5A;
		
		//printf("send state:%d \r\n",tls_ble_server_demo_api_send_msg(send_data,7));
		//printf("send state:%d \r\n",tls_ble_server_demo_api_send_msg(send_data,3));
		printf("send state:%d  %f  %f\r\n",tls_ble_server_demo_api_send_notify_msg(send_data,send_data_len),adc_data.adc_f[0],adc_data.adc_f[1]);
	}
}
//创建任务
void My_task(void)
{
	if(tls_os_queue_create(&ble_q, 32)!=TLS_OS_SUCCESS)
	{
		printf("create queue fail\n");
		return;
	}
	tls_os_task_create(NULL, NULL,
                       my_ble_msg_task,
                       NULL,
                       (void *)MyBLETaskStk,          /* task's stack start address */
                       MYBLE_TASK_SIZE * sizeof(u32), /* task's stack size, unit:byte */
                       MYBLE_TASK_PRIO,
                       0);
}
//add by zxx end

三、测试

视频:

w801蓝牙控制项目

四、附件

蓝牙调试器的工程存档。(文档用不了)
下载链接
其界面:
W801/W800蓝牙收发数据与控制设计(三)-实际项目:蓝牙传输温湿度数据_第2张图片

你可能感兴趣的:(嵌入式,课设,做题家,单片机,嵌入式,嵌入式硬件)