项目需求
手机通过蓝牙模块远程遥控风扇。
硬件接线
项目框图
1 plugin插座模块
1.1 plugin模块初始化
void plugin_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
HAL_RCC_GPIOB_CLK_ENABLE();
//调用GPIO初始化函数
gpio_initstruct.Pin = GPIO_PIN_6; //选择PB6
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;//浮空推完输出 低电平触发
gpio_initstruct.Pull = GPIO_PULLUP;// 上拉电阻,低电平触发
gpio_initstruct.Speed= GPIO_SPEED_FREQ_HIGH;//随意
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
plugin1_off();
}
1.2 初始化GPIO函数
void plugin1_on(void)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
}
1.3 打开插座的函数
void plugin_off(void)
{
//由电路图可知,将GPIO拉低
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
}
1.4 获取继电器的状态 --为什么
uint8_t plugin_status_get(void)
{
return (uint8_t)HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6)
}
2 串口模块代码封装
2.1 头文件
#include "sys.h"
#include "uart1.h"
#include "string.h"
#include "stdio.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 64
void uart1_init(uint32_t bound); /* 串口初始化函数 */
UART_HandleTypeDef uart1_handle
uint8_t uart1_rx_buf[UART_RX_BUF_SIZE];
uint16_t uart1_rx_len = 0;
/**
* @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;
}
2.2UART初始化
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.HwFlowCtl = HWCONTROL_NONE; /* 无硬件流控制 */
UART1_handle.Init.Parity = UART_PARITY_NONE; /*无奇偶校验位*/
uart1_handle.Init.Mode = UART_MODE_TX_RX; /*收发模式*/
HAL_UART_Init(&uart1_handle);
}
2.3 UART底层代码初始化
UART底层初始化函数
huart: UART句柄类型指针
此函数会被HAL_UART_Init()调用
完成时钟使能,引脚配置,中断配置
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
//GPIO,UART时钟使能
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
//GPIO配置串口 输入输出引脚 Tx
GPIO_InitTypeDef gpio_init_struct;
gpio_init_struct.Pin = GPIO_PIN_9;
gpio_init_struct.Mode = GPIO_MODE_AF_PP;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_ihit_struct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&gpio_init_struct);
//RX配置
gpio_init_struct.Pin = GPIO_PIN_10;
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
HAL_UART_Init(GPIOA,&gpio_init_struct);
//NVIC配置
HAL_NVIC_EnableIRQ(USART2_IRQn);
HAL_NVIC_SetPriority(USART2_IRQn,3,3);
//空闲中断输入
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
}
//蓝牙模块串口通道
else if(huart->Instance == USART2)
{
//GPIO,UART时钟使能
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
//GPIO配置串口 输入输出引脚 Tx
GPIO_InitTypeDef gpio_init_struct;
gpio_init_struct.Pin = GPIO_PIN_2;
gpio_init_struct.Mode = GPIO_MODE_AF_PP;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_ihit_struct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&gpio_init_struct);
//RX配置
gpio_init_struct.Pin = GPIO_PIN_3;
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
HAL_UART_Init(GPIOA,&gpio_init_struct);
//NVIC配置
HAL_NVIC_EnableIRQ(USART2_IRQn);
HAL_NVIC_SetPriority(USART2_IRQn,3,3);
//空闲中断输入
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
}
}
2.4UART1接收缓冲区清除
void uart1_rx_clear(void)
{
memset(uart1_rx_buf,0,sizeof(uart1_rx_buf));
uart1_rx_len = 0;
}
2.5 串口1中断服务函数
void USART1_IRQHandle(void)
{
uint8_t receive_data = 0;
if(__HAL_UART_GET_FLAG(&uart1_handle, UART_FLAG_RXNE) !=RESET)//非空判断
{
if(uart1_rx_len >= sizeof(uart1_rx_buf))
uart_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);//清楚空闲中断发送标志位
}
}
3蓝牙模块
3.5蓝牙模块头文件
#include "sys.h"
#include "bluetooth.h"
#include "string.h"
#include "stdarg.h"
#include "plugin.h"
/* UART收发缓冲大小 */
#define UART2_RX_BUF_SIZE 128
void bt_init(uint32_t bound); /* 串口初始化函数 */
//void bt_send(char *send_buf,uint8_t size);
void bt_send(char * format,...);
UART_HandleTypeDef uart2_handle;
uint8_t uart2_rx_buf[UART2_RX_NIF_SIZE];
uint16_t uart2)rx_len = 0;
3.1蓝牙串口初始化
void bt_init(uint32_t bound)
{
uart2_handle.Instance = USART2; /* USART1 */
uart2_handle.Init.BaudRate = bound; /* 波特率 */
uart2_handle.Init.WordLenght = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
uart2_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
uart2_handle.Init.Priaty = UART_PRIATY_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 */
}
3.2蓝牙串口数组数据清楚
void uart2_rx_clear(void)
{
memset(uart2_rx_buf,0,sizeof(uart2_rx_buf));
uart2_rx_len = 0;
}
3.3中断服务函数
void UART_IRQHandler(void)
{
uint8_t receive_data = 0;
if(__HAL_UART_GET_FLAG(&uart2_handle, UART_FLAG_RXNE) != RESET)//接收数据
{
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);
//判断是否有某个字符串用strstr 字符串中首串的地址
if(strstr(char *)uart2_rx_buf,"on" !=NULL)
plugin1_on();
if(strstr(char *)uart2_rx_buf,"off" !=NULL)
plugin1_off();
uart2_rx_clear();
__HAL_UART_CLEAR_IDLEFLAG(&uart2_handle);
}
}
3.4不定长传输
void bt_send(char * format,...)
{
uint8_t send_buf[128] = {0};
va_list arg; //创建一个参数列表va_list
va_start(arg,format); //初始化发送的数组
vsprintf((char *)send_buf,format,arg);
va_end(arg);
HAL_UART_Transmit(&uart2_handle,send_buf,sizeof(send_buf),100);
}