STM32开发之HC05基础驱动编写

时间:2024-02-23 20:54:24

驱动文件

头文件

//
// Created by shchl on 2024/2/22.
//

#ifndef F4_PROJECT_BLE_HC05_H
#define F4_PROJECT_BLE_HC05_H

#include "bsp.h"
#include "bsp_uart.h"

typedef enum {
    hc05_resp_ok_status, /*接收正确*/
    hc05_resp_timeout_status, /*超时*/
    hc05_resp_fail_status /*失败*/
} hc05_resp_status; /*hc05响应状态*/

void hc05_device_init(void);

/*-----------------------------底层驱动需要实现的接口----------------------------------------*/


extern void hc05_device_send(const char *cmd);

extern char *hc05_device_wait_resp(void); /*等待设备响应数据*/
extern void hc05_device_enter_at_mode(void); /*进入AT模式*/
extern void hc05_device_quit_at_mode(void); /*退出AT模式*/
/**
 * 接收来自远端的数据(非阻塞)
 * @param dst
 * @return
 */
extern uint16_t hc05_device_rec_remote_data(uint8_t *dst);
extern uint16_t hc05_device_send_remote_data(uint8_t *dst,uint16_t len);
/*---------------------------------------------------------------------*/


void hc05_set_delay_cb(void (*delay_ms_call)(uint32_t));

hc05_resp_status hc05_set_cmd(const char *cmd);

char *hc05_query_cmd(const char *cmd);

void hc05_delay_ms(uint32_t ms);

hc05_resp_status hc05_check(uint8_t tryCnt);

hc05_resp_status hc05_read_version(char *dst);

hc05_resp_status hc05_read_work_stat(char *dst);

hc05_resp_status hc05_read_addr(char *dst);

hc05_resp_status hc05_read_name(char *dst);

hc05_resp_status hc05_read_role(char *dst);

hc05_resp_status hc05_read_pwd(char *dst);

hc05_resp_status hc05_read_uart_cnf(char *dst);

#endif //F4_PROJECT_BLE_HC05_H

源文件

//
// Created by shchl on 2024/2/22.
//

#include "ble_hc05.h"

static bool hc05_sub_str(char *dst, const char *src, char *prefix_str, char *suffix_str);

static void (*hc05_delay_call)(uint32_t) =NULL;

void hc05_set_delay_cb(void (*delay_ms_call)(uint32_t)) {
    hc05_delay_call = delay_ms_call;
}

void hc05_delay_ms(uint32_t ms) {
    if (hc05_delay_call) {
        hc05_delay_call(ms);
    }
}


/**
 * 设置指令
 * @param cmd
 */
hc05_resp_status hc05_set_cmd(const char *cmd) {
    char *result = hc05_query_cmd(cmd);
    if (strstr(result, "OK")) {
        return hc05_resp_ok_status;
    } else if (strstr(result, "FAIL")) {
        return hc05_resp_fail_status;
    }
    return hc05_resp_timeout_status;

}

/**
 * 查询指令,并返回查询数据结果
 * @param cmd
 * @return
 */
char *hc05_query_cmd(const char *cmd) {
    /*进入 AT模式*/
    hc05_device_enter_at_mode();
    hc05_delay_ms(10);
    hc05_device_send(cmd);//发送并接收
    /*退出 AT模式*/
    hc05_device_quit_at_mode();
    return hc05_device_wait_resp();

}

/**
 * @brief 蓝牙设备模块检测
 * @return
 */
hc05_resp_status hc05_check(uint8_t tryCnt) {
    for (uint8_t i = 0; i < tryCnt; ++i) {
        if (hc05_set_cmd("AT\r\n") == hc05_resp_ok_status) {
            return hc05_resp_ok_status;
        }
    }
    return hc05_resp_timeout_status;
}

/**
 * 获取蓝牙设备版本号
 * @param dst 保存位置
 * @return
 */
