[feat] update peripheral api and demo

This commit is contained in:
jzlv 2021-06-04 17:40:12 +08:00
parent 658b0761db
commit a11dcbed30
341 changed files with 26075 additions and 2575 deletions

View file

@ -0,0 +1,201 @@
BLE 客户端和服务端互连
=======================
本 demo 基于 **bl702** 演示 **ble server****ble client** 连接和数据收发。
准备工具
-----------------------
- 两块 bl702 开发板 or 一块 bl702 开发板 + 手机 app
软件实现
-----------------------
BLE client 软件实现
^^^^^^^^^^^^^^^^^^^^^^^^
- 软件代码见 ``examples/ble/ble_central``
.. code-block:: C
:linenos:
static struct bt_conn_cb ble_tp_conn_callbacks = {
.connected = ble_tp_connected,
.disconnected = ble_tp_disconnected,
}
void ble_tp_init()
{
if( !isRegister )
{
isRegister = 1;
bt_conn_cb_register(&ble_tp_conn_callbacks);
}
}
- 在 ``bt_conn_cb_register`` 函数中,注册连接成功和断开连接的 ``callback`` 函数
- 在 ``ble_start_scan`` 函数中,设备就开始进行扫描
- 在 ``device_found`` 函数中,设备上传扫描到的蓝牙设备,代码通过 ``adv_name`` 来找到需要连接的蓝牙设备,发起连接
.. code-block:: C
:linenos:
static void ble_write_data_task(void *pvParameters)
{
int error;
uint8_t buf[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
while(1)
{
k_sem_take(&write_data_poll_sem, K_FOREVER);
BT_WARN("ble_write_data\r\n");
// Send data to server
error = bt_gatt_write_without_response(ble_tp_conn,char_hdl.tp_wr_hdl,buf,20,0);
BT_WARN("Write Complete (err %d)\r\n", error);
}
}
- 连接成功后,在 ``ble_write_data_task`` 函数, client 发送 ``buf`` 里面的数据到 server
.. code-block:: C
:linenos:
static u8_t notify_func(struct bt_conn *conn,struct bt_gatt_subscribe_params *params,const void *data, u16_t length);
- 连接成功后,在 ``notify_func`` 函数, client 接收来自 server 的数据, ``data`` 是数据内容, ``length`` 是数据长度
BLE server 软件实现
^^^^^^^^^^^^^^^^^^^^^^^^
- 软件代码见 ``examples/ble/ble_peripheral``
.. code-block:: C
:linenos:
int ble_start_adv(void)
{
struct bt_le_adv_param adv_param = {
//options:3, connectable undirected, adv one time
.options = 3, \
.interval_min = BT_GAP_ADV_FAST_INT_MIN_3, \
.interval_max = BT_GAP_ADV_FAST_INT_MAX_3, \
};
char *adv_name = "BL_TEST_01"; // This name must be the same as adv_name in ble_central
uint8_t data[1] = {(BT_LE_AD_LIMITED | BT_LE_AD_NO_BREDR)};
uint8_t data_uuid[2] = {0x12, 0x18};//0x1812
uint8_t data_appearance[2] = {0x80, 0x01};//0x0180
uint8_t data_manu[4] = {0x71, 0x01, 0x04, 0x13};
struct bt_data adv_data[] = {
BT_DATA(BT_DATA_FLAGS, data, 1),
BT_DATA(BT_DATA_UUID16_ALL, data_uuid, sizeof(data_uuid)),
BT_DATA(BT_DATA_GAP_APPEARANCE, data_appearance, sizeof(data_appearance)),
BT_DATA(BT_DATA_NAME_COMPLETE, adv_name, strlen(adv_name)),
BT_DATA(BT_DATA_MANUFACTURER_DATA, data_manu, sizeof(data_manu))
};
return bt_le_adv_start(&adv_param, adv_data, ARRAY_SIZE(adv_data), NULL, 0);
}
- 在 ``ble_start_adv`` 函数中, ``adv_name`` 设置这次广播的设备名称,设备就开始进行广播
.. code-block:: C
:linenos:
static int ble_tp_recv_wr(struct bt_conn *conn, const struct bt_gatt_attr *attr,const void *buf, u16_t len, u16_t offset, u8_t flags);
- 连接成功后, 在 ``ble_tp_recv_wr``server接收来自client的数据 ``buf`` 是数据内容, ``len`` 是数据长度
.. code-block:: C
:linenos:
static void ble_tp_notify_task(void *pvParameters)
{
int err = -1;
char data[244] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
k_sem_give(&notify_poll_sem);
while(1)
{
k_sem_take(&notify_poll_sem, K_FOREVER);
//send data to client
err = bt_gatt_notify(ble_tp_conn, get_attr(BT_CHAR_BLE_TP_NOT_ATTR_VAL_INDEX), data, (tx_mtu_size - 3));
BT_WARN("ble tp send notify : %d\n", err);
}
}
- 连接成功后,在 ``ble_tp_notify_task`` 函数, server 发送 ``data`` 里面的数据到 client.
编译和烧录
-----------------------------
- **CDK工具编译**
暂不支持
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=ble_peripheral SUPPORT_FREERTOS=y SUPPORT_FLOAT=y SUPPORT_BLE=y
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=ble_central SUPPORT_FREERTOS=y SUPPORT_FLOAT=y SUPPORT_BLE=y
- **烧录**
``使用bouffalo_dev_cube烧录代码``
实验现象
-----------------------------
- **两个 bl702 对连**
.. figure:: img/ble_client.png
:alt:
.. figure:: img/ble_server.png
:alt:
- **手机连接 bl702**
.. figure:: img/phone_connect.jpg
:alt:
- 连接成功,如下图所示
.. figure:: img/phone_connected.png
:alt:
- 收发数据步骤
- 点击 ``1`` 处 图标 ``Unknow Service`` 显示具体的 service 属性
- 点击 ``2`` 处 图标 开启 ``Notification`` ,允许 server 发送数据给 client
- 点击 ``3`` 处 图标 client 发送数据给 server填写自己想要发送的数据点击 ``SEND`` 按钮
.. figure:: img/ble_data.png
:alt:
.. figure:: img/receive_data.png
:alt:
.. figure:: img/write_data.jpg
:alt:

View file

@ -0,0 +1,28 @@
BOOT2 IAP
============================
IAP 是 In Application Programming 的首字母缩写IAP 是用户自己的程序在运行过程中对 User Flash的部分区域进行烧写
目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。
通常在用户需要实现 IAP 功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,
第一个项目程序不执行正常的功能操作,而只是通过某种通信管道(如 USB、USART )接收程序或数据,
执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。
Bouffalo Lab 为 IAP 功能应用提供了相应的 boot2_iap.bin 文件,并将其与 Dev Cube 软件包同步发布。
用户可以配合 Dev Cube 图形界面烧写软件,将已有的 boot2_iap.bin 文件烧录进目标板,烧录
一次之后,就可以通过 IAP 功能,在线更新用户代码。
bl_mcu_sdk 开源了 boot2_iap 的软件源码,用户可以到 examples/boot2_iap 查阅代码,并完成编译烧写。编译烧写过程可以参考《快速开发指南》介绍。
准备工具
-----------------------
- 最新版本的 Dev Cube
- Bl706 开发板
- TTL-USB 电平转换芯片
实验现象
-----------------------------
使用 Dev Cube 完成 IAP 功能的具体步骤,请参阅 `DevCube用户手册 <https://dev.bouffalolab.com/media/upload/doc/DevCube%E7%94%A8%E6%88%B7%E6%89%8B%E5%86%8Cv1.2.pdf>`_ <IAP程序下载>章节。

View file

@ -0,0 +1,2 @@
FATFS 文件系统读写
====================

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View file

@ -0,0 +1,95 @@
LowPower 低功耗评估
=========================
简介
------------------------
博流系列芯片拥有丰富的低功耗特性,以适配不同的低功耗应用场合。为了方便用户快速的评测使用 bl 系列 MCU 低功耗性能 bl_mcu_sdk 提供了一套抽象的低功耗接口,将低功耗等级分为四个等级,分别为
1. Running : Running 为代码正常运行时的功耗,由客户应用代码决定功耗。
2. WFI WFI 模式,只关闭了 CPU 以节省功耗,当用户退出 WFI 模式的时候程序将会继续运行。
3. PDS : PDS 模式,关闭了芯片上大多数电源域,同时关闭了 CPU ,可以通过内部 RTC 进行唤醒,或者使用特定的唤醒引脚唤醒。
4. HBN : HBN 模式,关闭了芯片上绝大多数电源域,关闭了 CPU ,可以通过内部 RTC 进行唤醒,或者使用特定的唤醒引脚唤醒。
如下表所示
+------------+------------+------------+---------------------+
|模式 |参考电流 |对应基础模式|唤醒源 |
+============+============+============+=====================+
|running |6.28 mA |run | |
+------------+------------+------------+---------------------+
|WFI |5.14 mA |WFI |任意中断 |
+------------+------------+------------+---------------------+
|PDS |10 uA |PDS 31 |内部RTC/引脚中断 |
+------------+------------+------------+---------------------+
|HBN |1 uA |HBN 1 |内部RTC/引脚中断 |
+------------+------------+------------+---------------------+
bl_mcu_sdk 提供了一个简单的低功耗参考示例 (bl_mcu_sdk Examples/power/powerTest/) ,旨在帮助用户快速评估低功耗功能,如果需要进一步适配自身的低功耗场景,采取不同的低功耗策略,请查阅相关 datasheet 或者寻找 Boufflao Lab 的技术支持。
上表中的参考电流是通过示例固件测试得出的。符合 bl70x 系列 MCU 的 spec 的描述, run wfi pds hbn 四种等级的定义简化了原先的 hbn level以及 pds level的设定。
见 bl702_bl704_bl706_DS_EN_Combo_1.9.pdf page 28
.. figure:: img/powerTable.png
**低功耗示例测试方法**
------------------------
**编译低功耗示例代码**
^^^^^^^^^^^^^^^^^^^^^^^^
在工程目录下键入 ``make APP=lowpower_test SUPPORT_SHELL=y BOARD=bl706_lp`` 完成低功耗示例 bl706 的编译。或者直接使用CDK工程完成编译下载
您可以参考本文档《快速开发指南》来获取更多编译烧写的信息。
当编译并烧写成功后连接串口到电脑端并复位芯片Xshell 会出现如下图所示的页面。
.. figure:: img/xShell页面.png
**准备低功耗测试所需的硬件环境**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- 可以串联电流表到电源端的电路板
- 电流表
- 一台 PC 主机(运行 Windows 或者 Linux 系统)
- TTL转USB
如下图所示,将电流表串联进入 bl706 模组的供电线路通过PC端的串口调试助手软件下发不同的低功耗指令使得 bl706 进入对应的低功耗模式
观察电流表示值,完成评估。
.. figure:: img/低功耗示意图.png
**使用Xshell开始评估低功耗性能**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
用户可以通过在 Xshell输入下述指令进入对应的低功耗模式。
``run``
- 复位芯片之后默认进入run模式没有进入任何低功耗模式芯片实际在运行 while(1); 语句。
``wfi``
- 进入wfi模式后面不加任何参数进入之后关闭CPU降低功耗
- 进入wfi模式后任何中断会唤醒例如uart中断。在Xshell中敲击回车会触发 bl706 UART RX中断因此可以通过此方法唤醒wfi低功耗模式。
``pds sleepTim``
- pds 可以选择带一个 sleepTim 的参数,决定其内部 RTC 唤醒时间。如果指令不带此参数,那么默认不使用 RTC 内部唤醒,目前的固件仅支持上电复位唤醒。
- 如果指令包含 sleepTim 参数pds 将会在sleepTim * clock_period 的时刻被唤醒,表现为复位芯片,重新打印起始报文。
- 进入低功耗模式后RTC的时钟是32K ,因此 sleepTim 为32768时表现为睡眠 1S 后唤醒。
``hbn sleepTim``
- hbn 可以选择带一个 sleepTim 的参数决定其内部RTC唤醒时间。如果指令不带此参数那么默认不使用 RTC 内部唤醒,目前的固件仅支持上电复位唤醒。
- 如果指令包含 sleepTim 参数hbn 将会在 sleepTim * clock_period 的时刻被唤醒,表现为复位芯片,重新打印起始报文。
- 进入低功耗模式后RTC的时钟是32K ,因此 sleepTim 为32768时表现为睡眠1S 后唤醒。

View file

@ -0,0 +1,32 @@
SHELL 命令行调试
====================
为方便用户使用 pc 或者其他控制器对开发板进行功能的调试(非仿真器调试),这里提供了 shell 命令行组件,类似于在 linux 下进行命令行操作。用户在 PC 端或者其他控制端进行命令的发送通过串口、usb、以太网、蓝牙、wifi等方式将数据发送给开发板的 shell 中shell 会读取接收的命令进行解析并对已经注册的内部函数扫描,扫描到与之匹配的函数以后,执行匹配的函数,并实时返回传入的键值和函数执行的结果给 pc or 控制端。其中需要注意,控制器端需要发送标准键盘的键值。
本 demo 将演示如何使用 **shell** 通过串口进行命令行调试。
准备工具
-----------------------
- pc控制端使用串口终端软件xshell或者mobaxterm
- 连接介质usb转串口 or 网络 or usb
软件实现
-------------------------
串口中使用 SHELL
^^^^^^^^^^^^^^^^^^^^
BLE 中使用 SHELL
^^^^^^^^^^^^^^^^^^^^
以太网中使用 SHELL
^^^^^^^^^^^^^^^^^^^^
SHELL 命令注册
^^^^^^^^^^^^^^^^^^^^
编译和烧录
-----------------------------
实验现象
-----------------------------

View file

@ -0,0 +1,143 @@
ADC - 按键检测电压
====================
本demo基于ADC使用按键的方式检测外部输入引脚的电压值。
硬件连接
-----------------------------
本demo基于BL706_AVB开发板:
::
GPIO function GPIO pin
----------------------------------
ADC CH8 <--> GPIO18
软件实现
-----------------------------
- 软件代码见 ``examples/adc/adc_key``
- ``ADC`` 设备的时钟源由板级描述文件 ``bsp/board/bl706_iot/clock_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_ADC_CLOCK_SOURCE ROOT_CLOCK_SOURCE_XCLK
#define BSP_ADC_CLOCK_DIV 0
- ``ADC`` 设备的复用引脚由板级描述文件 ``bsp/board/bl706_iot/pinmux_config.h`` 来配置
.. code-block:: C
:linenos:
#define CONFIG_GPIO18_FUNC GPIO_FUN_ADC
- ``ADC`` 设备配置由板级描述文件 ``bsp/board/bl706_iot/peripheral_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_USING_ADC0
#if defined(BSP_USING_ADC0)
#ifndef ADC0_CONFIG
#define ADC0_CONFIG \
{ \
.clk_div = ADC_CLOCK_DIV_32,\
.vref = ADC_VREF_3P2V,\
.continuous_conv_mode = DISABLE,\
.differential_mode = DISABLE,\
.data_width = ADC_DATA_WIDTH_16B_WITH_256_AVERAGE,\
.fifo_threshold = ADC_FIFO_THRESHOLD_1BYTE,\
.gain = ADC_GAIN_1\
}
#endif
#endif
.. code-block:: C
:linenos:
adc_channel_cfg_t adc_channel_cfg;
adc_channel_cfg.pos_channel = posChList;
adc_channel_cfg.neg_channel = negChList;
adc_register(ADC0_INDEX, "adc_key", DEVICE_OFLAG_STREAM_RX);
adc_key = device_find("adc_key");
if(adc_key)
{
ADC_DEV(adc_key)->continuous_conv_mode = ENABLE;
device_open(adc_key, DEVICE_OFLAG_STREAM_RX);
device_control(adc_key,DEVICE_CTRL_ADC_CHANNEL_CONFIG,&adc_channel_cfg);
}else{
MSG("device open failed\r\n");
}
adc_channel_start(adc_key);
- 首先调用 ``adc_register`` 函数注册 ``adc_key`` 设备当前注册为ADC0
- 然后通过 ``find`` 函数找到设备对应的句柄,保存于 ``adc_key`` 句柄中
- 然后使用 ``device_open`` 以轮询模式来打开 ``adc_key`` 设备,调用 ``device_control`` 完成ADC相关的配置
- 最后调用 ``adc_channel_start`` 启用ADC的转换
.. code-block:: C
:linenos:
device_read(adc_key,0,(void *)&result_val,1);
keyValue = get_adc_key_value(result_val.volt * 1000);
if( keyValue!=KEY_NO_VALUE){
MSG("key %d pressed\r\n",keyValue);
MSG("result_val.volt: %0.2f mv\n", (result_val.volt * 1000));
}
- 调用 ``device_read`` 读取 ``adc_key`` 设备信息保存到 ``result_val`` 结构体中
- 调用 ``get_adc_key_value`` 函数获取当前的键值和电压值
编译和烧录
-----------------------------
- **CDK工具编译**
打开项目中提供的工程文件adc_key.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_avb APP=adc_key
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------
本实验依次按下开发板上的SW1 ~ SW5会得到不同的电压值:
- key 0: 0V左右
- key 1: 0.1V左右
- key 2: 0.2V左右
- key 3: 0.3V左右
- key 4: 0.43V左右
实际运行结果如下图所示:
.. figure:: img/adc_key_result.png
见视频展示:
.. raw:: html
<iframe src="//player.bilibili.com/player.html?aid=887712205&bvid=BV1xK4y1P7ur&cid=330261457&page=5" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

View file

@ -0,0 +1,75 @@
GPIO 输出 - 流水灯
====================
本demo基于GPIO外设的输出模式编写。
硬件连接
-----------------------------
本 demo 基于BL706_IOT开发板连接方式如下
::
GPIO function GPIO pin
----------------------------------
D0 <--> GPIO22
D1 <--> GPIO29
D2 <--> GPIO30
D3 <--> GPIO31
.. figure:: img/blink_breath_sch.png
:alt:
软件实现
-----------------------------
- 软件代码见 ``examples/gpio/gpio_blink``
.. code-block:: C
:linenos:
gpio_set_mode(GPIO_PIN_22, GPIO_OUTPUT_PP_MODE);
gpio_set_mode(GPIO_PIN_29, GPIO_OUTPUT_PP_MODE);
gpio_set_mode(GPIO_PIN_30, GPIO_OUTPUT_PP_MODE);
gpio_set_mode(GPIO_PIN_31, GPIO_OUTPUT_PP_MODE);
- 使用上述代码将 ``GPIO22`` ``GPIO29`` ``GPIO30`` ``GPIO31`` 配置为输出上拉模式。
.. code-block:: C
:linenos:
gpio_write(GPIO_PIN_22, 0);
- 使用上述代码修改输出的电平值。
编译和烧录
-----------------------------
- **CDK 编译**
打开项目中提供的工程文件gpio_blink.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=gpio_blink
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------
见视频展示:
.. raw:: html
<iframe src="//player.bilibili.com/player.html?aid=887712205&bvid=BV1xK4y1P7ur&cid=326226616&page=3" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

View file

@ -0,0 +1,110 @@
PWM - 呼吸灯
====================
本demo基于PWM外设轮询模式编写。
硬件连接
-----------------------------
本 demo 基于BL706_IOT开发板连接方式如下
::
GPIO function GPIO pin
----------------------------------
PWM_CH2 <--> GPIO22
.. figure:: img/blink_breath_sch.png
:alt:
软件实现
-----------------------------
- 软件代码见 ``examples/pwm/pwm_breath_led``
- ``PWM`` 复用引脚由板级描述文件 ``bsp/board/bl706_iot/pinmux_config.h`` 来配置
.. code-block:: C
:linenos:
#define CONFIG_GPIO22_FUNC GPIO_FUN_PWM
- ``PWM`` 设备配置由板级描述文件 ``bsp/board/bl706_iot/peripheral_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_USING_PWM_CH2
#if defined(BSP_USING_PWM_CH2)
#ifndef PWM_CH2_CONFIG
#define PWM_CH2_CONFIG \
{ \
.ch = 2, \
.frequency = 1000000, \
.dutycycle = 0, \
.it_pulse_count = 0,\
}
#endif
#endif
.. code-block:: C
:linenos:
pwm_register(PWM_CH2_INDEX, "led_breath", DEVICE_OFLAG_RDWR);
struct device *led_breath = device_find("led_breath");
if (led_breath)
{
device_open(led_breath, DEVICE_OFLAG_STREAM_TX);
pwm_channel_start(led_breath);
}
- 首先调用 ``pwm_register`` 函数注册 ``PWM`` 设备的一个通道,当前注册 ``PWM_CH2``
- 然后通过 ``find`` 函数找到设备对应的句柄,保存于 ``led_breath`` 句柄中
- 使用 ``device_open`` 以轮询模式来打开 ``led_breath`` 设备
.. code-block:: C
:linenos:
pwm_config_t pwm_cfg = {
1000000,
0,
};
device_control(led_breath, DEVICE_CTRL_CONFIG, &pwm_cfg);
- 使用 ``device_contorl`` 函数,配合 ``DEVICE_CTRL_CONFIG`` 指令可以修改当前PWM通道的频率和占空比。
编译和烧录
-----------------------------
- **CDK 编译**
打开项目中提供的工程文件pwm_breath_led.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=pwm_breath_led
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------
见视频展示:
.. raw:: html
<iframe src="//player.bilibili.com/player.html?aid=887712205&bvid=BV1xK4y1P7ur&cid=326227924&page=4" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

View file

@ -0,0 +1,64 @@
GPIO 中断 - 按键检测
====================
本demo基于GPIO外设外部中断模式编写。
硬件连接
-----------------------------
本 demo 基于BL706_IOT开发板自行添加按键电路连接方式如下
::
GPIO function GPIO pin
----------------------------------
SW1 <--> GPIO11
.. figure:: img/button_sch.png
:alt:
软件实现
-----------------------------
- 软件代码见 ``examples/gpio/gpio_int``
.. code-block:: C
:linenos:
static void gpio11_int_callback(uint32_t pin)
{
MSG("gpio rising trigger !\r\n");
}
gpio_set_mode(GPIO_PIN_11,GPIO_SYNC_RISING_TRIGER_INT_MODE);
gpio_attach_irq(GPIO_PIN_11,gpio11_int_callback);
gpio_irq_enable(GPIO_PIN_11,ENABLE);
- 使用上述代码将 ``GPIO11`` 配置为GPIO上升沿中断触发模式并注册中断回调函数。
编译和烧录
-----------------------------
- **CDK 编译**
打开项目中提供的工程文件gpio_int.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=gpio_int
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------
当按键按下时,串口会打印 ``"gpio rising trigger !"``

View file

@ -0,0 +1,113 @@
DMA - RAM间数据搬运
====================
本demo基于DMA方向为memory to memory 模式,进行数据的搬运。
硬件连接
-----------------------------
软件实现
-----------------------------
- 软件代码见 ``examples/dma/dma_m2m``
- ``DMA`` 设备配置由板级描述文件 ``bsp/board/bl706_iot/peripheral_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_USING_DMA0_CH0
#if defined(BSP_USING_DMA0_CH0)
#ifndef DMA0_CH0_CONFIG
#define DMA0_CH0_CONFIG \
{ \
.id = 0, \
.ch = 0,\
.direction = DMA_MEMORY_TO_MEMORY,\
.transfer_mode = DMA_LLI_ONCE_MODE, \
.src_req = DMA_REQUEST_NONE, \
.dst_req = DMA_REQUEST_NONE, \
.src_width = DMA_TRANSFER_WIDTH_32BIT , \
.dst_width = DMA_TRANSFER_WIDTH_32BIT , \
}
#endif
#endif
.. code-block:: C
:linenos:
dma_register(DMA0_CH0_INDEX, "DMA", DEVICE_OFLAG_RDWR);
struct device *dma = device_find("DMA");
if (dma)
{
device_open(dma, 0);
device_set_callback(dma, dma_transfer_done);
device_control(dma, DEVICE_CTRL_SET_INT, NULL);
}
- 首先调用 ``dma_register`` 函数注册 ``DMA`` 设备的一个通道,当前注册 ``DMA_CH0``
- 然后通过 ``find`` 函数找到设备对应的句柄,保存于 ``dma`` 句柄中
- 最后使用 ``device_open`` 以默认模式来打开 ``dma`` 设备,调用 ``device_set_callback`` 注册一个dma通道0中断回调函数调用 ``device_control`` 开启dma传输完成中断
.. code-block:: C
:linenos:
dma_reload(dma,(uint32_t)dma_src_buffer,(uint32_t)dma_dst_buffer,8000);
dma_channel_start(dma);
- 调用 ``dma_reload`` 函数对dma 通道0的配置进行补充``DMA0_CH0_CONFIG`` 中已经补充了一部分配置,这边主要补充源数据地址和目标数据地址以及传输总长度
- 调用 ``dma_channel_start`` 开启dma传输
.. code-block:: C
:linenos:
void dma_transfer_done(struct device *dev, void *args, uint32_t size, uint32_t state)
{
uint32_t index=0;
if(!state)
{
MSG("dma transfer task done\r\n");
for(index=0;index<8000;index++){
if(dma_dst_buffer[index]!=0xff){
MSG("dma transfer error\r\n");
}
}
MSG("dma transfer success\r\n");
}
}
- 在中断函数中判断数据传输是否正确
编译和烧录
-----------------------------
- **CDK 编译**
打开项目中提供的工程文件dma_m2m.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=dma_m2m
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------
``dma_src_buffer`` 数组中的数据通过DMA 通道0 以源32位宽、目标32位宽传输到 ``dma_dst_buffer`` 数组中,数据传输完成并完整,串口打印 ``dma transfer success``

View file

@ -0,0 +1,117 @@
I2C - AT24CXX 读写
====================
硬件连接
-----------------------------
本 demo 基于BL706_IOT开发板自行添加 AT24CXX 电路,连接方式如下
::
GPIO function GPIO pin
----------------------------------
I2C_SCL <--> GPIO11
I2C_SDA <--> GPIO16
软件实现
-----------------------------
- 软件代码见 ``examples/i2c/i2c_at24cxx``
- ``I2C`` 设备的时钟源由板级描述文件 ``bsp/board/bl706_iot/clock_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_I2C_CLOCK_SOURCE ROOT_CLOCK_SOURCE_BCLK
#define BSP_I2C_CLOCK_DIV 0
- ``I2C`` 设备的复用引脚由板级描述文件 ``bsp/board/bl706_iot/pinmux_config.h`` 来配置
.. code-block:: C
:linenos:
#define CONFIG_GPIO11_FUNC GPIO_FUN_I2C
#define CONFIG_GPIO16_FUNC GPIO_FUN_I2C
- ``I2C`` 设备配置由板级描述文件 ``bsp/board/bl706_iot/peripheral_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_USING_I2C0
#if defined(BSP_USING_I2C0)
#ifndef I2C0_CONFIG
#define I2C0_CONFIG \
{ \
.id = 0, \
.mode = I2C_HW_MODE,\
.phase = 15, \
}
#endif
#endif
.. code-block:: C
:linenos:
i2c_register(I2C0_INDEX, "i2c", DEVICE_OFLAG_RDWR);
struct device *i2c0 = device_find("i2c");
if (i2c0)
{
MSG("device find success\r\n");
device_open(i2c0, 0);
}
- 首先调用 ``i2c_register`` 函数注册 ``I2C`` 设备,当前注册 ``I2C0``
- 然后通过 ``find`` 函数找到设备对应的句柄,保存于 ``i2c0`` 句柄中
- 最后使用 ``device_open`` 以默认模式来打开 ``I2C0`` 设备
.. code-block:: C
:linenos:
i2c_msg_t msg[2];
uint8_t buf[8] = {0};
msg[0].buf = buf;
msg[0].flags = SUB_ADDR_1BYTE | I2C_WR;
msg[0].len = 8;
msg[0].slaveaddr = 0x50;
msg[0].subaddr = 0x00;
msg[1].buf = buf;
msg[1].flags = SUB_ADDR_1BYTE | I2C_RD;
msg[1].len = 8;
msg[1].slaveaddr = 0x50;
msg[1].subaddr = 0x00;
if (i2c_transfer(i2c0, &msg[0], 2) == 0)
MSG("\r\n read:%0x\r\n", msg[1].buf[0] << 8 | msg[1].buf[1]);
- 调用 ``i2c_transfer`` 传输两个 ``msg``,一个 ``msg`` 代表向 eeprom 写入8字节数据一个 ``msg`` 代表从 eeprom 读取8字节数据
编译和烧录
-----------------------------
- **CDK 编译**
打开项目中提供的工程文件i2c_at24cxx.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=i2c_at24cxx
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -0,0 +1,55 @@
MTIMER - 内核定时器
====================
本demo基于 risc-v 内核自带的一个64位定时器MTIMER编写。MTIMER最大可以定时500年本demo可以为后面os tick提供参考。
硬件连接
-----------------------------
软件实现
-----------------------------
- 软件代码见 ``examples/systick``
- ``mtimer`` 时钟默认经过分频以后为 1M方便后面使用减少计算时间。
.. code-block:: C
:linenos:
void systick_isr()
{
static uint32_t tick=0;
tick++;
MSG("tick:%d\r\n",tick);
}
bflb_platform_set_alarm_time(1000000,systick_isr);
- 使用上述代码设置mtimer定时时间为1s并且注册中断回调函数。
编译和烧录
-----------------------------
- **CDK 编译**
打开项目中提供的工程文件systick.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=systick
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------
``tick`` 值每秒自增1并通过串口打印。

View file

@ -0,0 +1,145 @@
SPI - TFT LCD 显示
====================
硬件连接
-----------------------------
本 demo 基于BL706_AVB开发板**其中 MISO 和MOSI 默认进行了调换**,连接方式如下
::
GPIO function GPIO pin
----------------------------------
LCD_CS <--> GPIO10
LCD_DC <--> GPIO22
SPI_SCK <--> GPIO19
SPI_MISO <--> GPIO20
SPI_MOSI <--> GPIO21
软件实现
-----------------------------
- 软件代码见 ``examples/spi/spi_lcd``
- ``SPI`` 设备的时钟源由板级描述文件 ``bsp/board/bl706_avb/clock_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_SPI_CLOCK_SOURCE ROOT_CLOCK_SOURCE_BCLK
#define BSP_SPI_CLOCK_DIV 0
- ``SPI`` 设备的复用引脚由板级描述文件 ``bsp/board/bl706_avb/pinmux_config.h`` 来配置
.. code-block:: C
:linenos:
#define CONFIG_GPIO19_FUNC GPIO_FUN_SPI
#define CONFIG_GPIO20_FUNC GPIO_FUN_SPI
#define CONFIG_GPIO21_FUNC GPIO_FUN_SPI
- ``SPI`` 设备配置由板级描述文件 ``bsp/board/bl706_avb/peripheral_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_USING_SPI0
#if defined(BSP_USING_SPI0)
#ifndef SPI0_CONFIG
#define SPI0_CONFIG \
{ \
.id = 0, \
.clk = 36000000,\
.mode = SPI_MASTER_MODE, \
.direction = SPI_MSB_BYTE0_DIRECTION_FIRST, \
.clk_polaraity = SPI_POLARITY_LOW, \
.clk_phase = SPI_PHASE_1EDGE, \
.datasize = SPI_DATASIZE_8BIT, \
.fifo_threshold = 4, \
}
#endif
#endif
.. code-block:: C
:linenos:
gpio_set_mode(LCD_CS_PIN,GPIO_OUTPUT_MODE);
gpio_set_mode(LCD_DC_PIN,GPIO_OUTPUT_MODE);
gpio_write(LCD_CS_PIN,1); //CS1
gpio_write(LCD_DC_PIN,1); //DC
spi0 = device_find("spi0");
if(spi0)
{
device_close(spi0);
}
else{
spi_register(SPI0_INDEX,"spi0",DEVICE_OFLAG_RDWR);
spi0 = device_find("spi0");
}
if(spi0)
{
device_open(spi0,DEVICE_OFLAG_STREAM_TX|DEVICE_OFLAG_STREAM_RX);
}
- 配置 ``LCD_CS````LCD_DC`` 引脚为输出模式并拉高
- 调用 ``spi_register`` 函数注册 ``SPI`` 设备,当前注册 ``SPI0``
- 然后通过 ``find`` 函数找到设备对应的句柄,保存于 ``spi0`` 句柄中
- 最后使用 ``device_open`` 以轮询发送模式来打开 ``spi0`` 设备
.. code-block:: C
:linenos:
void LCD_WR_Byte(uint8_t data)
{
CS1_LOW;
DC_HIGH;
spi_transmit(spi0,&data,1,SPI_TRANSFER_TYPE_8BIT);
CS1_HIGH;
}
void LCD_WR_HalfWord(uint16_t data)
{
CS1_LOW;
DC_HIGH;
spi_transmit(spi0,&data,1,SPI_TRANSFER_TYPE_16BIT);
CS1_HIGH;
}
void LCD_WR_Word(uint32_t data)
{
CS1_LOW;
DC_HIGH;
spi_transmit(spi0,&data,1,SPI_TRANSFER_TYPE_32BIT);
CS1_HIGH;
}
- 为 LCD 显示驱动提供接口
编译和烧录
-----------------------------
- **CDK 编译**
打开项目中提供的工程文件spi_lcd.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_avb APP=spi_lcd
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------

View file

@ -0,0 +1,151 @@
UART - 数据自收发
====================
本demo基于 UART 外设轮询发送、接收FIFO中断模式编写。
硬件连接
-----------------------------
本 demo 基于BL706_IOT开发板连接方式如下
::
GPIO function GPIO pin
----------------------------------
UART0_TX <--> GPIO14
UART0_RX <--> GPIO15
软件实现
-----------------------------
- 软件代码见 ``examples/uart/uart_echo``
- ``UART`` 设备的时钟源由板级描述文件 ``bsp/board/bl706_iot/clock_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_UART_CLOCK_SOURCE ROOT_CLOCK_SOURCE_PLL_96M
#define BSP_UART_CLOCK_DIV 0
- ``UART`` 设备的复用引脚由板级描述文件 ``bsp/board/bl706_iot/pinmux_config.h`` 来配置
.. code-block:: C
:linenos:
#define CONFIG_GPIO14_FUNC GPIO_FUN_UART0_TX
#define CONFIG_GPIO15_FUNC GPIO_FUN_UART0_RX
- ``UART`` 设备配置由板级描述文件 ``bsp/board/bl706_iot/peripheral_config.h`` 来配置
.. code-block:: C
:linenos:
#define BSP_USING_UART0
#if defined(BSP_USING_UART0)
#ifndef UART0_CONFIG
#define UART0_CONFIG \
{ \
.id = 0, \
.baudrate = 2000000,\
.databits = UART_DATA_LEN_8, \
.stopbits = UART_STOP_ONE, \
.parity = UART_PAR_NONE, \
.fifo_threshold = 1, \
}
#endif
#endif
.. code-block:: C
:linenos:
bflb_platform_init();
- 在 ``bflb_platform_init`` 函数中,我们已经注册并且打开了一个调试用的串口设备,给用户实现一个 ``MSG`` 的基本功能用作打印输出报文。具体实现如下
.. code-block:: C
:linenos:
uart_register(board_get_debug_uart_index(), "debug_log", DEVICE_OFLAG_RDWR);
struct device *uart = device_find("debug_log");
if (uart)
{
device_open(uart, DEVICE_OFLAG_STREAM_TX | DEVICE_OFLAG_INT_RX);
device_set_callback(uart, uart_iqr_callback);
device_control(uart, DEVICE_CTRL_SET_INT, (void *)(UART_RX_FIFO_IT));
}
- 首先调用 ``uart_register`` 函数注册 ``UART`` 设备,当前注册 ``UART0``
- 然后通过 ``find`` 函数找到设备对应的句柄,保存于 ``uart`` 句柄中
- 最后使用 ``device_open`` 以轮询发送和中断接收来打开 ``uart`` 设备,调用 ``device_set_callback`` 注册一个 ``UART0`` 中断回调函数,调用 ``device_control`` 开启 ``UART RX FIFO`` 中断
.. code-block:: C
:linenos:
if (uart)
{
device_set_callback(uart, uart_irq_callback);
device_control(uart, DEVICE_CTRL_SET_INT, (void *)(UART_RX_FIFO_IT|UART_RTO_IT));
}
- 通过 ``device_set_callback`` 函数,注册用户指定的中断服务函数。通过 ``device_control`` 函数打开 ``RX FIFO````RTO`` 中断
.. code-block:: C
:linenos:
void uart_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t state)
{
if (state == UART_EVENT_RX_FIFO)
{
device_write(dev,0,(uint8_t *)args,size);
}
else if (state == UART_EVENT_RTO)
{
device_write(dev,0,(uint8_t *)args,size);
}
}
- 此函数是示例的中断服务函数,作用是将接受到的数据原封不动的发送出去。
- ``state`` 会返回 ``UART`` 设备的中断类型
- ``args`` 包含了返回数据指针
- ``size`` 包含返回数据的长度
- ``dev`` 为中断的 ``uart`` 设备句柄
- 当中断产生,将会调用 ``device_write`` 函数将接受到的数据发送回去。
编译和烧录
-----------------------------
- **CDK 编译**
打开项目中提供的工程文件uart_echo.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=uart_echo
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------
见视频展示:
.. raw:: html
<iframe src="//player.bilibili.com/player.html?aid=887712205&bvid=BV1xK4y1P7ur&cid=330261457&page=5" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>