小车避障功能的实现(第八天)
👨💻个人主页:@开发者-削好皮的Pineapple!
👨💻 hello 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!
👨💻 本文由 削好皮的Pineapple! 原创
👨💻 收录于专栏:C语言到基于STM32 的智能矿探小车
文章目录
- 🎶一、UART通信
- 🎶二、基于STM32F407固件库UART的配置流程
- 2.1 时钟使能
- 2.2 GPIO的配置
- 2.3 把GPIO复用成对应的串口
- 2.4 串口初始化
- 2.5 串口中断的配置
- 2.6 NVIC的配置
- 2.7 打开串口
- 2.8 中断服务函数的格式
- 2.9串口接收数据/发送数据的接口
- 🎶三、HC05模块
- 结束语🥇
⭐前言⭐
-本文是对UART通信、基于STM32F407固件库UART的配置流程以及HC05模块相关知识的笔记总结,涵盖了通信的基本概念、配置步骤和模块使用等内容,旨在为后续的嵌入式开发提供参考。
🎶一、UART通信
- UART 是异步全双工串行通信。
- 通信的前提:通信双方要同步。
- 同步机制和异步机制的区别在于通信双方是否有相同的参考(时钟线)。
- 有通用时钟线属于同步机制。
- 没有通用时钟线属于异步机制。
- 异步:通信双方没有通用时钟线,通信双方需要提前约定用相同的波特率进行通信。
- 同步机制和异步机制的区别在于通信双方是否有相同的参考(时钟线)。
- 单工通信:A 单向发送数据到 B(A ----> B)。
- 双工通信:
- 半双工通信:接收数据和发送数据不能够同时进行(A ------> B 与 A <------ B 不同时)。
- 全双工通信:接收数据和发送数据可以同时进行(A ------> B 与 A <------ B 同时)。
- 串行:发送/接收数据只用了一根数据线,每次只能 1bit 1bit 发送/接收。
- 支持串口(UART)通信的设备通常具有如下引脚:
设备A 设备B Tx Rx Rx Tx VCC VCC GND GND - 对于STM32F407本次使用的开发板上提供了三个UART引脚:P4(UART1)、P5(UART2)和P6(UART3)处。
🎶二、基于STM32F407固件库UART的配置流程
2.1 时钟使能
- 使能对应GPIO时钟:
RCC_AHB1PeriphClockCmd
。 - 使能对应的USARTx(USART1、USART2和USART3)时钟:
- 对于USART1,应该使用
RCC_APB2PeriphClockCmd
。 - 对于USART2和USART3,应该使用
RCC_APB1PeriphClockCmd
。
- 对于USART1,应该使用
2.2 GPIO的配置
- 使用
GPIO_Init
函数配置。- Tx:复用模式,推挽模式。
- Rx:复用模式,浮空模式。
- 注意:对于通信一般选择高速电平切换。
2.3 把GPIO复用成对应的串口
- 使用
GPIO_PinAFConfig
函数,函数格式为:GPIO_PinAFConfig(GPIO_TypeDef * GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
。GPIOx
:指定具体的GPIO组号,如GPIOA、GPIOB等。GPIO_PinSource
:指定具体的引脚编号,如GPIO_PinSource0、GPIO_PinSource1……GPIO_PinSource15。GPIO_AF
:指定具体要复用成的功能,如GPIO_AF_USART1(复用成串口1的引脚)、GPIO_AF_USART2(复用成串口2的引脚)等。
- 注意:该接口不支持位或。例如UASRT1的Tx接PA9,Rx接PA10时,配置如下:
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9 , GPIO_AF_UASRT1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10 , GPIO_AF_UASRT1);
2.4 串口初始化
- 使用
USART_Init
函数,函数格式为:USART_Init(USART_TypeDef * USARTx, USART_InitTypeDef * USART_InitStruct)
。USARTx
:指定具体的串口,如USART1、USART2、USART3。USART_InitStruct
结构体成员:USART_BaudRate
:指定具体的波特率,如115200、9600等。USART_WordLength
:指定数据位,常用USART_WordLength_8b
。USART_StopBits
:指定停止位,常用USART_StopBits_1
。USART_Parity
:奇偶校验位,常用USART_Parity_No
(无校验),还有USART_Parity_Even(偶校验)、USART_Parity_Odd(奇校验)。USART_Mode
:指定串口模式,USART_Mode_Rx
(接收数据)、USART_Mode_Tx
(发送数据)、USART_Mode_Rx | USART_Mode_Tx
(收发数据)。USART_HardwareFlowControl
:硬件控制流,常用USART_HardwareFlowControl_None
(无控制流)。
2.5 串口中断的配置
- 使用
USART_ITConfig
函数,函数格式为:USART_ITConfig(USART_TypeDef * USARTx, uint16_t USART_IT, FunctionalState NewState)
。USARTx
:指定具体的串口,如USART1、USART2、USART3。USART_IT
:指定触发因素,如USART_IT_RXNE
(接收数据触发中断)。NewState
:ENABLE
(使能)。
2.6 NVIC的配置
- 使用
NVIC_Init
函数,中断通道分别为USART1_IRQn
、USART2_IRQn
等。
2.7 打开串口
- 使用
USART_Cmd
函数,函数格式为:USART_Cmd(USART_TypeDef * USARTx, FunctionalState NewState)
。USARTx
:指定具体的串口,如USART1、USART2、USART3。NewState
:ENABLE
(使能)。
2.8 中断服务函数的格式
- 以USART1为例:
void USART1_IRQHandler(void) {if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET) //接收到数据{//...USART_ClearITPendingBit( USART1, USART_IT_RXNE);} }
2.9串口接收数据/发送数据的接口
-
接收数据:
USART_ReceiveData(USART_TypeDef * USARTx)
USARTx
:指定用什么串口接收数据,如USART1、USART2、USART3。- 返回值:返回接收到的数据。
- 说明:由于不能预料对方什么时候发送数据,一般开启串口接收数据的中断,该接口一般在中断服务函数中调用。
-
发送数据:
USART_SendData(USART_TypeDef * USARTx, uint16_t Data)
USARTx
:指定用什么串口发送数据,如USART1、USART2、USART3。Data
:要发送的数据。
-
相关配置修改:
- 在
smt32f4xx.h
的第144行HSE_VALUE
为8000000。 - 在
system_stm32f4xx.c
的第371行把25修改成8即可。 - 串口1用来下载程序,可按照串口1的配置流程,实现串口2和串口3的配置。
- 在
#include "stm32f4xx.h"
#include "uart.h"//串口1为例 Tx (PA9) Rx(PA10)
void uart_init(int bond)
{GPIO_InitTypeDef GPIO_InitStruct;USART_InitTypeDef USART_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;//1.时钟使能RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//2.GPIO初始化//TX 复用推挽GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;GPIO_Init(GPIOA, & GPIO_InitStruct);//RX 复用浮空GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;GPIO_Init(GPIOA, & GPIO_InitStruct);//3.把GPIO复用成对应的功能GPIO_PinAFConfig( GPIOA, GPIO_PinSource9, GPIO_AF_USART1);GPIO_PinAFConfig( GPIOA, GPIO_PinSource10, GPIO_AF_USART1);//4.串口初始化USART_InitStruct.USART_BaudRate = bond;//指定波特率USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_InitStruct.USART_Parity = USART_Parity_No;USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStruct);//5.串口接收数据中断USART_ITConfig( USART1, USART_IT_RXNE, ENABLE);//6.NVIC的配置NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStruct);//7.打开串口USART_Cmd( USART1, ENABLE);
}u8 recv; //串口1接收数据//串口中断服务函数
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET) //接收到数据{recv = USART_ReceiveData(USART1);USART_SendData(USART1, recv);USART_ClearITPendingBit( USART1, USART_IT_RXNE);}
}
#ifndef __UART_H__
#define __UART_H__
#include "stm32f4xx.h"//串口1为例 Tx (PA9) Rx(PA10)
void uart_init(int bond);extern u8 recv;#endif
🎶三、HC05模块
- HC05模块与单片机的连接:
HC05模块 单片机 VCC 5V GND GND TXD(发送数据的引脚) 单片机的RX RXD(接收数据的引脚) 单片机的TX
-
蓝牙的相关信息:
- 蓝牙的连接密码:1234。
- 蓝牙的设备名称:需要通过AT指令修改。
-
修改蓝牙设备名称的方法:
- 接线:
- VCC ----------- P4处的5V
- GND ----------- P4处的GND
- TX ---------- UART1处的1号引脚
- RX ---------- UART1处的2号引脚
- 如果按住按钮发送没有反应:
- 按住按钮重新给蓝牙模块上电,直到蓝牙模块上的指示灯闪烁变慢,说明此时进入了AT指令模式。
- 把波特率更改成38400,再尝试发送
AT+NAME=XXX
【回车】。
- 接线:
-
注意:请用手机配对自己的蓝牙设备,为了避免麻烦,蓝牙建议使用串口2或者串口3。
-
工作原理:
- 手机与蓝牙模块通过无线信号连接,蓝牙模块和单片机之间通过串口(USART2、USART3)通信。
- 手机发送给蓝牙模块的数据,蓝牙模块会完完整整的通过串口发送给单片机。
- 连接方式为 TX -------------- RX,RX -------------- TX。
- 在主函数直接调用,用手机蓝牙串口APP控制小车的运动状态。
#include "stm32f4xx.h"
#include "exit.h"
#include "car.h"
#include "delay.h"
//#include "remote.h"
#include "uart.h"
#include "led.h"// 声明全局变量recv
extern uint8_t recv;int main(void) {SystemInit();car_init();//remote_Init();delay_init(); // 初始化定时器led_init();uart_init(9600); // 初始化串口通信while(1) {if(recv == '1') {led_ctrl(D4, ON);}else if(recv == 'F') {car_up();}else if(recv == 'B') {car_back();}else if(recv == 'L') {car_left();}else if(recv == 'R') {car_right();}else if(recv == 'S') {car_stop();}delay_ms(1); // 实现实时循环,控制循环频率}
}
结束语🥇
🔥 订阅专栏持续学习:C语言到基于STM32的智能矿探小车
💬 欢迎点赞、收藏、留言讨论,一起攻克嵌入式开发!