[feat][docs] add english docs

This commit is contained in:
qqwang 2021-08-05 20:33:12 +08:00
parent 0d9f65c145
commit ac418d27a3
437 changed files with 52529 additions and 0 deletions

View file

@ -0,0 +1,199 @@
BLE Client And Server Interconnection
=======================================
This demo is based on **bl702** to demonstrate the connection and data sending and receiving of **ble server** and **ble client**.
Prepare
-----------------------
- Two bl702 boards or one bl702 board + mobile app
Software Implementation
----------------------------
BLE client software Implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- For the software code, see ``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);
}
}
- In the ``bt_conn_cb_register`` function, register the ``callback`` function for successful connection and disconnection
- In the ``ble_start_scan`` function, the device will start scanning
- In the ``device_found`` function, the device uploads the scanned Bluetooth device, the code uses ``adv_name`` to find the Bluetooth device that needs to be connected, and initiate the connection
.. 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);
}
}
- After the connection is successful, in the ``ble_write_data_task`` function, the client sends the data in ``buf`` to the 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);
- After the connection is successful, in the ``notify_func`` function, the client receives the data from the server, ``data`` is the data content, ``length`` is the data length
BLE server software implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- See ``examples/ble/ble_peripheral`` for the software code
.. 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);
}
- In the ``ble_start_adv`` function, ``adv_name`` sets the name of the broadcast device, and the device starts to broadcast
.. 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);
-After the connection is successful, in ``ble_tp_recv_wr``, the server receives the data from the client, ``buf`` is the data content, ``len`` is the data length
.. 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);
}
}
- After the connection is successful, in the ``ble_tp_notify_task`` function, the server sends the data in ``data`` to the client.
Compile and program
-----------------------------
- **CDK tool compilation**
Not currently supported
- **Command compilation**
.. 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
- **Program**
See :ref:`bl_dev_cube`
Experimental phenomena
-----------------------------
- **Two bl702 connections**
.. figure:: img/ble_client.png
:alt:
.. figure:: img/ble_server.png
:alt:
- **Mobile phone connect bl702**
.. figure:: img/phone_connect.jpg
:alt:
- The connection is successful, as shown in the figure below
.. figure:: img/phone_connected.png
:alt:
- Steps to send and receive data
- Click ``1`` ``Unknow Service`` to display specific service properties
- Click ``2`` to turn on ``Notification``, allowing the server to send data to the client
- Click ``3`` where the client sends data to the server, fill in the data you want to send, and click the ``SEND`` button
.. figure:: img/ble_data.png
:alt:
.. figure:: img/receive_data.png
:alt:
.. figure:: img/write_data.jpg
:alt:

View file

@ -0,0 +1,23 @@
BOOT2 IAP
============================
IAP (In Application Programming) is to program some areas of User Flash during the running of the user program. The purpose is to update the firmware program in the product through the reserved communication port after the product is released.
If you need to realize the IAP function, that is, it will be automatically updated when the user program is running. Need to write two project codes when designing the firmware program. The first project program does not perform normal functional operations, but only receives programs or data through some communication channel (such as USB, USART) to update the second part of the code, and the second project code is the real function Code.
Bouffalo Lab provides the boot2_iap.bin file and releases it simultaneously with the Dev Cube software package. Users can use Dev Cube to program boot2_iap.bin into the target board. After programming once, the user code can be updated online through the IAP function.
bl_mcu_sdk contains the source code of boot2_iap, users can check the code in examples/boot2_iap, and complete the compilation and programming. For the compilation and programming process, please refer to the introduction of "Quick Development Guide".
Prepare
-----------------------
- The latest version of Dev Cube
- Bl706
- TTL-USB
Experimental phenomena
-----------------------------
For the specific steps of using Dev Cube to complete the IAP function, please refer to `DevCube User Manual <https://dev.bouffalolab.com/media/upload/doc/DevCube%E7%94%A8%E6%88% B7%E6%89%8B%E5%86%8Cv1.3.pdf>`_ "IAP Program Download".

View file

