51 串口通信

51 串口通信

文章目录

  • 51 串口通信
    • 硬件电路
      • 电平标准
      • 常见通信接口
      • 通信方式
    • UART
      • 51单片机上的UART
      • 串口参数
      • 串口模式
      • 串口相关寄存器
    • 串口配置
      • 通过stc-isp自动配置
      • 通信工具配置
      • 模块化串口配置
      • 实例:根据接收的数据以二进制形式点亮LED

串口是一种应用广泛的通讯接口,成本低、易使用,可用于实现两个设备之间的互相通信

单片机可以用其带有的串口与另一单片机、计算机、其它硬件模块等通信

硬件电路

(图源:B站江协科技视频截图)

51 串口通信_第1张图片

TXD(Transmit Exchange Data)

RXD(receive external data)

交叉连接是因为TXD->RXD,延长线不需要交叉

如果两个设备各自都有供电,可以不接VCC

电平标准

电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:

  1. TTL(Transistor-Transistor Logic晶体管晶体管逻辑电路,就是单片机使用的电平)电平:+5V表示1,0V表示0(单片机用的)

  2. RS232电平:-3-15V表示1,+3+15V表示0(一般用在电脑等高电压的传输)

  3. RS485电平:两线压差+2+6V表示1,-2-6V表示0(差分信号)

RS485的两线压差是指两根线之前的电压差,而不是对地(传输距离远,更稳定,不使用差分信号的在10m之后就容易产生错误)

常见通信接口

名称 引脚定义 通信方式 特点 常见用途
UART TXD、RXD 全双工、异步 点对点通信 51单片机所用通信方式
I²C SCL、SDA 半双工、同步 可挂载多个设备 单片机开发板上的24C02用于存储数据,单片机通过I²C的通信接口实现读取和写入
SPI SCLK、MOSI、MISO、CS 全双工、同步 可挂载多个设备 DS1302等用到
1-Wire DQ 半双工、异步 可挂载多个设备 温度传感器等用到
CAN、USB等 CAN常用于汽车等,连接多个传感器,使用差分信号

通信方式

方式 特点
全双工 通信双方可以在同一时刻互相传输数据(有两数据线相互连接)
半双工 通信双方可以互相传输数据,但必须分时复用一根数据线(只有一根线)
单工 通信只能由一方发送到另一方,不能反向传输
同步 通信双方通信速率相同
异步 通信双方各自约定通信速率

通信速率:相当于在读取高低电平时采样的速率,速率正确才能接收到正确数据

同步:通信双方靠一根时钟线(比如上面提到的SCL、SCLK)来约定通信速率(不会导致收发错误)

总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)

(eg:I²C总线、SPI总线、1-Wire总线(满足总线的特点))

UART

51单片机上的UART

STC89C52RC有1个UART

有四种工作模式:

​ 模式0:同步移位寄存器

​ 模式1:8位UART,波特率可变(常用)

​ 模式2:9位UART,波特率固定

​ 模式3:9位UART,波特率可变

(图源:普中科技开发手册)

51 串口通信_第2张图片

51 串口通信_第3张图片

串口通信的接口和P30P31复用,操作P3的寄存器时则为IO,操作串口寄存器即为串口,不用单独区分

(STC89C52RC开发板上的USB转TTL下载模块)

51 串口通信_第4张图片

51 串口通信_第5张图片

串口参数

波特率:串口通信的速率(发送和接收各数据位的间隔时间)

波特率(Baud Rate)是指在串行通信中,单位时间内传输的符号(symbol)数量。它用于衡量串行数据传输速率或通信信号的变化速度。波特率通常以每秒传输的波特数来表示,单位为波特(baud)或者波特/秒(baud/s)。


在串行通信中,每个符号可以代表一个或多个比特(bits)。因此,波特率并不直接等同于比特率。比特率是指传输的比特数量,而波特率是指传输的符号数量。如果每个符号表示一个比特,则波特率和比特率相等;如果每个符号表示多个比特,则波特率高于比特率。

比特率与波特率_百度百科 (baidu.com)

检验位:用于数据验证(9位数据格式的最后一位,可用于奇偶校验等)

停止位:用于数据帧间隔

(图源:B站江协科技视频截图)

51 串口通信_第6张图片

串口模式

(图源:B站江协科技视频截图)

51 串口通信_第7张图片

数据通过总线传输,波特率由定时器T1控制,即在使用串口时需要配置定时器(经过2分频加16分频或者直接16分频)

发送时,先把8位的数据写入缓存,然后再发出去

接收时,先将数据接收到移位寄存器,然后移到缓存中

TI和RI表示发送中断和接收中断

(图源:普中科技开发手册)

51 串口通信_第8张图片

TI和RI用的是同一个中断通道,通过一个或门

串口相关寄存器

(图源:普中科技开发手册)

51 串口通信_第9张图片

注:PCON中只有SMOD和SMOD0是控制串口的,其余都是控制电源的

(图源:普中科技开发手册)

51 串口通信_第10张图片

51 串口通信_第11张图片

