蓝牙:GATT,属性,特性,服务

2023-05-16

接着上一篇。

通用属性配置文件(Generic Attribute Profile)

1.GATT简介

通用属性配置文件Generic Attribute Profile简称GATT。
GATT定义了属性类型并规定了如何使用,包括了一个数据传输和存储的框架和一些基本操作。中间包含了一些概念如特性characteristics,服务services等,在后面介绍。同时还定义了发现服务,特性和服务间的连接的处理过程,也包括读写特性值。

1.1.GATT的角色

GATT中定义了2种角色:服务器server和客户端client.
GATT的服务器是指提供数据的设备,而GATT的客户端是指通过GATT的服务器获取数据的设备。

1.2.GATT的层次

GATT服务器通过一个属性表来组织发送的数据。这里的关系大概是这样:
这里写图片描述
一个Profile中可包含一个或者多个服务;一个服务可包含一个或者多个特性(逻辑上的集合);一个特性至少包含两个属性:一个用于声明,其他用于存储属性值。

2.属性(Attribute)

一个属性包括句柄,UUID,值。
句柄是属性在GATT表中的索引,在一个设备中每个属性的句柄是唯一的。UUID包括属性表中的数据类型信息,它是理解属性表中值的每一个字节的关键信息。GATT表中可能有多个属性拥有相同的UUID值。
属性相关的数据结构:

/**@brief 属性元数据. */
typedef struct
{
  ble_gap_conn_sec_mode_t read_perm;       /**< 读权限 */
  ble_gap_conn_sec_mode_t write_perm;      /**< 写权限 */
  uint8_t                 vlen       :1;   /**< 属性长度. */
  uint8_t                 vloc       :2;   /**< 值存放的位置, 详情参照BLE_GATTS_VLOCS.*/
  uint8_t                 rd_auth    :1;   /**< 读许可,该值会在每次读操作后向应用重新发起请求*/ 
  uint8_t                 wr_auth    :1;   /**< 写许可会在每次读操作后向应用重新发起请求(但不写命令). */
} ble_gatts_attr_md_t;


/**@brief GATT 属性. */
typedef struct
{
  ble_uuid_t*          p_uuid;          /**< 指向属性的UUID */
  ble_gatts_attr_md_t* p_attr_md;       /**< 指向属性元数据的数据结构*/
  uint16_t             init_len;        /**< 初始化属性长度 */
  uint16_t             init_offs;       /**< 初始化属性偏移 */
  uint16_t             max_len;         /**< 最大属性长度,参照BLE_GATTS_ATTR_LENS_MAX*/
  uint8_t*             p_value;         /**< 指向属性数据。请注意如果 BLE_GATTS_VLOC_USER值的位置被选在attribute metadata结构体中,则需指向有效生命周期缓冲区。协议栈可能在没有得到应用程序许可的情况下直接操作 */
} ble_gatts_attr_t;


/**@brief GATT 属性内容. */
typedef struct
{
  ble_uuid_t           srvc_uuid;       /**< 服务UUID */
  ble_uuid_t           char_uuid;       /**< 特性的UUID(BLE_UUID_TYPE_UNKNOWN无效). */
  ble_uuid_t           desc_uuid;       /**< 描述UUID(BLE_UUID_TYPE_UNKNOWN无效). */
  uint16_t             srvc_handle;     /**< 服务句柄 */
  uint16_t             value_handle;    /**< 特性的处理句柄(BLE_GATT_HANDLE_INVALID 无效). */
  uint8_t              type;            /**< 属性类型, 参照BLE_GATTS_ATTR_TYPES. */
} ble_gatts_attr_context_t;

描述符:
在任何特性中的属性不是定义为属性值就是描述符。描述符是一个额外的属性,以提供更多特性的信息。这里有个特殊的描述符:客户端特性配置描述符cccd。这个描述符是给任意支持通知或指示功能的特性额外添加的。在cccd中写入1为使能通知功能,写入2使能指示功能,写0禁止通知和指示功能。

UUID:
在GATT规范中定义所有的属性都必须要有一个UUID值,UUID是全球唯一的128位的数据,用来识别不同的特性。
蓝牙核心规范制定了两种不同的UUID,一种是基本的UUID,一种是代替基本UUID的16为UUID。
我们协议栈的后面那里使用的就是代替基本UUID的16为UUID:先增加一个特定的基本UUID,在定义一个十六位的UUID。加载到基本UUID之上。源码中UUID如下:

