网站首页 > 技术文章 正文
首先在初始化时, MX_USART1_UART_Init()这个函数已经对串口中断进行了使能。
MX_USART1_UART_Init()这个函数中会调用HAL_UART_Init()这个库函数,而这个库函数最后会执行一个宏,__HAL_UART_ENABLE(huart);至此,串口的中断已打开。CPU此时可随时相应中断。
那串口的发送中断又是如何触发的呢?
这取决于串口发送寄存器的影子寄存器(理解:串口的数据寄存器DR是可以被用户操作的,而和DR相对应的还有一个寄存器TDR是影子寄存器,这个寄存器相对用户而言是不可操作的,真正的数据发送,是由这个寄存器移位送出的)的状态。
如果这个寄存器是空的,则马上置位串口状态SR寄存器中的标志位TXE,同时串口CR1寄存器的TXEIE位如果是使能状态,这些条件具备以后,CPU即进入了串口中断程序。这也就是串口发送中断的触发过程。
进入串口中断函数以后,串口中断函数USART1_IRQHandler(void)中会判断中断类型,根据中断类型调用相应子程序,比如发送中断、接收中断、各种错误中断等等。
单说发送中断,串口中断函数中如果判断的是发送中断,则调用UART_Transmit_IT(huart)这个函数。注意,这个函数是单字节发送函数,发送一个字节结束后即返回。
返回时会判断用户定义的所需要发送的字节数是否发送完成,这个是依靠一个变量计数实现,假如用户定义发送10个字节,则每发送一个字节,计数减一,当为零时,表示所有数据字节发送完成。如下:
选自UART_Transmit_IT(huart)函数内容
if (--huart->TxXferCount == 0U)
{
/* Disable the UART Transmit Complete Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
通过程序看到,如果预先定义的所有数据字节发送完成(TxXferCount ==0U),此时将关闭串口发送中断,同时使能发送完成中断。否则直接回复串口忙,表示当前正在发送预先定义的的数据字节,且没有发送完成。
这个是什么意思呢?
其实这里就是说,如果你预先定义的需要发送的字节数没有发送完成,将返回继续发送下一个字节;反之如果全部发送完成了,程序就把发送中断关闭了,同时打开了发送完成中断,也就是说这次的发送已经完成了,这为下面的回调函数处理设置了前提条件。
发送完成后,UART_Transmit_IT(huart)程序返回到调用处。当程序再次进入串口中断入口函数USART1_IRQHandler(void)的时候,此时的中断类型已经不再是发送寄存器空(TXE)中断,而是变成了发送完成中断(理解:此时TC已经被置位了)。如下:
/* 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;
}
这个时候,程序将转去执行UART_EndTransmit_IT(huart)这个函数,如下:
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart)
{
/* Disable the UART Transmit Complete Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TC);
/* Tx process is ended, restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Tx complete callback*/
huart->TxCpltCallback(huart);
#else
/*Call legacy weak Tx complete callback*/
HAL_UART_TxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
return HAL_OK;
}
这个函数中有个回调函数HAL_UART_TxCpltCallback(huart),可以由用户自行编写,在这里就可以编辑数据发送完成后要干的事,至此,一次串口的发送中断过程结束。
注意:如果要再次发起一次同样的过程,需要执行HAL_UART_Transmit_IT()这个函数,在这个函数中会再次开启发送寄存器空中断使能,然后重复上面的过程。
猜你喜欢
- 2024-10-12 STM32单片机-多串口printf()问题与ASCII码解析
- 2024-10-12 stm32F0 串口的几个特殊功能 stm32f1串口引脚
- 2024-10-12 STM32串口发送用哪个中断? stm32f4串口发送数据
- 2024-10-12 STM32F103编程学习——USB虚拟串口篇
- 2024-10-12 STM32F4入坑日记——串口发送数据(非中断)
- 2024-10-12 在货物监控设备研发时,STM32串口第一个字节丢失解怎么解决?
- 2024-10-12 STM32单片机采用环形缓冲区实现串口中断数据接收管理
- 2024-10-12 基于STM32的串口与DMA的完美组合(上)
- 2024-10-12 STM32下载程序新思路--使用串口下载STM32程序
- 2024-10-12 STM32F103编程学习——串口接收不定长数据
你 发表评论:
欢迎- 02-20利用神经网络模型检测摄像头上的可疑行为
- 02-20直击心灵:高频核心听力你了解吗?_高频听力的正常范围值是多少
- 02-20YOLOv8 POSE+XGBoost进行人体姿态检测
- 02-20100个篮球英文术语详细解释,从此听懂NBA解说
- 02-20最全紧固件中英文对照,外贸必备词典一
- 02-20带你开发一个视频动态手势识别模型
- 02-20详细介绍一下Java基础中HashMap如何进行扩容操作?
- 02-20GTX 1070 Ti显卡评测:你会购买哪一款?
- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)