STM32串口通信实现及原理详解

目录

通信基础知识

通信的本质

时钟信号划分

同步通信

异步通信

通信方式划分

串行通信

串行通信

串行传输

优点

缺点

 并行通信

并行通信

并行传输

优点

缺点

 通信方向划分

单工

半双工

全双工

 总线协议(电气协议)

USART

 串口通信协议

 数据帧格式

USART功能框图

 流控

概念

nRTS

nCTS

SCLK

相关寄存器

 串口控制寄存器

波特率寄存器

中断和状态寄存器

 数据接收寄存器

 数据发送寄存器

 实验:串口发送

实验要求

实物

 分析原理图

STM32CubeMX配置

 初始化代码分析

代码编写

1. 实现单个字符发送Uart_putchar()

2. 实现字符串发送Uart_puts()

 串口收发实验

1. 实现字符接收函数UART_getchar()

2. 实现字符串接收函数Uart_gets()

接收之后再发送

 HAL库函数

 串口发送函数

串口接收函数

printf重定向

实验:scanf重定向

要求

提示

代码示例

实验:LED灯控制

要求

串口扩展

TTL电平接口

RS-232电平

RS-485电平

差分信号

 拓扑结构

 RS-485收发器

 RS-485数据链路

典型电路

RS422 

SPI

IIC


通信基础知识

通信的本质

作用:进行数据交互和信息传递

条件:两个端,发送端和服务端

时钟信号划分

同步通信

通信双方根据同步信号通信,比如双方有一个共同的时钟信号(SPI全双工、I2C半双工),发送数据的时候会出现阻塞状态,需要等待数据传输完毕,程序才会执行下一行语句。

异步通信

通信双方有自己独立的系统时钟,双方或者多方需要确定好通信速度,异步通信不需要同步信号,但是并不是通信过程不同步(UART),发送数据的时候没有阻塞状态,执行发送数据语句后直接执行下一行语句。

通信方式划分

串行通信

串行通信

指同一时间只能传输或发送1bit的数据信息,因此只用一根信号线即可。

串行传输

数据一位一位串起来,逐个传输,数据按位顺序传输。

优点

占用引脚资源少

缺点

速度相对较慢

 并行通信

并行通信

指同一个时间可以接受或发送多个bit位的数据信息,因此需要多根信号线。

并行传输

使用多根线同时传输一个字的多个位,如八根线一次性传输8个位。

优点

数据传输速度快

缺点

占用引脚资源多

 通信方向划分

单工

单方向传输信息,要么接收信息,要么发送信息,只能做接收设备或者发送设备,例如大喇叭、遥控器、收音机等。

一根信号线只能单向发送或接收。

半双工

可以发送和接收,但是通信双方不能同时发送、接收,例如对讲机。

一根信号线既可以发送数据也可以接收数据,但是两者不能同时进行

全双工

可以在同一时刻既接收又发送数据,例如电话、智能手机。

两根信号线,一根发送数据,一根接收数据,实现同时接收发送数据,速度快。

 总线协议(电气协议)

TTL电平(5V)

        高电平1:2.4~5V        低电平0:0~0.5V

RS-232:RS-232电平

        高电平1:+3~+15V        低电平0:-15~-3V

RS-485:

是半双工的电气协议,是二进制差分信号,也就是实际的数据传输是通过判断这两条信号线上的电压差来实现,485的通讯距离可以达到几千米。

        高电平1:+2~+6V        低电平0:-6~-2V

USART

中文参考手册564页

USART(niversal Synchonous Asynchronous receiver transmitter )

 串口通信协议

 数据帧格式

空闲状态:信号线保持高电平

起始位:1位,处于低电平状态,数据包的起始位置

数据位:8位/9位

校验位:可以选择奇偶校验

        奇校验:数据为上1的个数 + 校验位上1的个数 = 奇数

        偶校验:数据为上1的个数 + 校验位上1的个数 = 偶数