#define LBS_UUID_BASE {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00}
#define LBS_UUID_SERVICE 0x1523
#define LBS_UUID_LED_CHAR 0x1525
#define LBS_UUID_BUTTON_CHAR 0x1524
//添加一个特定的基本UUID
ble_uuid128_t base_uuid = {LBS_UUID_BASE};
err_code = sd_ble_uuid_vs_add(&base_uuid, &p_lbs->uuid_type);

UUID数据结构:

/** @brief 128 bit UUID values. */
typedef struct
{ 
    unsigned char uuid128[16];     
} ble_uuid128_t;

/** @brief  Bluetooth Low Energy UUID type, encapsulates both 16-bit and 128-bit UUIDs. */
typedef struct
{
    uint16_t    uuid; /**< 16-bit UUID value or octets 12-13 of 128-bit UUID. */
    uint8_t     type; /**< UUID type, see @ref BLE_UUID_TYPES. If type is BLE_UUID_TYPE_UNKNOWN, the value of uuid is undefined. */
} ble_uuid_t;

3.特性(Characteristics)

一个特性至少包含2个属性:一个用于声明,一个用于存储属性值。通过GATT服务传输的数据必须映射成一系列的特性。可以把特性中的数据看成是一个个捆绑起来的数据,每个特性就是一个数据点。源码中特性的数据结构如下:

/**@brief GATT 特性表示格式 */
typedef struct
{
  uint8_t          format;      /**< 值的格式,参照BLE_GATT_CPF_FORMATS. */
  int8_t           exponent;    /**< 整数类型的指数 */
  uint16_t         unit;        /**< 蓝牙中分配的UUID*/
  uint8_t          name_space;  /**< 从蓝牙分配的命名空间,参见BLE_GATT_CPF_NAMESPACES.*/
  uint16_t         desc;        /**< 从蓝牙分配的命名空间描述,参见BLE_GATT_CPF_NAMESPACES.*/
} ble_gatts_char_pf_t;

/**@brief GATT 特性性质 */
typedef struct
{
  /* 标准性质 */
  uint8_t broadcast       :1; /**< 是否允许广播 */
  uint8_t read            :1; /**< 是否允许读操作 */
  uint8_t write_wo_resp   :1; /**< 是否允许命令写修改操作 */
  uint8_t write           :1; /**< 是否允许请求写修改操作*/
  uint8_t notify          :1; /**< 是否允许通知修改 */
  uint8_t indicate        :1; /**< 是否允许指示修改 */
  uint8_t auth_signed_wr  :1; /**< 是否允许签名写命令写入*/
} ble_gatt_char_props_t;

/**@brief GATT 特性元数据. */
typedef struct
{
  ble_gatt_char_props_t       char_props;               /**< 特性性质 */
  ble_gatt_char_ext_props_t   char_ext_props;           /**< 特性拓展性质 */
  uint8_t*                    p_char_user_desc;         /**< 指向UTF-8, NULL则无要求 */
  uint16_t                    char_user_desc_max_size;  /**< 用户描述符的最大字节长 */
  uint16_t                    char_user_desc_size;      /**< 用户描述字节, 必须小于等于char_user_desc_max_size */ 
  ble_gatts_char_pf_t*        p_char_pf;                /**< 指向现存的结构体格式,NULL则对描述符不做要求 */
  ble_gatts_attr_md_t*        p_user_desc_md;           /**< 用户描述符的Attribute元数据,NULL为默认值 */
  ble_gatts_attr_md_t*        p_cccd_md;                /**< cccd的Attribute元数据,NULL为默认值 */
  ble_gatts_attr_md_t*        p_sccd_md;                /**< sccd的Attribute元数据,NULL为默认值  */
} ble_gatts_char_md_t;


/**@brief GATT 特性定义句柄 */
typedef struct
{
  uint16_t          value_handle;       /**< 处理特征值句柄 */
  uint16_t          user_desc_handle;   /**< 处理用户描述符的句柄,BLE_GATT_HANDLE_INVALID为不存在 */
  uint16_t          cccd_handle;        /**< 处理CCCD的句柄,BLE_GATT_HANDLE_INVALID 为不存在*/
  uint16_t          sccd_handle;        /**< 处理SCCD的句柄,BLE_GATT_HANDLE_INVALID 为不存在. */
} ble_gatts_char_handles_t;

