nrf51822蓝牙学习笔记四


目前手里面有几个项目用的是nrf51822这款蓝牙芯片。由于我从未接触过蓝牙协议,所以在很多地方磕磕绊绊的,所以最近准备系统学习一下该芯片。并做一下笔记放在我的博客里面。系统学习资料来源于B站青峰电子。视频名称为 蓝牙nrf51822视频教程资料 编程开发 协议栈开发 青峰电子例程

UUID

UUID的原理

UUID含义是通用唯一识别码(Universally Unique Identifier),这是一个软件建构的标准。UUID是指再一台机器上生成的数字,它保证对再同一时空中的所有机器都是唯一的。通常平台会提供生成的API。

在GATT层中,规范定义的所有属性都有一个UUID值,UUID是全球唯一的128位的号码,它用来识别不同的特性。

蓝牙技术联盟UUID

所有的蓝牙技术联盟定义UUID共用了一个基本的UUID。0x0000xxxx00001000800000805F9B34FB。为了进一步进化UUID,每一个蓝牙技术联盟的属性有一个唯一的16位UUID,以代替基本UUID的xxxx部分。例如心率测量特性使用0x2A37。

供应商特定UUID

SoftDevice根据蓝牙技术联盟定义UUID类似的方式定义UUID:先增加一个特定的基本UUID,再定义一个16位的UUID,将16位UUID加载到基本的UUID中。这种采用为所有的定制属性定义一个共用的基本UUID的方式使得应用变的更加简单。

UUID的设置

uint32_t ble_nus_init(ble_nus_t * p_nus, const ble_nus_init_t * p_nus_init)
{
    uint32_t      err_code;
    ble_uuid_t    ble_uuid;
    //基本UUID,xxxx使用00 00占位,数组下标与显示方向相反
    ble_uuid128_t nus_base_uuid = NUS_BASE_UUID;

    if ((p_nus == NULL) || (p_nus_init == NULL))
    {
        return NRF_ERROR_NULL;
    }

    // Initialize the service structure.
    p_nus->conn_handle             = BLE_CONN_HANDLE_INVALID;
    p_nus->data_handler            = p_nus_init->data_handler;
    p_nus->is_notification_enabled = false;

    /**@snippet [Adding proprietary Service to S110 SoftDevice] */
    // Add a custom base UUID.
    //将16位UUID添加到128位基础UUID
    err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    ble_uuid.type = p_nus->uuid_type;
    ble_uuid.uuid = BLE_UUID_NUS_SERVICE;

    // Add the service.
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                        &ble_uuid,
                                        &p_nus->service_handle);
    /**@snippet [Adding proprietary Service to S110 SoftDevice] */
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    // Add the RX Characteristic.
    err_code = rx_char_add(p_nus, p_nus_init);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    // Add the TX Characteristic.
    err_code = tx_char_add(p_nus, p_nus_init);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    return NRF_SUCCESS;
}

串口透传

通过串口透传数据传输给蓝牙。

初始化串口

这个也太简单了吧。随便百度就OK。

服务的建立

服务ble_nus.c

双向数据传输

tx,rx两个子服务。

蓝牙遥控器的设计

基于蓝牙串口透传,通过蓝牙发起指令控制硬件,达到遥控器的目的。

nrf51822内部flash操作

flash事件派发

/**@brief Function for dispatching a system event to interested modules.
 *
 * @details This function is called from the System event interrupt handler after a system
 *          event has been received.
 *
 * @param[in] sys_evt  System stack event.
 */
static void sys_evt_dispatch(uint32_t sys_evt)
{
    pstorage_sys_event_handler(sys_evt);//需要有该函数,官方函数库,直接调用即可
    ble_advertising_on_sys_evt(sys_evt);
}

// Register with the SoftDevice handler module for BLE events.
err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);//ble_stack_init函数中,协议栈系统事件
APP_ERROR_CHECK(err_code);

flash初始化

static pstorage_handle_t      m_storage_handle;  /**< Persistent storage handle for blocks requested by the module. */

pstorage_module_param_t param;
// Initialize persistent storage module.
err_code = pstorage_init();//只能初始化一次,我曾经初始化两次而出现问题