@ -0,0 +1,2 @@
FATFS Read And Write
=======================

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: 25 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: 5.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -0,0 +1,93 @@
LowPower Evaluation
=========================
Introduction
------------------------
BL series chips have rich low-power features to adapt to different low-power applications. In order to facilitate users to quickly evaluate and use the low-power performance of bl series MCUs, bl_mcu_sdk provides a set of low-power interfaces. The low-power levels are divided into four levels.
1. Running: The power consumption when the CPU is running normally, and the power consumption is determined by the function executed by the customer application code.
2. WFI: WFI mode, the clock of the CPU is in the Gating state, the CPU stops running, and the program will continue to run when the user exits the WFI mode.
3. PDS: In PDS mode, most power domains on the chip are turned off, and the CPU is turned off at the same time. RAMs such as ITCM and DTCM in the same power domain as the CPU cannot be used. Only 64K OCTAM can save data. The internal RTC can be used to wake up, or use GPIO pins (when the GPIO power domain is not turned off) to wake up.
4. HBN: HBN mode, shuts down most of the power domains on the chip, shuts down the CPU and 64K OCRAM, only 4K RAM in the AON domain can save data. The internal RTC can be used to wake up, or a specific wake-up pin (pin located in the AON domain) can be used to wake up.
bl_mcu_sdk provides a simple low-power reference example (bl_mcu_sdk examples/power/lowpower_test/) to help users quickly evaluate low-power features. If you need to further adapt to your own low-power scenarios and adopt different low-power methods, please refer to the relevant datasheet or seek technical support from Boufflao Lab.
In this example, the clock selection of peripherals and CPU are both crystal oscillator 32M. The power consumption measurement results based on this example are shown in the following table:
+------------+---------------------+------------+------------------------------+-----------------------------------------------------------+
|Mode |Reference current |Basic mode |Wake-up source |Remark |
+============+=====================+============+==============================+===========================================================+
|Running |5.68 mA |Run | |All peripheral clocks are turned on |
+------------+---------------------+------------+------------------------------+-----------------------------------------------------------+
|WFI |3.14 mA |WFI |Any interruption |Except the serial port, other peripheral clocks are closed |
+------------+---------------------+------------+------------------------------+-----------------------------------------------------------+
|PDS |10 uA |PDS 31 |Internal RTC/pin interrupt |64K OCRAM to save data |
+------------+---------------------+------------+------------------------------+-----------------------------------------------------------+
|HBN |1 uA |HBN 1 |Internal RTC/pin interrupt |4K AON RAM to save data |
+------------+---------------------+------------+------------------------------+-----------------------------------------------------------+
The reference current in the above table is obtained through the sample firmware test. The definition of four levels of "run" " wfi" "pds" "hbn" simplifies the original setting of hbn level and pds level.
See bl702_bl704_bl706_DS_EN_Combo_1.9.pdf page 28
.. figure:: img/powerTable.png
**Low power consumption example test method**
-------------------------------------------------
**Compile low-power sample code**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Write ``make APP=lowpower_test SUPPORT_SHELL=y BOARD=bl706_lp`` in the project directory to complete the compilation of the low power consumption example bl706, or use the CDK project directly to complete the compilation and download.
You can refer to this document "Quick Development Guide" to get more information about compiling and programming.
When the compilation and programming are successful, connect the serial port to the computer and reset the chip, Xshell will display the page as shown in the figure below.
.. figure:: img/xShell_lowpower.png
**Prepare the hardware environment required for low-power testing**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- It is possible to connect the ammeter and the circuit board of the power supply side in series
- Ammeter
- PC (running Windows or Linux system)
- TTL to USB
As shown in the figure below, connect the ammeter in series into the power supply circuit of the bl706 module, and issue different low-power commands through the serial debugging assistant software on the PC side, so that the bl706 enters the corresponding low-power mode.
Observe the indicated current value and complete the evaluation.
.. figure:: img/lowpower_arch.png
**Use Xshell to start evaluating low-power performance**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The user can enter the corresponding low power consumption mode by entering the following commands in Xshell.
``run``
- After resetting the chip, it enters the run mode by default without entering any low power consumption mode. The chip is actually running the while(1); statement.
``wfi``
- Enter wfi mode without adding any parameters. After entering, the CPU is in clock gating state to reduce power consumption
- After entering wfi mode, any interrupt will wake up, such as uart interrupt. Pressing Enter in Xshell will trigger the BL706 UART RX interrupt, so the wfi low power consumption mode can be awakened by this method.
``pds sleeptime``
- pds can choose to take the parameter "sleeptime" to determine its internal RTC wake-up time. If the command does not carry this parameter, the RTC internal wake-up is not used by default. The current firmware only supports power-on reset wake-up.
- If the instruction contains the sleeptime parameter, pds will be awakened at the moment of ``sleeptime * clock_period``, which will behave as resetting the chip and reprinting the initial message.
- After entering the low-power mode, the RTC clock is 32K, so when the sleeptime is 32768, it appears to wake up after a second of sleep.
``hbn sleeptime``
- hbn can choose to take the parameter "sleeptime" to determine its internal RTC wake-up time. If the command does not carry this parameter, the RTC internal wake-up is not used by default. The current firmware only supports power-on reset wake-up.
- If the instruction contains the sleeptime parameter, hbn will be awakened at the moment of ``sleeptime * clock_period``, which will behave as resetting the chip and printing the start message again.
- After entering the low-power mode, the RTC clock is 32K, so when the sleeptime is 32768, it appears to wake up after a second of sleep.

View file

