STM32CubeMX之串口配置
串口通信是一种设备间非常常用的串行通信方式,以比特位的形式发送或接收数据,电子工程师经常使用这种方式来调试数据。本章节我们将学习串口发送和接收数据。STM32F103C8开发板通过串口协议和上位机软件对话,实现设备间的数据传输。
1.串口简介
通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。 USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。使用多缓冲器配置的DMA方式,可以实现高速数据通信。
串口是计算机上一种非常通用设备通信的协议。大多数计算机包含两个基于RS232的串口。串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。同时,串口通信协议也可以用于获取远程采集设备的数据。本次所所使用开发板为mini USB串口,有3个分别为USART1、USART2和USART3。我们将以串口1为例完成开发板与上位机之间通讯。
2.串口特性
- 全双工:串行发送TX和串行接收RX(发送数据和接收数据不会相互干扰);
- 异步通信:一帧数据包含起始位,数据位,(校验位)停止位;
- 最高通信速率:4.5Mbit/s
3.串口功能概述
任何USART双向通信至少需要两个脚:接收数据输入(RX)和发送数据输出(TX)。
- RX:接收数据串行输。通过过采样技术来区别数据和噪音,从而恢复数据。
- TX:发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器被激活,并且不发送数据时, TX引脚处于高电平。在单线和智能卡模式里,此I/O口被同时用于数据的发送和接收。
- 总线在发送或接收前应处于空闲状态。
- 一个起始位。
- 一个数据字(8或9位),最低有效位在前。
- 0.5, 1.5, 2个的停止位,由此表明数据帧的结束。
- 使用分数波特率发生器 —— 12位整数和4位小数的表示方法。
- 一个状态寄存器(USART_SR)。
- 数据寄存器(USART_DR)。
- 一个波特率寄存器(USART_BRR), 12位的整数和4位小数。
- 一个智能卡模式下的保护时间寄存器(USART_GTPR)。
4.串口特性描述
1.串口是全双工通讯,串行发送TX和串行接收RX(发送数据和接收数据不会相互干扰);
2.异步通信方式,一帧数据包含起始位,数据位,(校验位)停止位;
3.最高通信速率:4.5Mbit/s
字长可以通过编程USART_CR1 寄存器中的M位,如下图。在起始位期间, TX脚处于低电平,在停止位期间处于高电平。
空闲符号被视为完全由’1’组成的一个完整的数据帧,后面跟着包含了数据的下一帧的开始位(‘1’的位数也包括了停止位的位数)。
断开符号 被视为在一个帧周期内全部收到’0’(包括停止位期间,也是’0’)。在断开帧结束时,发送器再插入1 或2个停止位(‘1’)来应答起始位。
发送和接收由一共用的波特率发生器驱动,当发送器和接收器的使能位分别置位时,分别为其产生时钟。
5.硬件接口
使用跳线帽将PA9与CH340_RXD相连,PA10与CH340_TXD相连。
6.软件设计
打开STM32CbeMX软件,配置串口串口、开启串口中断。
串口1配置:全双工异步通信、波特率为115200、8个数据位、1个停止位、无校验位
优先级分组设置:2位抢占优先级2位副优先级
7.生成代码
- 基本参数配置示例
波特率、数据位、停止位、校验位
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200; //波特率
huart1.Init.WordLength = UART_WORDLENGTH_8B;//数据位
huart1.Init.StopBits = UART_STOPBITS_1;//停止位
huart1.Init.Parity = UART_PARITY_NONE;//校验位
huart1.Init.Mode = UART_MODE_TX_RX;//开启发送和接收功能
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
- 中断和硬件接口配置
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
uartHandle->Instance->CR1|=1<<5;//接收中断
// __HAL_UART_ENABLE_IT(uartHandle, UART_IT_RXNE);//开启接收中断
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
- 中断服务函数示例
HAL库将所有的中断服务函数都保存在stm32f1xx_it.c中。
串口1中断服务函数:
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
u8 c;
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
if(HAL_UART_GetState(&huart1) == HAL_UART_STATE_READY)//是否为串口接收中断
{
c=huart1.Instance->DR;//中断接收一个字符
if(usart1_cnt<200 && !usart1_flag)
{
usart1_rx_buff[usart1_cnt]=c;
if(c=='\n')
{
usart1_rx_buff[usart1_cnt-1]='\0';
usart1_flag=1;
}
else usart1_cnt++;
}
else usart1_flag=1;
}
/* USER CODE END USART1_IRQn 1 */
}
- printf函数重定向
为了方便硬件代码调试,可以通过串口完成printf函数重定向,修改底层fputc函数,将向标准输出的终端打印信息修改为向串口调试助手打印。
int fputc(int c, FILE *stream)
{
HAL_UART_Transmit(&huart1,(u8 *)&c,1,10);
return c;
}
- 主函数
主函数主要实现功能为通按键控制蜂鸣器开关,利用串口打印按键状态信息。通过串口中断实时处理串口接收信息。
key=KEY_GetVal();
if(key)
{
HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_SET);
HAL_Delay(50);
HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_RESET);
printf("串口发送数据测试,key=%d\n",key);
}
- 运行结果: