原创 EFR32_BLE开发记录

2024-1-16 19:14 518 3 3 分类: MCU/ 嵌入式 文集: EFR32MG低功耗蓝牙
什么是BLE

BLE:低功耗蓝牙,采用蓝牙4.0技术具有低成本,短距离特点。可以用于电子手环,蓝牙门锁等场景。

BLE如何进行通信 广播

BLE分为:中心设备和外设设备。

外设设备用GAP协议以广播形式告知中心设备,本机蓝牙可以被链接。中心设备可选择对发送过来的广播数据回复。回复的内容有设备名称,设备地址。也可不回复。

连接建立后就以client-server方式联系

中心设备(手机)作为client

外设设备(手环)作为serve

GATT协议

链接建立后,中心设备与外设设备用GATT协议通信

蓝牙应用层的协议,以profile文件的形式存储。

Profile文件结构如下

Service1

Characterisitic1

Characterisitic2

Service2

Characterisitic

….

每个profile包含若干个service,每个service包含若干个characteristic

而characteristic包含Properties ,value。

Properties 规定了cilent应以怎样的方式处理characteristic的内容

Properties的属性如下

属性名称

描述

read

支持 read 操作

write

支持 write 操作

notify

支持 notify 操作

indicate

支持 indicate 操作

当service端的蓝牙 characteristicr是Indicate 属性

客户端就必须要以indicate方式来读写characteristic

不能用其他三种。


无论是service还是characteristic最后都被封装成(Attribute

)att数据包。

ATT协议包括三部分 handle ,type,value

Handle: Attribute句柄。Client要访问Server的Attribute,都是通过这个句柄来访问的

在蓝牙数据包中一般都有这个值

Type :由UUID来定义。蓝牙联盟有统一的UUID设备标识。

具体使用使用时可以自定义也可用蓝牙联盟的。

Value:蓝牙数据包具体携带的值。

EFR32的BLE配置工具

到此我们只关心三件事情。
1.创建我们自定义的service和characteristic

2.用自定义的的characteristic向client发送数据

3.client接收数据

而GAP 和GATT都由EFR32的蓝牙SDK完成。

为了方便起见,我们首先分析一下EFR32的温度传感器例程代码。

在使用IDE的配置工具配置自定义的BLE任务

EFR32把蓝牙程序分成了两部分,一部分是bootloader,另一部分是蓝牙程序。

在下载蓝牙例程,需要先下载蓝牙的bootloader

导入一个蓝牙温度的例程

下载

https://www.silabs.com/documents/public/software/android-efr-connect.apk

如图所示

打开串口

打开IDE

看到有BLE组件

EFR32开发蓝牙工程分析及自定义一个蓝牙任务发送数据蓝牙工程分析

先来找蓝牙发送函数

搜索字符串“Temperature:”在工程中位置

在app.c的app_periodic_timer_cb函数里

这个函数是定时器的回调函数

周期性的获取温度值,并通过app_log_info和sl_bt_ht_temperature_measurement_indicate发送到串口与蓝牙。

sl_sensor_rht_get是温度获取函数

那么谁来调用app_periodic_timer_cb函数呢?

在app.的sl_bt_ht_temperature_measurement_indication_changed_cb

函数里调用用了app_periodic_timer_cb

通过源码可知,这个函数是在蓝牙连接建立后,client访问server中characteristic中的temperature_measurement子项时调用的。

调用方式是indicate。意思是server端发送完成后,client需要回复确认收到。

在sl_bt_ht_temperature_measurement_indication_changed_cb

进行了开启定时器,绑定回调函数操作

那sl_bt_ht_temperature_measurement_indication_changed_cb

是谁在调用?

是sl_bt_ht_on_event在调用

sl_bt_ht_on_event是蓝牙温度测量事件函数。

这个函数完成了温度测量的 characteristic从开始发送到发送完成关闭定时器的操作。

关心这几个部分。

sl_bt_gatt_server_write_attribute_value