@ -0,0 +1,217 @@
SHELL Command Debugging
=========================
In order to facilitate the user to use the pc or other controllers to debug the functions of the development board (non-emulator debugging), we provide users with a shell command component, which is similar to the command operation under linux. The user sends commands on the PC or other control terminals, and sends the data to the shell of the development board through serial port, usb, Ethernet, Bluetooth, wifi, etc. The shell will read the received commands for analysis and scan the registered internal functions. After scanning the matching function, execute the matching function, and return the incoming key value and the result of the function execution to the pc or control terminal in real time . It should be noted that the controller side needs to send the key value of the standard keyboard.
This demo will demonstrate how to use **shell** to debug commands through the serial port.
This shell component has the following functions:
- Support standard keyboard character control
- Support command auto completion
- Support up and down keys to view historical commands
- Support left and right keys to modify commands
- Support file system and network system debugging
Prepare
-----------------------
- PC control terminal uses serial terminal software: xshell or mobaxterm
- Connection medium: usb to serial port or network or usb
Hardware Connection
-----------------------------
This demo is based on BL706_IOT and the connection method is as follows
::
GPIO function GPIO pin
----------------------------------
UART0_TX <--> GPIO14
UART0_RX <--> GPIO15
Software Implementation
--------------------------
Shell porting to serial port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- See ``examples/shell`` for the software code
.. code-block:: C
:linenos:
#define BSP_UART_CLOCK_SOURCE ROOT_CLOCK_SOURCE_PLL_96M
#define BSP_UART_CLOCK_DIV 0
- Configure the ``UART`` device clock source, see ``bsp/board/bl706_iot/clock_config.h``
.. code-block:: C
:linenos:
#define CONFIG_GPIO14_FUNC GPIO_FUN_UART0_TX
#define CONFIG_GPIO15_FUNC GPIO_FUN_UART0_RX
- Configure ``UART`` device multiplexing pins, see ``bsp/board/bl706_iot/pinmux_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
- Enable ``BSP_USING_UART0`` and configure ``UART`` device configuration, see ``bsp/board/bl706_iot/peripheral_config.h``
.. code-block:: C
:linenos:
bflb_platform_init();
- In the ``bflb_platform_init`` function, we have registered and opened a serial port device for debugging, to provide users with a basic function of ``MSG`` for printing out messages. The specific implementation is as follows
.. 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, NULL);
device_control(uart, DEVICE_CTRL_CLR_INT, (void *)(UART_RX_FIFO_IT));
}
- First call the ``uart_register`` function to register the ``UART`` device, currently register ``UART0``
- Then use the ``find`` function to find the handle corresponding to the device and save it in the ``uart`` handle
- Finally use ``device_open`` to open the ``uart`` device with polling sending and interrupt receiving, the interrupt is closed by default and the receiving interrupt callback function is not registered
.. code-block:: C
:linenos:
struct device *uart = device_find("debug_log");
if (uart) {
device_set_callback(uart, shell_irq_callback);
device_control(uart, DEVICE_CTRL_SET_INT, (void *)(UART_RX_FIFO_IT));
}
- Register the receive interrupt service function for ``UART0`` through the ``device_set_callback`` function. Open the ``UART_RX_FIFO_IT`` interrupt via the ``device_control`` function
.. code-block:: C
:linenos:
void shell_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t state)
{
uint8_t data;
if (state == UART_EVENT_RX_FIFO) {
data = *(uint8_t *)args;
shell_handler(data);
}
}
-In the interrupt callback function, judge whether the ``state`` is ``UART_EVENT_RX_FIFO``, and if it is, pass the received byte to the ``shell_handler`` function.
.. code-block:: C
:linenos:
shell_init();
- Call ``shell_init`` to initialize the shell components.
SHELL Command Registration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Shell command registration uses the following two macros
.. code-block:: C
:linenos:
void hellowd()
{
MSG("hello World\r\n");
}
int echo(int argc, char *argv[])
{
MSG("%dparameter(s)\r\n", argc);
for (uint8_t i = 1; i < argc; i++) {
MSG("%s\r\n", argv[i]);
}
return 0;
}
SHELL_CMD_EXPORT(hellowd, hellowd test)
SHELL_CMD_EXPORT(echo, echo test)
.. code-block:: C
:linenos:
void hellowd()
{
MSG("hello World\r\n");
}
int cmd_echo(int argc, char *argv[])
{
MSG("%dparameter(s)\r\n", argc);
for (uint8_t i = 1; i < argc; i++) {
MSG("%s\r\n", argv[i]);
}
return 0;
}
SHELL_CMD_EXPORT_ALIAS(hellowd, hellwd,hellowd test)
SHELL_CMD_EXPORT_ALIAS(cmd_echo, echo,echo test)
Compile and Program
-----------------------------
- **CDK compile**
Open projectshell.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=shell SUPPORT_SHELL=y
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------
.. figure:: img/shell_demo.gif
:alt:
shell test

View file

@ -0,0 +1,150 @@
ADC - Key Detection Voltage
==============================
This demo mainly introduces the key functions of the ADC. The ADC is used to detect the voltage value of the key input pin and judge whether the corresponding key is pressed according to different voltage divisions.
Hardware Connection
-----------------------------
This demo is based on BL706_AVB:
::
GPIO function GPIO pin
----------------------------------
ADC CH8 <--> GPIO18
**Voltage divider circuit:**
.. figure:: img/adc_key_demo.png
:alt:
adc key
Software Implementation
-----------------------------
- For the code see ``examples/adc/adc_key``
.. code-block:: C
:linenos:
#define BSP_ADC_CLOCK_SOURCE ROOT_CLOCK_SOURCE_XCLK
#define BSP_ADC_CLOCK_DIV 0
- Configure the ``ADC`` device clock source, see ``bsp/board/bl706_avb/clock_config.h``
.. code-block:: C
:linenos:
#define CONFIG_GPIO18_FUNC GPIO_FUN_ADC
- Configure ``ADC`` device multiplexing pins, see ``bsp/board/bl706_avb/pinmux_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
- Enable ``BSP_USING_ADC0`` and configure the ``ADC`` device, see ``bsp/board/bl706_iot/peripheral_config.h``
.. 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);
- First call the ``adc_register`` function to register the ``adc_key`` device, which is currently registered as ADC0
- Then use the ``find`` function to find the handle corresponding to the device and save it in the ``adc_key`` handle
- Then use ``device_open`` to open the ``adc_key`` device in polling mode, and call ``device_control`` to complete the ADC related configuration
- Finally call ``adc_channel_start`` to enable ADC conversion
.. 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));
}
- Call ``device_read`` to read the ``adc_key`` device information and save it to the ``result_val`` structure
- Call the ``get_adc_key_value`` function to get the current key value and voltage value
Compile and Program
-----------------------------
- **CDK compilation**
Open projectadc_key.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_avb APP=adc_key
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------
In this experiment, pressing SW1 ~ SW5 on the board in turn will get different voltage values:
- key 0: ~0V
- key 1: ~0.1V
- key 2: ~0.2V
- key 3: ~0.3V
- key 4: ~0.43V
operation result:
.. figure:: img/adc_key_result.png
Video display:
.. raw:: html
<iframe src="https://player.bilibili.com/player.html?aid=887712205&bvid=BV1xK4y1P7ur&cid=330261457&page=5" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View file

@ -0,0 +1,9 @@
=======================
ADC
=======================
.. toctree::
:maxdepth: 1
ADC - Key Detection Voltage <adc_key_demo>

View file

