之前用hal库的时候都是用一些简单的,例如初始化一个IO用作LED指示,今天写的代码需要串口的例子,说真的看了官方的demo也没看出啥名堂,反而觉得用hal写串口驱动太麻烦了.
回顾下之前常见的串口写法,发送用的是阻塞式发送,一般都是发送一些调试信息,接收肯定用的是中断;
为了编程的方便,发送一般是跟printf绑定的,但是对于hal库这些我们又怎么来编写呢?
接下来我把我刚刚学习到的东西分享下,如果有错误请指教。
我的开发板是STM32F746G-DISCO,参考的是UART_TwoBoards_ComIT例子。
首先我们看看中断发送的例子:
/* Buffer used for transmission */
uint8_t aTxBuffer[] = "****UART_TwoBoards_ComIT****\r\n";
/* Buffer used for reception */
uint8_t aRxBuffer[RXBUFFERSIZE];
if(HAL_UART_Transmit_IT(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
{
Error_Handler();
}
发送就是aTxBuffer里的数据通过中断方式发送出去,因此这条语句是非阻塞式的,当发送完成后会回调
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle);
接下来我们把改成使用printf的来发送;
① 在main.c里添加
#include <stdio.h>
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) //MDK
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/* Loop until the end of transmission */
while(__HAL_UART_GET_FLAG(&UartHandle, UART_FLAG_TC) == RESET);
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
UartHandle.Instance->TDR = (uint8_t) ch;
return ch;
}
然后在串口初始化完毕后就可以调用printf语句试试了
printf("my printf test,compile time:%s %s\r\n",__DATE__,__TIME__);
本人特别喜欢用printf来调试,推荐使用115200波特率;
再说说接中断框架,先看源码:
int main()
{
//串口初始化
if(HAL_UART_Transmit_IT(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
{
Error_Handler();
}
while(1) //单片机的大循环
{
if(UartReady == SET)
{
UartReady =RESET;
//添加你的处理代码...
HAL_UART_Transmit_IT(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE);//再次打开中断接收代码
}
//其他代码...
}
}
/**
* @brief Rx Transfer completed callback
* @param UartHandle: UART handle
* @note This example shows a simple way to report end of DMA Rx transfer, and
* you can add your own implementation.
* @retval None
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
/* Set transmission flag: transfer complete */
UartReady = SET;
printf("HAL_UART_RxCpltCallback\r\n");
}
HAL库的中断接收效率很低,而且还很死板,必须接收指定字节才能回调接收完成函数,那能不能改成超时后再回调接收完成函数呢?当然是可以的,并且我已经改出来了,思路简单提下,在钩子函数里加个软件定时器,从接收到第一个字符开始倒计时,超过一定时间就调用接收回调函数,这里有个注意地方就是接收的时候接收指针千万不要溢出了!!!
对于我提出的方法比较感兴趣的可以给我留言,期待着跟大家一起探讨~