阿飞的秘术屋
认证:VIP会员
作者动态
emc防护原理
01-14 21:20
关于使用LVDS芯片进行屏幕通信过程中遇到的EMC问题
2023-12-25 13:15
RT-Thread 串口DMA发送代码解析
2023-12-21 16:58
滤波、去耦、旁路、储能傻傻分不清
2022-12-06 22:15
STM32H750使用LTDC驱动RGB屏幕显示
2022-03-20 14:16

STM32--HAL库--UART使用

写在前面的话欢迎大家在评论区指正错误,该博文是我在这几天使用hal库的时候碰到的问题的记录,对于暂时没有写的像dma、阻塞接收等函数,在后期如果我用道的话,我也会在该博文里面更新。当让也欢迎大家在评论区指正。

函数在这里不介绍关于DMA的操作,只是用有关串口的阻塞和非阻塞函数。

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

以上4个分别是串口的阻塞接受,发送和非阻塞的接受和发送。(关于阻塞和非阻塞,阻塞的过程cpu是需要等待的,而非阻塞的过程相当于中断)

关于在使用的时候遇到的问题发送HAL_UART_Transmit在发送方面,使用HAL_UART_Transmit阻塞数据发送的时候,一定要计算好发送数据的时间。如果发送时间到了,但是数据还没有发送完成的话,会导致没有发送的数据丢失。

HAL_UART_Transmit_IT该函数是以中断的方式发送的数据,是非阻塞的。在使用的时候,可以写成类似printf的函数。在这里我参照的是正点原子库函数版本改过来的。

void u2_printf(char *str,...)
{
	uint16_t j; 
	va_list ap; 
	va_start(ap,str);
	vsprintf((char*)USART2_T_M,str,ap);
	va_end(ap);
	HAL_UART_Transmit_IT(&huart2,(uint8_t *)USART2_T_M,strlen((const char*)USART2_T_M));
}

但是该函数还存在问题,在字符串中默认0x00是一个字符串的接受。所以自己写的这种类printf的函数并不能在字符串中间加入0x00进行数据发送。(0x00一般在某些模块的数据通信中会使用到)但是使用半主机模式下的printf函数可以解决该问题。

使用printf函数这一部分代码我参照的是正点原子的给出的代码,直接改过来使用的。使用的是半主机模式下的printf函数。

#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (uint8_t) ch;      
	return ch;
}
#endif

在这里面,通过更改USART1修改映射串口。

接收阻塞模式下的接收函数没有测试过,就不在这里写了。以后有机会用到了,会进行添加。

HAL_UART_Receive_IT使用中断的方式进行接受数据,在这里需要注意的一个点是,使用中断的方式接收到数据之后,需要在中断里面在调用一次HAL_UART_Receive_IT函数,重新开启下一次数据接收,否则会导致,接收完一次数据之后,不会接收下一次数据。

HAL_UART_Receive_IT(&huart2,&usart2_rdata,1);  
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)  
{
	if(huart->Instance == USART2)  //串口屏,接收中断
	{
	HAL_UART_Receive_IT(&huart2,&usart2_rdata,1);
	}
}

在这里我是用的是,接收一个字符后就会触发一次中断。当然也可以一次接收多个字符数据。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 5
收藏 2
关注 9
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