@ -0,0 +1,113 @@
DMA - Data Transfer Between RAM
=================================
This demo is based on the memory to memory mode of DMA for data transfer.
Hardware Connection
-----------------------------
None
Software Implementation
-----------------------------
- For the code see ``examples/dma/dma_m2m``
.. 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
- Enable ``BSP_USING_DMA0_CH0`` and configure the ``DMA`` device, see ``bsp/board/bl706_iot/peripheral_config.h``
.. 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);
}
- First call the ``dma_register`` function to register a channel of the ``DMA`` device, currently register ``DMA_CH0``
- Then use the ``find`` function to find the handle corresponding to the device and save it in the ``dma`` handle
- Finally use ``device_open`` to open the ``dma`` device in the default mode, call ``device_set_callback`` to register a dma channel 0 interrupt callback function, and call ``device_control`` to open the dma transmission completion interrupt
.. code-block:: C
:linenos:
dma_reload(dma,(uint32_t)dma_src_buffer,(uint32_t)dma_dst_buffer,8000);
dma_channel_start(dma);
- Call the ``dma_reload`` function to supplement the configuration of dma channel 0. A part of the configuration has been supplemented in ``DMA0_CH0_CONFIG``. Here we mainly supplement the source data address, destination data address and total transmission length
- Call ``dma_channel_start`` to start dma transmission
.. 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");
}
}
- Check whether the data transmission is correct in the interrupt function
Compile and Program
-----------------------------
- **CDK compilation**
Open project:dma_m2m.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=dma_m2m
- **Program**
详见 :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------
The data in the ``dma_src_buffer`` array is transferred to the ``dma_dst_buffer`` array through DMA channel 0 with a source 32-bit width and a target 32-bit width. After the data transfer is completed, the serial port prints ``dma transfer success``.

View file

@ -0,0 +1,9 @@
=======================
DMA
=======================
.. toctree::
:maxdepth: 1
DMA - Data Transfer Between RAM <dma_m2m_demo>

View file

@ -0,0 +1,75 @@
GPIO output - Lamp LED
=========================
This demo is based on the output mode of GPIO.
Hardware Connection
-----------------------------
This demo is based on BL706_IOT and the connection method is as follows
::
GPIO function GPIO pin
----------------------------------
D0 <--> GPIO22
D1 <--> GPIO29
D2 <--> GPIO30
D3 <--> GPIO31
.. figure:: img/blink_breath_sch.png
:alt:
Software Implementation
-----------------------------
- See ``examples/gpio/gpio_blink`` for the software code
.. 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);
- Use the above code to configure ``GPIO22`` ``GPIO29`` ``GPIO30`` ``GPIO31`` to output pull-up mode.
.. code-block:: C
:linenos:
gpio_write(GPIO_PIN_22, 0);
- Use the above code to modify the output level value.
Compile and Program
-----------------------------
- **CDK compilation**
Open project:gpio_blink.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=gpio_blink
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------
Video display:
.. raw:: html
<iframe src="https://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,64 @@
GPIO interrupt - Button detection
====================================
This demo is based on GPIO external interrupt mode.
Hardware Connection
-----------------------------
This demo is based on BL706_IOT, add the button circuit by yourself, the connection method is as follows
::
GPIO function GPIO pin
----------------------------------
SW1 <--> GPIO11
.. figure:: img/button_sch.png
:alt:
Software Implementation
-----------------------------
- See ``examples/gpio/gpio_int`` for the software code
.. 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);
- Use the above code to configure ``GPIO11`` as the GPIO rising edge interrupt trigger mode, and register the interrupt callback function.
Compile and Program
-----------------------------
- **CDK compilation**
Open project:gpio_int.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=gpio_int
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------
When the button is pressed, the serial port will print ``"gpio rising trigger !"``

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,10 @@
=======================
GPIO
=======================
.. toctree::
:maxdepth: 1
GPIO output - Lamp LED <blink_demo>
GPIO interrupt - Button Detection <button_demo>

View file

@ -0,0 +1,116 @@
I2C - AT24CXX read and write
================================
Hardware Connection
-----------------------------
This demo is based on BL706_IOT, add AT24CXX circuit by yourself, the connection method is as follows
::
GPIO function GPIO pin
----------------------------------
I2C_SCL <--> GPIO11
I2C_SDA <--> GPIO16
Software Implementation
-----------------------------
- See ``examples/i2c/i2c_at24cxx`` for the software code
.. code-block:: C
:linenos:
#define BSP_I2C_CLOCK_SOURCE ROOT_CLOCK_SOURCE_BCLK
#define BSP_I2C_CLOCK_DIV 0
- Configure the ``I2C`` device clock source, see ``bsp/board/bl706_iot/clock_config.h``
.. code-block:: C
:linenos:
#define CONFIG_GPIO11_FUNC GPIO_FUN_I2C
#define CONFIG_GPIO16_FUNC GPIO_FUN_I2C
- Configure ``I2C`` device multiplexing pins, see ``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
- Enable ``BSP_USING_I2C0`` and configure ``I2C`` device, see ``bsp/board/bl706_iot/peripheral_config.h``
.. 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);
}
- First call the ``i2c_register`` function to register the ``I2C`` device, currently register ``I2C0``
- Then use the ``find`` function to find the handle corresponding to the device and save it in the ``i2c0`` handle
- Finally use ``device_open`` to open the ``I2C0`` device in the default mode
.. 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]);
- Call ``i2c_transfer`` to transfer two ``msg``, one ``msg`` represents writing 8-byte data to eeprom, and one ``msg`` represents reading 8-byte data from eeprom
Compile and Program
-----------------------------
- **CDK compilation**
Open project:i2c_at24cxx.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=i2c_at24cxx
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------

View file

@ -0,0 +1,9 @@
=======================
I2C
=======================
.. toctree::
:maxdepth: 1
I2C - AT24CXX Read And Write <i2c_eeprom_demo>

View file

@ -0,0 +1,9 @@
=======================
MTIMER
=======================
.. toctree::
:maxdepth: 1
MTIMER - System Timer <mtimer_demo>

