历史上的今天
今天是:2025年05月30日(星期五)
2019年05月30日 | STM32L0xx_HAL_Driver库的使用——UART续
2019-05-30 来源:eefocus
单片机型号:STM32L051C8T6
开发环境MDK5.12
库版本:STM32L0xx_HAL_Driver V1.1.0
主机环境:Windows XP
承接上文,为采用双缓冲机制,重新开辟一个500字节的空间aTxBuffer来存放所需发送的字节,初始化uart_snd的指针
uart_snd.front = aTxBuffer;
uart_snd.rear = aTxBuffer; //两个指针指向相同的地址空间
编辑发送单字节的函数uart_char
/**********************************************************************
函数:uart_char()
函数作用:发送一个字节数据
参数:
uint8_t *fmt--------------------------------需要发送的数据
返回值:
上一版本:无
当前版本:1.0
作者:
最后修改时间:2015-04-08
说明:
**********************************************************************/
void uart_char(uint8_t fmt)
{
uint8_t ret = HAL_OK;
if(uart_snd.rear == uart_snd.front)
{
//队首指针和队尾指针相等表明当前没有数据需要发送,这里需要手动开启发送请求
*uart_snd.rear = fmt;
uart_snd.rear++;
if(uart_snd.rear >= aTxBuffer + BUFFSIZE)
uart_snd.rear = aTxBuffer;
do
{
ret = HAL_UART_Transmit_IT(&UartHandle,uart_snd.front,1);//请求发送下一个数据
}while(ret != HAL_OK);
}
else
{
*uart_snd.rear = fmt;
uart_snd.rear++;
if(uart_snd.rear >= aTxBuffer + BUFFSIZE)
uart_snd.rear = aTxBuffer;
}
}
在此判断是否是重新启动发送请求,如果是重新启动则需要手动发起请求,即调用HAL_UART_Transmit_IT()发送函数,如果已经在发送数据过程中则只需要更新rear指针即可。我们的uart_send函数也需要更改不再调用printf而是调用uart_char函数来实现
int8_t uart_send(uint8_t *fmt, uint8_t len)
{
while(len)
{
uart_char(*fmt);
fmt++;
len--;
}
return 0;
}
当数据发送成功后中断函数会调用HAL_UART_TxCpltCallback()回调函数来处理串口发送流程,
/**
* @brief Tx Transfer completed callback
* @param UartHandle: UART handle.
* @note This example shows a simple way to report end of IT Tx transfer, and
* you can add your own implementation.
* @retval None
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef * huart)
{
uint8_t ret = HAL_OK;
uart_snd.front++; //更新rear指针
if(uart_snd.front >= (aTxBuffer + BUFFSIZE))
uart_snd.front = aTxBuffer;
if(uart_snd.front != uart_snd.rear)
{
//如果队首指针和队尾指针不同表明缓冲区中有数据还未发送
do
{
ret = HAL_UART_Transmit_IT(&UartHandle,uart_snd.front,1);//请求发送下一个数据
}while(ret != HAL_OK);
}
}
这里我们要判断缓冲区中的数据是否已经发送完毕即判断front指针和rear指针是否相等,如果相等,则表明数据发送完毕,无需再调用HAL_UART_Transmit_IT()发送函数。至此发送流程编辑完毕,在主函数中调用uart_send()函数来进行测试
uint8_t *abc = "abcdefghijklmnopqrstuvwxyz0123456789rn";
while(1)
{
uart_send(abc,strlen(abc));
}
经测试发送正常,结果如下

一切显得顺风顺水,就在我以为大功告成之时,从PC机的串口工具向单片机发送了一些数据,结果单片机卡住了,串口输出也没得了。。。跟想象中的结果不一样那,之前采用单缓冲机制是完全没问题的,怎么使用双缓冲就有问题了呢,串口接收流程没有改动,只是改动了串口发送,而且单独测试串口发送也没问题,调试了半天看下是否有串口错误产生呢。因此增加了串口出错回调函数
/**
* @brief UART error callbacks
* @param UartHandle: UART handle
* @note This example shows a simple way to report transfer error, and you can
* add your own implementation.
* @retval None
*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)
{
printf("error code:%Xrn",UartHandle->ErrorCode);
}
在里面输出错误码,测试结果如下

输出的错误码为0x08,查找错误码的定义发现该错误码是ORE错误
/**
* @brief HAL UART Error Code structure definition
*/
typedef enum
{
HAL_UART_ERROR_NONE = 0x00, /*!< No error */
HAL_UART_ERROR_PE = 0x01, /*!< Parity error */
HAL_UART_ERROR_NE = 0x02, /*!< Noise error */
HAL_UART_ERROR_FE = 0x04, /*!< frame error */
HAL_UART_ERROR_ORE = 0x08, /*!< Overrun error */
HAL_UART_ERROR_DMA = 0x10 /*!< DMA transfer error */
}HAL_UART_ErrorTypeDef;
而我们知道ORE错误是只会出现在串口接收中,难道打开串口发送中断会影响到串口接收中断?想想总觉得不可能,这应该是全双工串口的那,两者应该是相互独立的才对那。这让我陷入了深深的纠结中。。。而且在测试结果中一旦出现了ORE错误会一直输出该错误,很明显该错误标志一直没有被清零,同时我也没有往单片机发送串口数据之前使用STM32F030C8T6型号单片机时会有串口乱进的情况是因为打开串口接收中断时会同时开启ORE中断,最后解决办法是在中断处理函数中增加错误标志的检测并清除相应的标志。本以为STM32L0xx_Hal_Driver库封装了这么多,会帮助我们减少这类错误呢,结果还是出现了,查看HAL_UART_Receive_IT()函数代码会发现该函数同样使能了各个错误中断
/* Enable the UART Parity Error Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_PE);
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
查看源代码中中断处理函数HAL_UART_IRQHandle()里面也进行了各个错误的判断以及清除标志操作。

史海拾趣
|
两个菜鸟问题: 1. 找到别人的代码: int order=0; AnsiString fileName,path=\"c:\\\\temp\\\\\"; FILE *fp; fileName= ...… 查看全部问答> |
|
使用QQ2440v3开发板,原机配置系统中可以看到FRIENDLYFlash盘符有16M的空间,自己定制系统后FRIENDLYFlash名称变为ResidentFlash,容量只有1.96M,不知道怎么回事,如何实现完全将所有剩余空间生成一个盘符… 查看全部问答> |
|
各位大哥,我刚接触VXWORKS不久,请大家指教。实验室有块powerpc104开发板(含有MPC8260+FPGA),8260与FPGA通过64位数据总线和32位地址总线(好像就是60X总线)连接,购买板子已自带BSP,怎么实现8260与FPGA在VXWORKS下的通信(中断,数据传递)啊 ...… 查看全部问答> |
|
各位用过的说说怎么设置,我设置的没有反应。 SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1); &nbs ...… 查看全部问答> |
|
今天学习了EEWORLD论坛中的launchpad课程,感觉讲得蛮详细的,介绍的很全面,学到了不少东西。可惜我还只是一个新手,有些东西还没彻底弄明白。好吧,就这些了,希望有高手能帮忙指导,谢谢。… 查看全部问答> |