停止位:1位,将电平信号拉高,代表一个数据包发送结束,回到空闲状态。

传输速度

        波特率(bps):每秒传输的数据位 单位是bit/s        1Byte=8bit

        常用的波特率:9600bit/s        115200bit/s

USART功能框图

中文参考手册中文参考手册568页

 TX:数据发送端

RX:数据接收端

 流控

概念

在两个设备正常通信时,由于处理速度不同,就会在某些情况下出现可能导致数据丢失的情况。例如台式机和单片机之间的通信,接收端数据缓冲区满的时候继续发送过来的数据就会丢失,但是流控能够解决这个问题。

nRTS

请求以发送(Request To Send),n表示低电平有效,当接收设备准备好接收新数据时就会把nRTS变成低电平;当接受寄存器满时,nRTS将被设置为高电平。

nCTS

清除以发送(Clear To Send)为输入信号,低电平有效。用于判断是否可以向对方发送数据,低电平说明该设备可以向对方发送数据。该引脚只适用于硬件流控器。

SCLK

发送器时钟输出引脚,这个引脚只适用于同步模式,(UART是异步通信)。

发送过程:由CPU或DMA向发送数据寄存器(TDR)写入要发送的数据,由发送移位寄存器将数据按位移动发送到发送端口。

接收过程:由CPU或DMA读取接受数据寄存器(RDR)中的数据。

相关寄存器

中文参考手册608页

 串口控制寄存器

USART_CR        决定帧格式:起始位 + 数据位 + 校验位 + 停止位

                          (设备功能初始化、通信帧格式配置)

                            USART_CR1

                            USART_CR2

                            USART_CR3

波特率寄存器

UASART_BRR        决定通信速度:bit/s

中断和状态寄存器

USART_ISR

 数据接收寄存器

USART_RDR        决定接收的数据:将要接收数据的读取

 数据发送寄存器

USART_RDR        决定发送的数据:将要发送的数据写入

 实验:串口发送

实验要求

通过单片机以1s间隔向电脑发送“helloworld”

实物

找到通信接口,P4

 分析原理图

 CH340:电平转换芯片,可以转换TTL电平—USB电平

 数据选择器/多路复用器

使用E和S进行控制

USB TDX连接到RXD

USB  RXD连接到TXD

 因此,要实现通信只需要把PA9和PA10设置为输入输出即可。

TX:发送        RX:接收

STM32CubeMX配置

 初始化代码分析

代码编写

1. 实现单个字符发送Uart_putchar()

void Uart_putchar(uint8_t ch)
{
	while(!(USART1->ISR & (1<<7)));		//	等待发送寄存器为空
		//ISR的第7位为1,说明发送数据寄存器为空,此时再写入要发送的数据
		//当发送数据寄存器为空时,while(!1);跳出循环,继续往下执行
	USART1->TDR = ch;
}

2. 实现字符串发送Uart_puts()

 串口收发实验

1. 实现字符接收函数UART_getchar()

uint8_t Uart_getchar()
{
	uint8_t ch;
	while(!(USART1->ISR & (1<<5)));		//等待接收数据寄存器非空
	ch = USART1->RDR;
	return ch;
}

2. 实现字符串接收函数Uart_gets()

uint8_t Uart_getchar()
{
	uint8_t ch;
	while(!(USART1->ISR & (1<<5)));		//等待接收数据寄存器非空
	ch = USART1->RDR;
	return ch;
}

void Uart_gets(uint8_t *p)
{
	uint8_t ch;
	while(1)
	{
		ch=Uart_getchar();
		if(ch !='\n')
		{
			*p=ch;
		}
		else
		{
			*p='\0';
			break;
		}
		p++;
	}
}

接收之后再发送

 HAL库函数

575页

 串口发送函数

HAL_StatusTypeDef HAL_UART_Transmit  (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size,  uint32_t Timeout) 
功能:以阻塞模式通过串口发送数据
参数:
    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) 