View file

@ -0,0 +1,56 @@
MTIMER - System Timer
========================
This demo is based on a 64-bit timer (MTIMER) that comes with the risc-v kernel. This demo can provide reference for os tick.
Hardware Connection
-----------------------------
None
Software Implementation
-----------------------------
- See ``examples/systick`` for the software code
.. note::
The ``mtimer`` clock defaults to 1M after frequency division, which is convenient for later use and reduces calculation time.
.. 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);
- Use the above code to set the mtimer timing time to 1s, and register the interrupt callback function.
Compile and Program
-----------------------------
- **CDK compilation**
Open project:systick.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=systick
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------
The ``tick`` value is incremented by 1 per second and printed through the serial port.

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View file

@ -0,0 +1,10 @@
=======================
PWM
=======================
.. toctree::
:maxdepth: 1
PWM - Breathing LED <pwm_breath_demo>
PWM - Drive Stepper Motor <pwm_step_motor>

View file

@ -0,0 +1,130 @@
PWM - Breathing LED
=========================
This demo is based on PWM polling mode.
Hardware Connection
-----------------------------
This demo is based on BL706_IOT, and the connection method is as follows
::
GPIO function GPIO pin
----------------------------------
PWM_CH2 <--> GPIO22
.. figure:: img/blink_breath_sch.png
:alt:
Software Implementation
-----------------------------
-See ``examples/pwm/pwm_breath_led`` for the software code
.. code-block:: C
:linenos:
#define BSP_PWM_CLOCK_SOURCE ROOT_CLOCK_SOURCE_XCLK
#define BSP_PWM_CLOCK_DIV 1
- Configure the ``PWM`` device clock source, see ``bsp/board/bl706_iot/clock_config.h``
.. code-block:: C
:linenos:
#define CONFIG_GPIO22_FUNC GPIO_FUN_PWM
- Configure ``PWM`` device multiplexing pins, see ``bsp/board/bl706_iot/pinmux_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
- Enable ``BSP_USING_PWM_CH2`` and configure ``PWM`` device configuration, see ``bsp/board/bl706_iot/peripheral_config.h``
.. 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) {
PWM_DEV(led_breath)->period = 32; //frequence = 32M/1/32 = 1Mhz
PWM_DEV(led_breath)->threshold_low = 16;
PWM_DEV(led_breath)->threshold_high = 32;
device_open(led_breath, DEVICE_OFLAG_STREAM_TX);
pwm_channel_start(led_breath);
}
- First call the ``pwm_register`` function to register a channel of the ``PWM`` device, currently register ``PWM_CH2``
- Then use the ``find`` function to find the handle corresponding to the device and save it in the ``led_breath`` handle
- Set the frequency of ``PWM_CH2`` to 1Mhz, and the duty cycle to 50%
- Use ``device_open`` to open the ``led_breath`` device in polling mode
.. code-block:: C
:linenos:
for (pwm_cfg.threshold_high = 0; pwm_cfg.threshold_high <= 32; pwm_cfg.threshold_high++) {
device_control(led_breath, DEIVCE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg);
bflb_platform_delay_ms(50);
}
for (pwm_cfg.threshold_high = 32; 0 <= pwm_cfg.threshold_high && pwm_cfg.threshold_high <= 32; pwm_cfg.threshold_high--) {
device_control(led_breath, DEIVCE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg);
bflb_platform_delay_ms(50);
}
- Use the ``device_contorl`` function with the ``DEIVCE_CTRL_PWM_DUTYCYCLE_CONFIG`` instruction to modify the duty cycle of the current PWM channel.
Compile and Program
-----------------------------
- **CDK compilation**
Open project:pwm_breath_led.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=pwm_breath_led
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------
.. figure:: img/pwm_demo.gif
:alt:
pwm breath led!
Video display:
.. 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,281 @@
PWM - 驱动步进电机
====================
步进电机是一种将电脉冲转化为角位移的执行机构。当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。可以通过控制脉冲个来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
本 demo 采用步进电机 28BYJ48 型四相八拍电机,使用 ULN2003 芯片驱动,电压为 DC5V—DC12V。当对步进电机施加一系列连续不断的控制脉冲时它可以连续不断地转动。每一个脉冲信号对应步进电机的某一相或两相绕组的通电状态改变一次也就对应转子转过一定的角度一个步距角。当通电状态的改变完成一个循环时转子转过一个齿距。
.. figure:: img/step_motor.png
:alt:
28BYJ48
.. figure:: img/uln2003.png
:alt:
ULN2003
这个步进电机内部有个真正的步进马达转子每一个脉冲能使这个真正的转子转动5.625°看下图的数据表格中的减速比是1:64意思是这个真正的步进马达转子转动64周才能让输出轴转动1周因此下图的表格中步距角度才写的是5.625°/64表明的意思是一个脉冲可以让输出轴转动5.625°/64的角度。所以要让马达转一周360° 则需要360/5.625*64=4096个脉冲。
脉冲(或拍)的数量决定转动的角度,单位时间内脉冲(或拍)的数量决定转动的速度
.. figure:: img/step_motor_info.png
:alt:
四相步进电机可以在不同的通电方式下运行,常见的通电方式有如下三种:
- 一相励磁单相绕组通电四拍A+,B+,A-,B-......
.. figure:: img/pwm_step_motor1.png
:alt:
- 二相励磁双相绕组通电四拍A+B+,B+A-,A-B-,B-A+......
.. figure:: img/pwm_step_motor2.png
:alt:
- 一二相励磁八拍A+B+,B+,B+A-,A-,A-B-,B-,B-A+,A+......
.. figure:: img/pwm_step_motor3.png
:alt:
硬件连接
-----------------------------
本 demo 基于BL706_IOT开发板连接方式如下
::
GPIO function GPIO pin
----------------------------------
PWM_CH0 <--> GPIO10
PWM_CH1 <--> GPIO11
PWM_CH2 <--> GPIO12
PWM_CH3 <--> GPIO3
.. figure:: img/pwm_step_motor.png
:alt:
参考电路
软件实现
-----------------------------
- 软件代码见 ``examples/pwm/pwm_step_motor``
.. code-block:: C
:linenos:
#define BSP_PWM_CLOCK_SOURCE ROOT_CLOCK_SOURCE_RC_32K
#define BSP_PWM_CLOCK_DIV 32
- 配置 ``PWM`` 设备时钟源,见 ``bsp/board/bl706_iot/clock_config.h``
.. code-block:: C
:linenos:
#define CONFIG_GPIO3_FUNC GPIO_FUN_PWM
#define CONFIG_GPIO10_FUNC GPIO_FUN_PWM
#define CONFIG_GPIO11_FUNC GPIO_FUN_PWM
#define CONFIG_GPIO12_FUNC GPIO_FUN_PWM
- 配置 ``PWM`` 设备复用引脚,见 ``bsp/board/bl706_iot/pinmux_config.h``
.. code-block:: C
:linenos:
#define BSP_USING_PWM_CH0
#define BSP_USING_PWM_CH1
#define BSP_USING_PWM_CH2
#define BSP_USING_PWM_CH3
#if defined(BSP_USING_PWM_CH0)
#ifndef PWM_CH0_CONFIG
#define PWM_CH0_CONFIG \
{ \
.ch = 0, \
.polarity_invert_mode = DISABLE, \
.period = 0, \
.threshold_low = 0, \
.threshold_high = 0, \
.it_pulse_count = 0, \
}
#endif
#endif
#if defined(BSP_USING_PWM_CH1)
#ifndef PWM_CH1_CONFIG
#define PWM_CH1_CONFIG \
{ \
.ch = 1, \
.polarity_invert_mode = DISABLE, \
.period = 0, \
.threshold_low = 0, \
.threshold_high = 0, \
.it_pulse_count = 0, \
}
#endif
#endif
#if defined(BSP_USING_PWM_CH2)
#ifndef PWM_CH2_CONFIG
#define PWM_CH2_CONFIG \
{ \
.ch = 2, \
.polarity_invert_mode = DISABLE, \
.period = 0, \
.threshold_low = 0, \
.threshold_high = 0, \
.it_pulse_count = 0, \
}
#endif
#endif
#if defined(BSP_USING_PWM_CH3)
#ifndef PWM_CH3_CONFIG
#define PWM_CH3_CONFIG \
{ \
.ch = 3, \
.polarity_invert_mode = DISABLE, \
.period = 0, \
.threshold_low = 0, \
.threshold_high = 0, \
.it_pulse_count = 0, \
}
#endif
#endif
- 使能 ``BSP_USING_PWM_CH0``, ``BSP_USING_PWM_CH1`` , ``BSP_USING_PWM_CH2``, ``BSP_USING_PWM_CH3`` 并配置 ``PWM`` 设备配置,见 ``bsp/board/bl706_iot/peripheral_config.h``
.. code-block:: C
:linenos:
pwm_register(PWM_CH0_INDEX, "motor_ch0", DEVICE_OFLAG_RDWR);
pwm_register(PWM_CH1_INDEX, "motor_ch1", DEVICE_OFLAG_RDWR);
pwm_register(PWM_CH2_INDEX, "motor_ch2", DEVICE_OFLAG_RDWR);
pwm_register(PWM_CH3_INDEX, "motor_ch3", DEVICE_OFLAG_RDWR);
motor_ch0 = device_find("motor_ch0");
motor_ch1 = device_find("motor_ch1");
motor_ch2 = device_find("motor_ch2");
motor_ch3 = device_find("motor_ch3");
if (motor_ch0) {
PWM_DEV(motor_ch0)->period = 8; //frequence = 32K/160/8 = 25hz
PWM_DEV(motor_ch0)->threshold_low = 2;
PWM_DEV(motor_ch0)->threshold_high = 7;
PWM_DEV(motor_ch0)->polarity_invert_mode = ENABLE;
device_open(motor_ch0, DEVICE_OFLAG_STREAM_TX);
}
if (motor_ch1) {
PWM_DEV(motor_ch1)->period = 8; //frequence = 32K/160/8 = 25hz
PWM_DEV(motor_ch1)->threshold_low = 1;
PWM_DEV(motor_ch1)->threshold_high = 4;
device_open(motor_ch1, DEVICE_OFLAG_STREAM_TX);
}
if (motor_ch2) {
PWM_DEV(motor_ch2)->period = 8; //frequence = 32K/160/8 = 25hz
PWM_DEV(motor_ch2)->threshold_low = 3;
PWM_DEV(motor_ch2)->threshold_high = 6;
device_open(motor_ch2, DEVICE_OFLAG_STREAM_TX);
}
if (motor_ch3) {
PWM_DEV(motor_ch3)->period = 8; //frequence = 32K/160/8 = 25hz
PWM_DEV(motor_ch3)->threshold_low = 5;
PWM_DEV(motor_ch3)->threshold_high = 8;
device_open(motor_ch3, DEVICE_OFLAG_STREAM_TX);
}
pwm_channel_start(motor_ch0);
pwm_channel_start(motor_ch1);
pwm_channel_start(motor_ch2);
pwm_channel_start(motor_ch3);
- 首先调用 ``pwm_register`` 函数注册 ``PWM`` 设备的一个通道,当前注册 PWM 通道0/1/2/3
- 然后通过 ``find`` 函数找到设备对应的句柄保存于4个句柄中
- 设置 4个通道 的频率为 125hz占空比为37.5%
- 使用 ``device_open`` 以轮询模式来打开 4个通道
.. code-block:: C
:linenos:
enum motor_dir_type {
CW,
CCW,
STOP
};
void motor_set_dir(enum motor_dir_type dir)
{
pwm_dutycycle_config_t pwm_cfg[4];
if (dir == CW) {
pwm_cfg[0].threshold_low = 2;
pwm_cfg[0].threshold_high = 7;
pwm_cfg[1].threshold_low = 1;
pwm_cfg[1].threshold_high = 4;
pwm_cfg[2].threshold_low = 3;
pwm_cfg[2].threshold_high = 6;
pwm_cfg[3].threshold_low = 5;
pwm_cfg[3].threshold_high = 8;
}
else if (dir == CCW) {
pwm_cfg[0].threshold_low = 2;
pwm_cfg[0].threshold_high = 7;
pwm_cfg[1].threshold_low = 5;
pwm_cfg[1].threshold_high = 8;
pwm_cfg[2].threshold_low = 3;
pwm_cfg[2].threshold_high = 6;
pwm_cfg[3].threshold_low = 1;
pwm_cfg[3].threshold_high = 4;
} else if (dir == STOP) {
pwm_cfg[0].threshold_low = 0;
pwm_cfg[0].threshold_high = 0;
pwm_cfg[1].threshold_low = 0;
pwm_cfg[1].threshold_high = 0;
pwm_cfg[2].threshold_low = 0;
pwm_cfg[2].threshold_high = 0;
pwm_cfg[3].threshold_low = 0;
pwm_cfg[3].threshold_high = 0;
}
device_control(motor_ch0, DEIVCE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg[0]);
device_control(motor_ch1, DEIVCE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg[1]);
device_control(motor_ch2, DEIVCE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg[2]);
device_control(motor_ch3, DEIVCE_CTRL_PWM_DUTYCYCLE_CONFIG, &pwm_cfg[3]);
}
- 使用 ``device_contorl`` 函数,配合 ``DEIVCE_CTRL_PWM_DUTYCYCLE_CONFIG`` 指令修改4个 PWM 通道的的高低阈值。
.. note:: 该函数的功能主要用于切换步进电机的方向
编译和烧录
-----------------------------
- **CDK 编译**
打开项目中提供的工程文件pwm_step_motor.cdkproj
参照 :ref:`windows_cdk_quick_start` 的步骤编译下载即可
- **命令行编译**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=pwm_step_motor
- **烧录**
详见 :ref:`bl_dev_cube`
实验现象
-----------------------------
.. figure:: img/pwm_step_motor.gif
:alt:

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 KiB