//dm_init中有初始化
//All context with respect to a particular device is stored contiguously.
param.block_size  = ALL_CONTEXT_SIZE;//块大小
param.block_count = DEVICE_MANAGER_MAX_BONDS;//块数目
param.cb          = dm_pstorage_cb_handler;//回调

err_code = pstorage_register(&param, &m_storage_handle);

flash读写

pstorage_handle_t block_handle;
err_code = pstorage_block_identifier_get(&m_storage_handle,0,&block_handle);//获取ID,有注册多次时需要用到,一次的话可以不调用
err_code = pstorage_clear(&block_handle, ALL_CONTEXT_SIZE);//擦除
err_code = pstorage_store(&block_handle,data,size,offset);//存储
err_code = pstorage_load(data,&block_handle,size,offset);//读取
pstorage_update(&block_handle,data,size,offset);//更新

flash存储接收内容

通过回调函数来进行存储,例程函数名及注释如下:

/**@brief Function for pstorage module callback.
 *
 * @param[in] p_handle Identifies module and block for which callback is received.
 * @param[in] op_code  Identifies the operation for which the event is notified.
 * @param[in] result   Identifies the result of flash access operation.
 *                     NRF_SUCCESS implies, operation succeeded.
 * @param[in] p_data   Identifies the application data pointer. In case of store operation, this
 *                     points to the resident source of application memory that application can now
 *                     free or reuse. In case of clear, this is NULL as no application pointer is
 *                     needed for this operation.
 * @param[in] data_len Length of data provided by the application for the operation.
 */
static void dm_pstorage_cb_handler(pstorage_handle_t * p_handle,
                                   uint8_t             op_code,
                                   uint32_t            result,
                                   uint8_t           * p_data,
                                   uint32_t            data_len)
{}

源代码太多,影响阅读,所以不贴代码,需要的话,自行阅读。

存储接收流程为手机发送数据->蓝牙数据处理->写入

此流程与例程功能并不相同。

蓝牙回调函数中如下代码:

pstorage_handle_t block_handle;
pstorage_block_identifier_get(&m_storage_handle,0,&block_handle);//注册一次可以不调用
pstorage_update(&block_handle,need_storage_data,len,offset);//更新数据

远程修改参数

流程:

蓝牙发送参数->蓝牙数据存储参数->重启初始化已经修改的参数

蓝牙温湿度采集

DHT11

单总线,很多开发板例程中都有它。也大多数使用的是模拟的IIC。

到这里了,不会还有人不会使用api去发送、接收蓝牙数据吧?不会吧不会吧!

广播包和数据包分析

使用Packet Sniffer工具进行抓包

抓包图:

img

广播包

