参考:

介绍

简介

特性

系统框图

查看引脚定义

在芯片数据手册查找
芯片数据手册下载方式参考获取资料手册
外设信息:

引脚定义:

相关函数

接口定义

UART_HandleTypeDef

UART_InitTypeDef

MSP回调函数机制

初始化钩子函数

中断回调

常用函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
HAL_UART_Init(UART_HandleTypeDef *huart);    //初始化usart外设

void HAL_UART_MspInit(UART_HandleTypeDef *huart); //初始化钩子函数

__HAL_RCC_USART1_CLK_ENABLE(); //使能usart1时钟

HAL_NVIC_EnableIRQ(USARTX_IRQn); //使能usartX中断

HAL_NVIC_SetPriority(USARTX_IRQn, 3, 3); //设置usartX中断优先级

HAL_UART_Receive_IT
(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); //开启接收中断

void USARTX_IRQHandler(void); //usartX中断服务函数

HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //中断处理公用函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //接收完成回调函数

// hal库发送数据
HAL_UART_Transmit
(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

// 寄存器发送数据
while ((USARTX->SR & 0X40) == 0);
USARTX->DR = (uint8_t)ch;

函数详解

HAL_UART_Init

HAL_UART_Receive_IT

HAL_UART_Transmit

应用示例

串口收发数据

宏定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define USART_TX_GPIO_PORT                  GPIOA
#define USART_TX_GPIO_PIN GPIO_PIN_9
#define USART_TX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */

#define USART_RX_GPIO_PORT GPIOA
#define USART_RX_GPIO_PIN GPIO_PIN_10
#define USART_RX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */

#define USART_UX USART1
#define USART_UX_IRQn USART1_IRQn
#define USART_UX_IRQHandler USART1_IRQHandler
#define USART_UX_CLK_ENABLE() do{ __HAL_RCC_USART1_CLK_ENABLE(); }while(0) /* USART1 时钟使能 */

/***************************************************/
#define USART_REC_LEN 200 /* 定义最大接收字节数 200 */
#define USART_EN_RX 1 /* 使能(1)/禁止(0)串口1接收 */
#define RXBUFFERSIZE 1 /* 缓存大小 */

全局变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* 接收缓冲, 最大USART_REC_LEN个字节. */
uint8_t g_usart_rx_buf[USART_REC_LEN];

/* 接收状态
* bit15, 接收完成标志
* bit14, 接收到0x0d
* bit13~0, 接收到的有效字节数目
*/
uint16_t g_usart_rx_sta = 0;

uint8_t g_rx_buffer[RXBUFFERSIZE]; /* HAL库使用的串口接收缓冲 */

UART_HandleTypeDef g_uart1_handle; /* UART句柄 */

初始化usart外设:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
* @brief 串口X初始化函数
* @param baudrate: 波特率, 根据自己需要设置波特率值
* @note 注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常.
* 这里的USART的时钟源在sys_stm32_clock_init()函数中已经设置过了.
* @retval 无
*/
void usart_init(uint32_t baudrate)
{

/*UART 初始化设置*/
g_uart1_handle.Instance = USART_UX; /* USART_UX */
g_uart1_handle.Init.BaudRate = baudrate; /* 波特率 */
g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式 */
g_uart1_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
g_uart1_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
g_uart1_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
HAL_UART_Init(&g_uart1_handle); /* HAL_UART_Init()会使能UART1 */

/* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
}

/**
* @brief UART底层初始化函数
* @param huart: UART句柄类型指针
* @note 此函数会被HAL_UART_Init()调用
* 完成时钟使能,引脚配置,中断配置
* @retval 无
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef gpio_init_struct;

if (huart->Instance == USART_UX) /* 如果是串口1,进行串口1 MSP初始化 */
{
USART_TX_GPIO_CLK_ENABLE(); /* 使能串口TX脚时钟 */
USART_RX_GPIO_CLK_ENABLE(); /* 使能串口RX脚时钟 */
USART_UX_CLK_ENABLE(); /* 使能串口时钟 */

gpio_init_struct.Pin = USART_TX_GPIO_PIN; /* 串口发送引脚号 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* IO速度设置为高速 */
HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct);

gpio_init_struct.Pin = USART_RX_GPIO_PIN; /* 串口RX脚 模式设置 */
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct); /* 串口RX脚 必须设置成输入模式 */

#if USART_EN_RX
HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* 使能USART1中断通道 */
HAL_NVIC_SetPriority(USART_UX_IRQn, 3, 3); /* 组2,最低优先级:抢占优先级3,子优先级3 */
#endif
}
}

中断函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* @brief 串口1中断服务函数
* @param 无
* @retval 无
*/
void USART_UX_IRQHandler(void)
{
#if SYS_SUPPORT_OS /* 使用OS */
OSIntEnter();
#endif

HAL_UART_IRQHandler(&g_uart1_handle); /* 调用HAL库中断处理公用函数 */

#if SYS_SUPPORT_OS /* 使用OS */
OSIntExit();
#endif

}

/**
* @brief 串口数据接收回调函数
数据处理在这里进行
* @param huart:串口句柄
* @retval 无
*/
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) /* 接收到的不是0x0a(即不是换行键) */
{
g_usart_rx_sta = 0; /* 接收错误,重新开始 */
}
else /* 接收到的是0x0a(即换行键) */
{
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);
}
}

主函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int main(void)
{
uint8_t len;
uint16_t times = 0;

HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(115200); /* 串口初始化 */

while(1)
{
if (g_usart_rx_sta & 0x8000) /* 接收到了数据? */
{
len = g_usart_rx_sta & 0x3fff; /* 得到此次接收到的数据长度 */
printf("\r\n您发送的消息为:\r\n");

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 % 5000 == 0)
{
printf("\r\n正点原子 STM32开发板 串口实验\r\n");
printf("正点原子@ALIENTEK\r\n\r\n\r\n");
}

if (times % 200 == 0) printf("请输入数据,以回车键结束\r\n");

if (times % 30 == 0) LED0_TOGGLE(); /* 闪烁LED,提示系统正在运行. */

delay_ms(10);
}
}
}