View file

@ -0,0 +1,9 @@
=======================
SPI
=======================
.. toctree::
:maxdepth: 1
SPI - TFT LCD Display <spi_lcd_demo>

View file

@ -0,0 +1,154 @@
SPI - TFT LCD Display
=======================
Hardware Connection
-----------------------------
This demo is based on BL706_AVB, and the connection method is as follows
::
GPIO function GPIO pin
----------------------------------
LCD_CS <--> GPIO10
LCD_DC <--> GPIO22
SPI_SCK <--> GPIO19
SPI_MISO <--> GPIO20
SPI_MOSI <--> GPIO21
Software Implementation
-----------------------------
- See ``examples/spi/spi_lcd`` for the software code
.. code-block:: C
:linenos:
#define BSP_SPI_CLOCK_SOURCE ROOT_CLOCK_SOURCE_BCLK
#define BSP_SPI_CLOCK_DIV 0
- Configure the ``SPI`` device clock source, see ``bsp/board/bl706_avb/clock_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
- Configure ``SPI`` device multiplexing pins, see ``bsp/board/bl706_avb/pinmux_config.h``
.. note::
``bsp/board/bl706_avb/pinmux_config.h`` is currently used by all demo demos, so you need to select ``PINMUX_SELECT`` as ``PINMUX_LVGL``, and open one of the demos
.. note::
In order to adapt to the bl702_avb hardware, the MOSI and MISO of SPI have been swapped by default. If you want to restore the default, modify ``SPI_SWAP_ENABLE`` in ``drivers/bl702_driver/hal_drv/default_config/spi_config.h`` to 0
.. 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
- Enable ``BSP_USING_SPI0`` and configure ``SPI`` device, see ``bsp/board/bl706_avb/peripheral_config.h``
.. 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);
}
- Configure the ``LCD_CS`` and ``LCD_DC`` pins as output mode and pull up
- Call ``spi_register`` function to register ``SPI`` device, currently register ``SPI0``
- Then use the ``find`` function to find the handle corresponding to the device and save it in the ``spi0`` handle
- Finally use ``device_open`` to open the ``spi0`` device in polling sending mode
.. 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;
}
- Provide interface for LCD display driver
Compile and Program
-----------------------------
- **CDK compilation**
Open project:spi_lcd.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_avb APP=spi_lcd
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------
.. figure:: img/spi_lcd.png
:alt:
spi display!