显示数据标记为11个部分。

  • Packet Sniffer抓包序列数,依次计数
  • 抓取包的延时
  • 广播包表示的是广播信道,数据包表示的是数据信道。
    数据链路层的两种信道:
    A:广播信道,提供给还没有建立连接的蓝牙设备提供发射广播、扫描、建立连接的信道。BLE有三个广播信道,37,38,39.广播设备分别在这三个信道各发送一次广播信号。传统蓝牙信道有16-32个,而BLE只有三个。因此BLE广播时间短。
    B:数据信道:提供给已经建立蓝牙连接的主从端提供可靠的数据通信信道。BLE规定有37个。为加强通讯的可靠性,避开干扰。BLE设备通过自适应跳频的方式在37个信道上传。
  • 接入地址:0xBE89BED6。所有BLE设备的广播帧都是使用的该地址,不分厂家
  • PDU type是广播类型(2 BYTE)。
    • 以ADV开头的帧表示为广播帧。是由advertiser发出的。有四种类型:
      ①ADV_IND:通用的可以建立连接的广播,nrf51822通常发此广播
      ②ADV_DIRECT_IND:快速广播。广播最长发射事件为1.28S。
      ③ADV_NONCONN_IND:不能建立连接的广播信号,ibeacon发此类广播
    • ADV_SCAN_IND为扫描帧,由scanner发出。
    • ADV_SCAN_REQ:为扫描请求帧,由scanner发出。只在scanner想从advertiser获取更多广播数据时发出。相应的,当ADV_SCAN_REQ被发出以后,advertiser会以SCAN_RSP作为回应
    • SCAN_RSP:ADV_SCAN_REQ回应。
    • CONNECT_REQ为scanner向advertiser发出
  • Txadd Rxadd用来表示发送该广播帧的蓝牙设备的蓝牙地址类型。1表示random address,0表示为public address。

    蓝牙协议规定,任何一个蓝牙设备必须拥有一个唯一的48bit的地址,用以标识身份。而且,在广播的时候,必须要把蓝牙地址广播出去。蓝牙地址有以下四种:

    • public address:该地址是公司通过IEEE申请获得的,称为OUI。这个地址是固定地址,全球唯一,不可修改。用24bit表(LSB)示公司名,24bit(MSB)用来分配给不同的产品类型。
    • random static address:是设备上电的时候随机生成或者芯片厂家在生产芯片的时候,随机烧录的不重复的48bit的蓝牙地址。nrf51822属于后者。该地址存放在FICR中,用户不可修改。最高位的后2bit必须位1。
    • private Non-Resolvable address和Private Resolvable address不常用,mac地址设置与分析中介绍。
    nrf51822采用的是Random static address。在启动的时候协议栈从FICR里读取作为设备的蓝牙地址。如果用户需要使用Public address则需要使用sd_ble_gap_address_set()这个函数重新设定蓝牙地址。
    length表示PDU payload大小
  • 蓝牙设备地址
  • PDU payload
    0E 09 4C 65 64 42 75 74 74 6F 6E 44 65 6D 6F为1组。0E代表本字段长度 09为LOCAL NAME,也就是蓝牙设备名称。可查ASCII表。表示该设备名称为LedButtonDemo.
    03 19 34 12为1组,03为本字段长度:19为APPEARANCE(外观,例如BLE_APPEARANCE_HID_MOUSE就会在手机或者PC中显示有鼠标图案),因为蓝牙拉松数据是低位在前,所以3412其实为1234.0x1234转成10进制为4660.APPEARANCE这个AD TYPE是新添加的TYPE,所以在CORE 4.0核心协议中找不到
    02 01 05为1组,02为字段长度,01是FLAGS 06表示设备只支持BLE,不支持传统蓝牙。05为04+01,见后图。
  • CRC:校验
  • RSSI:信号强度
  • FCS:反馈

信道分区图:

img

广播协议包:

img

蓝牙广播FLAG:

img

数据包

ble数据包

img

Access address为接入 地址,接入地址由主设备提供。地址随机生成。但是遵从一定规律。不同于广播接入地址固定,具体规定查看蓝牙协议。

Direction连接方向。M为主机,S为从机

ACK status响应

Data Type数据类型

Data Header报头。

​ MESN:下一个预期序列号。SN:序列号。MD:更多数据,PDU-Length:PDU长度。没有为0

img

  • 00:保留
  • 11:链路层控制报文:用于管理连接
  • 10:高级报文开始:可用于一个完整报文
  • 01高层报文延续

LED读写数据包

img

写入01

img

mac地址分析与设置

BLE设备地址类型

一个BLE设备,可以使用两种类型的地址(一个BLE设备可同时具备两种地址):Public Device Address(公共设备地址)和Random Device Address(随机设备地址)。而Random Device Address又分为Static Device Address(静态设备地址)和Private Device Address(私密设备 地址)两类。其中Private Device Address又可以分为Non-resolvable private Address(不可解析私密地址)和Resolvable private Address(可解析私密地址)。

公共设备地址

在通信系统中,设备地址是用来唯一识别一个物理设备的,如TCP/IP网络中的MAC地址、传统蓝牙中的蓝牙地址等。对设备地址而言,一个重要的特性就是唯一性。对经典蓝牙(BR/EDR)来说,其设备地址是一个48bit的数字,称作“48-bit universal LAN MAC addresses”。正常情况下,该地址需要向IEEE申请(就是购买)。IEEE保证地址的唯一性。这种地址分配方式,在BLE中保留下来,就是公共设备地址。由24-bit的company_id和24bit的company_assigned组成(已在本文中介绍)。

随机设备地址

在BLE时代,公共设备地址不够用了,原因如下:

1:需要购买,不小开销

2:申请与管理是相当繁琐、复杂。维护成本增大