ble_gatts_char_md_t结构体中的ble_gatt_char_props_t和ble_gatt_char_ext_props_t类型中记录了GATT的标准和拓展特性。典型的特性包括:
读:GATT客户端可以从GATT服务器中读取特性值
写和没有回应的写:允许GATT客户端写入一个值到GATT服务器的特性中。没有回应的写没有任何应用层上的确认或回应。
通知:允许GATT服务器在某个特性该改变的时候对GATT客户端进行提醒。
指示:允许GATT服务器在某个特性该改变的时候对GATT客户端进行提醒,并在应用层上确认。
广播。

4.服务(serive)

一个服务包括一个或者多个特性,这些特性是逻辑上的集合体。

5.源码部分分析

主程序中这些部分主要是对GATT相关内容的操作。这里的蓝牙在GATT中是作为服务器的角色。

5.1.连接参数

conn_params_init();     //初始化连接参数

static void conn_params_init(void)
{
    uint32_t               err_code;
    ble_conn_params_init_t cp_init;
    memset(&cp_init, 0, sizeof(cp_init));
    cp_init.p_conn_params                  = NULL;
    cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
    cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
    cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
    cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
    cp_init.disconnect_on_fail             = false;
    cp_init.evt_handler                    = on_conn_params_evt;
    cp_init.error_handler                  = conn_params_error_handler;

    err_code = ble_conn_params_init(&cp_init);   //初始化
    APP_ERROR_CHECK(err_code);
}

uint32_t ble_conn_params_init(const ble_conn_params_init_t * p_init)
{
    uint32_t err_code;
    m_conn_params_config = *p_init;
    m_change_param = false;
    if (p_init->p_conn_params != NULL)
    {
        m_preferred_conn_params = *p_init->p_conn_params;   
        // 设置栈的连接参数
        err_code = sd_ble_gap_ppcp_set(&m_preferred_conn_params);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }
    else
    {
        // 从栈上获取连接参数
        err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }
    m_conn_handle  = BLE_CONN_HANDLE_INVALID;
    m_update_count = 0;
    return app_timer_create(&m_conn_params_timer_id,
                            APP_TIMER_MODE_SINGLE_SHOT,
                            update_timeout_handler);
}

该函数中定义了一个连接参数结构体数据cp_init,用来保存连接参数。再调用ble_conn_params_init函数进行初始化,同时创建一个定时器。

5.2.自定义服务

该程序实现一个按键通知LED点亮的功能。
该部分程序是在services_init函数中添加的

typedef struct
{
    ble_lbs_led_write_handler_t led_write_handler;  /* 当LED的特性被写时调用的回调函数 */
} ble_lbs_init_t;

static void services_init(void)
{
    uint32_t err_code;
    ble_lbs_init_t init;

    init.led_write_handler = led_write_handler;

    err_code = ble_lbs_init(&m_lbs, &init);
    APP_ERROR_CHECK(err_code);
}

在函数职工定义了一个init变量,然后绑定到led_write_handler这个回调函数上,再调用ble_lbs_init进行初始化。在该函数中必须要添加服务,得到服务句柄。

uint32_t ble_lbs_init(ble_lbs_t * p_lbs, const ble_lbs_init_t * p_lbs_init)
{
    uint32_t   err_code;
    ble_uuid_t ble_uuid;

    // 初始化服务结构体
    p_lbs->conn_handle       = BLE_CONN_HANDLE_INVALID;
    p_lbs->led_write_handler = p_lbs_init->led_write_handler;

    // 添加服务
    ble_uuid128_t base_uuid = {LBS_UUID_BASE};
    err_code = sd_ble_uuid_vs_add(&base_uuid, &p_lbs->uuid_type); //绑定baseUUID
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    ble_uuid.type = p_lbs->uuid_type;
    ble_uuid.uuid = LBS_UUID_SERVICE;

    //这里是添加server服务UUID为0x1523,并得到一个唯一的句柄
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_lbs->service_handle);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    //这里是添加button服务 UUID为0x1524
    err_code = button_char_add(p_lbs, p_lbs_init);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    //这里是添加led服务 UUID为0x1525
    err_code = led_char_add(p_lbs, p_lbs_init);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    return NRF_SUCCESS;
}

下面举例button_char_add()。led_char_add函数的过程也与此类似。

