本帖最后由 我爱下载 于 2020-7-1 08:55 编辑

1.  设计简介
本设计是采用FR8016HA评估板作为蓝牙手柄,以BBC Micro:bit为核心的麦昆智能教育小车作为执行对象的一个蓝牙遥控小车的设计项目。但在实际设计过程中,发现Micro:bit启用蓝牙功能后已经没有内存空间继续完成小车控制部分代码的编写了,因此,修改了设计项目内容为再Micro:bit上,通过集成的LED阵列,指示FR8016HA蓝牙手柄的方向。
4.jpg        6.jpg 7.gif

2.  FR8016HA设计2.1. 硬件描述
为了实现蓝牙手柄的功能,使用了FR8016HA评估板的集成外设,主要有FR8016HA作为蓝牙主机、LCD作为显示模块、SH2100作为方向判别传感器。
3.png
SH2100的硬件接口电路,采用I2C接口完成6轴数据读取。
7.jpg
操作过程中,必须短接J1端子的11-12、13-14和15-16,完成CPU口的连接。
8.jpg
2.2. 软件功能描述
1)蓝牙主机功能
以SDK提供的ble_simple_central工程为基础,完成如下几个部分的调整。
l  安全参数配置的调整:
gap_security_param_t param =
  •     {
  •         .mitm = false,
  •         .ble_secure_conn = false,
  •         .io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT,
  •         .pair_init_mode = GAP_PAIRING_MODE_INITIATE,
  •         .bond_auth = true,
  •         .password = 0,
  • };
  • 复制代码
    pair_init_mode = GAP_PAIRING_MODE_INITIATE,表示主机可以主动发起连接;
    password = 0,表示免密码连接。设备端必须支持免密码连接功能。
    l  客户端(主机端)uuid定义
    系统中提供的短地址,实际中采用16字节长地址:
    #define SP_CHAR1_UUID            {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x03, 0x00, 0x40, 0x6e}
  • const gatt_uuid_t client_att_tb[] =
  • {
  •     [0]  =
  •     { UUID_SIZE_16, SP_CHAR1_UUID},
  •     [1]  =
  •     { UUID_SIZE_2, UUID16_ARR(SP_CHAR2_UUID)},
  • };
  • 复制代码
    这个地址就是Micro:bit蓝牙Uart的写属性UUID。
    l  Gap事件回调中广播事件响应
    case GAP_EVT_ADV_REPORT:
  •     {
  •         uint8_t scan_name[] = "BBC micro:bit";
  •       if (p_event->param.adv_rpt->data[4] == GAP_ADVTYPE_LOCAL_NAME_COMPLETE
  •    && memcmp(&(p_event->param.adv_rpt->data[5]), scan_name, 13) == 0)
  •      {
  •             gap_stop_scan();
  • co_printf("evt_type:0x%02x,rssi:%d\r\n",p_event->param.adv_rpt->evt_type,p_event->param.adv_rpt->rssi);
  •             co_printf("content:");
  • show_reg(p_event->param.adv_rpt->data,p_event->param.adv_rpt->length,1);
  •             gap_start_conn(&(p_event->param.adv_rpt->src_addr.addr),
  •                            p_event->param.adv_rpt->src_addr.addr_type,
  •                            12, 12, 0, 300);
  •         }
  •     }
  •     break;
  • 复制代码
    为了仅连接BBC Micro:bit设备,因此,指定        
    uint8_t scan_name[] = "BBCmicro:bit";
    蓝牙广播数据最长31字节,由于micro:bit广播数据中包含两个AD Struct,设备名字再第二个AD Struct中,因此AD Type从第4字节开始,
    p_event->param.adv_rpt->data[4]== GAP_ADVTYPE_LOCAL_NAME_COMPLETE
        表示后面是蓝牙设备名称;
    memcmp(&(p_event->param.adv_rpt->data[5]),scan_name, 13) == 0
        比较名称是否相同。
           如果比对相同,主机停止扫描,并发起连接,
           主机停止扫描:gap_stop_scan();
    主动发起连接:
    gap_start_conn(&(p_event->param.adv_rpt->src_addr.addr),
                              p_event->param.adv_rpt->src_addr.addr_type,
                               12, 12, 0, 300);
    l  Gap事件回调中主机连接事件响应
    当主机和设备连接建立后,产生该事件GAP_EVT_MASTER_CONNECT。
    case GAP_EVT_MASTER_CONNECT:
  •     {
  •         co_printf("master[%d],connect. link_num:%d\r\n",p_event->param.master_connect.conidx,gap_get_connect_num());
  •         master_link_conidx = (p_event->param.master_connect.conidx);
  • #if 0
  •         if (gap_security_get_bond_status())
  •             gap_security_enc_req(p_event->param.master_connect.conidx);
  •         else
  •             gap_security_pairing_req(p_event->param.master_connect.conidx);
  • #else
  •         co_printf("master[%d]_encrypted\r\n",p_event->param.master_encrypt_conidx);
  •         extern uint8_t client_id;
  •         gatt_discovery_all_peer_svc(client_id,p_event->param.master_encrypt_conidx);
  • #endif
  • //            simple_central_start_scan();
  •     }
  •     break;
  • 复制代码
    这里直接调用函数
    gatt_discovery_all_peer_svc(client_id,p_event->param.master_encrypt_conidx);
    获取设备的全部服务,不在启动主机扫描,因此屏蔽代码
    //            simple_central_start_scan();
    l  Gap事件回调中连接断开事件响应
    case GAP_EVT_DISCONNECT:
  •     {
  •         connect_status = 0;
  •         simple_central_start_scan();
  • #ifdef USER_MEM_API_ENABLE
  •         show_mem_list();
  •         //show_msg_list();
  •         show_ke_malloc();
  • #endif
  •     }
  •     break;
  • 复制代码
    这里当连接断开后,重新启动主机的扫描功能。
    l  Gatt信息发送
    由于蓝牙手柄为只发送功能,这里采用定时发送gatt信息的方法。
    gatt_client_write_t write;
  •        write.conidx = msg.conn_idx;
  •        write.client_id = client_id;
  •        write.att_idx = 0; //write
  •        write.p_data = str;
  •        write.data_len = 3;
  •        gatt_client_write_cmd(write);
  • 复制代码
    这里
           write.att_idx = 0; //write
    表示采用前面定义的客户端写UUID的16字节长地址写命令,
    gatt_client_write_cmd(write);
    写数据不需要设备响应。

    2)方向解算
    方向解算使用6轴SH2100的数据完成,厂家提供了SH2100的操作库函数,但是只完成了类似跳绳计数检测功能,我们可以使用基本数据获取功能,不使用他的检测计数功能。
    官方传感器SH2100的驱动中,提供了一个void gyroscope_timer_loop(void * arg)的周期函数,我们修改这个函数内容,然后计算方位角。
    void gyroscope_timer_loop(void * arg)
  • {
  •   uint8_t buf[12];
  •   uint8_t i;
  •   uint16_t temp;
  •   int16_t val[6];
  •   gyroscope_i2c_init(GYRO_IIC_CHL);
  •   I2C_Read_NBytes(GYRO_ADDRESS,0,12,buf);
  •   for(i=0;i<6;i++)
  •   {
  •       temp = buf[i*2+1];
  •       temp <<= 8;
  •       temp |= buf[i*2];
  •       val[i] = (int16_t)temp;
  •   }
  •   //方位角计算
  •   IMUupdate(gyro_x, gyro_y, gyro_z, val[0], val[1], val[2]);
  • }
  • 复制代码

    3)LCD显示
    LCD显示了我们的基本信息,厂家提供的库函数中,包含了全调的LCD操作函数,我们调用函数显示我们的内容就可以了。
    3.  Micro:bit设计
    micro:bit的设计采用makecode在线开发环境,以下简单介绍以下他的开发内容。
    为了使用蓝牙功能,我们必须增加系统的蓝牙支持,需要再高级->扩展中搜索“bluetooth”,并且安装这个支持包,系统同时提示和无线功能包冲突,这里直接选择删除无线功能增加蓝牙功能支持。
    另外我们还需要选择“项目设定”,并设置为:
    9.jpg
    保存。
    如下为程序图:
    1.jpg
    2.jpg
    3.jpg
    4.jpg



    4.  演示效果
    通过电池给板卡供电,拿在手里更舒服了。
    1.jpg 2.jpg 1.gif

    演示视频

    蓝牙主机程序代码: code.rar (12.03 KB, 下载次数: 21)