串口用的计时器1是“8位自动重装”模式:把两个计数器分开,一个中断后另一个自动重装(即两个计数器的一个用于计数,另一个用于保存一个固定数据,每次重置即为将保存的数值复制到计数所用计数器),只能计0~255,不用手动复位,可以减少运行时间

串口配置

通过stc-isp自动配置

51 串口通信_第12张图片

11.0592MHz的系统频率是没有误差的,可以选择较高的波特率,12MHZ的系统频率会有误差,波特率越高误差越大

12MHZ的波特率需要加倍,不加倍的话分频后时钟会变慢(时钟分频后可能无法得到准确的波特率)

波特率计算

在以下条件下:
@9600bps
TL1 = 0xFD;//253
TH1 = 0xFD; 

256-253=3(每次溢出需要的脉冲次数)

3*1.085(每个时间周期对应的时间(us)) = 3.255

T1溢出率(每秒溢出的次数)= 1s / 3.255us = 307,219.6620 = 0.3072196620MHz

0.3072196620MHz / 2 / 16 = 0.0096006144375MHz = 9600.61Hz

通过近似计算得到的结果并非整数,以下为通过计算器计算得出的结果

51 串口通信_第13张图片

对波特率倍速降低误差率的分析

(不一定对)

当晶振为12MHz时,选择4800bps,在波特率倍速的情况下,其实际波特率为2400bps,计数器初始化为243,计数13为1次溢出

即每13ns溢出一次,溢出率为76,923.0769

51 串口通信_第14张图片

4,807.6923076923076923076923076923

此时误差为0.16%


当不使用波特率倍速,计数器初始化为249,计数7次,溢出率为142,857.1428

在这里插入图片描述

4,464.285714285714

此时误差为6.99%


由此可知,当系统频率为12MHz时,1秒内的溢出次数(即溢出率)不为整数导致产生误差,而波特率倍速就是将溢出所需时间加长,从而降低每秒溢出的次数,即降低溢出率,通过这种方式可以使溢出率更加接近整数,从而降低误差。

#include 
#include "Delay.h"

void UART_inti()//[email protected]
//初始化寄存器
{
    SCON = 0x40;
    //0100 0000
    PCON = 0;
    //此处不需要配置中断

    //配置定时器1
    TMOD &= 0x0F;       //TMOD高四位置0
    TMOD |= 0x20;       //串口需要用“8位自动重装”模式
    TL1 = 0xFA;         //设置定时初始值
    TH1 = 0xFA;         //设置定时重载值
    ET1 = 0;            //禁止定时器中断
    TR1 = 1;            //定时器1开始计时
}

void UART_SendByte(unsigned int Byte)
//发送数据
{
    SBUF = Byte;
    //将数据写入SBUF
    while(TI == 0);
    //当发送未完成,保持在函数内

    TI = 0;
    //重置TI
}

unsigned char sec = 0;

void main()
{
    UART_inti();
    while(1)
    {
        UART_SendByte(sec);
        sec++;
        Delay(1000);
    }
}

通信工具配置

选择相应的波特率

HEX模式/十六进制模式/二进制模式:以原始数据的形式显示

文本模式/字符模式:以原始数据编码(ASCII美国信息交换标准代码)后的形式显示

51 串口通信_第15张图片

当发送数据的函数直接放在while并且没有任何延时时,打开串口接收的数据可能有错误,复位单片机即可(或者加一个延时,但是这样获得的第一个数据还是错误的)

模块化串口配置

#include 

void Uart1_Init(void)   //[email protected]
{
    PCON &= 0x7F;       //波特率不倍速
    SCON = 0x50;        //8位数据,可变波特率
    AUXR &= 0xBF;       //定时器时钟12T模式
    AUXR &= 0xFE;       //串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;       //设置定时器模式
    TMOD |= 0x20;       //设置定时器模式
    TL1 = 0xFD;         //设置定时初始值
    TH1 = 0xFD;         //设置定时重载值
    ET1 = 0;            //禁止定时器中断
    TR1 = 1;            //定时器1开始计时
}


void UART_SendByte(unsigned int Byte)
//发送数据
{
    SBUF = Byte;
    //将数据写入SBUF
    //这里SBUF不用特地判断,写入时为发送端SBUF,读取时为接收端SBUF
    while(TI == 0);
    //当发送未完成,保持在函数内

    TI = 0;
    //重置TI
}

实例:根据接收的数据以二进制形式点亮LED

//在初始化函数中添加
EA = 1;//启动所有中断
ES = 1;//启动串口中断
#include 
#include "Delay.h"
#include "Uart.h"

unsigned char sec = 0;

void main()
{
    Uart_Init();
    while(1)
    {

    }
}


void Uart_Routine() interrupt 4
//出发接收中断后的操作
{
    if(RI == 1)
    //防止发送中断导致操作进行
    {
        P2 = SBUF;
        //读取数据
        Uart_SendByte(SBUF);
        //发送接收到的数据
        RI = 0;
        //清零
    }
}

你可能感兴趣的:(51单片机学习,单片机,学习,51单片机)