功能:以阻塞模式通过串口接收数据
参数:
    UART_HandleTypeDef * huart 设备的句柄
    uint8_t * pData 输入缓存区首地址 
    uint16_t Size  接收的数据量
    uint32_t Timeout  超时时间(毫秒为单位)
返回值:接收状态

printf重定向

int  printf(const char * format,...)

printf函数底层调用的是fput函数,fputs()的功能是将要发送的数据写入到标准输出流stdout,格式如下:

int fputc(int /*c*/, FILE * /*stream*/) 

如果想让printf通过串口将数据输出,需要重写fputc(),将stdout重定向到TDR

int fputc(int ch,FILE* p)
{
	while(!(USART1->ISR & (1<<7)));
	USART1->TDR = ch;
}

实验:scanf重定向

要求

重写scanf,将输入重定向到串口

提示

scanf函数底层调用的是fgetc函数

代码示例

实验:LED灯控制

要求

通过串口接收指令(字符串)来控制开发板上LED灯的开关(用HAL库和重定向实现)

控制指令:

        B_ON    打开蓝灯

        B_CL    关闭蓝灯

        Y_ON    打开黄灯

        Y_CL    关闭黄灯

        G_ON   打开绿灯

        G_CL    关闭绿灯

串口扩展

串口通信(Serial Communication), 是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。是我们在硬件调试过程中最常见的一种通信方式。比如开发板和电脑之间,想要收到开发板的输出信息,就必须用到串口。串口通信又分为不同的方式,常见的有UART、RS232、RS485、RS422。要理解这几种通信方式的差异,必须先理解几种电平制式。

TTL电平接口

TTL(Transistor Transistor Logic)即晶体管-晶体管逻辑,TTL电平信号由TTL器件产生。最常见的就算是直接从MCU(主控芯片)产生。TTL电平信号被利用的最多是因为通常数据表示采用二进制规定,+5V等价于逻辑"1",0V等价于逻辑"0",这被称做TTL(晶体管-晶体管逻辑电平)信号系统,这是计算机处理器控制的设备内部各部分之间通信的标准技术。

比如上图中STM32F051的PA9和PA10就是串口的收发管脚,051主控会通过内部串口控制器将数据转换为0、1电平,然后交由这两条线传输。这个电平制式就是TTL电平。

RS-232电平

我们常见的电子电路中常使用TTL的电平标准,如我们的计算机内部识别的就是TTL电平,但TTL电平有个缺点就是它不适合远距离传输,所以为了增加串口通讯的远距离传输及抗干扰能力,我们通常会使用RS-232电平,RS-232电平使用-15V表示逻辑1,+15V表示逻辑0。MCU和一些应用模块通信通常都是TTL电平。电脑,工业设备或者一些模块通常都是232电平,最常见的就是我们电脑的DB9的接口,如果开发板想要和电脑进行通信,必须转换为232的电平。

 TTL到232的转换就需要借助电平转换芯片来实现,下面是常用的一个MAX232电平转换芯片的原理图。

TXD和RXD接到MCU的引脚上,通过芯片转换的TO-PC-RX和TO-PC-TX就是RS232电平了,可以直接接到我们的电脑上进行通信。

思考:

        以上介绍的MCU如果想和电脑进行通信,电路应该这么选择?

RS-485电平

RS-485和RS-232一样,都是串行通信标准,现在的标准名称是TIA485/EIA-485-A,但是人们会习惯称为RS-485标准,RS-485常用在工业、自动化、汽车和建筑物管理等领域。RS-485总线弥补了RS-232通信距离短,速率低的缺点,RS-485的速率可高达10Mbit/s,理论通讯距离可达1200米;RS-485和RS-232的单端传输不一样,是差分传输,使用一对双绞线,其中一根线定义为A,另一个定义为B。RS485采用差分信号负逻辑,逻辑"1”以两线间的电压差为-(2~6)V表示;逻辑"0"以两线间的电压差为+(2~6)V表示。所以原来一条线能表示的信号,现在需要两条线才能表示。所以RS485通信是半双工的。

