本帖最后由 zhongyuan186118 于 2016-11-9 21:18 编辑
在使用串口的过程中,曾经有不少困惑,后来经过实验求证,困惑逐步得到解决,今天就把相关的经验与大家分享一下。首先声明一下,我所使用的库是HAL库。实验开发板的主控芯片是stm32f103RBT6,所用的串口是uart1,并用两个led灯作为状态的显示。基于HAL库的串口收发有三种实现方式,分别是轮询(HAL_UART_Receive\HAL_UART_Transmit)、中断(HAL_UART_Receive_IT\HAL_UART_Transmit_IT)和DMA(HAL_UART_Receive_DMA\HAL_UART_Transmit_DMA),括号内便是对应得收发函数名称。这三种方式有一个共同的特点,那就是都要提供一个参数,这个参数就是收发数据的长度。对于发送数据,我们还能知道数据的长度;但是对于接收数据,我们要是不知道接收数据的大小,该怎么办呢?这里我并不打算仔细讲解,给大家分享一个帖子吧,里面讲解的很详细。
下面我分别设定几种场景,通过实验来观察相关的结果。
场景一:采用中断方式接收数据和采用DMA方式接收数据的比较。
定义字符串接收数组变量rx_buffer[4],最多可接收4个字符,开启Uart1的全局中断。在主函数中添加中断接收函数HAL_UART_Receive_IT(&huart1,rx_buffer,4),该语句是放在while循环语句中的。为了能够验证接收的数据是正确的,在中断处理函数中将接收到的数据再发送到串口调试助手上,中断处理函数void USART1_IRQHandler(void) 在stm32f1xx_it.c文件中。问题的关键就在于在中断处理函数中,我们采用哪种方式将数据发到串口调试助手上,前面提到有三种方式。在这里,我分别试验了三种方式。当采用中断方式接收数据时,如果在void USART1_IRQHandler(void)函数中采用轮询或者中断方式将接收到的数据再次发送到串口调试助手上,那么串口调试助手接收到的数据与你发送的数据将会不一致。但如果采用DMA方式发送数据时,将不会出现这种情况,发送的数据与接收的数据完全一致。具体的原因还不清楚。另外还有个问题就是,在程序下载到芯片中后,初次上电复位,初次发送数据,则串口调试助手上接收到数据全为0(HEX显示)。再次发送数据,就不会出现这样的问题了,这一点也不知道是什么原因。当采用DMA方式接收数据时,在void DMA1_Channel5_IRQHandler(void)函数中将接收到数据发送到串口调试助手上,则三种方式均可采用。其中void DMA1_Channel5_IRQHandler(void)是DMA方式接收数据的中断处理函数,在stm32f1xx_it.c文件中。所以,感觉采用DMA方式收发数据会更可靠一些。
场景二:中断处理函数IRQHandler和回调函数Callback的区别
中断处理函数与回调函数的类别非常多,这里仍是以串口的中断处理函数USART1_IRQHandler和回调函数HAL_UART_RXCpltCallback为例进行试验的。实验时用两个led灯作为实验结果指示。这里回调函数HAL_UART_RXCpltCallback放在了main.c文件中,函数中添加了点灯的语句,同时在void USART1_IRQHandler(void)函数中也添加了点灯的语句。在串口调试助手中,发送数据,会看到两个led灯同时亮起,说明程序接收到数据后,分别调用了中断处理函数和回调函数。有兴趣的同学可以亲自试验一下。因此,从这个角度来看,二者并没有明显的区别,至于其本质区别,我也不是很清楚,希望知道的同学可以发帖留言解答一下。
场景三:字符串接收数组大小的定义
假如你知道要接收数据的长度的话,那就好办多了。但如果你不知道要接收数据的长度的话,那么就尽可能的使接收数组的长度大些。当你接收的数据小于定义的数组大小的话,剩余的部分都会用\0来填充,这是字符串结束的标志。当你接收的数据大于定义的数组大小的话,便会造成一些数据的丢失和意想不到的后果。
以上情况是通过做些小实验获得的结果,如果有错误的地方,欢迎大虾们指正。
|