hc05_resp_status hc05_read_version(char *dst) {

    char *ptr = hc05_query_cmd("AT+VERSION?\r\n"); /**/
    if (ptr) {
        if (hc05_sub_str(dst, ptr, "VERSION:", "\r\n")) {
            return hc05_resp_ok_status;
        }
        return hc05_resp_fail_status;
    }
    return hc05_resp_timeout_status;
}
hc05_resp_status hc05_read_work_stat(char *dst){
    char *ptr = hc05_query_cmd("AT+STATE?\r\n"); /**/
    if (ptr) {
        if (hc05_sub_str(dst, ptr, "STATE:", "\r\n")) {
            return hc05_resp_ok_status;
        }
        return hc05_resp_fail_status;
    }
    return hc05_resp_timeout_status;
}

hc05_resp_status hc05_read_addr(char *dst){
    char *ptr = hc05_query_cmd("AT+ADDR?\r\n"); /**/
    if (ptr) {
        if (hc05_sub_str(dst, ptr, "ADDR:", "\r\n")) {
            return hc05_resp_ok_status;
        }
        return hc05_resp_fail_status;
    }
    return hc05_resp_timeout_status;
}

hc05_resp_status hc05_read_name(char *dst){
    char *ptr = hc05_query_cmd("AT+NAME?\r\n"); /**/
    if (ptr) {
        if (hc05_sub_str(dst, ptr, "NAME:", "\r\n")) {
            return hc05_resp_ok_status;
        }
        return hc05_resp_fail_status;
    }
    return hc05_resp_timeout_status;
}

hc05_resp_status hc05_read_role(char *dst){
    char *ptr = hc05_query_cmd("AT+ROLE?\r\n"); /**/
    if (ptr) {
        if (hc05_sub_str(dst, ptr, "ROLE:", "\r\n")) {
            return hc05_resp_ok_status;
        }
        return hc05_resp_fail_status;
    }
    return hc05_resp_timeout_status;
}

hc05_resp_status hc05_read_pwd(char *dst){
    char *ptr = hc05_query_cmd("AT+PSWD?\r\n"); /**/
    if (ptr) {
        if (hc05_sub_str(dst, ptr, "PSWD:", "\r\n")) {
            return hc05_resp_ok_status;
        }
        return hc05_resp_fail_status;
    }
    return hc05_resp_timeout_status;
}

hc05_resp_status hc05_read_uart_cnf(char *dst){
    char *ptr = hc05_query_cmd("AT+UART?\r\n"); /**/
    if (ptr) {
        if (hc05_sub_str(dst, ptr, "UART:", "\r\n")) {
            return hc05_resp_ok_status;
        }
        return hc05_resp_fail_status;
    }
    return hc05_resp_timeout_status;
}

/**
 * @brief 提取字符串到指定位置
 * @param dst 保存子串
 * @param src 原始字符串
 * @param prefix_str 前缀(可以为NULL)
 * @param suffix_str 后缀(可以为NULL)
 * @return 是否提取成功
 */
static bool hc05_sub_str(char *dst, const char *src, char *prefix_str, char *suffix_str) {
    const char *ptr_src = src;
    size_t sub_len; /*字串长度*/
    if (!ptr_src) return true;
    if (prefix_str != NULL) {
        ptr_src = strstr(ptr_src, prefix_str); /*查找前缀位置*/
        if (!ptr_src) return false;
        ptr_src += strlen(prefix_str); /**/
    }
    if (suffix_str) {
        char *endPtr = strstr(ptr_src, suffix_str);
        if (!endPtr) return false;
        sub_len = endPtr - ptr_src;
    } else {
        sub_len = strlen(ptr_src);
    }
    memcpy(dst, ptr_src, sub_len);
    dst[sub_len] = '\0'; /*添加结束符*/
    return true;
}

接口文件(对应硬件)

//
// Created by shchl on 2024/2/22.
//
#include "ble_hc05.h"