View file

@ -0,0 +1,9 @@
=======================
TIMER
=======================
.. toctree::
:maxdepth: 1
TIMER - Second Timing Interrupt <timer_interrupt_demo>

View file

@ -0,0 +1,109 @@
TIMER - Second Timing Interrupt
==================================
This demo is based on TIMER interrupt mode with second timing.
Hardware Connection
-----------------------------
None
Software Implementation
-----------------------------
- See ``examples/timer/timer_int`` for the software code
.. code-block:: C
:linenos:
#define BSP_TIMER0_CLOCK_SOURCE ROOT_CLOCK_SOURCE_FCLK
#define BSP_TIMER0_CLOCK_DIV 0
- Configure ``TIMER`` device clock source,see ``bsp/board/bl706_iot/clock_config.h``
.. code-block:: C
:linenos:
#define BSP_USING_TIMER0
#if defined(BSP_USING_TIMER0)
#ifndef TIMER0_CONFIG
#define TIMER0_CONFIG \
{ \
.id = 0, \
.cnt_mode = TIMER_CNT_PRELOAD, \
.trigger = TIMER_PRELOAD_TRIGGER_COMP2, \
.reload = 0, \
.timeout1 = 1000000, \
.timeout2 = 2000000, \
.timeout3 = 3000000, \
}
#endif
#endif
- Enable ``BSP_USING_TIMER0`` and configure ``TIMER0`` device,see ``bsp/board/bl706_iot/peripheral_config.h``
.. code-block:: C
:linenos:
timer_register(TIMER0_INDEX, "timer0");
timer0 = device_find("timer0");
if (timer0) {
device_open(timer0, DEVICE_OFLAG_INT_TX); /* 1s,2s,3s timing*/
device_set_callback(timer0, timer0_irq_callback);
device_control(timer0, DEVICE_CTRL_SET_INT, (void *)(TIMER_COMP0_IT | TIMER_COMP1_IT | TIMER_COMP2_IT));
} else {
MSG("timer device open failed! \n");
}
- Call ``timer_register`` function to register ``TIMER`` device, currently register ``TIMER0``
- Then use the ``find`` function to find the handle corresponding to the device and save it in the ``timer0`` handle
- Finally use ``device_open`` to open the ``timer0`` device in interrupt mode
- Call ``device_set_callback`` to register irq callback named ``timer0_irq_callback``. Call ``device_control`` to enable irq and configure timing period.
.. code-block:: C
:linenos:
void timer0_irq_callback(struct device *dev, void *args, uint32_t size, uint32_t state)
{
if (state == TIMER_EVENT_COMP0) {
MSG("timer event comp0! \r\n");
} else if (state == TIMER_EVENT_COMP1) {
MSG("timer event comp1! \r\n");
} else if (state == TIMER_EVENT_COMP2) {
BL_CASE_SUCCESS;
timer_timeout_cfg_t cfg = { 2, 12000000 }; /*modify compare id 2 timeout 12s*/
device_write(dev, 0, &cfg, sizeof(timer_timeout_cfg_t));
MSG("timer event comp2! \r\n");
}
}
- In irq callback,try to determine whether compare id flag is coming.
- Call ``device_write`` to modify compare id 2 timeout with 12s.
Compile and Program
-----------------------------
- **CDK compilation**
Open project:timer_int.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=timer_int
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------