static uint32_t button_char_add(ble_lbs_t * p_lbs, const ble_lbs_init_t * p_lbs_init)
{
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;

    memset(&cccd_md, 0, sizeof(cccd_md));
    //设置声明属性值
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
    cccd_md.vloc = BLE_GATTS_VLOC_STACK; //属性值分配在栈内存上

    memset(&char_md, 0, sizeof(char_md));
    //设置特性值
    char_md.char_props.read   = 1;
    char_md.char_props.notify = 1;
    char_md.p_char_user_desc  = NULL;
    char_md.p_char_pf         = NULL;
    char_md.p_user_desc_md    = NULL;
    char_md.p_cccd_md         = &cccd_md;
    char_md.p_sccd_md         = NULL;

    //设置按键UUID
    ble_uuid.type = p_lbs->uuid_type;
    ble_uuid.uuid = LBS_UUID_BUTTON_CHAR;

    memset(&attr_md, 0, sizeof(attr_md));
    //设置自定义属性值
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 0;

    memset(&attr_char_value, 0, sizeof(attr_char_value));
    //设置属性值
    attr_char_value.p_uuid       = &ble_uuid;
    attr_char_value.p_attr_md    = &attr_md;
    attr_char_value.init_len     = sizeof(uint8_t);
    attr_char_value.init_offs    = 0;
    attr_char_value.max_len      = sizeof(uint8_t);
    attr_char_value.p_value      = NULL;

    //添加按键服务
    return sd_ble_gatts_characteristic_add(p_lbs->service_handle, &char_md,
                                               &attr_char_value,
                                               &p_lbs->button_char_handles);
}

sd_ble_gatts_characteristic_add函数用来添加特性。第一个参数是要添加到的服务的句柄,第二个参数是特性值,在它上面绑定一个cccd的属性元数据(描述符),第三个参数值属性的描述,中间绑定了ble按键的UUID值和按键属性的元数据,第四个参数是返回的按键的特性和描述符的唯一句柄。

前面大概讲过,当协议栈启动之后,BLE的事件响应在初始化的时候被绑定到ble_evt_dispatch函数中了。而在这个函数中有一个ble_lbs_on_ble_evt的事件监测函数,代码如下:

void ble_lbs_on_ble_evt(ble_lbs_t * p_lbs, ble_evt_t * p_ble_evt)
{
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            on_connect(p_lbs, p_ble_evt);
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            on_disconnect(p_lbs, p_ble_evt);
            break;

        case BLE_GATTS_EVT_WRITE:
            on_write(p_lbs, p_ble_evt);
            break;

        default:
            break;
    }
}
static void on_disconnect(ble_lbs_t * p_lbs, ble_evt_t * p_ble_evt)
{
    UNUSED_PARAMETER(p_ble_evt);
    p_lbs->conn_handle = BLE_CONN_HANDLE_INVALID;
}
static void on_connect(ble_lbs_t * p_lbs, ble_evt_t * p_ble_evt)
{
    p_lbs->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
}
//写入回调函数,在初始化的时候别绑定。当有写入时回调
static void led_write_handler(ble_lbs_t * p_lbs, uint8_t led_state)
{
    if (led_state)
    {
        nrf_gpio_pin_set(LEDBUTTON_LED_PIN_NO);
    }
    else
    {
        nrf_gpio_pin_clear(LEDBUTTON_LED_PIN_NO);
    }
}

连接事件和断开事件调用函数on_connect和on_disconnect,和官方提供的on_connect和on_disconnect处理差不多。

typedef struct
{
  ble_evt_hdr_t header;                 /**< Event header. */
  union
  {
    ble_common_evt_t  common_evt; /**< Common Event, evt_id in BLE_EVT_* series. */
    ble_gap_evt_t     gap_evt;  /**< GAP originated event, evt_id in BLE_GAP_EVT_* series. */
    ble_l2cap_evt_t   l2cap_evt; /**< L2CAP originated event, evt_id in BLE_L2CAP_EVT* series. */
    ble_gattc_evt_t   gattc_evt; /**< GATT client originated event, evt_id in BLE_GATTC_EVT* series. */
    ble_gatts_evt_t   gatts_evt; /**< GATT server originated event, evt_id in BLE_GATTS_EVT* series. */
  } evt;
} ble_evt_t;


