历史上的今天
今天是:2025年06月16日(星期一)
2021年06月16日 | STM32CubeMX之串口使用(中断方式)
2021-06-16 来源:eefocus
环境:
开发板:STM32F4探索者(正点原子)
一. 在STM32CubeMX 图形化中开启串口中断
在 前一篇 STM32CubeMX之串口的使用 (阻塞模式) 的文章的基础上,打开串口中断,如下图所示:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cQaK8Sls-1594052855033)(/image/打开串口中断.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113802625.png?imageView2/2/w/550)
然后就可以生成工程了
二. 串口中断相关函数介绍
串口中断函数
如串口1中断函数: USART1_IRQHandler()
发送接收函数
串口中断模式发送: HAL_UART_Transmit_IT()
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
串口实例的指针
想要发送的数据的指针,如数组的首地址
想要发送数据的个数
串口中断模式接收: HAL_UART_Receive_IT()
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
串口实例的指针
接收数据缓冲块的首地址,如数组的首地址
想要接收数据的个数
相关回调函数
串口中断模式发送完成回调: HAL_UART_TxCpltCallback
串口中断模式接收完成回调: HAL_UART_RxCpltCallback
三. 串口中断函数使用实例
在 stm32f4xx_it.c 中,先看一下串口中断函数有没有添加上,如下图所示:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cqMs01qI-1594052855037)(/image/串口中断函数.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113802321.png?imageView2/2/w/550)
现在就可以使用中断相关发送接收函数了
在这里为了方便测试,我添加了一个如下结构体并进行了初始化:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9fgcYndu-1594052855039)(/image/测试串口中断的一个结构体.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113802647.png?imageView2/2/w/550)
发送数据
在主函数中,5s 进行一次发送
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PZ0qE45U-1594052855043)(/image/串口中断发送数据.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113802238.png?imageView2/2/w/550)
发送成功产生回调,该函数在main.c 中
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8l2DCUnN-1594052855045)(/image/串口中断发送成功回调.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113802439.png?imageView2/2/w/550)
然后在主程序中查询到发送成功,打印 send done
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m8bURewy-1594052855047)(/image/串口中断发送成功.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113803723.png?imageView2/2/w/550)
接收数据
在进入循环的之前,就说明串口要进行10个字节的数据接收
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K9WPQTR4-1594052855050)(/image/串口中断接收.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113803627.png?imageView2/2/w/550)
接收10个字节成功产生回调,该函数在main.c 中
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dClZsbkC-1594052855052)(/image/数据接收成功回调.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113803891.png?imageView2/2/w/550)
然后在主函数中,查询是否接收成功
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1iwq3Dhp-1594052855053)(/image/接收成功.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113804872.png?imageView2/2/w/550)
最后运行程序,可以在串口调试助手上显示
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j5kjHbQI-1594052855053)(/image/串口中断调试助手显示.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113804302.png?imageView2/2/w/550)
注意:
若定长串口中断接收数据,数据溢出,将会产生数据溢出错误,中断不再接收数据,如下图:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z9cCh14k-1594052855056)(/image/串口接收中断溢出错误.png?imageView2/2/w/550)]](https://8.eewimg.cn/news/uploadfile/2021/0616/20210616113804336.png?imageView2/2/w/550)
错误回调函数如下:
//错误回调
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if( rxtx_it_usart.huart1 == huart)
{
printf("error %drn",huart->ErrorCode);
}
}
1
2
3
4
5
6
7
8
以上例子,代码已上传
四. HAL库中的串口相关源码介绍
串口中断函数中的处理函数 HAL_UART_IRQHandler
/**
* @brief This function handles UART interrupt request.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t isrflags = READ_REG(huart->Instance->SR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
uint32_t cr3its = READ_REG(huart->Instance->CR3);
uint32_t errorflags = 0x00U;
uint32_t dmarequest = 0x00U;
/* If no error occurs */
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
if (errorflags == RESET)
{
/* UART in mode Receiver -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
return;
}
}
/* If some errors occur */
if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
{
/* UART parity error interrupt occurred ----------------------------------*/
if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_PE;
}
/* UART noise error interrupt occurred -----------------------------------*/
if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_NE;
}
/* UART frame error interrupt occurred -----------------------------------*/
if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_FE;
}
/* UART Over-Run interrupt occurred --------------------------------------*/
if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
{
huart->ErrorCode |= HAL_UART_ERROR_ORE;
}
/* Call UART Error Call back function if need be --------------------------*/
if (huart->ErrorCode != HAL_UART_ERROR_NONE)
{
/* UART in mode Receiver -----------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
// printf("rcv agin error %drn",huart->ErrorCode);
}
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
consider error as blocking */
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
{
/* Blocking error : transfer is aborted
Set the UART state ready to be able to start again the process,
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
UART_EndRxTransfer(huart);
/* Disable the UART DMA Rx request if enabled */
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
/* Abort the UART DMA Rx stream */
if (huart->hdmarx != NULL)
{
/* Set the UART DMA Abort callback :
will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
{
/* Call Directly XferAbortCallback function in case of error */
huart->hdmarx->XferAbortCallback(huart->hdmarx);
}
}
else
{
/* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
else
{
/* Call user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
//printf("dma over error rn");
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
else
{
/* Non Blocking error : transfer could go on.
Error is notified to user through user error callback */
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
//printf("usart over error rn");
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
huart->ErrorCode = HAL_UART_ERROR_NONE;
}
}
return;
} /* End if some error occurs */
/* UART in mode Transmitter ------------------------------------------------*/
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
{
UART_Transmit_IT(huart);
return;
}
/* UART in mode Transmitter end --------------------------------------------*/
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
{
UART_EndTransmit_IT(huart);
return;
}
}
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
主要是分为四个部分:
先读寄存器状态
uint32_t isrflags = READ_REG(huart->Instance->SR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
uint32_t cr3its = READ_REG(huart->Instance->CR3);
1
2
3
如果没有错误状态产生,且是接收中断,就进行数据接收
if (errorflags == RESET)
{
/* UART in mode Receiver -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
return;
}
}
1
2
3
4
5
6
7
8
9
错误处理
//当有parity error,noise error,frame error,Over-Run 错误产生的时候,通过以下回调来处理
HAL_UART_ErrorCallback(huart);
1
2
注意:
通过查看HAL库,会发现该函数的定义用了关键字__weak (弱符号声明) ,如下:
__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
史海拾趣
|
由于中国巨大的汽车市场,各个国际汽车巨头目前纷纷在中国各地投资建厂,汽车制造商为了扩大品牌占有率和汽车销售,会对原有厂房或生产线进行扩建或改造,同时,由于汽车厂商的建厂、改造,必然会带动相关零部件厂商间的竞争,从而零部件厂商也会为 ...… 查看全部问答> |
|
2010年电子报(PDF版本)--1月4日,更新下半年总目录,全部上传完毕 2010年的电子报,PDF版本的,大家来看看啊 第11期在第31楼, 第12期在第38楼, 第十三期在45楼, 第14、15期在51、52楼 第16期在56楼 第17期在58楼 第18期在67楼 第19、20期在88、89楼 第21、22期在91、92楼 第23、24期在94、95 ...… 查看全部问答> |
|
高手进来指导下:关于MC33996和MC33993的开关量输入和开关量输出电路的设计及程序 各位大虾。。小弟刚接手设计一个用MC9S08DZ60与MC33993和MC33996设计一个开关量输入输出的电路,想请你们指导下电路及程序,请设计过这个电路的高手指导下。谢谢哈。····· … 查看全部问答> |
|
北京时间2011年3月11日下午14时46分左右,日本东北地区宫城县北部发生里氏8.8级特大地震。震中位于日本本州岛仙台港以东130公里处。此地震对日本国宫城县、岩手县、枥木县、福岛县、茨城县、山形县等地造成强烈伤害。由于宫城县、岩手县、枥木县 ...… 查看全部问答> |




