HC-05的简介与使用

第一部分*********************!!!!!!!!蓝牙模块HC-05

蓝牙概述

蓝牙(Bluetooth)是一种用于无线通信的技术标准,允许设备在短距离内进行数据交换和通信。它是由爱立信(Ericsson)公司在1994年推出的,以取代传统的有线连接方式,使设备之间能够实现低功耗、低成本的数据传输和通信。     

蓝牙作为一种小范围无线连接技术,具有低功耗、低成本、方便快捷的特点,被广泛应用于无线耳机、智能手表、无线遥控等场景,是实现无线通信的主流技术之一。

蓝牙协议各个版本

HC-05模块简介

HC-05参数

HC-05工作模式

HC-05角色 

1. Master(主角色)——查询周围 SPP 蓝牙从设备,并主动发起连接,从而建立主、从蓝牙设备间的透明数据传输通道。

2. Slave(从角色)——被动连接;

3. Slave-Loop(回环角色)——被动连接,接收远程蓝牙主设备数据并将数据原样返回给远程蓝牙主设备;

引脚定义

怎么进入命令响应工作模式(AT指令模式) 

用手按着模块上的按键,再给蓝牙模块上电。当蓝牙模块上的灯慢闪的时候就说明进入了配置模式了。

1  按下模块上的按键(PIO11置高)

2  对HC-05重新上电,模块进入AT命令响应工作模式。

3  使用串口助手,配置成波特率38400,数据位8 位,停止位1 位,无校验位,无流控制。

4  串口助手发送字符串“AT\r\n”,正常情况下模块会给出“OK\r\n”,“\r\n”为回车换行,也叫做新行。

 HC-05工作流程

AT指令模式配置HC-05模块

重新上电模块,进入自动连接工作模块,连接从模块(也可以使用AT指令,在AT指令模式下连接从模块)。

建立蓝牙连接,LED常量,直接使用串口完成通信

电脑串口助手配置

在配置蓝牙的时候一定要将串口助手按这个要求配置:设置波特率 38400,数据位 8 位,停止位 1 位,无校验位,这是固定操作!

常见指令

常见的指令 

首先我们要明确串口通信的条件,我们需要设置8位数据位,1为停止位,无检验,波特率为38400,这样才可以与HC-05进行串口通信,当然这些配置都可以在后续的AT指令中更改。

并且要以文本模式发送指令,编码格式为 utf-8,每个指令后面也要加上换行(‘\r\n’)。

1  第一个测试指令,我们直接通过串口发送“AT”即可,然后就会给我们回复“OK”,用这个没什么意义的指令可以来测试我们是否成功进入到了AT指令模式(其实通过LED的闪烁情况也可以知道)。

2  发送复位指令之后,HC-05进入复位,如果没有按下按钮的话,会默认进入到配对模式。成功后回复“OK”。

 

恢复的默认配置同上图。发送完成后貌似是自动复位了,也可能不是,反正我的HC-05从原本的AT指令模式变成配对模式了。

而且设备名称也不是上面说的“H-C-2010-06-01”而是“HC-05”,也可能是因为我的是兼容版HC-05,具体的情况以你们自己手上的HC-05为准。

不带参数的话就是回复设备名称,加“OK”,带参数的话就是修改蓝牙名称并且回复“OK”。

默认就是从机,当然我们也可以修改为主机。

这边要注意的是,配对码(密码)需要用英文半角的双引号括起来。

LED和蓝牙模块代码对比1:

 

实验现象:

代码部分(详解)

hc05.c

#include "hc05.h"
#include "delay.h"

//代码片段是一些预处理指令,用于定义宏和一些常量。
#define    HC05_DelayMs(t)                Delay_Ms(t)//当调用 HC05_DelayMs(t) 时,实际上会调用 Delay_Ms(t) 函数。
#define    HC05_GPIO_LOW                  0   //这通常用于表示某种特定状态,例如在这里,可能表示低电平或关闭状态。
#define    HC05_GPIO_HIGH                 1   //它被赋值为1。类似地,这个宏可能表示高电平或打开状态。


#if defined (STM32F40_41xxx)

//配置输入输出
//用于配置一个GPIO引脚为输出模式。它接受两个参数:port 表示GPIO端口,pin 表示端口上的引脚。
#define    HC05_CONFIG_IO_OUTPUT(port, pin)          {GPIO_InitTypeDef GPIO_InitStructure; \
                                                    GPIO_InitStructure.GPIO_Mode     =  GPIO_Mode_OUT; \
                                                    GPIO_InitStructure.GPIO_OType    = GPIO_OType_PP;\
                                                    GPIO_InitStructure.GPIO_PuPd     = GPIO_PuPd_UP; \
                                                    GPIO_InitStructure.GPIO_Speed    =  GPIO_Speed_50MHz; \
                                                    GPIO_InitStructure.GPIO_Pin      =  pin ; \
                                                    GPIO_Init(port, &GPIO_InitStructure);}
//读取一个GPIO引脚的当前值。它接受两个参数:port 和 pin,分别表示GPIO端口和引脚。
#define    HC05_CONFIG_IO_INPUT(port, pin)           {GPIO_InitTypeDef GPIO_InitStructure; \
                                                    GPIO_InitStructure.GPIO_Mode     =  GPIO_Mode_IN; \
                                                    GPIO_InitStructure.GPIO_PuPd     = GPIO_PuPd_UP; \
                                                    GPIO_InitStructure.GPIO_Speed    =  GPIO_Speed_50MHz; \
                                                    GPIO_InitStructure.GPIO_Pin      =  pin ; \
                                                    GPIO_Init(port, &GPIO_InitStructure);}
//用于读取一个GPIO引脚的当前值。它接受两个参数:port 和 pin,分别表示GPIO端口和引脚。
#define    HC05_IO_GET_VALUE(port, pin)               GPIO_ReadInputDataBit(port, pin)

//用于设置一个GPIO引脚的输出值。它接受三个参数:port、pin 和 value,分别表示GPIO端口、引脚和要设置的值(HC05_GPIO_HIGH 或 HC05_GPIO_LOW)。
#define    HC05_IO_SET(port, pin, value)              { if(value == HC05_GPIO_HIGH) \
                                                         GPIO_SetBits(port, pin); \
                                                     else \
                                                         GPIO_ResetBits(port, pin);}
//时钟开启 时钟使能
#define    RCC_GPIO_CLOCK_ENABLE(GPIOX)            { if (GPIOX  == GPIOA)         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); \
                                                     else if (GPIOX  == GPIOB)    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); \
                                                     else if (GPIOX  == GPIOC)    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); \
                                                     else if (GPIOX  == GPIOD)    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); \
                                                     else if (GPIOX  == GPIOE)    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE); \
                                                     else if (GPIOX  == GPIOF)    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); \
                                                     else if (GPIOX  == GPIOG)    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE); \
                                                     else printf("gpio clock no enable\r\n"); \
                                                   }
#endif

                                                   
//调试模式
//如果 HC05_DEBUG_MODE 的值为1,表示处于调试模式,那么 hc05_log 会被定义为 printf 函数,用于打印格式化的日志信息。
#if (HC05_DEBUG_MODE == 1)
    #define hc05_log(format, ...)                     printf(format, ##__VA_ARGS__)
#else
    #define hc05_log(format, ...)
//如果 HC05_DEBUG_MODE 的值不为1,表示不处于调试模式,那么 hc05_log 会被定义为空,即不执行任何操作,这样就可以在不需要输出调试信息时避免编译器产生多余的代码。                                                   
#endif




/******************************************************************************
 * @brief     发送一个字符
 *
 * @param[in]  bt           :  BlueTooth_t结构体指针
 * @param[in]  ch           :  要发送的字符
 *
 * @return     0, 表示成功, 其他值表示失败
 *函数的作用是通过蓝牙发送一个字符。
 ******************************************************************************/
//函数的声明,指定了函数名 send_char,参数类型为指向 BlueTooth_t 结构的指针 bt 和一个字符 ch,返回类型为 int。
static int send_char(BlueTooth_t* bt, char ch)
{
    while((bt->uart->SR & 0X40) == 0);
    bt->uart->DR = (uint16_t)ch;//一旦蓝牙模块准备好发送字符,就会将要发送的字符 ch 写入 bt 结构体中的 uart 成员的 DR(数据寄存器)中。


    return 0;
}
//这是一个 while 循环,它的条件是等待蓝牙模块准备好发送下一个字符。这里使用了位运算和与操作,检查 bt 
//结构体中的 uart 成员的 SR(状态寄存器)的第六位是否为 1,如果不为 1,则表示蓝牙模块还没有准备好
//发送下一个字符,程序会一直在这里循环等待。



/******************************************************************************
 * @brief     发送字符串
 *
 * @param[in]  bt           :  BlueTooth_t结构体指针
 * @param[in]  str          :  字符串
 *
 * @return     返回具体发送的字节数
 *用于向蓝牙模块发送字符串数据。
 ******************************************************************************/
static int send_string(BlueTooth_t* bt, const char* str)
{
    uint32_t i = 0;
    uint32_t len = strlen(str);
    for (i = 0; i < len; i++) {
        send_char(bt, str[i]);
    }

    return i;
}




/******************************************************************************
 * @brief     发送AT指令函数
 *
 * @param[in]  bt           :  BlueTooth_t结构体指针
 * @param[in]  at_cmd       :  AT指令
 * @param[in]  response     :  AT指令的回响
 * @param[in]  timeout_ms   :  超时时间
 *
 * @return     0, 表示成功, 其他值表示失败
 *用于发送 AT 指令并等待响应的函数。以下是对注释的解释:
 ******************************************************************************/
static int send_at_cmd(BlueTooth_t *bt, const char *at_cmd, const char *response, uint32_t timeout_ms)
{ //用于发送 AT 指令并等待响应。它接受一个指向 BlueTooth_t 结构的指针 bt,一个表示要发送的 AT 指令的字符串 at_cmd,
  //一个表示期望的响应的字符串 response,以及一个表示超时时间的毫秒数 timeout_ms。它返回一个整数值,表示执行结果。
    bt->rx_buffer_current_cnt = 0;// 这行代码将接收缓冲区的当前计数器置为0,准备接收新的响应数据。
    memset(bt->rx_buffer, 0, sizeof(bt->rx_buffer));//这行代码用于将接收缓冲区中的所有元素都设置为0,以清除其中的任何残留数据。
    send_string(bt, at_cmd);//这行代码调用了一个名为 send_string 的函数,用于发送字符串类型的数据至蓝牙模块。
    send_string(bt, "\r\n");// 这行代码发送一个回车换行符,以结束当前的 AT 指令。
    timeout_ms = timeout_ms == 0 ? 0xFFFFFFFF : timeout_ms;  //timeout_ms为0,表示延时最长时间,0xFFFFFFFF ms
    do {
        if (strstr((const char *)bt->rx_buffer, response) != NULL) {  //回应信息正确
            return 0;
        }
        HC05_DelayMs(1);
    }while(timeout_ms--);
//循环条件为 timeout_ms 不为0。在循环内部,检查接收缓冲区中是否包含期望的响应字符串,
    //如果包含,则返回0表示成功;否则,等待1毫秒,直到超时。
    if (!timeout_ms)  //发送超时
        return -1;
//如果超时时间为0,即等待时间已经用尽,则返回-1表示发送超时。
    return -2;
}




/******************************************************************************
 * @brief     使用AT指令对蓝牙模块配置参数,重新复位
 *
 * @param[in]  bt   :  BlueTooth_t结构体指针
 *
 * @return     0, 表示初始化成功, 其他值表示失败
 *通过发送一系列的 AT 指令给蓝牙模块,来执行重置操作,并记录每个指令的执行结果和模块的响应内容。
 ******************************************************************************/