static void on_write(ble_lbs_t * p_lbs, ble_evt_t * p_ble_evt)
{
    ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;

    if ((p_evt_write->handle == p_lbs->led_char_handles.value_handle) &&
        (p_evt_write->len == 1) &&
        (p_lbs->led_write_handler != NULL))
    {
        p_lbs->led_write_handler(p_lbs, p_evt_write->data[0]);
    }
}

这里会从事件结构体ble_evt_t中获取(强制转换)GATTS的事件信息(ble_gatts_evt_write_t结构体),然后根据写入的信息完成回调函数的调用。至此为一个服务调用的流程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

蓝牙:GATT,属性,特性,服务 的相关文章

  • esp32 arduino psram使用

    esp32 arduino固件是已经支持psram了的 xff0c 是模式2 xff0c 所以要使用heap caps malloc来分配 注意选择wrover modelus xff0c 其他的可能驱动不支持 示例代码 xff1a inc
  • 事件驱动框架(二)——状态机

    事件驱动框架 xff08 二 xff09 说明 本篇接上一篇事件驱动框架之后 xff0c 介绍状态机的原理相关的 xff0c 以及事件驱动框架下事件处理状态机的实现 因为代码大多还是参照QP源码 xff0c 所以仅供学习使用 有限状态机介绍
  • 小米10如何安装google play商店

    查了一下网上说可以安装gmail 小米商店就会自动安装google play的 xff0c 但是发现gmail在小米商店已经提示说 因为软件本身问题不能给安装 34 xff0c 查了一无果 xff0c 于是用之前华为安装google的apk
  • php 上传目录权限问题导致无法上传

    php除了有大小严格限制导致失败 xff0c 还有就是上传目录权限问题导致失败 xff0c 如果权限问题执行以下命令即可 sudo chown R www data www data Users George Desktop uploads

