欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > 【STM32单片机_(HAL库)】6-6-1【串口通信UART、USART】【蓝牙遥控插座项目】HC-08蓝牙模块实验

【STM32单片机_(HAL库)】6-6-1【串口通信UART、USART】【蓝牙遥控插座项目】HC-08蓝牙模块实验

2025/2/23 19:40:25 来源:https://blog.csdn.net/labvvv/article/details/142905472  浏览:    关键词:【STM32单片机_(HAL库)】6-6-1【串口通信UART、USART】【蓝牙遥控插座项目】HC-08蓝牙模块实验

通信示意图
在这里插入图片描述

1.硬件

  • STM32单片机最小系统
  • HC-08蓝牙模块

2.软件

  • bluetooth驱动文件添加
  • main.c程序
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "bluetooth.h"int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* 初始化LED灯 */uart1_init(115200);                 /*串口1初始化*/bt_init(115200);                    /*蓝牙模块初始化,波特率根据自己设置的*/printf("hello world!\r\n");uint8_t i = 0;while(1){ bt_send("hello, bt%d\r\n", i++);//类似于printf效果delay_ms(500);
//        led1_on();
//        led2_off();
//        delay_ms(500);
//        led1_off();
//        led2_on();
//        delay_ms(500);}
}
  • uart1.c程序
