usart串口以及通信基本概念

文章目录

  • 通讯的基本概念
    • 串行通信与并行通讯
      • 串行通信
      • 并行通信
      • 两种通信方式的比较
    • 全双工、半双工及单工通讯
      • 概念
      • **模型图**
    • 同步通讯与异步通讯
      • 模型图
        • 同步通讯模型图
        • 异步通讯模型图
    • 通讯速率
      • 比特率 (Bitrate) :
      • 波特率”(Baudrate):
  • USART——串口通讯
    • 串口通讯协议简介
      • 物理层
        • RS-232通讯图
          • 电平标准
      • TTL与RS232对比图
      • DB9信号线的说明
      • 协议层
    • USART简介
      • USART功能框图
      • 第一部分-功能引脚
        • USART引脚在stm32f103的引脚图分布
      • 第二部分-数据寄存器
        • USART_DR
        • TDR 和 RDR
        • 其他-控制器
      • 第三部分-接发送器
        • **发送器**
        • **接收器**
      • 第四部分-波特率
        • 波特率计算公式
      • 校验控制和中断系统
        • 校验
        • 中断系统
  • 代码
    • USART初始化结构体
    • USART时钟初始化结构体

通讯的基本概念

串行通信与并行通讯

串行通信

usart串口以及通信基本概念_第1张图片

串行通讯是指设备之间通过少量数据信号线 (一般是 8 根以下),地线以及控制信号线,按数据位形式一位一位地传输数据的通讯方式。

并行通信

usart串口以及通信基本概念_第2张图片

并行通讯一般是指使用 8、16、32 及 64 根或更多的数据线进行传输的通讯方式。

两种通信方式的比较

特性 串行通信 并行通信
通讯距离 较远 较近
抗干扰能力 较强 较弱
传输速率 较慢 较高
成本 较低 较高

具体选择:要速度选并行通信,要稳定选串行通信

全双工、半双工及单工通讯

主要用信道的方向来区分

概念

通讯方式 说明
全双工 在同一时刻,两个设备之间可以同时收发数据
半双工 两个设备可以同时收发数据,但是不能再同一时刻进行
单工 在任何时刻都只能进行一个方向的通讯,一个固定为发射设备,另一个固定为接收设备

模型图

usart串口以及通信基本概念_第3张图片

同步通讯与异步通讯

具体区别:是否有时钟信号

通讯方式 说明
同步通讯 收发设备双方会使用一根信号线表示时钟信号,在时钟信号的驱动下双方进行协调,同步数据
异步通讯 直接在数据信号中穿插一些同步用的信号位,或者把主体数据进行打包,以数据帧的格式传输数据

模型图

同步通讯模型图

usart串口以及通信基本概念_第4张图片

异步通讯模型图

usart串口以及通信基本概念_第5张图片

同步传递速率高,但是要求也高。

异步要求低,但是包含帧的各种标识符,所以允许误差小。

通讯速率

衡量通讯性能的重要参数就是通讯速率

比特率 (Bitrate) :

即每秒钟传输的二进制位数,单位为比特每秒 (bit/s)。

波特率”(Baudrate):

它表示每秒钟传输了多少个码元。而码元是通讯信号调制的概念,通讯中常用时间间隔相同的符号来表示一个二进制数字,这样的信号称为码元。

USART——串口通讯

串口通讯协议简介

STM32 标准库则是在寄存器与用户代码之间的软件层。对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和协议层。

物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。

协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。简单来说物理层规定我们用嘴巴还是用肢体来交流,协议层则规定我们用中文还是英文来交流。

物理层

RS-232通讯图

usart串口以及通信基本概念_第6张图片

在上面的通讯方式中,两个通讯设备的“DB9 接口”之间通过串口信号线建立起连接,串口信号线中使用“RS-232 标准”传输数据信号。由于 RS-232 电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个“电平转换芯片”转换成控制器能识别的“TTL 标准”的电平信号,才能实现通讯。