#define HC05_AT_GPIO_PIN GPIO_PIN_9
#define HC05_AT_GPIO_PORT GPIOC
#define HC05_AT_GPIO_CLK_EN() __HAL_RCC_GPIOC_CLK_ENABLE()
#define hc05_uart_dev uart1_dev
static bool isCmdDatResp = false; /*是发送 指令数据标志位*/

static void hc05_device_start_rec(void);

static uint8_t hc05_rx_buf[UART1_RX_BUF_LEN];

void hc05_device_init(void) {
    /*设置对应的延迟函数回调*/
    hc05_set_delay_cb(HAL_Delay);
    /*对应GPIO硬件初始化*/
    HC05_AT_GPIO_CLK_EN();
    GPIO_InitTypeDef GPIO_Init;
    GPIO_Init.Pin = HC05_AT_GPIO_PIN;
    GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_Init.Pull = GPIO_PULLDOWN;
    GPIO_Init.Speed = GPIO_SPEED_MEDIUM;
    HAL_GPIO_Init(HC05_AT_GPIO_PORT, &GPIO_Init);
    /*对应串口硬件初始化*/
    uart1_dev_init(115200);
    hc05_device_start_rec();
    /*退出at模式*/
    hc05_device_quit_at_mode();

}


__weak void hc05_device_send(const char *cmd) {
    HAL_UART_Transmit(&hc05_uart_dev.uart_handle, (uint8_t *) cmd, strlen(cmd), 20);
}

__weak char *hc05_device_wait_resp(void) {
    for (int i = 0; i < 10; ++i) {
        hc05_delay_ms(10);
        uint32_t len = CacheBuffer_Read_Data(hc05_uart_dev.rx_cache_ptr, hc05_rx_buf);
        if (len > 0) {
            hc05_rx_buf[len] = '\0';
//            printf("HC05_Rec_Str len:%lu,data:%s\r\n", len, hc05_rx_buf);
            return (char *) hc05_rx_buf;
        }


    }
    return NULL;
}

__weak uint16_t hc05_device_rec_remote_data(uint8_t *dst) {
    hc05_device_quit_at_mode();
    return CacheBuffer_Read_Data(hc05_uart_dev.rx_cache_ptr, dst);
}
 uint16_t hc05_device_send_remote_data(uint8_t *dst,uint16_t len){
     hc05_device_quit_at_mode();
     HAL_UART_Transmit(&hc05_uart_dev.uart_handle, dst, len, 20);
     return len;
}
__weak void hc05_device_enter_at_mode(void) {
    HAL_GPIO_WritePin(HC05_AT_GPIO_PORT, HC05_AT_GPIO_PIN, GPIO_PIN_SET);
}

__weak void hc05_device_quit_at_mode(void) {
    HAL_GPIO_WritePin(HC05_AT_GPIO_PORT, HC05_AT_GPIO_PIN, GPIO_PIN_RESET);
}

/**
 * 串口函数回调中使用
 * @param Size
 */
void HAL_UARTEx_RxEventCallback_HC05(uint16_t Size) {
    CacheBuffer_Update_Data_Len(hc05_uart_dev.rx_cache_ptr, Size);
    /*重新接收数据*/
    hc05_device_start_rec();
}

static void hc05_device_start_rec(void) {
    HAL_UARTEx_ReceiveToIdle_DMA(&hc05_uart_dev.uart_handle,
                                 hc05_uart_dev.rx_cache_ptr->List[hc05_uart_dev.rx_cache_ptr->InIndex].start,
                                 CACHE_BUFFER_ONE_DATA_MAX_LEN);
}

串口驱动文件(针对stm32f4芯片,根据需要修改)

bsp_uart.h

//
// Created by shchl on 2024/2/21.
//

#ifndef BSP_UART_H
#define BSP_UART_H

#include "bsp.h"

#include "cachebuffer.h"

#define UART_PRINTF_DEV uart2_dev.uart_handle
/*-----------------------------------串口1配置----------------------------------------*/
#define UART1_DEV_RX_CACHE_ENABLE               1        /*串口1设备接收缓冲区使能*/
#define UART1_DEV_TX_CACHE_ENABLE               0         /*串口1设备发送缓冲区使能*/
#define UART1_IT_ENABLE                         1                   /*串口1中断*/

