本文使用环境:
主控:W801 (开发板)
兼容:W800 AIR101
蓝牙调试器:如下图
参考前文:
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蓝牙控制项目