1.从轮询到中断
许多人更喜欢使用轮询的方式,而不喜欢使用中断。
这是否与我们的天性有关呢?每个人都喜欢掌握一切,肯定都不喜欢被打断。我们经常会有这样的经历:正在和别人说某件事,突然电话打进来,通话结束后突然想不起刚才讲到哪了!这种糟糕的体验对我们的影响是如此深刻,以至于我们可能认为机器也是一样的,频繁的中断会不会把事情搞乱呢?幸运的是,尽管机器大部分时间都比人笨一些,但在处理这类问题时却能做到非常准确。机器在收到中断时会先把当前正在进行的工作记录下来,然后处理中断事件,处理完中断后完全恢复原来的工作状态。
深思熟虑,我们是不是也可以在接电话前用个小本子记录一下当时正在说的事情呢?为什么我们没有这么做呢?一个原因可能是我们手头没有笔,另一个原因可能是我们可能过于自信,认为自己比机器聪明。当然,最有可能的原因是我们大多数时候都在谈论乏味的话题,哈哈。
我们使用Keil打开以下工程:
STM32Cube_FW_F0_V1.11.0\Projects\STM32F030R8-Nucleo\Examples\UART\UART_TwoBoards_ComIT\MDK-ARM\Project.uvprojx
此时,如果不仔细观察,几乎看不出与轮询操作的代码有什么区别。特别是初始化部分,完全一样。那么中断方式在哪里呢?
好的,我们往下面继续找,终于会发现一些不同之处:
在这里我们发现串口发送调用了一个不同的函数。秘密就在这个函数里:
HAL_UART_Transmit_IT 这个函数有三个参数:
UART_HandleTypeDef *huart, 让函数知道处理的是哪个串口
uint8_t *pData, 需要发送的数据首地址
uint16_t Size 发送数据的大小(长度)
这个函数的三个步骤:
Step1: 把待发送数据区的首地址,长度赋给串口的 Handle。
Step2: 根据参数(8B还是9B),挂载不同的处理函数。
Step3: 开中断(串口发送寄存器空将产生中断)。
HAL_UART_Transmit_IT 函数执行完这些任务就退出了,主程序可以继续执行其它的操作。这是和轮询完全不同的。我们回头看一下轮询方式的 HAL_UART_Transmit 就会发现这个函数一直要等到所有数据都发送完才退出,在此期间MCU被100%占用,没有办法做其它的事情。轮询方式发送函数里有个参数 5000,这是一个发送超时参数,不管有没有发送完,5秒以后强制退出此函数,防止由于硬件或其它原因卡死在这个函数里。
2.再谈Handle
对于 Handle 这个词,我们没有用”句柄”这种翻译,因为”句柄”这个词本身也是生造出来的,这个词本身就不太好理解,容易把人引入歧途。所以我们认为 Handle 这个词不翻译为好。Handle 是一个重要的概念,所以我们需要反复体会用它来管理硬件模块的好处。
我们可以把它想象成一个负责装卸货船的办事处,类型声明(如 UART_HandleTypeDef ) 是一个创建办事处的模板。如果有五个码头,那就创建五个办事处,这些办事处是相似的,但每个办事处又不同,它们建在不同的码头,有不同的人员,可以调用不同的车队。这个办事处可以等待中央机构(MCU)的命令,也可以用更好的办法。
中断的方式就像我们给这个办事处建立一个自动处理流程,码头来了一个空货船,则自动触发办事处中的一些办事员调动车队把货物运到船上。而轮询方式就像所有的事情都要等待中央指挥中心(MCU)下达命令,即使办事处一堆人员正无所事事。
下面的 Handle 就好比是一个这样的办事处,初始化的过程就是告知它建在 USART1,以及波特率,有无奇偶校验,停止位等信息。
HAL_UART_Transmit_IT 函数告知此办事处有一堆 8BIT 货物在仓库 aTxBuffer 存放,并通过把 TxISR 指向适合的车队( 函数 UART_TxISR_8BIT ),建立了一个自动处理流程。
3.中断产生,执行的流程
我们从下图中可以看到从中断产生到执行的过程,一个是发送寄存器空产生中断时,一个是发送完成产生中断时。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !