Press ESC to close

UART通信_深入理解(理论+实践)

UART通信_深入理解(理论+实践)

1. 理论知识

1.1 定义和概述

UART是 "通用异步收发器" ( Universal Asynchronous Receiver/Transmitter ) 的缩写,通常简称为UART。是一种异步串行通信接口,用于将数据通过串列通信进行传输。

1.2 硬件组成

常见的串口板会有四根线,VCC供电线、GND地线、TX数据发送端口、RX数据接收端口。使用上,GND连接保证两设备共地,有统一的参考平面;一方tx接另一方rx;vcc按需连接。

1.3 工作原理

发送端将数据写入移位寄存器,然后发送数据帧;

接收端通过内部时钟信号控制,在每个时钟脉冲采样接收到的信号状态;

数据帧由起始比特、数据比特、奇偶校验和停止位组成;

UART提供缓冲区存储接收的数据,并向处理器报告新数据可用。

串口参数及时序图:

波特率:串口通信的速率(发送和接收各数据位的间隔时间),每秒传输的bit数;

波特率通常是通过系统定时器转化而来:

校验位:用于数据验证;

停止位:用于数据帧间隔;

8位数据格式(LSB最低有效位,MSB最高有效位,一般默认地位优先传输):

9位数据格式:

串口模式图:

1.4 主要特点

异步通信,不用同步信号;

串行通信,数据按比特顺序逐个发送,而不是像并行通信那样一次发送整个字节;

自动同步,接收端会自动识别数据帧的起始点;

可靠性高,有停止位和奇偶校验来检测传输错误;

低成本,单向只需要一根线就可进行通信,比并行通信硬件成本更低。

1.5 应用

手机设计和测试中控制CPU与其他部分的消息传送;

连接调制解调器(modem)的串口;

PC机上的异步通信串口通信(COM接口);

嵌入式系统中的低成本串口通信解决方案。

1.6 补充说明

UART串口通信指是硬件电路类型,具体电平通信协议通常是采用 TTL电平。

TTL电平 :+5V 表示 1 ,0V 表示 0;

RS232电平: -3 ~ -15V 表示 1 ,+3V ~ +15V表示 0;

RS485电平:两线压差 +2 ~ +6V 表示 1 ,-2 ~ -6V 表示0;

更多RS232协议相关内容见随笔:https://www.cnblogs.com/yangyang13/p/18658555

由于电脑上大多数RS232接口的淘汰,现在大多采用串口板实现UART串口通信,其电路设计原理等相关内容见随笔:

USART与UART的区别是多了同步通信功能;

USART 通用同步异步收发机(Universal Synchronous Asynchronous Receiver Transmitter)

2. 实践验证

2.1 寄存器方式

验证的硬件环境:AI8051U实验箱 (STC公司产品,搭载当前最新的ai8051芯片)

2.1.1 串口相关寄存器

补充:

四种串口模式的特点应用场景如下:

同步位移串行方式

特点:同步信号进行数据传输,数据位移位与同步信号对齐

应用场景:高速数据传输,并且需要精确控制传输时间

可变波特率8位数据方式

特点:波特率可变,数据帧为8位

应用场景:计算机外设,嵌入式等,相对灵活,兼容性强

固定波特率9位数据方式

特点:数据帧9位,多出的一位常用来作为地址/数据标识位或者奇偶校验,增加通信的可靠性或实现多机通信协议

应用场景:对通信可靠性要求比较高的场景,如工业控制中的多点通信

可变波特率9位数据方式

特点:波特率可变,9位数据帧,平衡了数据传输速率和数据完整性的要求

应用场景:需要动态调整传输参数的应用,如智能传感器网络、复杂分布式控制系统

串口中断及波特率涉及到定时器,见随笔:

2.1.2 代码

main.c

/************* 功能说明 **************

本例程基于AI8051U为主控芯片的实验箱进行编写测试。

串口1全双工中断方式收发通讯程序。

通过PC向MCU发送数据, MCU收到后通过串口1把收到的数据原样返回.

下载时, 选择时钟 24MHz.

******************************************/

#include "ai8051u.h" // 调用头文件

#include "stdio.h"

#include "intrins.h"

#include "UART.h"

unsigned char srcc = 1;

void Delay100ms(void) //@24.000MHz

{

unsigned long edata i;

_nop_();

_nop_();

i = 599998UL;

while (i) i--;

}

/******************** 主函数 **************************/

void main(void)

{

WTST = 0; // 设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快

EAXFR = 1; // 扩展寄存器(XFR)访问使能

CKCON = 0; // 提高访问XRAM速度

P0M1 = 0x00; P0M0 = 0x00; // 设置所有IO口为准双向口

P1M1 = 0x00; P1M0 = 0x00;

P2M1 = 0x00; P2M0 = 0x00;

P3M1 = 0x00; P3M0 = 0x00;

P4M1 = 0x00; P4M0 = 0x00;

P5M1 = 0x00; P5M0 = 0x00;

P6M1 = 0x00; P6M0 = 0x00;

P7M1 = 0x00; P7M0 = 0x00;

Uart1_Init();

while (1)

{

P40 = 0;

P0 = ~srcc;

// UART_SendByte(srcc);

// Delay100ms();

// srcc++;

}

}

void Uart1_Isr(void) interrupt 4

{

if (TI) //检测串口1发送中断

{

TI = 0; //清除串口1发送中断请求位

}

if (RI) //检测串口1接收中断

{

srcc = (unsigned char)SBUF;

UART_SendByte(srcc);

RI = 0; //清除串口1接收中断请求位

}

}

UART.c

#include "ai8051u.h"

void Uart1_Init(void) //9600bps@24.000MHz

{

SCON = 0x50; //8位数据,可变波特率

AUXR |= 0x40; //定时器时钟1T模式

AUXR &= 0xFE; //串口1选择定时器1为波特率发生器

TMOD &= 0x0F; //设置定时器模式

TL1 = 0x8F; //设置定时初始值

TH1 = 0xFD; //设置定时初始值

ET1 = 0; //禁止定时器中断

TR1 = 1; //定时器1开始计时

ES = 1; //使能串口1中断

EA = 1;

P_SW1 = (P_SW1 & ~0xc0) | 0x40;

}

void UART_SendByte(unsigned char Byte)

{

SBUF = Byte;

while(TI);

TI=0;

}

2.1.3 现象

单片机向上位机发送信息

上位机向单片机发送信息后返回

串口界面:

实验板子:0x45 :小端模式, 1010 0010

2.1.4 难点

ai8051u这款芯片是最近才接触到的,它烧录程序用的是USB-UART形式,串口1和烧录口是同一引脚。一开始想着怎么在同一引脚完成串口通信,它烧录完后,串口自动掉了。USB-CDC模式也是首次了解,这个模式的源码啃了一天没啃下来(后续再深入学习)。后面在手册中找到了可以把串口1转移到其他引脚进行通信。

中断中不能操作寄存器,while循环中就可以,想把串口传的值直接在串口中断给到P0,P0直接没反应了。通过中间变量传递,在while中赋值就没事。

2.2 库函数方式(HAL库)

2.2.1 CubMX配置

2.2.2 功能代码

2.2.3 现象

串口发送数据控制灯亮灭: