BT04A蓝牙模块驱动库 - 轻量级、跨平台的嵌入式蓝牙解决方案
BT04A模块简介
BT04A是一款基于蓝牙4.0协议的经典串口透传模块,以其稳定性高、成本低廉、使用简单等特点在嵌入式领域广受欢迎。该模块采用CSR主流蓝牙芯片,支持SPP蓝牙串口协议,能够为传统设备快速添加无线通信功能。
模块特性
-
蓝牙版本: 蓝牙4.0,兼容蓝牙2.1/3.0设备
-
工作模式: 支持主从模式一体,可通过AT命令切换
-
传输距离: 空旷环境下可达10米以上
-
接口类型: UART串口接口,支持1200-115200bps波特率
-
供电电压: 3.3V DC,低功耗设计
-
工作温度: -40℃ ~ +85℃,工业级稳定性
典型应用
-
工业设备数据无线传输
-
智能家居控制模块
-
医疗仪器数据采集
-
车载设备通信
-
教学实验设备
驱动库概述
本驱动库为BT04A蓝牙模块提供了完整的嵌入式软件解决方案,采用硬件抽象层设计,支持多种MCU平台,提供简单易用的API接口。
主要特性
🔧 核心功能
-
双模式支持: 同时支持主模式(Master)和从模式(Slave)工作
-
灵活配置: 支持设备名称、PIN码、波特率等参数动态配置
-
AT命令集: 完整的AT命令控制接口,支持模块所有功能配置
🚀 性能优势
-
轻量级设计: 代码体积小,资源占用低,适合资源受限的嵌入式环境
-
超时重试: 内置超时检测和自动重试机制,提高通信可靠性
-
异步处理: 非阻塞式设计,支持在实时操作系统中使用
🔌 硬件抽象
-
平台无关: 通过回调函数机制实现与硬件平台的解耦
-
引脚抽象: 统一的GPIO控制接口,支持多种MCU架构
-
串口适配: 灵活的串口数据传输接口,易于集成到现有项目
快速开始
1. 初始化操作接口
// 定义操作回调函数
bt04a_ops_t ops = {
.send_data = uart_send_data,
.receive_data = uart_receive_data,
.delay_ms = hal_delay_ms,
.clear_rx_data = uart_clear_rx,
.set_pin = gpio_set_pin,
.read_pin = gpio_read_pin
};
// 初始化操作接口
bt04a_ops_init(&ops);
2. 配置模块参数
// 模块配置
bt04a_config_t config = {
.device_name = "MyBT04A",
.pin_code = "1234",
.baudrate = BT04A_BAUD_9600,
.mode = BT04A_MODE_SLAVE,
.en_port = GPIOA,
.en_pin = GPIO_PIN_0,
.state_port = GPIOA,
.state_pin = GPIO_PIN_1,
.response_timeout_ms = 1000,
.command_delay_ms = 100
};
// 初始化模块
bt04a_init(&config);
3. 数据收发示例
// 发送数据
uint8_t data[] = "Hello Bluetooth!";
bt04a_send_data(data, strlen(data));
// 接收数据
uint8_t buffer[256];
uint16_t len = bt04a_receive_data(buffer, sizeof(buffer));
// 格式化输出
bt04a_printf("Temperature: %.2f C\r\n", temperature);
API功能分类
初始化管理
-
bt04a_ops_init()- 初始化操作回调函数 -
bt04a_init()- 初始化蓝牙模块 -
bt04a_deinit()- 释放模块资源
配置管理
-
bt04a_set_name()- 设置设备名称 -
bt04a_set_pin()- 设置PIN码 -
bt04a_set_baudrate()- 设置通信波特率 -
bt04a_set_mode()- 设置主从模式
状态监控
-
bt04a_get_connection_state()- 获取连接状态 -
bt04a_is_connected()- 检查连接状态 -
bt04a_test_connection()- 测试模块连接
数据通信
-
bt04a_send_data()- 发送原始数据 -
bt04a_send_string()- 发送字符串 -
bt04a_printf()- 格式化发送 -
bt04a_receive_data()- 接收数据
-
bt04a_test_connection()- 测试模块连接
架构改进建议
本例使用的是静态全局变量的设计模式,优点是使用比较简单,缺点也很明显发,一次只能使用一个实例并且存在线程不安全的隐患等等。对于改进建议可以把函数改成传入句柄结构体的方式,把操作结构体和配置结构体合并。
源代码及其使用示例
驱动源文件
/**
******************************************************************************
* @file bt04a_driver.c
* @author
* @brief BT04A蓝牙模块驱动源文件
* @version V2.0.0
* @date 2025
******************************************************************************
* @attention
*
* 本文件实现BT04A蓝牙模块的完整驱动功能,包括:
*
* 基础功能实现:
* - AT指令测试和模块检测
* - 工作模式设置(主从模式)
* - 设备名称和PIN码配置
* - 波特率设置和验证
* - 模块初始化和去初始化
*
* 连接管理实现:
* - 连接状态检测和监控
* - 配对过程管理
* - 连接建立和断开处理
*
* AT命令处理实现:
* - AT指令封装和发送
* - 响应数据解析和验证
* - 超时处理和错误重试
* - 状态检测和反馈
*
* 硬件控制实现:
* - 使能引脚控制
* - 状态引脚读取
* - 模块复位功能
*
* 主要特性:
* - 支持主从模式工作
* - 灵活的回调函数机制
* - 完整的错误处理和重试
* - 统一的API接口实现
* - 高效的数据传输支持
* - 与底层HAL库完全解耦
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdbool.h>
#include "bt04a_driver.h"
#include "debug_log.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup BT04A_AT_Commands BT04A AT命令定义
* @{
*/
#define BT04A_AT_TEST "AT" /*!< AT测试命令 */
#define BT04A_AT_NAME "AT+NAME" /*!< 设置设备名称命令 */
#define BT04A_AT_PIN "AT+PIN" /*!< 设置PIN码命令 */
#define BT04A_AT_BAUD "AT+BAUD" /*!< 设置波特率命令 */
#define BT04A_AT_ROLE "AT+ROLE" /*!< 设置工作模式命令 */
#define BT04A_AT_VERSION "AT+VERSION" /*!< 查询版本信息命令 */
#define BT04A_AT_RESET "AT+RESET" /*!< 复位命令 */
#define BT04A_AT_ORGL "AT+ORGL" /*!< 恢复出厂设置命令 */
/**
* @}
*/
/** @defgroup BT04A_AT_Responses BT04A AT响应定义
* @{
*/
#define BT04A_RESPONSE_OK "OK" /*!< 成功响应 */
#define BT04A_RESPONSE_ERROR "ERROR" /*!< 错误响应 */
#define BT04A_RESPONSE_FAIL "FAIL" /*!< 失败响应 */
/**
* @}
*/
/** @defgroup BT04A_Debug_Config BT04A调试配置
* @{
*/
#if !defined(LOG_INFO)
#define LOG_INFO(...) ((void)0)
#endif
#if !defined(LOG_ERROR)
#define LOG_ERROR(...) ((void)0)
#endif
/**
* @}
*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/** @defgroup BT04A_Private_Variables BT04A私有变量
* @{
*/
static bt04a_ops_t g_bt04a_ops; /*!< BT04A操作回调函数结构体 */
static bt04a_config_t g_bt04a_config; /*!< BT04A配置结构体 */
static bool g_bt04a_initialized = false; /*!< BT04A初始化标志 */
/**
* @}
*/
/* Exported variables --------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static bt04a_result_t bt04a_send_at_command(const char *cmd, char *response, uint16_t timeout_ms);
static bt04a_result_t bt04a_at_test(void);
static bt04a_result_t bt04a_set_role_internal(bt04a_mode_t mode);
static bt04a_result_t bt04a_set_baudrate_internal(bt04a_baudrate_t baudrate);
static bt04a_result_t bt04a_set_name_internal(const char *name);
static bt04a_result_t bt04a_set_pin_internal(const char *pin);
static bool bt04a_check_response(const char *response, const char *expected);
static void bt04a_hardware_enable(bool enable);
static bool bt04a_read_state_pin(void);
/* Exported functions --------------------------------------------------------*/
/** @defgroup BT04A_Exported_Functions BT04A导出函数
* @{
*/
/** @defgroup BT04A_Init_Functions BT04A初始化函数
* @{
*/
/**
* @brief 初始化BT04A操作回调函数
* @param ops: 回调函数结构体指针
* @retval BT04A_OK: 初始化成功, BT04A_ERROR: 初始化失败
* @note 必须在使用BT04A其他功能前调用此函数配置底层操作接口
*/
bt04a_result_t bt04a_ops_init(bt04a_ops_t *ops)
{
if (ops == NULL)
{
return BT04A_ERROR;
}
// 检查必要的回调函数是否存在
if (ops->send_data == NULL || ops->receive_data == NULL || ops->delay_ms == NULL)
{
return BT04A_ERROR;
}
// 复制回调函数
g_bt04a_ops.send_data = ops->send_data;
g_bt04a_ops.receive_data = ops->receive_data;
g_bt04a_ops.delay_ms = ops->delay_ms;
g_bt04a_ops.clear_rx_data = ops->clear_rx_data;
g_bt04a_ops.set_pin = ops->set_pin;
g_bt04a_ops.read_pin = ops->read_pin;
return BT04A_OK;
}
/**
* @brief 初始化BT04A蓝牙模块
* @param config: 配置结构体指针
* @retval BT04A_OK: 初始化成功, BT04A_ERROR: 初始化失败
* @note 初始化BT04A模块并配置相关参数
*/
bt04a_result_t bt04a_init(const bt04a_config_t *config)
{
if (config == NULL)
{
LOG_ERROR("BT04A配置参数为空\r\n");
return BT04A_ERROR;
}
// 检查回调函数是否已初始化
if (g_bt04a_ops.send_data == NULL)
{
LOG_ERROR("BT04A回调函数未初始化\r\n");
return BT04A_ERROR;
}
LOG_INFO("BT04A初始化开始...\r\n");
// 复制配置参数
memcpy(&g_bt04a_config, config, sizeof(bt04a_config_t));
// 硬件使能
bt04a_hardware_enable(true);
g_bt04a_ops.delay_ms(100);
// 清除接收缓冲区
if (g_bt04a_ops.clear_rx_data != NULL)
{
g_bt04a_ops.clear_rx_data();
}
// 测试AT命令
LOG_INFO("1. 测试BT04A是否响应...\r\n");
if (bt04a_at_test() != BT04A_OK)
{
LOG_ERROR("BT04A AT测试失败\r\n");
return BT04A_ERROR;
}
// 设置工作模式
LOG_INFO("2. 设置工作模式...\r\n");
// 有些模块无法设置模式
// if (bt04a_set_role_internal(config->mode) != BT04A_OK)
// {
// LOG_ERROR("BT04A工作模式设置失败\r\n");
// return BT04A_ERROR;
// }
// 设置设备名称
LOG_INFO("3. 设置设备名称...\r\n");
if (bt04a_set_name_internal(config->device_name) != BT04A_OK)
{
LOG_ERROR("BT04A设备名称设置失败\r\n");
return BT04A_ERROR;
}
// 设置PIN码
LOG_INFO("4. 设置PIN码...\r\n");
if (bt04a_set_pin_internal(config->pin_code) != BT04A_OK)
{
LOG_ERROR("BT04A PIN码设置失败\r\n");
return BT04A_ERROR;
}
// 设置波特率
LOG_INFO("5. 设置波特率...\r\n");
if (bt04a_set_baudrate_internal(config->baudrate) != BT04A_OK)
{
LOG_ERROR("BT04A波特率设置失败\r\n");
return BT04A_ERROR;
}
g_bt04a_initialized = true;
LOG_INFO("BT04A初始化完成\r\n");
return BT04A_OK;
}
/**
* @brief 去初始化BT04A蓝牙模块
* @param 无
* @retval BT04A_OK: 去初始化成功
* @note 关闭BT04A模块并清理资源
*/
bt04a_result_t bt04a_deinit(void)
{
// 硬件禁用
bt04a_hardware_enable(false);
// 清除初始化标志
g_bt04a_initialized = false;
// 清零配置
memset(&g_bt04a_config, 0, sizeof(bt04a_config_t));
LOG_INFO("BT04A去初始化完成\r\n");
return BT04A_OK;
}
/**
* @}
*/
/** @defgroup BT04A_Config_Functions BT04A配置函数
* @{
*/
/**
* @brief 设置BT04A设备名称
* @param name: 设备名称字符串
* @retval BT04A_OK: 设置成功, BT04A_ERROR: 设置失败
* @note 设置BT04A的蓝牙设备名称
*/
bt04a_result_t bt04a_set_name(const char *name)
{
if (!g_bt04a_initialized || name == NULL)
{
return BT04A_ERROR;
}
if (strlen(name) >= BT04A_MAX_NAME_LEN)
{
return BT04A_ERROR;
}
bt04a_result_t result = bt04a_set_name_internal(name);
if (result == BT04A_OK)
{
strcpy(g_bt04a_config.device_name, name);
}
return result;
}
/**
* @brief 设置BT04A PIN码
* @param pin: PIN码字符串
* @retval BT04A_OK: 设置成功, BT04A_ERROR: 设置失败
* @note 设置BT04A的配对PIN码
*/
bt04a_result_t bt04a_set_pin(const char *pin)
{
if (!g_bt04a_initialized || pin == NULL)
{
return BT04A_ERROR;
}
if (strlen(pin) >= BT04A_MAX_PIN_LEN)
{
return BT04A_ERROR;
}
bt04a_result_t result = bt04a_set_pin_internal(pin);
if (result == BT04A_OK)
{
strcpy(g_bt04a_config.pin_code, pin);
}
return result;
}
/**
* @brief 设置BT04A波特率
* @param baudrate: 波特率枚举值
* @retval BT04A_OK: 设置成功, BT04A_ERROR: 设置失败
* @note 设置BT04A的通信波特率
*/
bt04a_result_t bt04a_set_baudrate(bt04a_baudrate_t baudrate)
{
if (!g_bt04a_initialized)
{
return BT04A_ERROR;
}
bt04a_result_t result = bt04a_set_baudrate_internal(baudrate);
if (result == BT04A_OK)
{
g_bt04a_config.baudrate = baudrate;
}
return result;
}
/**
* @brief 设置BT04A工作模式
* @param mode: 工作模式枚举值
* @retval BT04A_OK: 设置成功, BT04A_ERROR: 设置失败
* @note 设置BT04A的主从工作模式
*/
bt04a_result_t bt04a_set_mode(bt04a_mode_t mode)
{
if (!g_bt04a_initialized)
{
return BT04A_ERROR;
}
bt04a_result_t result = bt04a_set_role_internal(mode);
if (result == BT04A_OK)
{
g_bt04a_config.mode = mode;
}
return result;
}
/**
* @brief 获取BT04A当前配置
* @param config: 配置结构体指针
* @retval BT04A_OK: 获取成功, BT04A_ERROR: 获取失败
* @note 获取BT04A的当前配置参数
*/
bt04a_result_t bt04a_get_config(bt04a_config_t *config)
{
if (!g_bt04a_initialized || config == NULL)
{
return BT04A_ERROR;
}
memcpy(config, &g_bt04a_config, sizeof(bt04a_config_t));
return BT04A_OK;
}
/**
* @}
*/
/** @defgroup BT04A_Control_Functions BT04A控制函数
* @{
*/
/**
* @brief 进入AT命令模式
* @param 无
* @retval BT04A_OK: 进入成功, BT04A_ERROR: 进入失败
* @note 使BT04A进入AT命令配置模式
*/
bt04a_result_t bt04a_enter_at_mode(void)
{
if (!g_bt04a_initialized)
{
return BT04A_ERROR;
}
// BT04A默认就在AT模式,只需要测试连接
return bt04a_at_test();
}
/**
* @brief 退出AT命令模式
* @param 无
* @retval BT04A_OK: 退出成功
* @note 使BT04A退出AT命令模式进入数据传输模式
*/
bt04a_result_t bt04a_exit_at_mode(void)
{
if (!g_bt04a_initialized)
{
return BT04A_ERROR;
}
// BT04A在没有连接时自动处于AT模式,连接后自动进入数据模式
return BT04A_OK;
}
/**
* @brief 复位BT04A模块
* @param 无
* @retval BT04A_OK: 复位成功, BT04A_ERROR: 复位失败
* @note 软件复位BT04A模块
*/
bt04a_result_t bt04a_reset(void)
{
if (!g_bt04a_initialized)
{
return BT04A_ERROR;
}
char response[64];
bt04a_result_t result = bt04a_send_at_command(BT04A_AT_RESET, response, g_bt04a_config.response_timeout_ms);
if (result == BT04A_OK)
{
// 复位后需要等待模块重新启动
g_bt04a_ops.delay_ms(1000);
LOG_INFO("BT04A复位完成\r\n");
}
return result;
}
/**
* @brief 使能/禁用BT04A模块
* @param enable: true-使能, false-禁用
* @retval BT04A_OK: 操作成功, BT04A_ERROR: 操作失败
* @note 通过硬件引脚控制BT04A模块的使能状态
*/
bt04a_result_t bt04a_enable(bool enable)
{
if (!g_bt04a_initialized)
{
return BT04A_ERROR;
}
bt04a_hardware_enable(enable);
if (enable)
{
g_bt04a_ops.delay_ms(100); // 使能后等待模块启动
LOG_INFO("BT04A模块已使能\r\n");
}
else
{
LOG_INFO("BT04A模块已禁用\r\n");
}
return BT04A_OK;
}
/**
* @}
*/
/** @defgroup BT04A_Status_Functions BT04A状态函数
* @{
*/
/**
* @brief 获取BT04A连接状态
* @param 无
* @retval bt04a_state_t: 连接状态枚举值
* @note 通过状态引脚读取BT04A的连接状态
*/
bt04a_state_t bt04a_get_connection_state(void)
{
if (!g_bt04a_initialized)
{
return BT04A_STATE_UNKNOWN;
}
// 通过状态引脚读取连接状态
if (bt04a_read_state_pin())
{
return BT04A_STATE_CONNECTED;
}
else
{
return BT04A_STATE_DISCONNECTED;
}
}
/**
* @brief 测试BT04A连接
* @param 无
* @retval BT04A_OK: 连接正常, BT04A_ERROR: 连接异常
* @note 通过AT命令测试BT04A模块的连接状态
*/
bt04a_result_t bt04a_test_connection(void)
{
if (!g_bt04a_initialized)
{
return BT04A_ERROR;
}
return bt04a_at_test();
}
/**
* @brief 检查BT04A是否已连接
* @param 无
* @retval true: 已连接, false: 未连接
* @note 检查BT04A是否与其他设备建立了蓝牙连接
*/
bool bt04a_is_connected(void)
{
return (bt04a_get_connection_state() == BT04A_STATE_CONNECTED);
}
/**
* @}
*/
/** @defgroup BT04A_Data_Functions BT04A数据函数
* @{
*/
/**
* @brief 发送数据
* @param data: 数据缓冲区指针
* @param len: 数据长度
* @retval BT04A_OK: 发送成功, BT04A_ERROR: 发送失败
* @note 通过BT04A发送数据
*/
bt04a_result_t bt04a_send_data(const uint8_t *data, uint16_t len)
{
if (!g_bt04a_initialized || data == NULL || len == 0)
{
return BT04A_ERROR;
}
g_bt04a_ops.send_data(data, len);
return BT04A_OK;
}
/**
* @brief 发送字符串
* @param string: 字符串指针
* @retval BT04A_OK: 发送成功, BT04A_ERROR: 发送失败
* @note 通过BT04A发送字符串数据
*/
bt04a_result_t bt04a_send_string(const char *string)
{
if (!g_bt04a_initialized || string == NULL)
{
return BT04A_ERROR;
}
uint16_t len = strlen(string);
return bt04a_send_data((const uint8_t *)string, len);
}
/**
* @brief 通过BT04A蓝牙模块发送格式化字符串
* @param format: 格式化字符串
* @param ...: 可变参数列表
* @retval 发送的字符数,失败返回-1
* @note 类似printf函数,将格式化后的字符串通过蓝牙发送
*/
int bt04a_printf(const char *format, ...)
{
char buffer[256]; // 定义缓冲区,根据需要调整大小
va_list args;
int len;
if (!g_bt04a_initialized || format == NULL)
{
return -1;
}
// 格式化字符串
va_start(args, format);
len = vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
// 检查格式化是否成功
if (len < 0 || len >= sizeof(buffer))
{
return -1;
}
// 通过BT04A发送字符串
if (bt04a_send_string(buffer) == BT04A_OK)
{
return len;
}
else
{
return -1;
}
}
/**
* @brief 接收数据
* @param buffer: 接收缓冲区指针
* @param max_len: 缓冲区最大长度
* @retval 实际接收的数据长度
* @note 从BT04A接收数据
*/
uint16_t bt04a_receive_data(uint8_t *buffer, uint16_t max_len)
{
if (!g_bt04a_initialized || buffer == NULL || max_len == 0)
{
return 0;
}
return g_bt04a_ops.receive_data(buffer, max_len);
}
/**
* @brief 清除接收缓冲区
* @param 无
* @retval 无
* @note 清除BT04A的接收缓冲区
*/
void bt04a_clear_buffer(void)
{
if (g_bt04a_initialized && g_bt04a_ops.clear_rx_data != NULL)
{
g_bt04a_ops.clear_rx_data();
}
}
/**
* @}
*/
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief 发送AT命令并等待响应
* @param cmd: AT命令字符串
* @param response: 响应缓冲区
* @param timeout_ms: 超时时间(毫秒)
* @retval BT04A_OK: 命令执行成功, BT04A_ERROR: 命令执行失败, BT04A_TIMEOUT: 超时
* @note 发送AT命令到BT04A并等待响应
*/
static bt04a_result_t bt04a_send_at_command(const char *cmd, char *response, uint16_t timeout_ms)
{
if (cmd == NULL)
{
return BT04A_ERROR;
}
// 清除接收缓冲区
if (g_bt04a_ops.clear_rx_data != NULL)
{
g_bt04a_ops.clear_rx_data();
}
// 发送AT命令
char at_cmd[64];
snprintf(at_cmd, sizeof(at_cmd), "%s\r\n", cmd);
g_bt04a_ops.send_data((const uint8_t *)at_cmd, strlen(at_cmd));
// 等待响应
uint32_t start_time = 0;
uint16_t received_len = 0;
uint8_t g_bt04a_rx_buffer[BT04A_BUFFER_SIZE] = {0};
while (start_time < timeout_ms)
{
received_len = g_bt04a_ops.receive_data(g_bt04a_rx_buffer, BT04A_BUFFER_SIZE - 1);
if (received_len > 0)
{
g_bt04a_rx_buffer[received_len] = '\0';
if (response != NULL)
{
strcpy(response, (char *)g_bt04a_rx_buffer);
}
// 检查响应
if (bt04a_check_response((char *)g_bt04a_rx_buffer, BT04A_RESPONSE_OK))
{
return BT04A_OK;
}
else if (bt04a_check_response((char *)g_bt04a_rx_buffer, BT04A_RESPONSE_ERROR) ||
bt04a_check_response((char *)g_bt04a_rx_buffer, BT04A_RESPONSE_FAIL))
{
return BT04A_ERROR;
}
}
g_bt04a_ops.delay_ms(10);
start_time += 10;
}
return BT04A_TIMEOUT;
}
/**
* @brief AT测试命令
* @param 无
* @retval BT04A_OK: 测试成功, BT04A_ERROR: 测试失败
* @note 发送AT测试命令检查模块响应
*/
static bt04a_result_t bt04a_at_test(void)
{
char response[64];
return bt04a_send_at_command(BT04A_AT_TEST, response, g_bt04a_config.response_timeout_ms);
}
/**
* @brief 设置工作模式内部函数
* @param mode: 工作模式
* @retval BT04A_OK: 设置成功, BT04A_ERROR: 设置失败
* @note 内部函数,设置BT04A的工作模式
*/
static bt04a_result_t bt04a_set_role_internal(bt04a_mode_t mode)
{
char cmd[32];
char response[64];
snprintf(cmd, sizeof(cmd), "%s%d", BT04A_AT_ROLE, (int)mode);
bt04a_result_t result = bt04a_send_at_command(cmd, response, g_bt04a_config.response_timeout_ms);
if (result == BT04A_OK)
{
g_bt04a_ops.delay_ms(g_bt04a_config.command_delay_ms);
}
return result;
}
/**
* @brief 设置波特率内部函数
* @param baudrate: 波特率
* @retval BT04A_OK: 设置成功, BT04A_ERROR: 设置失败
* @note 内部函数,设置BT04A的波特率
*/
static bt04a_result_t bt04a_set_baudrate_internal(bt04a_baudrate_t baudrate)
{
char cmd[32];
char response[64];
int baud_code;
// 将波特率转换为BT04A的编码
switch (baudrate)
{
case BT04A_BAUD_1200:
baud_code = 1;
break;
case BT04A_BAUD_2400:
baud_code = 2;
break;
case BT04A_BAUD_4800:
baud_code = 3;
break;
case BT04A_BAUD_9600:
baud_code = 4;
break;
case BT04A_BAUD_19200:
baud_code = 5;
break;
case BT04A_BAUD_38400:
baud_code = 6;
break;
case BT04A_BAUD_57600:
baud_code = 7;
break;
case BT04A_BAUD_115200:
baud_code = 8;
break;
default:
return BT04A_ERROR;
}
snprintf(cmd, sizeof(cmd), "%s%d", BT04A_AT_BAUD, baud_code);
bt04a_result_t result = bt04a_send_at_command(cmd, response, g_bt04a_config.response_timeout_ms);
if (result == BT04A_OK)
{
g_bt04a_ops.delay_ms(g_bt04a_config.command_delay_ms);
}
return result;
}
/**
* @brief 设置设备名称内部函数
* @param name: 设备名称
* @retval BT04A_OK: 设置成功, BT04A_ERROR: 设置失败
* @note 内部函数,设置BT04A的设备名称
*/
static bt04a_result_t bt04a_set_name_internal(const char *name)
{
char cmd[64];
char response[64];
snprintf(cmd, sizeof(cmd), "%s%s", BT04A_AT_NAME, name);
bt04a_result_t result = bt04a_send_at_command(cmd, response, g_bt04a_config.response_timeout_ms);
if (result == BT04A_OK)
{
g_bt04a_ops.delay_ms(g_bt04a_config.command_delay_ms);
}
return result;
}
/**
* @brief 设置PIN码内部函数
* @param pin: PIN码
* @retval BT04A_OK: 设置成功, BT04A_ERROR: 设置失败
* @note 内部函数,设置BT04A的PIN码
*/
static bt04a_result_t bt04a_set_pin_internal(const char *pin)
{
char cmd[32];
char response[64];
snprintf(cmd, sizeof(cmd), "%s%s", BT04A_AT_PIN, pin);
bt04a_result_t result = bt04a_send_at_command(cmd, response, g_bt04a_config.response_timeout_ms);
if (result == BT04A_OK)
{
g_bt04a_ops.delay_ms(g_bt04a_config.command_delay_ms);
}
return result;
}
/**
* @brief 检查AT命令响应
* @param response: 响应字符串
* @param expected: 期望的响应
* @retval true: 响应匹配, false: 响应不匹配
* @note 检查AT命令的响应是否符合预期
*/
static bool bt04a_check_response(const char *response, const char *expected)
{
if (response == NULL || expected == NULL)
{
return false;
}
return (strstr(response, expected) != NULL);
}
/**
* @brief 硬件使能控制
* @param enable: true-使能, false-禁用
* @retval 无
* @note 通过硬件引脚控制BT04A模块的使能状态
*/
static void bt04a_hardware_enable(bool enable)
{
if (g_bt04a_ops.set_pin != NULL && g_bt04a_config.en_port != NULL)
{
g_bt04a_ops.set_pin(g_bt04a_config.en_port, g_bt04a_config.en_pin, enable);
}
}
/**
* @brief 读取状态引脚
* @param 无
* @retval true: 高电平, false: 低电平
* @note 读取BT04A模块的状态引脚电平
*/
static bool bt04a_read_state_pin(void)
{
if (g_bt04a_ops.read_pin != NULL && g_bt04a_config.state_port != NULL)
{
return g_bt04a_ops.read_pin(g_bt04a_config.state_port, g_bt04a_config.state_pin);
}
return false;
}
驱动头文件
/**
******************************************************************************
* @file bt04a_driver.h
* @author
* @brief BT04A蓝牙模块驱动头文件
* @version V2.0.0
* @date 2025
******************************************************************************
* @attention
*
* 本文件提供BT04A蓝牙模块的完整驱动接口,支持以下功能:
*
* 基础功能:
* - 蓝牙模块初始化与配置
* - AT命令模式控制
* - 设备名称和PIN码设置
* - 波特率配置
* - 工作模式设置(主从模式)
*
* 连接管理:
* - 连接状态检测
* - 配对管理
* - 连接建立与断开
*
* 硬件控制:
* - 使能引脚控制
* - 状态引脚检测
* - 模块复位功能
*
* 主要特性:
* - 支持主从模式工作
* - 灵活的回调函数机制
* - 完整的错误处理
* - 统一的API接口设计
* - 与底层HAL库解耦
*
******************************************************************************
*/
#ifndef _BT04A_DRIVER_H
#define _BT04A_DRIVER_H
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
/* Exported types ------------------------------------------------------------*/
/**
* @brief BT04A操作回调函数结构体
* @note 用于配置BT04A模块的底层操作接口
*/
typedef struct
{
void (*send_data)(const uint8_t *p_data, uint16_t size); /*!< 数据发送函数指针 */
uint16_t (*receive_data)(uint8_t *p_data, uint16_t size); /*!< 数据接收函数指针 */
void (*delay_ms)(uint32_t ms); /*!< 毫秒延时函数指针 */
void (*clear_rx_data)(void); /*!< 清除接收数据函数指针 */
void (*set_pin)(void *port, uint16_t pin, bool state); /*!< GPIO引脚设置函数指针 */
bool (*read_pin)(void *port, uint16_t pin); /*!< GPIO引脚读取函数指针 */
} bt04a_ops_t;
/**
* @brief BT04A操作结果枚举类型
* @note 用于表示BT04A各种操作的执行结果
*/
typedef enum
{
BT04A_OK = 0, /*!< 操作成功 */
BT04A_ERROR = 1, /*!< 操作失败 */
BT04A_TIMEOUT = 2, /*!< 操作超时 */
BT04A_BUSY = 3, /*!< 模块忙碌 */
} bt04a_result_t;
/**
* @brief BT04A工作模式枚举
*/
typedef enum
{
BT04A_MODE_SLAVE = 0, /*!< 从机模式 */
BT04A_MODE_MASTER = 1, /*!< 主机模式 */
} bt04a_mode_t;
/**
* @brief BT04A波特率枚举
*/
typedef enum
{
BT04A_BAUD_1200 = 1200, /*!< 1200bps */
BT04A_BAUD_2400 = 2400, /*!< 2400bps */
BT04A_BAUD_4800 = 4800, /*!< 4800bps */
BT04A_BAUD_9600 = 9600, /*!< 9600bps */
BT04A_BAUD_19200 = 19200, /*!< 19200bps */
BT04A_BAUD_38400 = 38400, /*!< 38400bps */
BT04A_BAUD_57600 = 57600, /*!< 57600bps */
BT04A_BAUD_115200 = 115200, /*!< 115200bps */
} bt04a_baudrate_t;
/**
* @brief BT04A连接状态枚举
*/
typedef enum
{
BT04A_STATE_DISCONNECTED = 0, /*!< 未连接 */
BT04A_STATE_CONNECTED = 1, /*!< 已连接 */
BT04A_STATE_UNKNOWN = 2, /*!< 状态未知 */
} bt04a_state_t;
/**
* @brief BT04A配置结构体
*/
typedef struct
{
char device_name[32]; /*!< 设备名称 */
char pin_code[16]; /*!< PIN码 */
bt04a_baudrate_t baudrate; /*!< 波特率 */
bt04a_mode_t mode; /*!< 工作模式 */
/* 硬件控制引脚配置 */
void *en_port; /*!< 使能引脚端口 */
uint16_t en_pin; /*!< 使能引脚号 */
void *state_port; /*!< 状态引脚端口 */
uint16_t state_pin; /*!< 状态引脚号 */
/* 超时配置 */
uint16_t response_timeout_ms; /*!< AT命令响应超时时间(ms) */
uint16_t command_delay_ms; /*!< AT命令间隔延时(ms) */
} bt04a_config_t;
/* Exported constants --------------------------------------------------------*/
/** @defgroup BT04A_Default_Config BT04A默认配置参数
* @{
*/
#define BT04A_DEFAULT_NAME "BT04A" /*!< 默认设备名称 */
#define BT04A_DEFAULT_PIN "1234" /*!< 默认PIN码 */
#define BT04A_DEFAULT_BAUDRATE BT04A_BAUD_9600 /*!< 默认波特率 */
#define BT04A_DEFAULT_MODE BT04A_MODE_SLAVE /*!< 默认工作模式 */
#define BT04A_DEFAULT_TIMEOUT 1000 /*!< 默认超时时间(ms) */
#define BT04A_DEFAULT_DELAY 100 /*!< 默认命令延时(ms) */
/**
* @}
*/
/** @defgroup BT04A_Buffer_Size BT04A缓冲区大小定义
* @{
*/
#define BT04A_MAX_NAME_LEN 32 /*!< 最大设备名称长度 */
#define BT04A_MAX_PIN_LEN 16 /*!< 最大PIN码长度 */
#define BT04A_BUFFER_SIZE 256 /*!< 数据缓冲区大小 */
#define BT04A_MAX_LENGTH BT04A_BUFFER_SIZE
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup BT04A_Init_Functions BT04A初始化函数
* @{
*/
bt04a_result_t bt04a_ops_init(bt04a_ops_t *ops);
bt04a_result_t bt04a_init(const bt04a_config_t *config);
bt04a_result_t bt04a_deinit(void);
/**
* @}
*/
/** @defgroup BT04A_Config_Functions BT04A配置函数
* @{
*/
bt04a_result_t bt04a_set_name(const char *name);
bt04a_result_t bt04a_set_pin(const char *pin);
bt04a_result_t bt04a_set_baudrate(bt04a_baudrate_t baudrate);
bt04a_result_t bt04a_set_mode(bt04a_mode_t mode);
bt04a_result_t bt04a_get_config(bt04a_config_t *config);
/**
* @}
*/
/** @defgroup BT04A_Control_Functions BT04A控制函数
* @{
*/
bt04a_result_t bt04a_enter_at_mode(void);
bt04a_result_t bt04a_exit_at_mode(void);
bt04a_result_t bt04a_reset(void);
bt04a_result_t bt04a_enable(bool enable);
/**
* @}
*/
/** @defgroup BT04A_Status_Functions BT04A状态函数
* @{
*/
bt04a_state_t bt04a_get_connection_state(void);
bt04a_result_t bt04a_test_connection(void);
bool bt04a_is_connected(void);
/**
* @}
*/
/** @defgroup BT04A_Data_Functions BT04A数据函数
* @{
*/
bt04a_result_t bt04a_send_data(const uint8_t *data, uint16_t len);
bt04a_result_t bt04a_send_string(const char *string);
int bt04a_printf(const char *format, ...);
uint16_t bt04a_receive_data(uint8_t *buffer, uint16_t max_len);
void bt04a_clear_buffer(void);
/**
* @}
*/
#endif /* _BT04A_DRIVER_H */
初始化实例
这里发送数据是单片机串口的发送,接收是单片机串口的接收
#include "uart_driver.h"
#include "debug_log.h"
#include "tim_driver.h"
#include "bt04a_port.h"
#include "bt04a_driver.h"
#include <string.h>
static void bt04a_port_send_data(const uint8_t *p_data, uint16_t size)
{
uart1_putdatas(p_data, size);
}
static uint16_t bt04a_port_receive_data(uint8_t *p_data, uint16_t size)
{
return uart1_read_data(p_data, size);
}
static void bt04a_port_clear_buffer(void)
{
uart_buffer_clear(pg_uart1_handle);
}
bool bt04a_port_init(void)
{
bool error = false;
uart1_init(); // 初始化UART1的DMA接收
// 初始化BT04A蓝牙模块回调函数
bt04a_ops_t bt04a_ops =
{
.send_data = bt04a_port_send_data,
.receive_data = bt04a_port_receive_data,
.delay_ms = mdelay,
.clear_rx_data = bt04a_port_clear_buffer,
.set_pin = NULL,
.read_pin = NULL
};
// 初始化BT04A操作回调函数
if (bt04a_ops_init(&bt04a_ops) != BT04A_OK)
{
LOG_ERROR("BT04A callback init failed");
}
// 配置BT04A蓝牙模块参数
bt04a_config_t bt04a_config =
{
.baudrate = BT04A_BAUD_9600,
.mode = BT04A_MODE_SLAVE,
.en_port = NULL, // 如果不使用使能引脚可设为NULL
.en_pin = 0,
.state_port = NULL, // 如果不使用状态引脚可设为NULL
.state_pin = 0,
.response_timeout_ms = BT04A_DEFAULT_TIMEOUT,
.command_delay_ms = BT04A_DEFAULT_DELAY
};
// 复制设备名称和PIN码
strcpy(bt04a_config.device_name, BT04A_DEFAULT_NAME);
strcpy(bt04a_config.pin_code, BT04A_DEFAULT_PIN);
// 初始化BT04A模块
if (bt04a_init(&bt04a_config) == BT04A_OK)
{
LOG_INFO("BT04A module init success");
error = false;
}
else
{
LOG_ERROR("BT04A module init failed");
error = true;
}
bt04a_clear_buffer();
return !error; // 成功时返回true,失败时返回false
}
8696

被折叠的 条评论
为什么被折叠?



