一、需要的资源 1、 JUMA 例程源码(链接: http://pan.baidu.com/s/1gfhkcfT 密码: aavh) 2、 一台电脑,已经安装好MDK 3、 一台手机(安卓版本4.3+;苹果设备4S +) 4、 小钢炮低功耗蓝牙开发板一块(点击申请) 5、 一个调试器(本文使用STLink) 二、硬件 1、 开发环境配置 参考官网的配置教程:http://www.juma.io/doc/zh/stm32_platform/cannon_env/ 2、 开发板配置 (1) 将开发板上的boot0用跳帽与GND短接。 (2) 将STLink的对应引脚(G-GND,D-SWDIO,C-SWCLK,V-VCC)与开发板SWD处的排针相连。 三、软件 1、 目录结构 __Sensortag__ |-apk(相应的安卓手机App安装文件) |-src(例程的嵌入式源码) |-system(聚码SDK、内核文件、驱动、中间件等源文件) |-product(示例工程目录)开发者可基于这目录下的MDK工程实现自己逻辑
2、 工程打开 (1) 双击工程目录中的工程文件CAF.uvprojx
(2) 如果出现下面的画面,是提示你安装工程所需要的STM32F4的包文件。 这里我给出两种方案:第一种是你可以选择点击Install直接在线安装,这个一般来说应该是比较慢(网速好能翻墙的忽略);第二种是点击cancel,在论坛里面下载我已经下载好的包文件,下载分享的帖子地址在论坛(http://52cannon.com/bbs/thread-217-1-1.html),直接下载下来双击也可以安装。
(3) 包文件安装 直接双击下载下来的
会自动识别默认安装路径在keil的安装文件夹,不用修改。直接next.然后等待安装完成,大概需要几分钟。
(4) 重新打开工程文件,就不会有提示了。 3、 源码解析 (1) 打开工程后,打开文件列表,可以找到app.c这个文件就是应用层逻辑实现的源码。
(2) 下面来看一下app.c里面的代码逻辑 jsensor_app_set_sensors(void),这个函数是传感器设置/初始化入口,注意区别函数体当中的jsensor_app_set_sensor(uint16_t sid)函数,两个区别只是结尾少个“S”, jsensor_app_set_sensor是设置/初始化某一个特定的传感器,传感器通过已经定义的sid来区别。
void jsensor_app_set_sensors(void) { jsensor_app_set_sensor(JSENSOR_TYPE_HUMITY_TEMP);//初始化温湿度传感器 jsensor_app_set_sensor(JSENSOR_TYPE_PRESSURE);//初始化压力传感器 jsensor_app_set_sensor(JSENSOR_TYPE_MOTION_6AXIS);//初始化六轴传感器 jsensor_app_set_sensor(JSENSOR_TYPE_MAGNET);//初始化磁力计 }
On_ready(void),这个函数是应用层的入口函数,对于不做底层驱动修改的的开发者来说,这里就是开发板上电之后第一个执行的函数。 voidon_ready(void) { //定义一些需要初始配置的蓝牙基本参数及数组 uint8_t tx_power_level = 7; uint16_t adv_interval = 100; uint8_t bdAddr[6]; char name[32]; //全局变量running是判断开发板是否被连接的标志,初始化为0 running = 0;
BSP_LED_On(LED0);//点亮板子上D3处的 LED HCI_get_bdAddr(bdAddr);//获取设备地址,连接到设备名上面,方便手机检索的时候区别不同的板子。 sprintf(name, "%s %01x%01x",board_name, bdAddr[0], bdAddr[1]); /*Config Adv Parameter And Ready to Adv*/ ble_set_adv_param(name, bdAddr,tx_power_level, adv_interval);//初始化蓝牙广播的基本参数:广播的名字,设备地址,发射功率,广播间隔 ble_device_start_advertising();//开启蓝牙广播 }
下面是一些获取传感器的值得函数 //读取温度值函数 staticvoid read_temperature(void* arg) // sensorread temperature { int16_t humidity; int16_t temperature; JSensor_HUM_TEMP_Typedef tdef;
if (!running) return;
tdef.humidity = &humidity; tdef.temperature = &temperature;
if (JSENSOR_OK ==jsensor_app_read_sensor(JSENSOR_TYPE_HUMITY_TEMP, (void *)&tdef)) { ble_device_send(0x00, 2, (uint8_t*)&temperature);//发送回手机温度的值 }
run_after_delay(read_humidity, NULL,UPDATE_INTERVAL); //UPDATE_INTERVAL是读取不同传感器直接的间隔时间100ms,这个函数是在100ms之后来运行读取湿度值函数read_humidity()。 }
//读取湿度值函数 staticvoid read_humidity(void* arg) // sensorread humidity { int16_t humidity; int16_t temperature; JSensor_HUM_TEMP_Typedef tdef;
if (!running) return;
tdef.humidity = &humidity; tdef.temperature = &temperature;
if (JSENSOR_OK ==jsensor_app_read_sensor(JSENSOR_TYPE_HUMITY_TEMP, (void *)&tdef)) { ble_device_send(0x01, 2, (uint8_t*)&humidity); }
run_after_delay(read_pressure, NULL,UPDATE_INTERVAL); }
staticvoid read_pressure(void* arg) // sensorread pressure { JSensor_Press_Typedef tdef; int32_t pressure;
if (!running) return;
tdef.pressure = &pressure;
if (JSENSOR_OK ==jsensor_app_read_sensor(JSENSOR_TYPE_PRESSURE, (void *)&tdef)) { ble_device_send(0x02, 3, (uint8_t*)&pressure); }
run_after_delay(read_mag, NULL,UPDATE_INTERVAL); }
//读取磁力计值 staticvoid read_mag(void* arg) // sensorread magenetometer { JSensor_MAG_Typedef tdef; int8_t MAG[6];
if (!running) return;
tdef.MAG = MAG;
if(JSENSOR_OK ==jsensor_app_read_sensor(JSENSOR_TYPE_MAGNET, (void *)&tdef)) { ble_device_send(0x03, 6,(uint8_t*)MAG); //printf("%x,%x,%x,%x,%x,%x\n\r",MAG[0],MAG[1],MAG[2],MAG[3],MAG[4],MAG[5]); }
run_after_delay(read_acc, NULL,UPDATE_INTERVAL); } //读取加速度传感器数据 staticvoid read_acc(void* arg) // sensorread accelerometer { JSensor_AXIS_Typedef tdef; int8_t ACC[6], GRO[6];
if (!running) return;
tdef.ACC = ACC; tdef.GRO = GRO;
if (JSENSOR_OK ==jsensor_app_read_sensor(JSENSOR_TYPE_MOTION_6AXIS, (void *)&tdef)) { ble_device_send(0x04, 6,(uint8_t*)ACC); }
run_after_delay(read_gyro, NULL,UPDATE_INTERVAL); } 读取陀螺仪数据 staticvoid read_gyro(void* arg) // sensorread gyroscopic { JSensor_AXIS_Typedef tdef; int8_t ACC[6], GRO[6];
if (!running) return;
tdef.ACC = ACC; tdef.GRO = GRO;
if (JSENSOR_OK ==jsensor_app_read_sensor(JSENSOR_TYPE_MOTION_6AXIS, (void *)&tdef)) { ble_device_send(0x05, 6,(uint8_t*)GRO); }
run_after_delay(read_temperature, NULL,UPDATE_INTERVAL); }
下面的函数都是回调函数,已经都在聚码SDK中声明注册过,只需要在其中实现应用层具体的逻辑功能即可。当相应的事件发生的时候,系统会自动调用相对应回调函数。 //设备收到蓝牙数据回调函数,获取到的数据长度为length,存储在value中。Type为类型,用户可以用来自定义通信协议,不同类型区别不同数据,与手机端作匹配。 voidble_device_on_message(uint8_t type, uint16_t length, uint8_t* value) { }
//设备在和手机蓝牙连接上时的回调函数 voidble_device_on_connect(void) { running = 1;
run_after_delay(led_off, NULL, 150);//进入闪光灯 run_after_delay(read_temperature, NULL,UPDATE_INTERVAL); }
//设备蓝牙被断开时候的回调函数,参数是resaon,目前有定义两种原因,1、手机主动正常协商断开;2、意外非正常断开(距离太远、突然断电、协议栈崩溃等意外原因) voidble_device_on_disconnect(uint8_t reason) { running = 0; /* Make the device connectable again. */ Ble_conn_state = BLE_CONNECTABLE; ble_device_start_advertising();//设备重新开启蓝牙广播,方便手机可以继续连接 }
|