在本地 GATT 数据库中写入属性值。如果本地 GATT 数据库中的属性具有指示或通知属性,且客户端已启用通知或指示功能,则写入该属性的值不会触发向远程 GATT 客户端发送通知或指示。

gattdb_temperature_measurement

    case sl_bt_evt_gatt_server_characteristic_status_id:

*@brief表示本地客户端特征配置

*描述符被远程GATT客户端更改,或者来自的确认

*远程GATT客户端在成功接收

*指示

*

来梳理下sl_bt_ht_on_event完成的事情

刚开始进入蓝牙温度任务

先执行 health_thermometer_init();

往蓝牙gatt数据库中写入temperature_type的属性。

温度数据发送都是按照这个属性(att)发送的

之后case sl_bt_evt_gatt_server_characteristic_status_id

说temperature_type的属性的蓝牙通信建立。

gattdb_temperature_measurement == evt->data.evt_gatt_server_characteristic_status.characteristic

判断蓝牙句柄拿到的uuid是否是gatt数据库中有的

(sl_bt_gatt_server_client_config == (sl_bt_gatt_server_characteristic_status_flag_t)evt->data.evt_gatt_server_characteristic_status.status_flags

客户端的characteristic已经改变

执行sl_bt_ht_temperature_measurement_indication_changed_cb

当蓝牙温度att通信关闭执行

 case sl_bt_evt_connection_closed_id:

      sl_bt_connection_closed_cb(evt->data.evt_connection_closed.reason,

                                 evt->data.evt_connection_closed.connection);

      break;

接下来看看sl_bt_ht_on_event是由谁调用

在sl_bluebooth.c的sl_bt_process_event里调用。

这是处理蓝牙任务函数包括

  sl_bt_in_place_ota_dfu_on_event(evt);

  sl_gatt_service_device_information_on_event(evt);

  sl_bt_ht_on_event(evt);

  sl_bt_on_event(evt);//这是个虚函数里面没有代码

与配置工具对应

在在sl_bluebooth.c的sl_bt_step里调用。sl_bt_step轮询蓝牙堆栈中的事件并进行处理

在sl_event_handler.c的sl_stack_process_action调用sl_bt_step

在sl_system_process_action.c的sl_system_process_action调用sl_stack_process_action

sl_system_process_action进行系统初始化和操作处理

*此函数调用一组自动生成的函数,这些函数位于`autogen/sl_event_handler.c`中。

可以使用事件处理程序组件提供的事件处理程序API为以下事件注册处理程序:

 *   - platform_init      -> sl_platform_init()

 *   - driver_init        -> sl_driver_init()

 *   - service_init       -> sl_service_init()

 *   - stack_init         -> sl_stack_init()

 *   - internal_app_init  -> sl_internal_app_init()

sl_system_process_action()在main函数while中调用

到这里已经把应用相关代码过了一遍

如图

C:.Users.18739.AppData.Local.Microsoft.Windows.INetCache.Content.Word.蓝牙sdk.png

我们只需要关心

修改sl_bt_ht_on_event函数变成我们自己的

仿照修改即可

接下来看看发送函数

  sc = sl_bt_ht_temperature_measurement_indicate(app_connection,

                                                 temperature,

                                                 false);

app_connection,蓝牙句柄

temperature温度值

false是摄氏度/true是华氏温度

在sl_bt_ht_temperature_measurement_indicate里进行了温度的数据封装操作

temperature_measurement_val_to_buf

把温度数据封装到五个字节的数据包里

第一个字节是温度类型

其余是温度值

  uint32_t tmp_value = ((uint32_t)value & 0x00ffffffu) \

                       | ((uint32_t)(-3) << 24);

  buffer[0] = fahrenheit ? TEMPERATURE_MEASUREMENT_FLAG_UNITS : 0;

  buffer[1] = tmp_value & 0xff;

  buffer[2] = (tmp_value >> 8) & 0xff;

  buffer[3] = (tmp_value >> 16) & 0xff;

  buffer[4] = (tmp_value >> 24) & 0xff;

要转回去

        a= (data[4]<<8)|data[3];

        a=(a<<8)|data[2];

        a=(a<<8)|data[1];

        a=a&0xffffff;

用最底层sl_bt_gatt_server_send_indication发送

  sc = sl_bt_gatt_server_send_indication(

    connection,

    gattdb_temperature_measurement,

   sizeof(buf),

    buf);

connection句柄

gattdb_temperature_measurement gatt的属性

  sizeof(buf),数据包大小

buf数据包 是一个指针类型const uint8_t* value

自定义GATT的service characteristic 并发送

进入blue配置工具

配置GATT数据库

如图

GATT数据库

再添加一个

接下

修改即可

在Health_Thermometer添加

void demo_init()

{

}

void sl_bt_demo_on_event(sl_bt_msg_t *evt)

{

// Handle stack events

switch (SL_BT_MSG_ID(evt->header)) {

case sl_bt_evt_system_boot_id:

demo_init();

break;

case sl_bt_evt_connection_closed_id:

sl_bt_demo_connection_closed_cb(evt->data.evt_connection_closed.reason,

evt->data.evt_connection_closed.connection);

break;

case sl_bt_evt_gatt_server_characteristic_status_id:

if (gattdb_test == evt->data.evt_gatt_server_characteristic_status.characteristic) {

// client characteristic configuration changed by remote GATT client

if (sl_bt_gatt_server_client_config == (sl_bt_gatt_server_characteristic_status_flag_t)evt->data.evt_gatt_server_characteristic_status.status_flags) {

sl_bt_demo_indication_changed_cb(

evt->data.evt_gatt_server_characteristic_status.connection,

(sl_bt_gatt_client_config_flag_t)evt->data.evt_gatt_server_characteristic_status.client_config_flags);

}

// confirmation of indication received from remove GATT client

else if (sl_bt_gatt_server_confirmation == (sl_bt_gatt_server_characteristic_status_flag_t)evt->data.evt_gatt_server_characteristic_status.status_flags) {

sl_bt_demo_indication_confirmed_cb(

evt->data.evt_gatt_server_characteristic_status.connection);

} else {

}

}

break;

default:

break;

}

}

App.c里添加

//demo code

#include "gatt_db.h"

static app_timer_t app_periodic_timer1;

static uint8_t app_connection1 = 0;

void demo_timer_cb()

{printf("demo_timer_cb()");

uint8_t c=10;

sl_bt_gatt_server_send_indication(

app_connection1,

gattdb_test,//要发送数据的characteristic

1,

&c);

}

/**************************************************************************//**

demo

* Indication changed callback

*

* Called when indication of temperature measurement is enabled/disabled by

* the client.

*****************************************************************************/

void sl_bt_demo_indication_changed_cb(uint8_t connection,

sl_bt_gatt_client_config_flag_t client_config)

{

app_connection1 = connection;

// Indication or notification enabled.

if (sl_bt_gatt_disable != client_config) {

// Start timer used for periodic indications.

app_timer_start(&app_periodic_timer1,

1 * 1000,

demo_timer_cb,

NULL,

true);

// Send first indication.

demo_timer_cb();

}

// Indications disabled.

else {

// Stop timer used for periodic indications.

(void)app_timer_stop(&demo_timer_cb);

}

}

void sl_bt_demo_connection_closed_cb(uint16_t reason, uint8_t connection)

{

(void)reason;

(void)connection;

sl_status_t sc;

// Stop timer.

sc = app_timer_stop(&app_periodic_timer1);

}

并在sl_bt_process_event添加sl_bt_demo_on_event

结果如图

主要参考

Silabs的蓝牙demo文档

UG103.14: Bluetooth® LE Fundamentals (silabs.com)

QSG169: Bluetooth® Quick-Start Guide for SDK v3.x and Higher (silabs.com)

ug434-bluetooth-c-soc-dev-guide-sdk-v3x.pdf (silabs.com)

博客园夜行过客专栏

https://www.cnblogs.com/yongdaimi/category/1543239.html

龙言飞语

https://zhuanlan.zhihu.com/p/346972549

作者: x鑫鑫, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-3984612.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
3
关闭 站长推荐上一条 /3 下一条