查看: 781|回复: 2

[原创] 小钢炮(CANNON) SensorTag例程上手及代码解析

[复制链接]

14

主题

3

好友

949

积分

举人

Rank: 4

  • TA的每日心情
    开心
    2016-7-19 13:45
  • 签到天数: 53 天

    [LV.5]常住居民I

    发表于 2016-5-5 10:44:36 |显示全部楼层
    一、需要的资源
    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


    1.png

    (2)      如果出现下面的画面,是提示你安装工程所需要的STM32F4的包文件。
    这里我给出两种方案:第一种是你可以选择点击Install直接在线安装,这个一般来说应该是比较慢(网速好能翻墙的忽略);第二种是点击cancel,在论坛里面下载我已经下载好的包文件,下载分享的帖子地址在论坛(http://52cannon.com/bbs/thread-217-1-1.html),直接下载下来双击也可以安装。 2.png

    3.png


    (3)      包文件安装
    直接双击下载下来的

    4.png
    会自动识别默认安装路径在keil的安装文件夹,不用修改。直接next.然后等待安装完成,大概需要几分钟。 5.png

    (4)      重新打开工程文件,就不会有提示了。
    3、  源码解析
    (1)      打开工程后,打开文件列表,可以找到app.c这个文件就是应用层逻辑实现的源码。


    6.png

    (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();//设备重新开启蓝牙广播,方便手机可以继续连接
    }



    回复

    使用道具 举报

    32

    主题

    0

    好友

    2060

    积分

    进士

    Rank: 5Rank: 5

  • TA的每日心情
    慵懒
    10 小时前
  • 签到天数: 527 天

    [LV.9]以坛为家II

    爱板会员勋章 活跃会员勋章 发帖机器勋章 在线达人勋章

    发表于 2016-5-5 12:46:32 |显示全部楼层
    搞不明白主函数怎么调用应用层函数的,没有头文件包括
    回复

    使用道具 举报

    14

    主题

    3

    好友

    949

    积分

    举人

    Rank: 4

  • TA的每日心情
    开心
    2016-7-19 13:45
  • 签到天数: 53 天

    [LV.5]常住居民I

    发表于 2016-5-5 14:17:01 |显示全部楼层
    wambob 发表于 2016-5-5 12:46
    搞不明白主函数怎么调用应用层函数的,没有头文件包括

    主函数中有个dispatch函数,所有任务都是通过这个调度器来运行的。同时可以运行32个任务。编程机制是单线程异步编程机制。应用层都是通过回调函数来运行逻辑。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

    站长推荐上一条 /6 下一条


    手机版|爱板网 |网站地图  

    GMT+8, 2016-12-4 12:01 , Processed in 0.146730 second(s), 12 queries , Memcache On.

    苏公网安备 32059002001056号

    Powered by Discuz!

    回顶部