#define UART1_RX_BUF_LEN                        1024
#define UART1_TX_BUF_LEN                        1024
/*-----------------------------------串口2配置----------------------------------------*/
#define UART2_DEV_RX_CACHE_ENABLE               0       /*串口2设备接收缓冲区使能*/
#define UART2_DEV_TX_CACHE_ENABLE               0       /*串口2设备发送缓冲区使能*/
#define UART2_IT_ENABLE                         0       /*串口2中断*/
#define UART2_RX_BUF_LEN                        1024
#define UART2_TX_BUF_LEN                        1024
typedef struct {
    CacheBuffer_t *rx_cache_ptr; /*接收缓存*/
    CacheBuffer_t *tx_cache_ptr; /*发送缓存*/
    UART_HandleTypeDef uart_handle;
} uart_dev_t; /*串口设备*/
extern uart_dev_t uart1_dev;
extern uart_dev_t uart2_dev;
void uart1_dev_init(uint32_t baud);

void uart2_dev_init(uint32_t baud);


#endif //BSP_UART_H

bsp_uart.c

//
// Created by shchl on 2024/2/21.
//

#include "bsp_uart.h"

static void uart_conf_init(UART_HandleTypeDef *uart_handle, uint32_t baud);

uart_dev_t uart1_dev = {.uart_handle.Instance=USART1};
#if UART1_DEV_RX_CACHE_ENABLE
static CacheBuffer_t uart1_rx_cache;
static uint8_t uart1_rx_buf[UART1_RX_BUF_LEN] = {0};
#endif
#if UART1_DEV_TX_CACHE_ENABLE
static CacheBuffer_t uart1_tx_cache;
static uint8_t uart1_tx_buf[UART1_TX_BUF_LEN] = {0};
#endif

/**
 * 重写串口printf
 * @param file
 * @param ptr
 * @param len
 * @return
 */
int _write(int file, char *ptr, int len)
{
    (void)file;
    HAL_UART_Transmit(&UART_PRINTF_DEV, (const uint8_t *) ptr, len, 200);
    return len;
}
void uart1_dev_init(uint32_t baud) {
#if UART1_DEV_RX_CACHE_ENABLE
    uart1_dev.rx_cache_ptr = &uart1_rx_cache;
    CacheBuffer_Init(uart1_dev.rx_cache_ptr, uart1_rx_buf, UART1_RX_BUF_LEN);

#endif

#if UART1_DEV_TX_CACHE_ENABLE
    uart1_dev.tx_cache_ptr = &uart1_tx_cache;
    CacheBuffer_Init(uart1_dev.tx_cache_ptr, uart1_tx_buf, UART1_TX_BUF_LEN);
#endif
    uart_conf_init(&uart1_dev.uart_handle, baud);
}


uart_dev_t uart2_dev = {.uart_handle.Instance=USART2};
#if UART2_DEV_RX_CACHE_ENABLE
static CacheBuffer_t uart2_rx_cache;
static uint8_t uart2_rx_buf[UART2_RX_BUF_LEN] = {0};
#endif
#if UART2_DEV_TX_CACHE_ENABLE
static CacheBuffer_t uart2_tx_cache;
static uint8_t uart2_tx_buf[UART2_TX_BUF_LEN] = {0};
#endif

/**
 * @brief 串口2设备 初始化
 * @param baud
 */
void uart2_dev_init(uint32_t baud) {
#if UART2_DEV_RX_CACHE_ENABLE
    uart2_dev.rx_cache_ptr = &uart2_rx_cache;
    CacheBuffer_Init(uart2_dev.rx_cache_ptr, uart2_rx_buf, UART2_RX_BUF_LEN);

#endif

#if UART2_DEV_TX_CACHE_ENABLE
    uart2_dev.tx_cache_ptr = &uart2_tx_cache;