int bt_software_reset(struct blue_tooth *bt)
//这是一个函数定义,它接受一个指向 struct blue_tooth 结构的指针作为参数,并返回一个整数值。
{
    char tmp_buffer[20];
    int ret = 0;
    HC05_IO_SET(bt->port[HC05_EN], bt->pin[HC05_EN], HC05_GPIO_HIGH);
    //这行代码设置蓝牙模块的使能引脚为高电平,以便激活模块。
    Delay_Ms(1000);
   //暂停执行代码1秒钟。
    memset(tmp_buffer, 0, sizeof(tmp_buffer));
    //这行代码用于将 tmp_buffer 数组中的所有元素都设置为0,以清除其中的任何残留数据。
    sprintf(tmp_buffer, "AT");
    //这行代码将字符串 "AT" 格式化并存储到 tmp_buffer 中,表示发送 AT 指令给蓝牙模块。
    ret = send_at_cmd(bt, tmp_buffer, "OK", 1000);
    //这行代码调用了一个名为 send_at_cmd 的函数,该函数用于发送 AT 指令给蓝牙模块,并等待接收到 "OK" 响应,最多等待1秒钟。
    hc05_log("AT: %d  %s\r\n", ret, bt->rx_buffer);
    //这行代码记录了发送 AT 指令的结果和接收到的响应内容。
    memset(tmp_buffer, 0, sizeof(tmp_buffer));
    sprintf(tmp_buffer, "AT+NAME=HC-05");//指令的作用是设置蓝牙模块的名称为 "HC-05"。
    ret = send_at_cmd(bt, tmp_buffer, "OK", 1000);

    hc05_log("AT+NAME: %d  %s\r\n", ret, bt->rx_buffer);

    memset(tmp_buffer, 0, sizeof(tmp_buffer));
    sprintf(tmp_buffer, "AT+ROLE=0");
    ret = send_at_cmd(bt, tmp_buffer, "OK", 1000);
//调用 send_at_cmd 函数发送命令给蓝牙模块,并等待蓝牙模块返回 "OK"。
    hc05_log("AT+ROLE: %d  %s\r\n", ret, bt->rx_buffer);

    memset(tmp_buffer, 0, sizeof(tmp_buffer));
    sprintf(tmp_buffer, "AT+PSWD=\"123456\"");
    ret = send_at_cmd(bt, tmp_buffer, "OK", 1000);

    hc05_log("AT+PSWD: %d  %s\r\n", ret, bt->rx_buffer);

    memset(tmp_buffer, 0, sizeof(tmp_buffer));
    sprintf(tmp_buffer, "AT+UART=38400,0,0");

    hc05_log("AT+UART: %d  %s\r\n", ret, bt->rx_buffer);

    memset(tmp_buffer, 0, sizeof(tmp_buffer));
    sprintf(tmp_buffer, "AT+RESET");
    ret = send_at_cmd(bt, tmp_buffer, "OK", 1000);

    hc05_log("AT+RESET: %d  %s\r\n", ret, bt->rx_buffer);

    HC05_IO_SET(bt->port[HC05_EN], bt->pin[HC05_EN], HC05_GPIO_LOW);
    //最后一行代码将蓝牙模块的使能引脚设置为低电平,以便关闭模块。
    return 0;
}
//通过发送一系列的AT指令给蓝牙模块,来配置其名称、角色、密码、波特率等参数,并通过 hc05_log 函数输出每个AT指令执行的结果。



/******************************************************************************
 * @brief     初始化HC-05模块用到的硬件资源
 *
 * @param[in]  bt   :  BlueTooth_t结构体指针
 *
 * @return     无
 *
 ******************************************************************************/
