STM32基础教程(CubeMX)—— 串口通信(USART协议)

串口通信原理

串口通信

   通过单一数据线进行数据传输的通信方式,另外还有并行通信的方式。串口通信一次只能发送一个字符,包括起始位、数据位、校验位和停止位。

单工、半双工、全双工、异步、同步
  • 单工:数据只能单向传输。
  • 半双工:数据可以双向传输,但是不能同时发送。
  • 全双工:数据可以双向传输,且可以同时发送。
  • 异步(Universal):通信双方的时钟不一样时的通信。
  • 同步(Synchronous):通信双方的时钟一样时的通信。
UART和USART
  • UART(通用异步收发器)和USART(通用同步异步收发器):串口通信的一种通信协议。速率不快,可全双工,结构上一般由波特率发生器、UART/USART发送器、UART/USART接收器组成,硬件上只有两条线,一收一发。
  • 通信格式:通信时,高电平表示没有数据传输,高电平后的第一个低电平表示数据传输开始,之后接受数据,接受完毕后拉到高电平,最少需要一个高电平的停止位。即,传送一个字节,至少需要10位的空间。通信的两个芯片必须共地,两个芯片的输出TXD和输入RXD分别连接(A的输入连接B的输出),且STM32的TXD设置为输出推挽模式,RXD设置为输入上拉模式。通信频率就是波特率,即一个信号保持的时间是波特率的导数。
  • 与电脑的通信:UART通信方式电脑不具备,电脑的通信方式是USB通信,它比UART复杂得多。为了实现串口与电脑的通信,需要通过一个转换芯片来进行协议的转换,并且在电脑端还需要软件来显示串口发送来的内容,这个软件就是“串口调试助手”。

CubeMX的操作

USART的设置
  1. 在"Pinout & Configuration"界面下,左侧选择下拉菜单"Connectivity",下拉菜单中选择USART,你会发现有好几个可以选择,具体使用哪个,需要参考原理图,看USB转串口连接的是哪个,这里选择USART1。
  2. 中间的界面里出现对应的窗口,“Mode”下“Mode”选择异步通信(asynchronous)。
  3. “Mode”下方的“Configuration”中,选择"Parameter Settings"窗口。第一个下拉菜单第一个波特率一般选择115200就可以了,第二个数据位选8位,第三个奇偶校验选择无(),第四个停止位一般选1位(设置成2位更可靠)。
  4. “Mode”下方的“Configuration”中,选择"NVIC Settings"窗口,勾选串口中断。原则:一个中断服务一个外设,不同中断使用相同变量保证他们的优先级一致。防止出现未知错误(打断造成的错误)。
  5. 设置作为串口通信的串口的状态,即输入(Rx)设置为上拉电阻,输出(Tx)设置为推挽模式(Altermate Function Push Pull)。输入上拉是因为USART协议中,高电平表示没有信号传入。

Keil5的操作

阻塞式发送数据
  • 不带中断的发送:使用函数HAL_UART_Transmit(UART的地址,发送的数组的地址,发送的数组的大小,发送的时间)。其中“发送的数组的大小”是指发送的字节数,不包括空字符;“发送的时间”参数限制了发送的总时间,如果发送的总时间超过这个事件就不发送了。
  • 重定向Printf函数:stdio.h头文件中声明了一个fputc函数,使用printf发送字符串时,相当于多次调用这个函数,所以,只要在自己的任意一个c文件中定义这个函数并编辑,把传入它的这个字符输出到自己想要的地方即可完成对Printf的重定向,传入它的文件指针不管,就可以在其他地方如常使用Printf了。
自己重新编写的fputc函数示例(发送到USART1)
 /**
  * @brief 对Printf进行重定向的函数,发送到USART1,不带中断
  * @param ch是printf函数需要发送的一个字符;file是目标文件,这里没有使用这个参数
  * @retval 未知
  */
 int fputc(int ch, FILE * file)
 {
 	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,50);
	return 0;
 }
阻塞式接收数据
  • 利用中断接收:定义一个全局变量字符数组,在主函数中调用带中断的接收函数HAL_UART_Receive_IT(USART通道地址,接受的数据存放的数组地址,接受的数据大小)。之后再中断回调函数HAL_UART_RxCpltCallback中对接收到的数据进行处理,并且再使用一次带终端的接收函数开始下一次的数据接收。

例程,该程序还将历史接收数据存储了起来:
主函数文件中定义全局变量:uint16_t Key_Detection(GPIO_TypeDef * Key_Port, uint16_t Key_Pin, GPIO_PinState Level);
主函数中调用带中断的数据接收函数HAL_UART_Receive_IT(&huart1,USART_Receive,1);
中断回调函数所在文件需加头文件:#include "stdio.h" #include "lcd.h" #include "math.h" #include "string.h"
中断回调函数:

extern uint8_t USART_Receive[5], USART_Receive_Save[200],USART_Receive_Number;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	char str[100] = {0};
	if(huart == &huart1)
	{
		/*将接收到的数据显示在LCD上*/
		strcat(str,"I have received:");
		strcat(str,(char *)USART_Receive);
		LCD_ShowString(5,305,200,5,12,(uint8_t *)str);
		/*将接收到的数据存储在Save数组中,并且开始接受下一个字节*/
		USART_Receive_Save[USART_Receive_Number] = USART_Receive[0];
		USART_Receive_Number++;
		HAL_UART_Receive_IT(&huart1,USART_Receive,1);
	}
使用DMA进行通信

原理:DMA是一个寄存器,完成搬运数据的任务。在完成任务后会通知CPU完成,如果有设置中断就进入相应的中断,期间CPU不被占用。

  1. 配置好串烤的相关参数
  2. 配置DMA,配置的地方就在设置USART的地方,在下方的窗口里面找到DMA的界面,选择添加一个DMA,配置一般选择默认就可以了。DMA的模式分为普通模式和循环模式,循环模式就是把要求发送的数据重复发送,直到接收到停止指令。
  3. DMA无法使用printf发送,它的发送函数为HAL_UART_Transmit_DMA(UART地址,发送的数组,发送的字节数),发送的字节数不知道时,可以使用"string.h"里面的strlen(字符串);。它的接收函数为HAL_UART_Receive_DMA(UART地址,接收的数组,接收的字节数)
DMA不定长接收

原理:就是说,未知数据长度大小,当不发送数据一定时间的时候就认为数据已经结束了。串口闲置中断就是,当接收了数据之后,串口闲置了一个字节的长度之后就会触发串口闲置中断。

猜你喜欢

转载自blog.csdn.net/weixin_43718316/article/details/107988929