#include "sys.h"
#include "uart1.h"
#include "string.h"UART_HandleTypeDef uart1_handle;                                            /* UART1句柄 */uint8_t uart1_rx_buf[UART1_RX_BUF_SIZE];                                    /* UART1接收缓冲区 */
uint16_t uart1_rx_len = 0;                                                  /* UART1接收字符长度 *//*** @brief       重定义fputc函数* @note        printf函数最终会通过调用fputc输出字符串到串口*/
int fputc(int ch, FILE *f)
{while ((USART1->SR & 0X40) == 0);                                       /* 等待上一个字符发送完成 */USART1->DR = (uint8_t)ch;                                               /* 将要发送的字符 ch 写入到DR寄存器 */return ch;
}/*** @brief       串口1初始化函数* @param       baudrate: 波特率, 根据自己需要设置波特率值* @retval      无*/
void uart1_init(uint32_t baudrate)
{/*UART1 初始化设置*/uart1_handle.Instance = USART1;                                         /* USART1 */uart1_handle.Init.BaudRate = baudrate;                                  /* 波特率 */uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;                      /* 字长为8位数据格式 */uart1_handle.Init.StopBits = UART_STOPBITS_1;                           /* 一个停止位 */uart1_handle.Init.Parity = UART_PARITY_NONE;                            /* 无奇偶校验位 */uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;                      /* 无硬件流控 */uart1_handle.Init.Mode = UART_MODE_TX_RX;                               /* 收发模式 */HAL_UART_Init(&uart1_handle);                                           /* HAL_UART_Init()会使能UART1 */
}/*** @brief       UART底层初始化函数* @param       huart: UART句柄类型指针* @note        此函数会被HAL_UART_Init()调用*              完成时钟使能,引脚配置,中断配置* @retval      无*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{GPIO_InitTypeDef gpio_init_struct;if (huart->Instance == USART1)                                          /* 如果是串口1,进行串口1 MSP初始化 */{__HAL_RCC_GPIOA_CLK_ENABLE();                                       /* 使能串口TX脚时钟 */__HAL_RCC_USART1_CLK_ENABLE();                                      /* 使能串口时钟 */gpio_init_struct.Pin = GPIO_PIN_9;                                  /* 串口发送引脚号TX(PA9) */gpio_init_struct.Mode = GPIO_MODE_AF_PP;                            /* 复用推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                                /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;                      /* IO速度设置为高速 */HAL_GPIO_Init(GPIOA, &gpio_init_struct);gpio_init_struct.Pin = GPIO_PIN_10;                                 /* 串口RX脚 模式设置 RX(PA10)*/gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;    HAL_GPIO_Init(GPIOA, &gpio_init_struct);                            /* 串口RX脚 必须设置成输入模式 */HAL_NVIC_EnableIRQ(USART1_IRQn);                                    /* 使能USART1中断通道 */HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);                            /* 组2,最低优先级:抢占优先级3,子优先级3 */__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);                          /* 使能UART1接收中断 */__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);                          /* 使能UART1总线空闲中断 */}else if (huart->Instance == USART2)                                          /* 如果是串口2,进行串口2 MSP初始化 */{__HAL_RCC_GPIOA_CLK_ENABLE();                                       /* 使能串口TX脚时钟 */__HAL_RCC_USART2_CLK_ENABLE();                                      /* 使能串口时钟 */gpio_init_struct.Pin = GPIO_PIN_2;                                  /* 串口发送引脚号TX(PA2) */gpio_init_struct.Mode = GPIO_MODE_AF_PP;                            /* 复用推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                                /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;                      /* IO速度设置为高速 */HAL_GPIO_Init(GPIOA, &gpio_init_struct);gpio_init_struct.Pin = GPIO_PIN_3;                                 /* 串口RX脚 模式设置 RX(PA3)*/gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;    HAL_GPIO_Init(GPIOA, &gpio_init_struct);                            /* 串口RX脚 必须设置成输入模式 */HAL_NVIC_EnableIRQ(USART2_IRQn);                                    /* 使能USART2中断通道 */HAL_NVIC_SetPriority(USART2_IRQn, 3, 3);                            /* 组2,最低优先级:抢占优先级3,子优先级3 */__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);                          /* 使能UART2接收中断 */__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);                          /* 使能UART2总线空闲中断 */}
}/*** @brief       UART1接收缓冲区清除* @param       无* @retval      无*/
void uart1_rx_clear(void)
{memset(uart1_rx_buf, 0, sizeof(uart1_rx_buf));                          /* 清空接收缓冲区 */uart1_rx_len = 0;                                                       /* 接收计数器清零 */
}/*** @brief       串口1中断服务函数* @note        在此使用接收中断及空闲中断,实现不定长数据收发* @param       无* @retval      无*/
void USART1_IRQHandler(void)
{uint8_t receive_data = 0;   if(__HAL_UART_GET_FLAG(&uart1_handle, UART_FLAG_RXNE) != RESET){        /* 获取接收RXNE标志位是否被置位 */if(uart1_rx_len >= sizeof(uart1_rx_buf))                            /* 如果接收的字符数大于接收缓冲区大小, */uart1_rx_len = 0;                                               /* 则将接收计数器清零 */HAL_UART_Receive(&uart1_handle, &receive_data, 1, 1000);            /* 接收一个字符 */uart1_rx_buf[uart1_rx_len++] = receive_data;                        /* 将接收到的字符保存在接收缓冲区 */}if (__HAL_UART_GET_FLAG(&uart1_handle, UART_FLAG_IDLE) != RESET)        /* 获取接收空闲中断标志位是否被置位 */{printf("recv: %s\r\n", uart1_rx_buf);                               /* 将接收到的数据打印出来 */uart1_rx_clear();__HAL_UART_CLEAR_IDLEFLAG(&uart1_handle);                           /* 清除UART总线空闲中断 */}
}
  • uart1.h程序
#ifndef __USART_H__
#define __USART_H__#include "stdio.h"
#include "sys.h"/* 错误代码 */
#define UART_EOK                     0      /* 没有错误 */
#define UART_ERROR                   1      /* 通用错误 */
#define UART_ETIMEOUT                2      /* 超时错误 */
#define UART_EINVAL                  3      /* 参数错误 *//* UART收发缓冲大小 */
#define UART1_RX_BUF_SIZE            128
#define UART1_TX_BUF_SIZE            64void uart1_init(uint32_t bound);            /* 串口初始化函数 */#endif
  • bluetooth.c程序
#include "sys.h"
#include "bluetooth.h"
#include "string.h"
#include "stdarg.h"//包含va_list的头文件UART_HandleTypeDef uart2_handle;                                            /* uart2句柄 */uint8_t uart2_rx_buf[UART2_RX_BUF_SIZE];                                    /* uart2接收缓冲区 */
uint16_t uart2_rx_len = 0;                                                  /* uart2接收字符长度 *//*** @brief       串口1初始化函数* @param       baudrate: 波特率, 根据自己需要设置波特率值* @retval      无*/
void bt_init(uint32_t baudrate)
{/*uart2 初始化设置*/uart2_handle.Instance = USART2;                                         /* USART2 */uart2_handle.Init.BaudRate = baudrate;                                  /* 波特率 */uart2_handle.Init.WordLength = UART_WORDLENGTH_8B;                      /* 字长为8位数据格式 */uart2_handle.Init.StopBits = UART_STOPBITS_1;                           /* 一个停止位 */uart2_handle.Init.Parity = UART_PARITY_NONE;                            /* 无奇偶校验位 */uart2_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;                      /* 无硬件流控 */uart2_handle.Init.Mode = UART_MODE_TX_RX;                               /* 收发模式 */HAL_UART_Init(&uart2_handle);                                           /* HAL_UART_Init()会使能uart2 */
}/*** @brief       uart2接收缓冲区清除* @param       无* @retval      无*/
void uart2_rx_clear(void)
{memset(uart2_rx_buf, 0, sizeof(uart2_rx_buf));                          /* 清空接收缓冲区 */uart2_rx_len = 0;                                                       /* 接收计数器清零 */
}/*** @brief       串口2中断服务函数* @note        在此使用接收中断及空闲中断,实现不定长数据收发* @param       无* @retval      无*/
void USART2_IRQHandler(void)
{uint8_t receive_data = 0;   if(__HAL_UART_GET_FLAG(&uart2_handle, UART_FLAG_RXNE) != RESET){        /* 获取接收RXNE标志位是否被置位 */if(uart2_rx_len >= sizeof(uart2_rx_buf))                            /* 如果接收的字符数大于接收缓冲区大小, */uart2_rx_len = 0;                                               /* 则将接收计数器清零 */HAL_UART_Receive(&uart2_handle, &receive_data, 1, 1000);            /* 接收一个字符 */uart2_rx_buf[uart2_rx_len++] = receive_data;                        /* 将接收到的字符保存在接收缓冲区 */}if (__HAL_UART_GET_FLAG(&uart2_handle, UART_FLAG_IDLE) != RESET)        /* 获取接收空闲中断标志位是否被置位 */{printf("bt recv: %s\r\n", uart2_rx_buf);                               /* 将接收到的数据打印出来 */uart2_rx_clear();__HAL_UART_CLEAR_IDLEFLAG(&uart2_handle);                           /* 清除UART总线空闲中断 */}
}//void bt_send(char *send_buf, uint8_t size)
//{
//    HAL_UART_Transmit(&uart2_handle, (uint8_t *)send_buf, size, 100);
//}void bt_send(char * format, ...)//不定长传入参数
{uint8_t send_buf[128] ={0};va_list arg;va_start(arg, format);vsprintf((char *)send_buf, format, arg);va_end(arg);HAL_UART_Transmit(&uart2_handle, send_buf, sizeof(send_buf), 100);//串口发送函数
}
  • bluetooth.h程序
#ifndef __BLUETOOTH_H__
#define __BLUETOOTH_H__#include "stdio.h"
#include "sys.h"/* UART收发缓冲大小 */    //蓝牙用串口2
#define UART2_RX_BUF_SIZE            128
#define UART2_TX_BUF_SIZE            64void bt_init(uint32_t bound);            /* 串口初始化函数 */
//void bt_send(char *send_buf, uint8_t size);
void bt_send(char * format, ...);#endif

3.实物效果

  • 硬件模块接线
STM32USB转TTLHC-08蓝牙模块
串口1—PA9(TX)RX
串口1—PA10(RX)TX
串口2—PA2(TX)RX
串口2—PA3(RX)TX
5V5V5V
GNDGNDGND

ST-Link下载方式

  • 实验现象
    将STM32单片机与蓝牙连接,打开蓝牙串口助手连接蓝牙,蓝牙模块上蓝灯长亮时,代表已连接。此时点击蓝牙串口助手HC-08界面,可以看到蓝牙模块发送来的数据。

HC-08蓝牙模块实验keil源文件

热搜词