static void bt_hw_init(BlueTooth_t* bt)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* 初始化用大的时钟 */
    RCC_GPIO_CLOCK_ENABLE(bt->port[HC05_TX]);
    RCC_GPIO_CLOCK_ENABLE(bt->port[HC05_RX]);
    RCC_GPIO_CLOCK_ENABLE(bt->port[HC05_EN]);
    RCC_GPIO_CLOCK_ENABLE(bt->port[HC05_STATE]);

    /* USART端口配置 */
    GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_AF;              //复用功能
    GPIO_InitStructure.GPIO_Speed  = GPIO_Speed_50MHz;          //速度50MHz
    GPIO_InitStructure.GPIO_OType  = GPIO_OType_PP;             //推挽复用输出
    GPIO_InitStructure.GPIO_PuPd   = GPIO_PuPd_UP;              //上拉
    
    GPIO_InitStructure.GPIO_Pin = bt->pin[HC05_TX];
    GPIO_Init(bt->port[HC05_TX], &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = bt->pin[HC05_RX];
    GPIO_Init(bt->port[HC05_RX], &GPIO_InitStructure);

    /* 配置EN、STATUS引脚 */
    GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_OUT;             //EN引脚配置为输出
    GPIO_InitStructure.GPIO_Pin = bt->pin[HC05_EN];
    GPIO_Init(bt->port[HC05_EN], &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode   = GPIO_Mode_IN;             //STATUS引脚配置为输入
    GPIO_InitStructure.GPIO_Pin = bt->pin[HC05_STATE];
    GPIO_Init(bt->port[HC05_STATE], &GPIO_InitStructure);

    /* USART 初始化设置 */
    USART_InitStructure.USART_BaudRate              = HC05_UART_BAUD_RATE;              //波特率设置
    USART_InitStructure.USART_WordLength            = USART_WordLength_8b;              //8位数据位长
    USART_InitStructure.USART_StopBits              = USART_StopBits_1;                 //一个停止位
    USART_InitStructure.USART_Parity                = USART_Parity_No;                  //无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl   = USART_HardwareFlowControl_None;   //无硬件数据流控制
    USART_InitStructure.USART_Mode                  = USART_Mode_Rx | USART_Mode_Tx;    //收发模式
    USART_Init(bt->uart, &USART_InitStructure);                                         //初始化串口
    USART_Cmd(bt->uart, ENABLE);                                                        //使能串口
    USART_ITConfig(bt->uart, USART_IT_RXNE, ENABLE);                                    //开启串口接受中断

    /* 串口的NVIC配置 */
    NVIC_InitStructure.NVIC_IRQChannel                     = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority   = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority          = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd                  = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}




/******************************************************************************
 * @brief     初始化HC-05模块
 *
 * @param[in]  bt   :  BlueTooth_t结构体指针
 *
 * @return     0, 表示初始化成功, 其他值表示失败
 *
 ******************************************************************************/
int BT_Init(BlueTooth_t *bt)
{
    if(!bt)
        return -1;

    bt->rx_buffer_current_cnt = 0;
    bt->rx_buffer_total_length = HC05_RECEIVE_BUFFER_SIZE;
    memset(bt->rx_buffer, 0, sizeof(bt->rx_buffer));

    /* 初始化用到的硬件 */
    bt_hw_init(bt);

    /* 使用AT指令初始化HC-05模块 */
    bt_software_reset(bt);

    return 0;
}




/******************************************************************************
 * @brief     获得蓝牙模块连接的状态
 *
 * @param[in]  bt   :  BlueTooth_t结构体指针
 *
 * @return     HC05_STATUS_CONNECT, 表示蓝牙模块已连接, 
 *             HC05_STATUS_DISCONNECT,其他值表示失败
 *
 ******************************************************************************/
BT_ConnectStatus_t BT_GetBlueToothStatus(BlueTooth_t *bt)
{
    uint8_t pin_status = 0;

    pin_status = HC05_IO_GET_VALUE(bt->port[HC05_STATE], bt->pin[HC05_STATE]);

    if (pin_status) {   //连接
        return HC05_STATUS_CONNECT;
    } else {
        return HC05_STATUS_DISCONNECT;
    }
}




/******************************************************************************
 * @brief     蓝牙模块缓存区里面是否有数据
 *
 * @param[in]  bt   :  BlueTooth_t结构体指针
 *
 * @return     true 表示缓存区有数据, 
 *             false 表示缓存区没有数据
 *
 ******************************************************************************/
bool BT_IsReceiveData(BlueTooth_t *bt)
{
    if (bt->rx_buffer_current_cnt) {
        return true;
        
    } else {
        return false;
    }
}




/******************************************************************************
 * @brief     读取蓝牙模块缓存区里面的数据
 *
 * @param[in]  bt            :  BlueTooth_t结构体指针
 * @param[in]  pReadBuffer   :  读缓存区指针
 * @param[in]  u32ReadCount  :  读取的数据量
 *
 * @return     返回读取到的数据
 *
 ******************************************************************************/
int BT_ReceiveData(BlueTooth_t *bt, uint8_t *pReadBuffer, uint32_t u32ReadCount)
{
    if (u32ReadCount >= bt->rx_buffer_current_cnt) {
        memcpy(pReadBuffer, bt->rx_buffer, bt->rx_buffer_current_cnt);
        bt->rx_buffer_current_cnt = 0;
        return bt->rx_buffer_current_cnt;
    } else {
        memcpy(pReadBuffer, bt->rx_buffer, u32ReadCount);
        bt->rx_buffer_current_cnt = 0;
        return u32ReadCount;
    }

}




/******************************************************************************
 * @brief     向蓝牙模块发送数据
 *
 * @param[in]  bt            :  BlueTooth_t结构体指针
 * @param[in]  pReadBuffer   :  写缓存区指针
 * @param[in]  u32ReadCount  :  要发送的数据量
 *
 * @return     返回读取到的数据
 *
 ******************************************************************************/
int BT_SendData(BlueTooth_t *bt, uint8_t *pWriteBuffer, uint32_t u32WriteCount)
{
    int i = 0;
    for (i = 0; i < u32WriteCount; i++) {
        send_char(bt, pWriteBuffer[i]);
    }
    return i;
}

hc05.h

#ifndef  __HC05_H
#define  __HC05_H


#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#include "delay.h"


#define HC05_UART_BAUD_RATE                (38400U)
#define HC05_RECEIVE_BUFFER_SIZE           (1024U)
#define HC05_DEBUG_MODE                     0

//与芯片相关的部分 换芯片只需改动此处
#if defined (STM32F40_41xxx)

#include "stm32f4xx.h"

typedef    GPIO_TypeDef*   GPIO_Port_t;
typedef    USART_TypeDef*  UART_t;
//与芯片相关的部分 换芯片只需改动此处


#else

#error hc05.h: No processor defined!

#endif


typedef GPIO_Port_t gpio;


//蓝牙的链接状态
typedef enum bt_status
{
    HC05_STATUS_DISCONNECT = 0,
    HC05_STATUS_CONNECT = 1,
}BT_ConnectStatus_t;

//四个引脚
enum HC05Pin_t
{
    HC05_TX = 0,
    HC05_RX = 1,
    HC05_EN = 2,
    HC05_STATE = 3,
    HC05_COUNT             //
};


//初始化蓝牙结构体
//串口资源收发 引脚
typedef struct blue_tooth{ 
    UART_t             uart;
    GPIO_Port_t        port[HC05_COUNT];
    uint16_t           pin[HC05_COUNT];
    uint32_t           rx_buffer_current_cnt;
    uint32_t           rx_buffer_total_length;                  //缓冲区总的长度
    char               rx_buffer[HC05_RECEIVE_BUFFER_SIZE];       //接受AT指令的缓冲区
}BlueTooth_t;


int BT_Init(BlueTooth_t *bt);
BT_ConnectStatus_t BT_GetBlueToothStatus(BlueTooth_t *bt);
bool BT_IsReceiveData(BlueTooth_t *bt);
int BT_ReceiveData(BlueTooth_t *bt, uint8_t *pReadBuffer, uint32_t u32ReadCount);
int BT_SendData(BlueTooth_t *bt, uint8_t *pBuffer, uint32_t u32WriteCount);


#endif

main.c

#include "main.h"



BlueTooth_t gBL;
int main(void)
{
    BT_ConnectStatus_t s = 0;
    char buffer[100];
    int i = 0;
    char rx_buffer[100];

    Delay_Init();
    Debug_Init(115200);
    printf("BL\r\n");

    /* 初始化串口2对应时钟 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    
    /* 串口2对应引脚复用映射 */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
    gBL.uart = USART2;

    gBL.port[HC05_TX] = GPIOA;
    gBL.pin[HC05_TX] = GPIO_Pin_2;

    gBL.port[HC05_RX] = GPIOA;
    gBL.pin[HC05_RX] = GPIO_Pin_3;

    gBL.port[HC05_EN] = GPIOA;
    gBL.pin[HC05_EN] = GPIO_Pin_4;

    gBL.port[HC05_STATE] = GPIOA;
    gBL.pin[HC05_STATE] = GPIO_Pin_5;

    BT_Init(&gBL);

    while (1) {
        s = BT_GetBlueToothStatus(&gBL);    //判断蓝牙是否连接
        if (s) {
            printf("蓝牙连接\r\n");
            sprintf(buffer, "i: %d\r\n", i++);
            BT_SendData(&gBL, buffer, strlen(buffer));

            if (BT_IsReceiveData(&gBL)) {
                memset(rx_buffer, 0, sizeof(rx_buffer));
                BT_ReceiveData(&gBL, rx_buffer, 100);
                printf("rx_buffer: %s\r\n", rx_buffer);
            }

        }
        Delay_Ms(500);
    }
}





void USART2_IRQHandler(void)
{
    uint16_t ret = 0;
    if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
        ret= USART2->DR;
        gBL.rx_buffer[gBL.rx_buffer_current_cnt % sizeof(gBL.rx_buffer)] = ret;
        gBL.rx_buffer_current_cnt++;
    }

}

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值