View file

@ -0,0 +1,9 @@
=======================
UART
=======================
.. toctree::
:maxdepth: 1
UART - Loopback <uart_loopback_demo>

View file

@ -0,0 +1,150 @@
UART - Loopback
====================
This demo is based on UART polling sending and receiving FIFO interrupt mode.
Hardware Connection
-----------------------------
This demo is based on BL706_IOT and the connection method is as follows
::
GPIO function GPIO pin
----------------------------------
UART0_TX <--> GPIO14
UART0_RX <--> GPIO15
Software Implementation
-----------------------------
- See ``examples/uart/uart_echo`` for the software code
.. code-block:: C
:linenos:
#define BSP_UART_CLOCK_SOURCE ROOT_CLOCK_SOURCE_PLL_96M
#define BSP_UART_CLOCK_DIV 0
-Configure the ``UART`` device clock source, see ``bsp/board/bl706_iot/clock_config.h``
.. code-block:: C
:linenos:
#define CONFIG_GPIO14_FUNC GPIO_FUN_UART0_TX
#define CONFIG_GPIO15_FUNC GPIO_FUN_UART0_RX
- Configure ``UART`` device multiplexing pins, see ``bsp/board/bl706_iot/pinmux_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
- Enable ``BSP_USING_UART0`` and configure the ``UART`` device, see ``bsp/board/bl706_iot/peripheral_config.h``
.. code-block:: C
:linenos:
bflb_platform_init();
- In the ``bflb_platform_init`` function, we have registered and opened a serial port device for debugging, to provide users with a basic function of ``MSG`` for printing out messages. The specific implementation is as follows
.. 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, NULL);
device_control(uart, DEVICE_CTRL_CLR_INT, (void *)(UART_RX_FIFO_IT));
}
- First call the ``uart_register`` function to register the ``UART`` device, currently register ``UART0``
- Then use the ``find`` function to find the handle corresponding to the device and save it in the ``uart`` handle
- Finally use ``device_open`` to open the ``uart`` device with polling sending and interrupt receiving, the interrupt is closed by default and the receiving interrupt callback function is not registered
.. 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));
}
- Register the user-specified ``UART0`` receiving interrupt service function through the ``device_set_callback`` function. Open the ``RX_FIFO`` and ``RTO`` interrupts through the ``device_control`` function
.. 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);
}
}
- This function is the interrupt service function of the example, and its function is to send out the received data.
- ``state`` will return the interrupt type of the ``UART`` device
- ``args`` contains the return data pointer
- ``size`` contains the length of the returned data
- ``dev`` is the handle of the interrupted ``uart`` device
- When an interrupt occurs, the ``device_write`` function will be called to send the received data back.
Compile and Program
-----------------------------
- **CDK compilation**
Open project:uart_echo.cdkproj
Refer to the steps of :ref:`windows_cdk_quick_start` to compile and download
- **Command compilation**
.. code-block:: bash
:linenos:
$ cd <sdk_path>/bl_mcu_sdk
$ make BOARD=bl706_iot APP=uart_echo
- **Program**
See :ref:`bl_dev_cube`
Experimental Phenomena
-----------------------------
Video display:
.. raw:: html
<iframe src="https://player.bilibili.com/player.html?aid=887712205&bvid=BV1xK4y1P7ur&cid=330261457&page=5" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>