随机推荐

  • KeilC STM32添加.c .h文件的方法

    嵌入式初学者添加 c h文件是可能会出现 h头文件无法生效的问题 xff0c 在此将本人经历总结如下 xff0c 供大家参考 1 xff0c 把所需添加的文件 xff0c 放到这个文件夹下 项目名称 Core Src 2 xff0c 右击此
  • 传感器——ATGM332D 北斗定位模块

    NO 8 模型用GPS测速仪 xff08 已完成 xff09 xff08 更新第二版本 xff09 这个是用显示屏显示的 定位精度2 5m GPS模块VCC Arduino的5v GPS模块GND Arduino的GND GPS模块TXD
  • stm32f10--- 学习日志2021-07-10

    不知道标题是啥 xff0c 学到什么记录什么 寄存器占四个字节 偏移地址 xff1a 0x04 基地址 xff1a 0x4001 1000叫做GPIOC的基地址 APB2外设时钟使能寄存器 0x4002 1018 单片机认为它只是一个数值
  • 【unp】unix网络编程卷1-->环境搭建(ubuntu14.04)

    学习unp网络编程 xff0c 树上的例子均存在 include 34 unp h 34 xff0c 故需要对环境进行配置 1 到资源页下载unpv13e 2 解压并将unpv13e 移动到相应的文件夹下 3 编译 gt cd unpv13
  • 北醒激光雷达模组 资料汇总

    目录 1 文档说明1 1 北醒单点系列雷达激光模组相关资料1 2 北醒面阵系列雷达激光模组相关资料1 2 1 产品基本介绍1 2 2 Benewake 北醒 短距 TF LC02 2m资料整理1 2 3 Benewake 北醒 短距 TF
  • TFmini Plus在开源飞控PX4上的应用

    TFmini Plus在开源飞控PX4上的应用 PX4有着自己独特的优势 xff0c 受到广大爱好者的喜爱 TFmini Plus是北醒公司推出的性价比极高的激光雷达 xff0c 受到广大爱好者的追捧 本文介绍TFmini Plus和PX4
  • Benewake TFmini-S\TFmimi Plus\TFluna\TF02-Pro 串口版本雷达在STM32的例程

    目录 文档说明北醒串口标准通讯协议硬件接线Lidar通讯代码1 初始化USART1 2 开启USART1的空闲中断 3 USART2 IRQHandler增加中断判断4 中断处理函数 xff0c 用于接收雷达数据 协议处理注 xff1a 换
  • 使用CH341 I2C连接北醒TF系列I2C模式 Python例程

    目录 硬件接线 xff1a 源码结果输出 本文介绍了北醒单点系列雷达IIC模式下使用CH341芯片转接板读取雷达数据的例程 例程下载 xff1a 链接 https pan baidu com s 1KVJ fINxUgKZny2Gdi8T2
  • 蓝牙nrf51822程序的分析(一)

    蓝牙nrf51822程序的分析 一 最近继续用NRF51822开发一个东西 无奈之前没接触过蓝牙 连蓝牙串口模块也没有 所以对蓝牙的基础知识不够 xff0c 后面看了之后接着补充 花了2天时间把提供的NRF51822的程序大致看明白了 xf
  • 常用Arduino板介绍

    目录 NANO板介绍烧录说明 UNO板介绍烧录说明 Pro mini板介绍烧录说明 DUE板介绍烧录说明 NANO板介绍 概述 xff1a Arduino Nano是一款基于ATMega328P xff08 Arduino Nano 3 x
  • Modbus设备在Modbus scan上面的使用方法

    操作教程 参数 xff1a DeviceID xff1a 485从站 寄存器地址 xff1a 查询设备地址表 北醒雷达Dist在0x0000开始 读取寄存器长度 xff1a 雷达数据长度值 格式 xff1a MODBUS RTU 串口协议
  • Raspberry Pi Pico C/C++语言在Windows环境下开发环境搭建 Raspberry Pi Pico C/C++ SDK

    目录 前言Raspberry Pi Pico介绍需要支持的软件软件安装配置及注意事项ARM GCC compiler的安装CMake的安装Git 安装Visual Studio 2019的安装Visual Studio Code的配置Pyt
  • 【LoRa32U4II】介绍以及基于Arduino IDE编译环境搭建及测试

    目录 LoRa 模块LoRa32u4 II介绍LoRa32u4 II 资料下载LoRa32u4 II 规格介绍LoRa32u4 II 脚位说明 编译环境介绍电脑系统编译软件Arduino需求库 编译环境搭建及测试LoRa32u4 II 测试
  • 【Benewake(北醒) 】短距 TF-LC02 2m资料整理

    目录 1 TF LC02简要说明1 1 性能参数1 2产品图片及尺寸 2 运用2 1 在开源板Arduino上的运用2 2 在Python上的应用 1 TF LC02简要说明 1 1 性能参数 1 2产品图片及尺寸 2 运用 2 1 在开源
  • 【Arduino】Benewake(北醒) TF-LC02(TTL)基于Arduino 开发板运用说明

    目录 前言Benewake 北醒 TF LC02产品简要说明Arduino开发板介绍Benewake 北醒 TF LC02 接口及通讯协议说明接口定义串口协议说明通讯协议说明功能码说明 接线示意图例程说明配置软硬串口定义获取TOF数据的结构
  • 【Benewake(北醒) 】中距 TF02-i 40m工业版本CAN/485介绍以及资料整理

    目录 1 前言2 产品介绍3 产品快速测试3 1 产品规格书及使用说明书3 2 通用指令串口助手使用说明3 3 产品快速测试说明 4 基于开源硬件的运用整理4 1 在开源飞控上的运用 5 基于其他的运用整理5 1 在PLC上的运用说明5 2
  • 【ESP32 DEVKIT_V1】基于Arduino IDE环境搭建

    目录 一 前言二 板子介绍三 环境搭建1 Arduino IDE的安装2 在Arduino IDE上添加外包链接3 添加好外包链接后就可以下载对应的板子库文件 测试1 先把开发板接到电脑 xff0c 并在Arduino IDE上选择对应的开
  • 【ESP32 DEVKIT_V1】北醒TF系列雷达在ESP32 DEVKIT_V1开发板上的运用

    目录 前言一 硬件准备二 硬件接线说明串口接线示意图 xff1a I2C接先示意图 三 软件搭建及测试1 使用Arduino IDE编译教程2 使用vsCode 43 Arduino教程2 1 在vsCode上使用Arduino的环境搭建2
  • 【vsCode + Arduino】在Visual Studio Code编译Arduino项目

    目录 前言一 参考文档二 操作步骤2 1 安装Arduino IDE2 2 在vsCode里安装Arduino插件2 3 配置arduino的安装路径2 4 配置好后打开一个Arduino的项目文件夹进行相应的配置 三 目前已知问题 前言
  • 蓝牙:GATT,属性,特性,服务

    接着上一篇 通用属性配置文件 xff08 Generic Attribute Profile xff09 1 GATT简介 通用属性配置文件Generic Attribute Profile简称GATT GATT定义了属性类型并规定了如何使