提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
自己STM32F4串口通信的基本记录
提示:以下是本篇文章正文内容,下面案例可供参考
一、串口通信是什么?
UART串口通信我相信大家都是耳熟能详,本文基于STM32F4,详细说明了基于HAL库,串口通信的相关配置过程。
二、串口通信的配置步骤
1.初始化串口相关参数,使能串口(HAL_UART_Init)
首先查看一下该函数的声明:
HAL_StatuesTypeDef HAL_UART_Init(UART_HandleTypedef *huart)
函数描述:
用于初始化异步模式的收发器。
函数形参:
形参是串口的句柄,UART_HandleTypedef的结构体类型,其定义如下图:
1)指针Instance:指向UART寄存器的基地址。实际上这个基地址在HAL库中已经定义好了。
2)Init:UART的初始化结构体。用于配置通讯参数:波特率、字长、停止位、奇偶校验等等
3)pTxBuffer、TxXferSize、TxXferCount:分别指向发送缓冲区的地址,发送数据的大小,发送数据的个数。
3)pRxBuffer、RxXferSize、RxXferCount:分别指向接收缓冲区的地址,接收数据的大小,接收数据的个数。
4)结构体的其他内容暂时用不到,这里不再做介绍。
UART_InitTypeDef:
typedef struct
{
uint32_t BaudRate;
uint32_t WordLength;
uint32_t StopBits;
uint32_t Parity;
uint32_t Mode;
uint32_t HwFlowCtl;
uint32_t OverSampling;
} UART_InitTypeDef;
1) BaudRate:波特率设置。一般设置为9600、115200。
2)WordLength:数据帧字长,可选8位或9位。在这里我们设置为8位字长的数据格式。
3)StopBits:停止位设置,可选0.5,1,1.5,2个停止位,我们选择一个停止位。
4) Parity:奇偶校验。通常设置为无奇偶校验。
5)Mode:UART模式选择,可以设置为只发、只收、或者收发模式。我们设置为收发模式。
5)HwFlowCtl:硬件流控制,我们设置为无硬件流控制。
6)OverSampling:过采样选择,通常选择16倍过采样
注意:上述的结构体成员变量可选择的范围在HAL库中都被宏定义枚举类型,按照要求选择即可。如图:
2.串口相关IO配置、复用设置以及串口中断优先级配置和使能
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
HAL_UART_MspInit:在HAL在库中,该函数被定义为一个弱函数。用于可以重定义该函数。在实际程序中,我们通常在该函数中完成串口的相关IO配置、复用设置以及串口中断优先级设置和使能。例如串口一:
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef gpio_init_struct; /*GPIO初始化结构体*/
if (huart->Instance == USART_UX) /* 如果是串口1,进行串口1 MSP初始化 */
{
__HAL_RCC_USART1_CLK_ENABLE(); /* USART1 时钟使能 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 发送引脚时钟使能 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 接收引脚时钟使能 */
gpio_init_struct.Pin = GPIO_Pin_9; /* TX引脚 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = GPIO_AF7_USART1; /* 复用为USART1 */
HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct); /* 初始化发送引脚 */
gpio_init_struct.Pin = GPIO_Pin_10; /* RX引脚 */
gpio_init_struct.Alternate = GPIO_AF7_USART1; /* 复用为USART1 */
HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct); /* 初始化接收引脚 */
#if USART_EN_RX /*如果接受使能,在uart.h中宏定义为1*/
HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* 使能USART1中断通道 */
HAL_NVIC_SetPriority(USART_UX_IRQn, 3, 3); /* 抢占优先级3,子优先级3 */
#endif
}
}
3.开启串口接收中断函数
/* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
函数描述:接收中断函数
函数形参:第一个参数是串口的句柄,第二个是接缓冲区的地址,第三个参数是接收的数据量
注意:该函数会在串口的初始化函数(uart_init)和接收的回调函数中被调用
4.编写接收中断服务函数USART_UX_IRQHandler
在USART_UX_IRQHandler中调用HAL库中断处理公用函数HAL_UART_IRQHandler(&g_uart1_handle),然后在该函数内部再调用中断回调函数HAL_UART_RxCpltCallback来处理用户的逻辑代码。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART_UX) /* 如果是串口1 */
{
if ((g_usart_rx_sta & 0x8000) == 0) /* 接收未完成 */
{
if (g_usart_rx_sta & 0x4000) /* 接收到了0x0d */
{
if (g_rx_buffer[0] != 0x0a)
{
g_usart_rx_sta = 0; /* 接收错误,重新开始 */
}
else
{
g_usart_rx_sta |= 0x8000; /* 接收完成了 */
}
}
else /* 还没收到0X0D */
{
if (g_rx_buffer[0] == 0x0d)
{
g_usart_rx_sta |= 0x4000;
}
else
{
g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = g_rx_buffer[0] ;
g_usart_rx_sta++;
if (g_usart_rx_sta> (USART_REC_LEN - 1))
{
g_usart_rx_sta = 0; /* 接收数据错误,重新开始接收 */
}
}
}
}
HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
}
}
g_usart_rx_sta | ||
bit15 | bit14 | bit13~0 |
接收完成标志 | 接收到0X0D标志 | 接收到有效字节个数 |
三、主函数的编写
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
int main(void)
{
uint8_t len;
uint16_t times = 0;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(360, 25, 2, 8); /* 设置时钟,180Mhz */
delay_init(180); /* 延时初始化 */
usart_init(115200); /* 初始化USART */
while (1)
{
if (g_usart_rx_sta & 0x8000) /* 接收到了数据? */
{
len = g_usart_rx_sta & 0x3fff;
HAL_UART_Transmit(&g_uart1_handle, (uint8_t *)g_usart_rx_buf, len, 1000); /* 发送接收到的数据 */
while(__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_TC) != SET); /* 等待发送结束 */
printf("\r\n\r\n"); /* 插入换行 */
g_usart_rx_sta = 0;
}
else
{
times++;
if (times % 1000 == 0)
{
printf("请输入数据,以回车键结束\r\n");
}
delay_ms(10);
}
}
}
代码如下(示例):
data = pd.read_csv(
'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())
总结
串口学习的记录,仅供参考。