电平标准

usart串口以及通信基本概念_第7张图片

RS-232这样的协议给高低电平的表示留出了超级大的容错相比TTL有助于信号远距离的传输以及信号的稳定性。

TTL与RS232对比图

usart串口以及通信基本概念_第8张图片

因为控制器一般使用 TTL 电平标准,所以常常会使用 MAX3232 芯片对 TTL 及 RS-232 电平的信号进行互相转换。

DB9信号线的说明

usart串口以及通信基本概念_第9张图片

usart串口以及通信基本概念_第10张图片

usart串口以及通信基本概念_第11张图片

串口线中的 RTS、CTS、DSR、DTR 及 DCD 信号,使用逻辑 1 表示信号有效,逻辑 0 表示信号无效。例如,当计算机端控制 DTR 信号线表示为逻辑 1 时,它是为了告知远端的调制调解器,本机已准备好接收数据,0 则表示还没准备就绪。

在目前的其它工业控制使用的串口通讯中,一般只使用 RXD、TXD 以及 GND 三条信号线,直接传输数据信号,而 RTS、CTS、DSR、DTR 及 DCD 信号都被裁剪掉了。

协议层

串口通讯的数据包由发送设备通过自身的 TXD 接口传输到接收设备的 RXD 接口。

在串口通讯的协议层中,规定了数据包的内容,它由启始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据,其组成见图串口数据包的基本组成 。

usart串口以及通信基本概念_第12张图片

(还挺像单工的)

名称 说明
通讯的起始和停止信号 串口通讯的一个数据包从起始信号开始,直到停止信号。结束数据包的起始信号由一个逻辑 0 的,而数据包的停止信号可由 0.5、1、1.5 或 2 个逻辑 1 的数据位表示。(只要双方约定一样就ok)
有效数据 起始位之后紧接着的就是要传输的主体数据内容,常被约定为 5、6、7 或 8 位长
数据检验 奇校验 (odd)、偶校验(even)、0 校验 (space)、1 校验 (mark) 以及无校验 (noparity)。用来简单的检测数据是否有好好的被传过来

USART简介

通用同步异步收发器 (Universal Synchronous Asynchronous Receiver and Transmitter) 是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。

