《单片机—HLK-W801开发环境搭建》
《单片机—HLK-W801蓝牙BLE功能测试》
昨天吧demo运行明白了,今天那就来看一下手机通过蓝牙远程遥控点亮开发板的LED吧,虽然这并不是低功耗蓝牙的典型用法,但是通过这种手段,能够快速学习一下W801这套恶心的SDK代码,也算是一种福报。嚯,正好这个芯片是阿里生产的,这不是正应了马老的一句话么。
这里用的手机蓝牙调试工具叫nRF connect。应用商店也可以搜索BLE,就能搜索到很多蓝牙开发的工具,不过都会各种申请手机权限,定位啊,相册啊,不允许就没法用,简直就是流氓行为,这国家早就说过了这种问题,无奈就是没办法啊。
不过这款软件倒是挺好的,没有申请什么权限
直接就可以使用。让人感动。
原有的demo中,我们知道了需要让开发板自动运行成为BLE的server,需要两部分
核心的代码就这两个函数
demo_bt_enable();
demo_ble_server_on();
不过你想要干净的将这两个函数的实现复制到你的主函数文件中,那还是想多了,里面用了一些的全局变量,例如打印等级,或者adapter状态。
所以,你干脆,人家给你造了一套代码,你干嘛还想自己写,就直接用它的demo代码,直接在包含好所有的头文件,然后调用这两个函数,就完事了。
所以主要代码就这样写
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();
就能够让开发板以server身份运行起来了。简单吧
这里就需要找到BLE server接收命令的地方,就在这个函数当中
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);
}
om = SLIST_NEXT(om, om_next);
}
return 0;
default:
assert(0);
return BLE_ATT_ERR_UNLIKELY;
}
}
其中它指明了一个逻辑,就是如果没有输出函数指针g_ble_uart_output_fptr,那么就自动打印出来,找到了接收消息的地方就办了。我们就已经可以将数据或者命令通过蓝牙,从手机发送到开发板了。
这里为了将我们的代码稍微独立出来一点,用了一个消息队列queue,将蓝牙收到的命令,通过queue发送到我的主任务当中,这部分放在主函数文件中,那么以后就直接在这里修改需求,不必再关心消息传递过程了。
主函数中创建队列,并启动监控接收任务
if(tls_os_queue_create(&MyBLE_QUEUE, 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);
消息接收任务
void my_ble_msg_task(void *sdata)
{
void *msg;
for(;;)
{
tls_os_queue_receive(MyBLE_QUEUE, (void **)&msg, 0, 0);
printf("myble revice %ld \n",(u32)msg);
}
}
将前面的输出打印,替换为发送消息,我们目前只取第一个字节,足够传递信息了。
//print_bytes(om->om_data, om->om_len);
if(om->om_len>0)
{
tls_os_queue_send(MyBLE_QUEUE, (void *)(om->om_data[0]), 0);
}
这样,启动之后,消息自动就会发送到我这个任务中来,我们就只专心处理这个消息即可。
这里将消息转化为控制LED的亮灭,达到了测试效果
这里只要控制GPIO输出低电平,就可以点亮LED,输出高电平就熄灭。
点亮过程。
tls_gpio_cfg(MyLED1_IO, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_write(MyLED1_IO,0);
首先运行开发板,等待server状态启动。
然后手机打开测试工具,扫描到开发板,连接上
然后点击上箭头,进行数据发送
发送0,可以控制led点亮
开发板被点亮了
发送1过去,开发板熄灭。
这套SDK,把FreeRTOS原有的内容,加以了封装,例如
//消息队列
tls_os_status_t tls_os_queue_create(tls_os_queue_t **queue, u32 queue_size)
//任务创建
tls_os_status_t tls_os_task_create(tls_os_task_t *task,
const char* name,
void (*entry)(void* param),
void* param,
u8 *stk_start,
u32 stk_size,
u32 prio,
u32 flag)
//延迟
void tls_os_time_delay(u32 ticks)
这套明明,也是没看出来有啥好的,搞得总和tls加密联系起来,其实没有半毛钱关系
可以用它封装好的代码,例如我上面用到的消息队列。这样可以使代码显得干净,也可以用freeRTOS原有的功能,没有本质的区别,就看你喜好了。关于FreeRTOS的用法,可以参考我的几篇文章
FreeRTOS学习—“任务”篇
FreeRTOS学习—“消息队列”篇
FreeRTOS学习—“信号量”篇
FreeRTOS学习—“事件组”篇
FreeRTOS学习—“定时器”篇
花费了三个小时做了个demo,写了一篇文章,只是提供一种解决问题的思路,有时候,不太需要你理解功能多透彻,只要是会切入,找到实现的关键点,很快就能做出点东西。
不过当然不是说深入理解不好,一旦出现一些稳定性的bug,可能就需要深入理解代码了。
时间就是金钱,效率就是生命,不过有时候,拼命去赶时间,也不是好事,今早高峰,看见一辆车
气囊也出来了,玻璃也碎了。哎,希望救护车帮你再抢点时间出来吧。但愿人没事。