HAL库学习05-串口通信:轮询、中断和DMA三种方式详解

一、原理介绍

串行通信的通讯方式可以分为两类:
1、同步通信,带时钟信号的传输,如SPI、IIC、USART
2、异步传输,不带时钟信号的传输,如UART、USART

UART通用异步收发器:UART口指的是一种物理接口形式(硬件)

UART是异步,全双工串口总线。它比同步串口复杂很多。有两根线,一根TXD用于发送,一根RXD用于接收。
UART的串行数据传输不需要使用时钟信号来同步传输,而是依赖于发送设备和接收设备之间预定义的配置。(约定固定波特率) 对于发送设备和接收设备来说,两者的串行通信配置应该设置为完全相同。

起始位:表示数据传输的开始,电平逻辑为“0” 。 数据位:可能值有5、6、7、8、9,表示传输这几个bit 位数据。一般取值为8,因为一个ASCII 字符值为8 位。 奇偶校验位:用于接收方对接收到的数据进行校验,校验“1” 的位数为偶数(偶校验) 或奇数(奇校验),以此来校验数据传送的正确性,使用时不需要此位也可以。 停止位:表示一帧数据的结束。电平逻辑为“1”。 如果用通用IO口模拟UART总线,则需一个输入口,一个输出口。

USART是通用同步/异步收发器:其可选使用异步方式,那将和UART无区别,如果是同步,则需要多一根时钟线(USART_CK)

串口发送接收有三种模式:轮询、中断和 DMA
补充几个名词:
Asynchronous:异步通信
Synchronous : 同步通信
Single Wire (Half-Duplex) :单线/半双工

二、STM32和PC进行数据互发

1、扫描接收发送

(1)、选择USART
(2)、设置MODE为异步通信(Asynchronous)
引脚一般自动设置为PA9、PA10

首先要在main.c或者是usart.c中对printf()和scanf()进行重定义,方便使用
记得要在头文件中输入#include "stdio.h"

int fputc(int ch,FILE *f)
{
HAL_UART_Transmit (&huart1 ,(uint8_t *)&ch,1,HAL_MAX_DELAY );
return ch;
}
int fgetc(iFILE *f)
{
uint8_t ch=0;
HAL_UART_Receive (&huart1 ,&ch,1,HAL_MAX_DELAY );
return ch;
}

这样子就可以直接利用printf进行发送,打印

 while (1)
  {
    ch=getchar();
    HAL_UART_Transmit(&huart1,&ch,1,0);
  }

当然也可以用这种方式

uint8_t data[1];
while (1)
{
if(HAL_UART_Receive(&huart1,data,sizeof(data),HAL_MAX_DELAY)==HAL_OK){
		HAL_UART_Transmit (&huart1 ,data,sizeof(data),HAL_MAX_DELAY );
    }
}

1、中断接收发送

中断接收发送理解:原来的轮询方式是你一遍遍的询问前台你的外卖到了吗,在这期间你无法腾出时间去干其他事情,而中断则是外卖到了,前台告诉你,然后你去拿,在此期间你是可以做其他的事情的。
打开NVIC中断

补充一个函数:中断方式串口接收触发中断(接收完成)所调用的函数(void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart))用这个回调函数实现中断后的动作,
代码编写
在 main.c 中,while 循环前,串口初始化后,添加接收中断开启函数,这样在第一次接收到数据的时候才会触发中断,切记要添加该函数。

HAL_UART_Receive_IT(&huart1,(uint8_t*)data,sizeof(data));//data是自己定义的接收中断缓冲

在main.c下方添加中断回调函数,实现串口的发送和接收

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		HAL_UART_Transmit_IT(&huart1,data,sizeof(data));//发送你输入的内容
		HAL_UART_Receive_IT(&huart1,(uint8_t*)data,sizeof(data));//打开下一次串口接收中断
		}
}

3、DAM接收发送

DMA接收发送理解:中断是外卖来了,前台打电话给你然后你去取,会有这样子一种情况就是你现在在干一些其他的紧急事情(比如说你在考试),这时候你就需要其他人帮你拿一下外卖,DMA就是充当这个角色
Cubemax中点击DMA中的ADD,添加RX通道和TX通道

代码编写
在 main.c 中,while 循环前,串口初始化后,添加DMA方式接收中断开启函数,这样在第一次接收到数据的时候才会触发中断,切记要添加该函数。

HAL_UART_Receive_DMA(&huart1,data,sizeof(data));//data是自己定义的接收中断缓冲

在main.c下方添加中断回调函数,实现串口的发送和接收

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		HAL_UART_Transmit_DMA(&huart1,data,sizeof(data));
		HAL_UART_Receive_DMA(&huart1,data,sizeof(data));
	}
}

以上就是关于串口收发的三种方式了,不知道有没有写清楚,后面有更好的表述方式会重修修改的。

物联沃分享整理
物联沃-IOTWORD物联网 » HAL库学习05-串口通信:轮询、中断和DMA三种方式详解

发表评论