USART 还有一个 UART(UniversalAsynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。

简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。

串行通信一般是以帧格式传输数据,即是一帧一帧的传输,每帧包含有起始信号、数据信息、停止信息,可能还有校验信息。

USART功能框图

usart串口以及通信基本概念_第13张图片

第一部分-功能引脚

功能引脚 作用
TX 发送数据输出引脚3
RX 接收数据输入引脚
SW_RX 数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引脚
nRTS 请求以发送 (Request To Send),n 表示低电平有效。如果使能 RTS 流控制,当 USART 接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,nRTS 将被设置为高电平。该引脚只适用于硬件流控制。(0可以寄存,1不可以寄存,爷满了)
nCTS 清除以发送 (Clear To Send),n 表示低电平有效。如果使能 CTS 流控制,发送器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制
SCLK 发送器时钟输出引脚。这个引脚仅适用于同步模式
USART引脚在stm32f103的引脚图分布

usart串口以及通信基本概念_第14张图片

第二部分-数据寄存器

数据寄存器 功能
USART_DR 包含了已发送的数据或者接收到的数据
TDR 和 RDR 介于系统总线和移位寄存器之间。
USART_DR

实际是包含了两个寄存器,一个专门用于发送的可写 TDR,一个专门用于接收的可读 RDR。当进行发送操作时,往 USART_DR写入数据会自动存储在 TDR 内;当进行读取操作时,向 USART_DR 读取数据会自动提取 RDR数据

TDR 和 RDR

都是介于系统总线和移位寄存器之间。串行通信是一个位一个位传输的,发送时把TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接收时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到 RDR。

其他-控制器

USART 有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等等。使用USART 之前需要向 USART_CR1 寄存器的 UE 位置 1 使能 USART,UE 位用来开启供给给串口的时钟。发送或者接收数据字长可选 8 位或 9 位,由 USART_CR1 的 M 位控制。

第三部分-接发送器

发送器

当 USART_CR1 寄存器的发送使能位 TE 置 1 时,启动数据发送,发送移位寄存器的数据会在 TX引脚输出,低位在前,高位在后。如果是同步模式 SCLK 也输出时钟信号。

一个字符帧发送需要三个部分:起始位 + 数据帧 + 停止位。起始位是一个位周期的低电平,位周期就是每一位占用的时间;数据帧就是我们要发送的 8 位或 9 位数据,数据是从最低位开始传输的;停止位是一定时间周期的高电平。停止位时间长短是可以通过 USART 控制寄存器 2(USART_CR2) 的 STOP[1:0] 位控制,可选 0.5个、1 个、1.5 个和 2 个停止位。默认使用 1 个停止位。2 个停止位适用于正常 USART 模式、单线模式和调制解调器模式。0.5 个和 1.5 个停止位用于智能卡模式。当选择 8 位字长,使用 1 个停止位时,具体发送字符时序图见图字符发送时序图 。

usart串口以及通信基本概念_第15张图片
usart串口以及通信基本概念_第16张图片

当发送使能位 TE 置 1 之后,发送器开始会先发送一个空闲帧 (一个数据帧长度的高电平),接下来就可以往 USART_DR 寄存器写入要发送的数据。在写入最后一个数据后,需要等待 USART 状态寄存器 (USART_SR) 的 TC 位为 1,表示数据传输完成,如果 USART_CR1 寄存器的 TCIE 位置1,将产生中断。

接收器

如果将 USART_CR1 寄存器的 RE 位置 1,使能 USART 接收,使得接收器在 RX 线开始搜索

起始位。在确定到起始位后就根据 RX 线电平状态把数据存放在接收移位寄存器内。接收完成

后就把接收移位寄存器数据移到 RDR 内,并把 USART_SR 寄存器的 RXNE 位置 1,同时如果

USART_CR2 寄存器的 RXNEIE 置 1 的话可以产生中断。

在接收数据时,编程的时候有几个比较重要的标志位我们来总结下。

名称 描述
RE 接收使能
RXNE 读数据寄存器非空
RXNEIE 接收完成中断使能

第四部分-波特率

波特率计算公式

usart串口以及通信基本概念_第17张图片

校验控制和中断系统

校验

STM32F103 系列控制器 USART 支持奇偶校验。当使用校验位时,串口传输的长度将是 8 位的数据帧加上 1 位的校验位总共 9 位,此时 USART_CR1 寄存器的 M 位需要设置为 1,即 9 数据位。将 USART_CR1 寄存器的 PCE 位置 1 就可以启动奇偶校验控制,奇偶校验由硬件自动完成。启动了奇偶校验控制之后,在发送数据帧时会自动添加校验位,接收数据时自动验证校验位。接收数据时如果出现奇偶校验位验证失败,会见 USART_SR 寄存器的 PE 位置 1,并可以产生奇偶校验中断。

使能了奇偶校验控制后,每个字符帧的格式将变成:起始位 + 数据帧 + 校验位 + 停止位。

中断系统

usart串口以及通信基本概念_第18张图片

代码

USART初始化结构体

typedef struct {
uint32_t USART_BaudRate; // 波特率
uint16_t USART_WordLength; // 字长
uint16_t USART_StopBits; // 停止位
uint16_t USART_Parity; // 校验位
uint16_t USART_Mode; // USART 模式
uint16_t USART_HardwareFlowControl; // 硬件流控制
} USART_InitTypeDef;
结构体成员 功能
USART_Baudrate 设置波特率一般为2400 9600 19200 115200
USART_WordLength 数据帧字长 8或9位
USART_StopBits 停止位,可选 0.5 个、1 个、1.5 个和 2 个停止位
USART_Parity 奇偶校验Odd Even No
USART_Mode 有 USART_Mode_Rx 和 USART_Mode_Tx 接或收
USART_HardwareFlowControl 硬件流控制选择,只有在硬件流控制模式才有效,可选有使能

USART时钟初始化结构体

typedef struct {
uint16_t USART_Clock; // 时钟使能控制
uint16_t USART_CPOL; // 时钟极性
uint16_t USART_CPHA; // 时钟相位
uint16_t USART_LastBit; // 最尾位时钟脉冲
} USART_ClockInitTypeDef;
结构体成员 功能
USART_Clock 下 SCLK 引脚上时钟输出使能控制,可选禁止时钟输出 (USART_Clock_Disable) 或开启时钟输出 (USART_Clock_Enable)
USART_CPOL SCLK 引脚上输出时钟极性,设置低电平 (USART_CPOL_Low) 或高电平 (USART_CPOL_High)
USART_CPHA SCLK 引脚上输出时钟相位设置,钟第一个变化沿捕获数据 (USART_CPHA_1Edge) 或在时钟第二个变化沿捕获数据。
USART_LastBit 选择在发送最后一个数据位的时候时钟脉冲是否在 SCLK 引脚输出,可以是不输出脉冲 (USART_LastBit_Disable)、输出脉冲 (USART_LastBit_Enable)。它设定 USART_CR2 寄存器的 LBCL 位的值

上输出时钟极性,设置低电平 (USART_CPOL_Low) 或高电平 (USART_CPOL_High) |
| USART_CPHA | SCLK 引脚上输出时钟相位设置,钟第一个变化沿捕获数据 (USART_CPHA_1Edge) 或在时钟第二个变化沿捕获数据。 |
| USART_LastBit | 选择在发送最后一个数据位的时候时钟脉冲是否在 SCLK 引脚输出,可以是不输出脉冲 (USART_LastBit_Disable)、输出脉冲 (USART_LastBit_Enable)。它设定 USART_CR2 寄存器的 LBCL 位的值 |

void USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	// 打开串口GPIO的时钟
	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
	
	// 打开串口外设的时钟
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

	// 将USART Tx的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  // 将USART Rx的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
	
	// 配置串口的工作参数
	// 配置波特率
	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
	// 配置 针数据字长
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	// 配置停止位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	// 配置校验位
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	// 配置硬件流控制
	USART_InitStructure.USART_HardwareFlowControl = 
	USART_HardwareFlowControl_None;
	// 配置工作模式,收发一起
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	// 完成串口的初始化配置
	USART_Init(DEBUG_USARTx, &USART_InitStructure);	
	
	// 使能串口
	USART_Cmd(DEBUG_USARTx, ENABLE);	    
}

/*****************  发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
	/* 发送一个字节数据到USART */
	USART_SendData(pUSARTx,ch);
		
	/* 等待发送数据寄存器为空 */
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}

/*****************  发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
	unsigned int k=0;
  do 
  {
      Usart_SendByte( pUSARTx, *(str + k) );
      k++;
  } while(*(str + k)!='\0');
  
  /* 等待发送完成 */
  while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
  {}
}

/*****************  发送一个16位数 **********************/
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
	uint8_t temp_h, temp_l;
	
	/* 取出高八位 */
	temp_h = (ch&0XFF00)>>8;
	/* 取出低八位 */
	temp_l = ch&0XFF;
	
	/* 发送高八位 */
	USART_SendData(pUSARTx,temp_h);	
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
	
	/* 发送低八位 */
	USART_SendData(pUSARTx,temp_l);	
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}

///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
		/* 发送一个字节数据到串口 */
		USART_SendData(DEBUG_USARTx, (uint8_t) ch);
		
		/* 等待发送完毕 */
		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);		
	
		return (ch);
}

///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
		/* 等待串口输入数据 */
		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(DEBUG_USARTx);
}

你可能感兴趣的:(stm32,stm32,嵌入式硬件)