STM32F4 CubeMX+MDK5配置串口

本文详细介绍了如何使用CubeMX配置STM32串口,包括阻塞式和中断式接收。重点讲解了中断接收的实现方式,特别是HAL_UART_Receive_IT()函数的使用,以及如何通过判断特定字符或时间间隔来确定接收完成。同时,还展示了通过重定向printf函数实现串口发送的方法。
摘要由CSDN通过智能技术生成

我也是小白一个,为了让自己对知识掌握得更牢一点写下这篇博客。如果大家发现什么问题欢迎指出

  1. CubeMX实现串口的基本配置在这里插入图片描述
    使能串口中断
  2. 串口接收
       串口的接收会比较复杂,大家慢慢看
       串口接收通过HAL库来实现,串口的HAL库接收函数有三种
         HAL_UART_Receive;
         HAL_UART_Receive_IT;
         HAL_UART_Receive_DMA;

  由于第三种涉及到DMA,这里就只讲前面两种
   HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);是阻塞式接收函数,也就是串口在接收数据时,单片机会处于等待状态,直到串口接收完成,单片机才继续处理后面的程序。这种方式优点缺点都很明显,优点是逻辑简单,缺点占用处理器资源。
   HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);通过串口中断来实现串口数据的接收。
  首先我们要在程序中调用HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);使能串口接收中断。(CubeMX并没有帮我们使能!) 并且在接收完一次数据后,要再次使能,不然串口可能无法正常接收。
  使能完成后,当串口接收到足够数量的字符,就会产生接收中断。
   程序会先进入USART1_IRQHandler()在里面调用HAL_UART_IRQHandler();
  在这个HAL库函数中,程序会判断发生的是哪一种中断,比如:接收、发送、错误中断等,然后调用相应的中断函数。在这个中断函数里再调用对应的回调函数HAL_UART_RxCpltCallback();
  这个过程看起来让人头晕,但在编程的时候,我们只需要改写回调函数就行,前面的过程CubeMX已经帮我们封装好了。

  1. 串口接收的逻辑
      我们在上面说到,调用HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);后,程序会在收到我们指定的size个数据后进入中断。但在我们的日常使用中,我们一般不能知道上位机会发送多少个字节的数据过来。因此,我们也就不知道什么时候结束串口数据接收,通过接收到合适长度的数据来进入中断的方法就显得很鸡肋。因此,我们想出了一些办法来处理这个问题。
      下面要说到的这两个方法是我从正点原子的例程中总结出来的。
      A. 通过判断是否连续收到0x0a,0x0d这两个数据来判断一次传输是否完成
    我们将HAL_UART_Receive_IT()uint16_t size设置为1,也就是收到一个字节的数据就进入中断,并且这个数据会被保存在uint8_t *pData中。然后我们自己定义一个保存接收串口数据的数组 uint_8 USART_RX_BUF[USART_REC_LEN];和一个该数组的索引号USART_RX_STAUSART_RX_STA的高两位用来标志接收是否完成。
       在我们自己编写的回调函数中,将每次接收到的一个字节的uint8_t *pData保存到USART_RX_BUF[USART_REC_LEN]中,并使USART_RX_STA++。如果连续收到0x0a,0x0d这两个数据,USART_RX_STA的最高位就会被置一,标志接收完成。检测到USART_RX_STA的最高位为一后,我们就可以读取USART_RX_BUF中的数据,也就是这一次上位机发来的数据。当然,这要求上位机在它要发送的数据结尾加上0x0a,0x0d这两个数据。
      B. 通过判断接收连续2个字符之间的时间差不大于100ms来决定是不是一次连续的数据
      这里我们同样用USART_RX_STA的最高位来做标志,但是置一的条件不同了。在初始化过程中,我们配置一个定时器,每次进入串口接收回调函数的时候,将定时器的值清零,并使能。如果串口收到的两个字符时间差太大,定时器超过一定的值,就会进入定时器中断。在定时器的中断里,我们将USART_RX_STA的最高位置一。

  2. 串口发送
      串口发送可以通过将printf函数重定向实现,非常方便。只需在main.c中加入如下代码(转载自正点原子例程)

//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
//#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)	
#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 = (u8) ch;      
	return ch;
}
#endif 

  当然,通过HAL库函数进行发送也是可以的

    HAL_UART_Transmit();
    HAL_UART_Transmit_IT();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值