STM32基础教程(CubeMX)串口通信(USART协议)
程序员文章站
2022-04-17 09:00:27
串口通信原理串口通信 通过单一数据线进行数据传输的通信方式,另外还有并行通信的方式。串口通信一次只能发送一个字符,包括起始位、数据位、校验位和停止位。单工、半双工、全双工、异步、同步单工:数据只能单向传输。半双工:数据可以双向传输,但是不能同时发送。全双工:数据可以双向传输,且可以同时发送。异步(Universal):通信双方的时钟不一样时的通信。同步(Synchronous):通信双方的时钟一样时的通信。UART和USARTUART(通用异步收发器)和USART(通用同步异步...
串口通信原理
串口通信
通过单一数据线进行数据传输的通信方式,另外还有并行通信的方式。串口通信一次只能发送一个字符,包括起始位、数据位、校验位和停止位。
单工、半双工、全双工、异步、同步
- 单工:数据只能单向传输。
- 半双工:数据可以双向传输,但是不能同时发送。
- 全双工:数据可以双向传输,且可以同时发送。
- 异步(Universal):通信双方的时钟不一样时的通信。
- 同步(Synchronous):通信双方的时钟一样时的通信。
UART和USART
- UART(通用异步收发器)和USART(通用同步异步收发器):串口通信的一种通信协议。速率不快,可全双工,结构上一般由波特率发生器、UART/USART发送器、UART/USART接收器组成,硬件上只有两条线,一收一发。
- 通信格式:通信时,高电平表示没有数据传输,高电平后的第一个低电平表示数据传输开始,之后接受数据,接受完毕后拉到高电平,最少需要一个高电平的停止位。即,传送一个字节,至少需要10位的空间。通信的两个芯片必须共地,两个芯片的输出TXD和输入RXD分别连接(A的输入连接B的输出),且STM32的TXD设置为输出推挽模式,RXD设置为输入上拉模式。通信频率就是波特率,即一个信号保持的时间是波特率的导数。
- 与电脑的通信:UART通信方式电脑不具备,电脑的通信方式是USB通信,它比UART复杂得多。为了实现串口与电脑的通信,需要通过一个转换芯片来进行协议的转换,并且在电脑端还需要软件来显示串口发送来的内容,这个软件就是“串口调试助手”。
CubeMX的操作
USART的设置
- 在"Pinout & Configuration"界面下,左侧选择下拉菜单"Connectivity",下拉菜单中选择USART,你会发现有好几个可以选择,具体使用哪个,需要参考原理图,看USB转串口连接的是哪个,这里选择USART1。
- 中间的界面里出现对应的窗口,“Mode”下“Mode”选择异步通信(asynchronous)。
- “Mode”下方的“Configuration”中,选择"Parameter Settings"窗口。第一个下拉菜单第一个波特率一般选择115200就可以了,第二个数据位选8位,第三个奇偶校验选择无(),第四个停止位一般选1位(设置成2位更可靠)。
- “Mode”下方的“Configuration”中,选择"NVIC Settings"窗口,勾选串口中断。原则:一个中断服务一个外设,不同中断使用相同变量保证他们的优先级一致。防止出现未知错误(打断造成的错误)。
- 设置作为串口通信的串口的状态,即输入(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不被占用。
- 配置好串烤的相关参数
- 配置DMA,配置的地方就在设置USART的地方,在下方的窗口里面找到DMA的界面,选择添加一个DMA,配置一般选择默认就可以了。DMA的模式分为普通模式和循环模式,循环模式就是把要求发送的数据重复发送,直到接收到停止指令。
-
DMA无法使用printf发送,它的发送函数为
HAL_UART_Transmit_DMA(UART地址,发送的数组,发送的字节数)
,发送的字节数不知道时,可以使用"string.h"里面的strlen(字符串);
。它的接收函数为HAL_UART_Receive_DMA(UART地址,接收的数组,接收的字节数)
DMA不定长接收
原理:就是说,未知数据长度大小,当不发送数据一定时间的时候就认为数据已经结束了。串口闲置中断就是,当接收了数据之后,串口闲置了一个字节的长度之后就会触发串口闲置中断。
本文地址:https://blog.csdn.net/weixin_43718316/article/details/107988929