STM32——串口
一、数据通信的基础概念
1.1 串行/并行通信
1.2 单工/半双工/全双工通信
1.3 同步/异步通信
1.4 常见的串行通信接口
二、串口(RS-232)
2.1 什么是串口
串行通信接口:指按位发送和接收的接口。如:RS-232/422/485等。
2.2 设备间的RS-232通信示意图
2.3 STM32串口与电脑USB口通信示意图
2.4 RS-232异步通信协议
三、STM32的USART
3.1 STM32的USART简介
Universal synchronous asynchronous receiver transmitter,通用同步异步收发器。
Universal asynchronous receiver transmitter,通用异步收发器。
USART/UART都可以与外部设备进行全双工异步通信。
USART,我们常用的也是异步通信。
STM32的USART主要特征
1,全双工异步通信
2,单线半双工通信
3,单独的发送器和接收器使能位
4,可配置使用DMA的多缓冲器通信
5, 多个带标志的中断源
3.2 STM32F1/F4/F7的USART框图
3.3 设置USART/UART波特率(F1)
3.4 USART寄存器介绍(F1)
控制寄存器1(CR1)
该寄存器需要完成的配置:
位13:使能USART
位12:配置8个数据位
位10:禁止检验控制
位5:使能接收缓冲区非空中断
位3:使能发送
位2:使能接收
控制寄存器2(CR2)
控制寄存器3(CR3)
数据寄存器(DR)
状态寄存器(SR)
四、HAL库回调机制
4.1 HAL库外设初始化MSP回调机制
4.2 HAL库中断回调机制
五、USART/UART异步通信配置步骤
5.1 配置步骤
5.2 HAL库相关函数介绍
六、IO引脚复用功能
6.1 概念
通用: IO端口的输入或输出是由GPIO外设控制,我们称之为通用
复用: IO端口的输入或输出是由其它非GPIO外设控制,我们称之为复用
6.2 STM32F1的IO引脚复用
七、案例(接收和发送一个字符)
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
/* printf函数 */
#if 1
#if (__ARMCC_VERSION >= 6010050)
__asm(".global __use_no_semihosting\n\t");
__asm(".global __ARM_use_no_argv \n\t");
#else
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
#endif
int _ttywrch(int ch)
{
ch = ch;
return ch;
}
void _sys_exit(int x)
{
x = x;
}
char *_sys_command_string(char *cmd, int len)
{
return NULL;
}
FILE __stdout;
int fputc(int ch, FILE *f)
{
while ((USART1->SR & 0X40) == 0);
USART1->DR = (uint8_t)ch;
return ch;
}
#endif
/******************************************************************************************/
UART_HandleTypeDef g_uart1_handle; /* 句柄 */
uint8_t g_rx_buffer[1];//接收缓冲区
uint8_t g_usart_isrx_flag = 0;//串口接收到数据标志
void usart_init(uint32_t baudrate)
{
g_uart1_handle.Instance = USART1;//基地址
g_uart1_handle.Init.BaudRate = baudrate;//波特率
g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;//
g_uart1_handle.Init.StopBits = UART_STOPBITS_1;//停止位
g_uart1_handle.Init.Parity = UART_PARITY_NONE;//校验位
g_uart1_handle.Init.Mode = UART_MODE_TX_RX;//模式
g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;//硬件流控
HAL_UART_Init(&g_uart1_handle);
//开启串口接收异步中断
HAL_UART_Receive_IT(&g_uart1_handle,(uint8_t*)g_rx_buffer,1);
}
/* MSP回调函数 */
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef gpio_init_struct;
if(huart->Instance == USART1)
{
__HAL_RCC_USART1_CLK_ENABLE();//使能USART1对应的时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
//初始化IO
gpio_init_struct.Pin = GPIO_PIN_9 ;
gpio_init_struct.Mode = GPIO_MODE_AF_PP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH ;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
gpio_init_struct.Pin = GPIO_PIN_10 ;
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
//使能中断,设置优先级
HAL_NVIC_SetPriority(USART1_IRQn,2,2);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}
/* 串口1的中断服务函数 */
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&g_uart1_handle);
//由于上面的函数会失能串口接收中断因此需要重新使能
HAL_UART_Receive_IT(&g_uart1_handle,(uint8_t*)g_rx_buffer,1);
}
/* 接收完成回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
g_usart_isrx_flag = 1;
}
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
int main(void)
{
HAL_Init();
sys_stm32_clock_init(RCC_PLL_MUL9);
delay_init(72);
usart_init(115200); /* 波特率位115200 */
printf("请输入一个字符:\r\n");
while(1)
{
if(g_usart_isrx_flag == 1)
{
printf("输入的字符为\r\n");
//发送
HAL_UART_Transmit(&g_uart1_handle,(uint8_t*)g_rx_buffer,1,1000);
while(__HAL_UART_GET_FLAG(&g_uart1_handle,UART_FLAG_TC) != 1);
printf("\r\n");
g_usart_isrx_flag = 0;
}
else
{
delay_ms(50);
}
}
}