3: 安全因素,BLE很大一部分应用场景是广播通讯。意味只要设备地址,就可以获取所有信息。不安全。

因此BLE协议新增该地址。设备地址不是固定分配,而是设备启动后随机生成

静态设备地址

该地址是设备在上电随机生成的地址,nrf51822官方例程默认使用静态地址。

特征总结:

1:最高两位必须为11

2:剩余最后46位是一个随机数,不可全为0也不可全为1.

3:在一个上电周期内保持不变

4:下一次上电可以改变,但不是强制的。如果改变,上次保存的连接信息将会失效

应用场景总结:

1:46位随机数,可解决唯一性问题。相同概率很小

2:地址随机生成,可解决公共设备地址带来的费用和维护问题

私密设备地址

此地址更近一步,通过定时更新、地址加密方法,提高蓝牙地址的可靠性和安全性。根据地址是否解密,又分为两类。

不可解析私密地址

该地址会定时更新,更新周期由GAP规定,称作T_GAP,建议值是15分钟。

特征总结:

1:最高两位必须为00

2:剩余最后46位是一个随机数,不可全为0也不可全为1.

3:以T_GAP为周期定时更新。

自己有可能都不知道变成什么地址了,沙雕一样的方式,该地址类型不常用。

可解析私密地址

该地址比较有用,通过一个随机数和IRK密码生成,因此只可能被拥有相同IRK的设备扫描到,可以防止被位置设备扫描和跟踪。

格式如下:

img

特征:

A:由两部分组成,高位是随机数部分,最高两个bit为10,用于表示地址类型。低位时随机数和IRK经过hash运算得到的hash值。运算公式为hash=ah(IRK,prand)

B:当对端BLE设备扫描到该类型蓝牙地址后,会使用保存在本机的IRK,和该地址中的prand,进行同样的hash运算,并将运算结果和地址中的hash字段进行比较,相同的时候才进行后续操作。该过程称为解析。

C:以T_GAP为周期,定时更新,哪怕在广播、扫描、已连接过程中也可能改变。

D:不能单独使用,因此使用该类型的地址的话,设备需要同时具备公共设备地址或者静态设备地址中的一种。

地址配置

此时可以看广播包数据分析的第六部分和第七部分 ,如果是随机地址可通过查看地址最高两位来判断地址类型。

函数api:

SVCALL(SD_BLE_GAP_ADDRESS_SET, uint32_t, sd_ble_gap_address_set(uint8_t addr_cycle_mode, const ble_gap_addr_t *p_addr));
//addr_cycle_mode :
//①:BLE_GAP_ADDR_CYCLE_MODE_AUTO:该模式下,设置为可解析私密地址或者不可解析私密地址。协议栈内部会自动周期性根据结构体p_addr中的addr_type元素生成地址
//②:BLE_GAP_ADDR_CYCLE_MODE_NONE:该模式下,可以使用public地址和static random类型,addr中存放的最高两位必须为11,不然会被认为无效且自动替换。替换为蓝牙mac地址。和没有使用该函数一样。

默认状态:

官方demo是没有主动调用过该函数,都默认使用静态设备地址。是芯片出厂就设置的。

这两个视频应该是放反了

蓝牙信号rssi读取

rssi接收的信号强度指示。用于判断连接质量。以及是否增大广播发送强度。

为什么是负值

无线信号多为mW级别,对他进行了极化,转换为dbm而已。

公式:Rssi=10 * log§

将P带入即可。

API

/**@brief Start reporting the received signal strength to the application. 
 *
 * A new event is reported whenever the RSSI value changes, until @ref sd_ble_gap_rssi_stop is called.
 *
 * @param[in] conn_handle        Connection handle.
 * @param[in] threshold_dbm      Minimum change in dBm before triggering the @ref BLE_GAP_EVT_RSSI_CHANGED event. Events are disabled if threshold_dbm equals @ref BLE_GAP_RSSI_THRESHOLD_INVALID.
 * @param[in] skip_count         Number of RSSI samples with a change of threshold_dbm or more before sending a new @ref BLE_GAP_EVT_RSSI_CHANGED event.
 *
 * @retval ::NRF_SUCCESS                   Successfully activated RSSI reporting.
 * @retval ::NRF_ERROR_INVALID_STATE       Disconnection in progress. Invalid state to perform operation.
 * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied.
 */
SVCALL(SD_BLE_GAP_RSSI_START, uint32_t, sd_ble_gap_rssi_start(uint16_t conn_handle, uint8_t threshold_dbm, uint8_t skip_count));
//开始测量信号强度

/**@brief Get the received signal strength for the last connection event.
 *
 * @param[in]  conn_handle Connection handle.
 * @param[out] p_rssi      Pointer to the location where the RSSI measurement shall be stored.
 *
 * @ref sd_ble_gap_rssi_start must be called to start reporting RSSI before using this function. @ref NRF_ERROR_NOT_FOUND
 * will be returned until RSSI was sampled for the first time after calling @ref sd_ble_gap_rssi_start.
 *
 * @retval ::NRF_SUCCESS                   Successfully read the RSSI.
 * @retval ::NRF_ERROR_NOT_FOUND           No sample is available.
 * @retval ::NRF_ERROR_INVALID_ADDR        Invalid pointer supplied.
 * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied.
 * @retval ::NRF_ERROR_INVALID_STATE       RSSI reporting is not ongoing, or disconnection in progress.
 */
SVCALL(SD_BLE_GAP_RSSI_GET, uint32_t, sd_ble_gap_rssi_get(uint16_t conn_handle, int8_t *p_rssi));
//获取信号强度

蓝牙发射功率的设置

nrf51822可以设置9个发送等级分别是-40,-30,-20,-16,-12,-8,-4,0,4dBm。如果没有设置,则默认为0dbm。

1,广播初始化:设置广播的tx_power_level,用于初始化广播的发送功率。

#define TX_POWER_LEVEL 0
static void advertising_init(void){
    int8_t tx_power_level=TX_POWER_LEVEL;
    advdata.p_tx_power_level = &tx_power_level;
    ble_advertisingOinit(&advdata,&scanrsp,&options,on_adv_evt,NULL);
}

2,GAP初始化:通过sd_ble_gap_tx_power_set设置。该函数可动态修改发送功率。

errcode = sd_ble_gap_tx_power_set(TX_POWER_LEVEL);

本文章首发于本人个人网站

nrf51822中文参考手册,nRF51822 是一款集成nRF51x系列无线收发器的超低功耗的片上系统 (Soc) , 包含一个32位ARM Cortex-M0 CPU , flash 存储器和模拟、数字外设。NORDIC SEMICONDUCTOR nRF51822 Product Specification v1.3 Liability disclaimer Nordic Semiconductor ASa reserves the right to make changes without further notice to the product to improve reliability, function or design. Nordic Semiconductor asa does not assume any liability arising out of the application or use of any product or circuits described herein ife support applications Nordic Semiconductor's products are not designed for use in life support appliances, devices, or systems where malfunction of these products can reasonably be expected to result in personal injury. Nordic Semiconductor ASa customers using or selling these products for use in such applications do so at their own risk and agree to fully indemnify Nordic Semiconductor ASA for any damages resulting from such improper use or sale Contact details Foryournearestdistributorpleasevisitwww.nordicsemi.com Information regarding product updates, downloads, and technical support can be accessed through your My Page account on our home page Main office: Otto Nielsens veg 12 Mailing address: Nordic Semiconductor 7052 Trondheim P.O. Box 2336 Norway 7004 Trondhe Phone:+4772898900 Norway 4772898989 画N远 NS-EN ISO 9001 CERTIFICATEDFIRM RoHS and reach statement Nordic semiconductor's products meet the requirements of Directive 2002/95/EC of the European Parliament and of the Council on the restriction of Hazardous Substances(roHS)and the requirements of the reach regulation(EC 1907/2006)on Registration, Evaluation, Authorization and Restriction of Chemicals. The SvHC(Substances of Very High Concern) candidate list is continually being updated Complete hazardous substance reports material composition reports and latest version of nordics reach statementcanbefoundonourwebsitewww.nordicsemicom Page 2 of 67 NORDIC SEMICONDUCTOR nRF51822 Product Specification v1.3 Datasheet status Status Description Objective Pro
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值