eefocus_3896990 发表于 2026-10-7 15:41:03

【瑞萨BLE/WIFI模块测评】5、DA14531蓝牙模块数据接收


开发套件中的DA14531模块,实现蓝牙串口数据的透传,DA14531模块连接到开发板的PMOD2接口上,串口发送的数据,由DA14531模块通过蓝牙GATT服务发送蓝牙接收端,比如瑞萨推出的SmartBond App。

# 1、硬件连接

查看开发板和DA14531模块的原理图,

!(//m.qjumbo.com/forum/data/attachment/forum/202610/07/153800m39al038ev9lhy3h.png)


|DA14531模块引脚|MCU引脚|
|----|----|
|RXD|P411|
|TXD|P410|
|CONNECT|P414|
|LPR|P609|

使用DA14531模块时,需要将LPR引脚设置为GPIO Output高电平,将模块退出低功耗模式。

!(//m.qjumbo.com/forum/data/attachment/forum/202610/07/153811zo7uyf7yzprps7pp.png)


AT指令通过串口传输到DA14531模块,串口的配置参数如下

!(//m.qjumbo.com/forum/data/attachment/forum/202610/07/153817gcgjszqqb7csrbz7.png)

保存并生成配置代码。

# 2、模块驱动代码

定义BLE模块传输相关的宏定义、数据结构体以及变量和函数声明如下。

```c
#include "hal_data.h"
#include <stdbool.h>
#include <stdint.h>

#define BLE_IDENTITY_RESULT_AT       (1UL << 0)
#define BLE_IDENTITY_RESULT_VERSION(1UL << 1)
#define BLE_IDENTITY_RESULT_NAME   (1UL << 2)
#define BLE_IDENTITY_RESULT_MAC      (1UL << 3)
#define BLE_IDENTITY_RESULT_ALL      (BLE_IDENTITY_RESULT_AT      | \
                                    BLE_IDENTITY_RESULT_VERSION | \
                                    BLE_IDENTITY_RESULT_NAME    | \
                                    BLE_IDENTITY_RESULT_MAC)

#define BLE_IDENTITY_RESPONSE_SIZE   (64U)

typedef enum e_ble_transport_mode
{
    BLE_TRANSPORT_MODE_BOOT = 0,
    BLE_TRANSPORT_MODE_AT,
    BLE_TRANSPORT_MODE_TRANSPARENT,
} ble_transport_mode_t;

/* Driver state and counters intended for debugger inspection. */
extern volatile ble_transport_mode_t g_ble_mode;
extern volatile bool               g_ble_connected;
extern volatile uint32_t             g_ble_connection_change_count;
extern volatile uart_event_t         g_ble_last_uart_event;
extern volatile uint32_t             g_ble_uart_error_flags;
extern volatile fsp_err_t            g_ble_last_error;
extern volatile uint32_t             g_ble_rx_total;
extern volatile uint32_t             g_ble_tx_total;
extern volatile uint32_t             g_ble_rx_overflow_count;
extern volatile uint32_t             g_ble_tx_overflow_count;
extern volatile uint32_t             g_ble_at_timeout_count;

extern volatile uint32_t g_ble_command_success_mask;
extern volatile char   g_ble_at_response;
extern volatile char   g_ble_version_response;
extern volatile char   g_ble_name_response;
extern volatile char   g_ble_mac_response;
extern volatile uint32_t g_ble_at_response_length;
extern volatile uint32_t g_ble_version_response_length;
extern volatile uint32_t g_ble_name_response_length;
extern volatile uint32_t g_ble_mac_response_length;

fsp_err_t ble_transport_init(void);
void      ble_transport_poll(void);
bool      ble_transport_is_connected(void);
uint32_tble_transport_read(uint8_t * p_destination, uint32_t destination_size);
uint32_tble_transport_write(uint8_t const * p_source, uint32_t length);
uint32_tble_transport_rx_available(void);
bool      ble_get_byte(uint8_t *b);   /* 从BLE缓存区读取1字节 */
```

BLE模块的驱动代码如下

```c
#include "ble_transport.h"

#define BLE_RING_BUFFER_SIZE      (256U)
#define BLE_RING_BUFFER_MASK      (BLE_RING_BUFFER_SIZE - 1U)
#define BLE_UART_TX_CHUNK_SIZE      (64U)
#define BLE_AT_RX_BUFFER_SIZE       (128U)
#define BLE_MODULE_BOOT_DELAY_MS    (1000U)
#define BLE_AT_RESPONSE_TIMEOUT_MS(1000U)
#define BLE_AT_RESPONSE_QUIET_MS    (30U)
#define BLE_UART_TX_TIMEOUT_MS      (500U)

#if (0U != (BLE_RING_BUFFER_SIZE & BLE_RING_BUFFER_MASK))
#error "BLE_RING_BUFFER_SIZE must be a power of two."
#endif

volatile ble_transport_mode_t g_ble_mode                  = BLE_TRANSPORT_MODE_BOOT;
volatile bool               g_ble_connected               = false;
volatile uint32_t             g_ble_connection_change_count = 0U;
volatile uart_event_t         g_ble_last_uart_event          = (uart_event_t) 0U;
volatile uint32_t             g_ble_uart_error_flags         = 0U;
volatile fsp_err_t            g_ble_last_error               = FSP_SUCCESS;
volatile uint32_t             g_ble_rx_total               = 0U;
volatile uint32_t             g_ble_tx_total               = 0U;
volatile uint32_t             g_ble_rx_overflow_count      = 0U;
volatile uint32_t             g_ble_tx_overflow_count      = 0U;
volatile uint32_t             g_ble_at_timeout_count         = 0U;

volatile uint32_t g_ble_command_success_mask = 0U;
volatile char   g_ble_at_response      = {0};
volatile char   g_ble_version_response = {0};
volatile char   g_ble_name_response    = {0};
volatile char   g_ble_mac_response   = {0};
volatile uint32_t g_ble_at_response_length                        = 0U;
volatile uint32_t g_ble_version_response_length                     = 0U;
volatile uint32_t g_ble_name_response_length                        = 0U;
volatile uint32_t g_ble_mac_response_length                         = 0U;

static volatile uint8_tg_rx_ring;
static volatile uint32_t g_rx_head = 0U;
static volatile uint32_t g_rx_tail = 0U;
static volatile uint8_tg_tx_ring;
static volatile uint32_t g_tx_head = 0U;
static volatile uint32_t g_tx_tail = 0U;

static volatile uint8_tg_at_rx_buffer;
static volatile uint32_t g_at_rx_length = 0U;
static volatile bool   g_uart_tx_complete = false;
static volatile bool   g_uart_tx_busy   = false;
static volatile uint32_t g_uart_tx_active_length = 0U;
static uint8_t         g_uart_tx_chunk;

static uint8_t const g_at_test_command[]    = "AT?\r\n";
static uint8_t const g_at_version_command[] = "AT+VER?\r\n";
static uint8_t const g_at_name_command[]    = "AT+NAME?\r\n";
static uint8_t const g_at_mac_command[]   = "AT+MAC?\r\n";

static void ble_rx_ring_push(uint8_t data)
{
    uint32_t const head = g_rx_head;
    uint32_t const next = (head + 1U) & BLE_RING_BUFFER_MASK;

    if (next != g_rx_tail)
    {
      g_rx_ring = data;
      g_rx_head       = next;
      g_ble_rx_total++;
    }
    else
    {
      g_ble_rx_overflow_count++;
    }
}

static void ble_at_rx_clear(void)
{
    g_at_rx_length    = 0U;
    g_at_rx_buffer = 0U;
}

void ble_uart_callback(uart_callback_args_t * p_args)
{
    if (NULL == p_args)
    {
      return;
    }

    g_ble_last_uart_event = p_args->event;

    if (UART_EVENT_RX_CHAR == p_args->event)
    {
      uint8_t const data = (uint8_t) p_args->data;

      if (BLE_TRANSPORT_MODE_AT == g_ble_mode)
      {
            uint32_t const index = g_at_rx_length;

            if (index < (BLE_AT_RX_BUFFER_SIZE - 1U))
            {
                g_at_rx_buffer      = data;
                g_at_rx_length             = index + 1U;
                g_at_rx_buffer = 0U;
            }
            else
            {
                g_ble_rx_overflow_count++;
            }
      }
      else if (BLE_TRANSPORT_MODE_TRANSPARENT == g_ble_mode)
      {
            ble_rx_ring_push(data);
      }
      else
      {
            /* Ignore bytes received before the driver has selected a mode. */
      }
    }
    else if (UART_EVENT_TX_COMPLETE == p_args->event)
    {
      g_uart_tx_complete = true;

      if ((BLE_TRANSPORT_MODE_TRANSPARENT == g_ble_mode) && g_uart_tx_busy)
      {
            g_ble_tx_total          += g_uart_tx_active_length;
            g_uart_tx_active_length= 0U;
            g_uart_tx_busy         = false;
      }
    }
    else if ((UART_EVENT_ERR_PARITY == p_args->event) ||
             (UART_EVENT_ERR_FRAMING == p_args->event) ||
             (UART_EVENT_ERR_OVERFLOW == p_args->event) ||
             (UART_EVENT_BREAK_DETECT == p_args->event))
    {
      g_ble_uart_error_flags |= (uint32_t) p_args->event;
    }
    else
    {
      /* No action is required for the remaining UART events. */
    }
}

static bool ble_at_wait_for_response(void)
{
    uint32_t last_length = 0U;
    uint32_t quiet_ms    = 0U;

    for (uint32_t elapsed_ms = 0U; elapsed_ms < BLE_AT_RESPONSE_TIMEOUT_MS; elapsed_ms++)
    {
      uint32_t const current_length = g_at_rx_length;

      if (current_length != last_length)
      {
            last_length = current_length;
            quiet_ms    = 0U;
      }
      else if (current_length > 0U)
      {
            quiet_ms++;
            if (quiet_ms >= BLE_AT_RESPONSE_QUIET_MS)
            {
                return true;
            }
      }
      else
      {
            /* Still waiting for the first response byte. */
      }

      R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
    }

    return (g_at_rx_length > 0U);
}

static uint32_t ble_at_copy_response(volatile char * p_destination, uint32_t destination_size)
{
    uint32_t length = g_at_rx_length;

    if (length >= destination_size)
    {
      length = destination_size - 1U;
    }

    for (uint32_t i = 0U; i < length; i++)
    {
      p_destination = (char) g_at_rx_buffer;
    }
    p_destination = '\0';

    return length;
}

static bool ble_at_execute(uint8_t const   * p_command,
                           uint32_t            command_length,
                           volatile char   * p_response,
                           uint32_t            response_size,
                           volatile uint32_t * p_response_length,
                           uint32_t            result_bit)
{
    ble_at_rx_clear();
    g_uart_tx_complete = false;

    fsp_err_t const err = R_SCI_UART_Write(&g_uart0_ctrl, p_command, command_length);
    if (FSP_SUCCESS != err)
    {
      g_ble_last_error   = err;
      *p_response_length = 0U;
      p_response      = '\0';
      return false;
    }

    for (uint32_t elapsed_ms = 0U;
         (elapsed_ms < BLE_UART_TX_TIMEOUT_MS) && !g_uart_tx_complete;
         elapsed_ms++)
    {
      R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
    }

    if (!g_uart_tx_complete)
    {
      g_ble_last_error = FSP_ERR_TIMEOUT;
      g_ble_at_timeout_count++;
      *p_response_length = 0U;
      p_response      = '\0';
      return false;
    }

    bool const response_received = ble_at_wait_for_response();
    *p_response_length = ble_at_copy_response(p_response, response_size);

    if (response_received)
    {
      g_ble_command_success_mask |= result_bit;
    }
    else
    {
      g_ble_at_timeout_count++;
    }

    R_BSP_SoftwareDelay(50U, BSP_DELAY_UNITS_MILLISECONDS);

    return response_received;
}

static void ble_transport_update_connection(void)
{
    bsp_io_level_t level = BSP_IO_LEVEL_LOW;
    fsp_err_t const err = R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_14, &level);

    if (FSP_SUCCESS != err)
    {
      g_ble_last_error = err;
      return;
    }

    bool const connected = (BSP_IO_LEVEL_HIGH == level);
    if (connected != g_ble_connected)
    {
      g_ble_connected = connected;
      g_ble_connection_change_count++;

      if (!connected)
      {
            /* Do not transmit stale application data after the next connection. */
            g_tx_tail = g_tx_head;
      }
    }
}

fsp_err_t ble_transport_init(void)
{
    fsp_err_t err;

    g_ble_mode                  = BLE_TRANSPORT_MODE_BOOT;
    g_ble_connected               = false;
    g_ble_connection_change_count = 0U;
    g_ble_last_error            = FSP_SUCCESS;
    g_ble_uart_error_flags      = 0U;
    g_ble_rx_total                = 0U;
    g_ble_tx_total                = 0U;
    g_ble_rx_overflow_count       = 0U;
    g_ble_tx_overflow_count       = 0U;
    g_ble_at_timeout_count      = 0U;
    g_ble_command_success_mask    = 0U;
    g_rx_head = 0U;
    g_rx_tail = 0U;
    g_tx_head = 0U;
    g_tx_tail = 0U;
    g_uart_tx_busy = false;
    g_uart_tx_active_length = 0U;

    /* PMOD2 pin 9: DA14531 LPR. A high level enables the module UART. */
    err = R_IOPORT_PinCfg(&g_ioport_ctrl,
                        BSP_IO_PORT_06_PIN_09,
                        IOPORT_CFG_PORT_DIRECTION_OUTPUT | IOPORT_CFG_PORT_OUTPUT_HIGH);
    if (FSP_SUCCESS != err)
    {
      g_ble_last_error = err;
      return err;
    }

    /* PMOD2 pin 7: DA14531 CONNECT. The module drives it high while BLE is connected. */
    err = R_IOPORT_PinCfg(&g_ioport_ctrl,
                        BSP_IO_PORT_04_PIN_14,
                        IOPORT_CFG_PORT_DIRECTION_INPUT);
    if (FSP_SUCCESS != err)
    {
      g_ble_last_error = err;
      return err;
    }

    err = R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
    if (FSP_SUCCESS != err)
    {
      g_ble_last_error = err;
      return err;
    }

    g_ble_mode = BLE_TRANSPORT_MODE_AT;
    R_BSP_SoftwareDelay(BLE_MODULE_BOOT_DELAY_MS, BSP_DELAY_UNITS_MILLISECONDS);

    /* Discard the optional boot banner and read the module identity. */
    ble_at_rx_clear();

    (void) ble_at_execute(g_at_test_command,
                        (uint32_t) (sizeof(g_at_test_command) - 1U),
                        g_ble_at_response,
                        BLE_IDENTITY_RESPONSE_SIZE,
                        &g_ble_at_response_length,
                        BLE_IDENTITY_RESULT_AT);

    (void) ble_at_execute(g_at_version_command,
                        (uint32_t) (sizeof(g_at_version_command) - 1U),
                        g_ble_version_response,
                        BLE_IDENTITY_RESPONSE_SIZE,
                        &g_ble_version_response_length,
                        BLE_IDENTITY_RESULT_VERSION);

    (void) ble_at_execute(g_at_name_command,
                        (uint32_t) (sizeof(g_at_name_command) - 1U),
                        g_ble_name_response,
                        BLE_IDENTITY_RESPONSE_SIZE,
                        &g_ble_name_response_length,
                        BLE_IDENTITY_RESULT_NAME);

    (void) ble_at_execute(g_at_mac_command,
                        (uint32_t) (sizeof(g_at_mac_command) - 1U),
                        g_ble_mac_response,
                        BLE_IDENTITY_RESPONSE_SIZE,
                        &g_ble_mac_response_length,
                        BLE_IDENTITY_RESULT_MAC);

    g_rx_head= 0U;
    g_rx_tail= 0U;
    g_ble_mode = BLE_TRANSPORT_MODE_TRANSPARENT;
    ble_transport_update_connection();

    return FSP_SUCCESS;
}

uint32_t ble_transport_rx_available(void)
{
    return (g_rx_head - g_rx_tail) & BLE_RING_BUFFER_MASK;
}

uint32_t ble_transport_read(uint8_t * p_destination, uint32_t destination_size)
{
    if ((NULL == p_destination) || (0U == destination_size))
    {
      return 0U;
    }

    uint32_t count = 0U;
    while ((count < destination_size) && (g_rx_tail != g_rx_head))
    {
      uint32_t const tail = g_rx_tail;
      p_destination = g_rx_ring;
      g_rx_tail = (tail + 1U) & BLE_RING_BUFFER_MASK;
      count++;
    }

    return count;
}

static inline bool ble_buffer_get(uint8_t *b) {
    if (g_rx_head == g_rx_tail) return false; /* empty */
    *b = g_rx_ring;
    g_rx_tail = (g_rx_tail + 1) & BLE_RING_BUFFER_MASK;
    return true;
}

bool      ble_get_byte(uint8_t *b)   /* 从g_rx_ring取1字节 */
{
    return ble_buffer_get(b);
}

uint32_t ble_transport_write(uint8_t const * p_source, uint32_t length)
{
    if ((NULL == p_source) || (0U == length) || !g_ble_connected)
    {
      return 0U;
    }

    uint32_t queued = 0U;
    while (queued < length)
    {
      uint32_t const head = g_tx_head;
      uint32_t const next = (head + 1U) & BLE_RING_BUFFER_MASK;

      if (next == g_tx_tail)
      {
            break;
      }

      g_tx_ring = p_source;
      g_tx_head       = next;
      queued++;
    }

    g_ble_tx_overflow_count += length - queued;

    return queued;
}

static void ble_transport_start_next_tx(void)
{
    if (g_uart_tx_busy || !g_ble_connected || (g_tx_tail == g_tx_head))
    {
      return;
    }

    uint32_t length = 0U;
    while ((length < BLE_UART_TX_CHUNK_SIZE) && (g_tx_tail != g_tx_head))
    {
      uint32_t const tail = g_tx_tail;
      g_uart_tx_chunk = g_tx_ring;
      g_tx_tail = (tail + 1U) & BLE_RING_BUFFER_MASK;
      length++;
    }

    g_uart_tx_active_length = length;
    g_uart_tx_complete      = false;
    g_uart_tx_busy          = true;

    fsp_err_t const err = R_SCI_UART_Write(&g_uart0_ctrl, g_uart_tx_chunk, length);
    if (FSP_SUCCESS != err)
    {
      g_ble_last_error         = err;
      g_ble_tx_overflow_count += length;
      g_uart_tx_active_length= 0U;
      g_uart_tx_busy         = false;
    }
}

void ble_transport_poll(void)
{
    ble_transport_update_connection();
    ble_transport_start_next_tx();
}

bool ble_transport_is_connected(void)
{
    return g_ble_connected;
}
```

# 3、DA14531模块数据Echo

以下代码实现接收DA14531模块的初始化,通过检测Connect引脚的状态判断模块是否与手机APP连接,接收来自DA14531的数据并将接收的数据发送给手机APP显示。

```c
#include "hal_data.h"
#include "ble_transport.h"
#include <stdbool.h>
#include "common_utils.h"

/*
* RAECO4M2 V2.0 + DA14531 application bring-up.
*
* LED1:      P405, active high.
* BLE UART:    SCI0, P411/TXD0, P410/RXD0, 115200 8N1.
* BLE LPR:   P609, output high.
* BLE CONNECT: P414, input; high while a phone is connected.
*
* The application echoes every byte received from the phone back through the
* DA14531. Enable notifications for CodeLess Outbound Command in SmartBond.
*/

typedef enum e_diagnostic_reason
{
    DIAGNOSTIC_REASON_NONE          = 0,
    DIAGNOSTIC_REASON_LED_PIN_CFG   = 1,
    DIAGNOSTIC_REASON_CPU_EXCEPTION = 2,
    DIAGNOSTIC_REASON_BLE_INIT      = 3,
} diagnostic_reason_t;

#define APP_ECHO_BUFFER_SIZE (64U)
#define APP_LED_BLINK_MS   (500U)

volatile diagnostic_reason_t g_diagnostic_reason = DIAGNOSTIC_REASON_NONE;
volatile fsp_err_t            g_diagnostic_error= FSP_SUCCESS;
volatile uint32_t             g_fault_exception   = 0U;
volatile uint32_t             g_fault_cfsr      = 0U;
volatile uint32_t             g_fault_hfsr      = 0U;
volatile uint32_t             g_fault_dfsr      = 0U;
volatile uint32_t             g_fault_mmfar       = 0U;
volatile uint32_t             g_fault_bfar      = 0U;

/* Application state intended for debugger inspection. */
volatile bool   g_app_ble_identity_ok       = false;
volatile bool   g_app_ble_connected         = false;
volatile uint8_tg_app_last_rx_data = {0U};
volatile uint32_t g_app_last_rx_length         = 0U;
volatile uint32_t g_app_rx_message_count       = 0U;
volatile uint32_t g_app_echo_queued_total      = 0U;
volatile uint32_t g_app_echo_dropped_total   = 0U;

void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SecureFault_Handler(void);

static void diagnostic_stop(diagnostic_reason_t reason, fsp_err_t error)
{
    g_diagnostic_reason = reason;
    g_diagnostic_error= error;

    if (0U != (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk))
    {
      __BKPT(0);
    }

    while (1)
    {
      __NOP();
    }
}

static void cpu_exception_stop(void)
{
    g_fault_exception = SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk;
    g_fault_cfsr      = SCB->CFSR;
    g_fault_hfsr      = SCB->HFSR;
    g_fault_dfsr      = SCB->DFSR;
    g_fault_mmfar   = SCB->MMFAR;
    g_fault_bfar      = SCB->BFAR;

    diagnostic_stop(DIAGNOSTIC_REASON_CPU_EXCEPTION, FSP_ERR_ASSERTION);
}

void HardFault_Handler(void)
{
    cpu_exception_stop();
}

void MemManage_Handler(void)
{
    cpu_exception_stop();
}

void BusFault_Handler(void)
{
    cpu_exception_stop();
}

void UsageFault_Handler(void)
{
    cpu_exception_stop();
}

void SecureFault_Handler(void)
{
    cpu_exception_stop();
}

void hal_entry(void)
{
    fsp_err_t err;
    uint8_t   echo_buffer;
    bool      led_level      = false;
    uint32_tled_elapsed_ms = 0U;

    /* IOPORT is opened by R_BSP_WarmStart() before main() is called. */
    err = R_IOPORT_PinCfg(&g_ioport_ctrl,
                        BSP_IO_PORT_04_PIN_05,
                        IOPORT_CFG_PORT_DIRECTION_OUTPUT | IOPORT_CFG_PORT_OUTPUT_LOW);
    if (FSP_SUCCESS != err)
    {
      diagnostic_stop(DIAGNOSTIC_REASON_LED_PIN_CFG, err);
    }

    err = ble_transport_init();
    if (FSP_SUCCESS != err)
    {
      diagnostic_stop(DIAGNOSTIC_REASON_BLE_INIT, err);
    }

    g_app_ble_identity_ok = (BLE_IDENTITY_RESULT_ALL == g_ble_command_success_mask);

    while (1)
    {
      ble_transport_poll();
      g_app_ble_connected = ble_transport_is_connected();

      uint32_t const received = ble_transport_read(echo_buffer, sizeof(echo_buffer));
      if (received > 0U)
      {
            for (uint32_t i = 0U; i < received; i++)
            {
                g_app_last_rx_data = echo_buffer;
            }
            g_app_last_rx_data = 0U;
            g_app_last_rx_length         = received;
            g_app_rx_message_count++;

            uint32_t const queued = ble_transport_write(echo_buffer, received);
            g_app_echo_queued_total+= queued;
            g_app_echo_dropped_total += received - queued;
      }

      if (g_app_ble_connected)
      {
            led_level      = true;
            led_elapsed_ms = 0U;
      }
      else
      {
            led_elapsed_ms++;
            if (led_elapsed_ms >= APP_LED_BLINK_MS)
            {
                led_elapsed_ms = 0U;
                led_level      = !led_level;
            }
      }

      (void) R_IOPORT_PinWrite(&g_ioport_ctrl,
                                 BSP_IO_PORT_04_PIN_05,
                                 led_level ? BSP_IO_LEVEL_HIGH : BSP_IO_LEVEL_LOW);

      R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
    }
}
```

在手机上运行SmartConfig软件,通过其中的Codeless Inbound GATT发送数据,在Codeless Outbound GATT接收数据,通过发送和接收的数据对比,确认程序功能实现正常。

!(//m.qjumbo.com/forum/data/attachment/forum/202610/07/153846qkkzgiupzgpgiduq.png)

页: [1]
查看完整版本: 【瑞萨BLE/WIFI模块测评】5、DA14531蓝牙模块数据接收

Baidu
map