差分信号

长距离布线会有信号衰减,而且引入噪声和干扰的可能性更大,在线缆A和B上的表现就是电压幅度的变化,但是,采用差分线的好处就是,差值相减就会忽略掉干扰依旧能输出正常的信号,把这种差分接收器忽略两条信号线上相同电压的能力称为共模抑制。

标准规定:

        逻辑1:+2V to +6V

        逻辑0:-6V to -2V。

RS-485不需要使用特定的总线电压,只看最小差分电压,在较长的电缆长度上,接收器接收到的电压可能会降低到+/- 200 mV,这对于RS-485仍然是完全可以接受的,这也是RS-485的优点之一。

 拓扑结构

RS485有两线制和四线制两种接线,四线制只能实现点对点的通信方式,现很少采用,多采用的是两线制接线方式,这种接线方式为总线拓扑结构,在同一总线上最多可以挂接32个节点。RS-485总线同I^2C,也是主从模式,支持点对点单从机模式,也支持多从机模式,不支持多主机模式。

 RS-485收发器

RS-485是差分传输,如果用单片机控制RS-485接口的设备,需要用到收发器,这一点和CAN总线是类似的,如下是一个MCU控制一个RS-485的图示。

 RS-485数据链路

上面讲到的RS-485收发器的工作原理,下面简单描述RS-485的数据链路。

主机发送给从机或者从机发送给主机,都会占用到A和B线,所以RS-485多用在半双工模式。

典型电路

TTL到485的转换同样需要电平转换芯片来做,下面是常用的一个MAX485电平转换芯片原理图。

RS422 

EIA-422(过去称为RS-422)是一系列的规定采用4线,全双工,差分传输,多点通信的数据传输协议。它采用平衡传输采用单向/非可逆,有使能端或没有使能端的传输线。和RS-485不同的是EIA-422不允许出现多个发送端而只能有多个接受端。硬件构成上EIA-422 (RS-422)相当于两组EIA-485(RS-485),即两个半双工的EIA-485(RS-485)构成一个全双工的EIA-422(RS-422)。

 RS422只是485的扩展,将原来的半双工变为双工通信。典型电路图如上图,原理相同,这里不再赘述。

SPI

串口、网口通常用于设备之间的通信,如果是设备上芯片直接通信,我们通常选择更加高速的通信总线,比如SPI、I^2C等。SPI是采用主从方式工作,主机通常为MCU,从机通常为EPROM、Flash,AD/DA,音视频处理芯片等。一般由SCLK、CS、MOSI,MISO四根线组成,有的地方可能是:SCK、SS、SDI、SDO等名称,都是一样的含义,当有多个从机存在时,通过CS来选择要控制的从机设备。

典型电路图,左边四个黄色引脚接到MCU上,通过程序控制MCU的SPI控制器来完成对外扩Flash的读写。

IIC

IIC(Inter-Integrated Circuit)是一个多主从的串行总线,又叫I^2C,是由飞利浦公司发明的通讯总线,属于半双工同步传输类型总线。IIC总线是非常常见的数据总线,仅仅使用两条线就能完成多机通讯,一条SCL时钟线,另外一条双向数据线SDA。

 

串行数据线SDA——负责在设备间传输串行数据  串行时钟线SCL——负责产生同步时钟脉冲串行数据线SDA——负责在设备间传输串行数据  串行时钟线SCL——负责产生同步时钟脉冲

通信双方约定好通信时钟后,SCL来输出时钟,主机会首先发送要通信的从机地址,然后通过SDA线发送数据。下图是STM32的MCU和E2PROM芯片AT24C02芯片连接的一个典型电路图。通过程序控制MCU的IIC控制器来完成对E2PROM的读写。

 

物联沃分享整理
物联沃-IOTWORD物联网 » STM32串口通信实现及原理详解

发表评论