Skip to content

1.8 串口通信实验 ​

学习目标:理解 UART 串口通信原理,掌握波特率设置,实现单片机与上位机(虚拟终端)的收发通信。

实验原理 ​

串口通信基础 ​

UART(通用异步收发器)通过一根发送线(TXD)和一根接收线(RXD)按异步串行方式传输数据。51 单片机串口(UART)引脚:

  • P3.0 / RXD:接收数据
  • P3.1 / TXD:发送数据
单片机                 上位机
┌──────┐               ┌──────────┐
│ TXD  ├──────────────►│ RXD      │
│ RXD  ├───────────────│ TXD      │
│ GND  ├───────────────│ GND      │
└──────┘               └──────────┘
(需共地!)

数据帧格式 ​

起始位(0) | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | 停止位(1)
  • 空闲时为高电平
  • 起始位:1 位低电平(标志数据开始)
  • 数据位:8 位(本实验)
  • 停止位:1 位高电平(标志数据结束)

波特率 ​

波特率 = 每秒传输的比特数(bps)。51 串口波特率由定时器 1 产生:

波特率 = (2^SMOD / 32) × 定时器1溢出率

常用配置:12MHz 晶振,定时器 1 方式 2 自动重装,波特率 4800 时初值 0xF3。

程序设计 ​

串口初始化函数 ​

c
/****************************************************
 * 串口初始化:方式1(8位UART),波特率4800
 * 使用定时器1方式2作为波特率发生器
 ****************************************************/
void uart_init(void)
{
    SCON = 0x50;    // 方式1:8位UART,REN=1(允许接收)
    TMOD &= 0x0F;   // 清定时器1模式位
    TMOD |= 0x20;   // 定时器1,方式2(8位自动重装)
    TH1 = 0xF3;     // 波特率 4800(12MHz)
    TL1 = 0xF3;
    TR1 = 1;        // 启动定时器1
    // ES = 1;      // (如需中断接收,打开串口中断)
    // EA = 1;      // 打开总中断
}

发送一个字节 / 字符串 ​

c
// 发送一个字节
void send_byte(unsigned char dat)
{
    SBUF = dat;                 // 数据写入发送缓冲
    while (TI == 0);            // 等待发送完成
    TI = 0;                     // 清发送完成标志
}

// 发送字符串
void send_string(unsigned char *str)
{
    while (*str != '\0')
    {
        send_byte(*str++);
    }
}

主程序:发送 + 接收回显 ​

c
/****************************************************
 * 实验名称:串口通信——发送字符串 + 接收回显
 ****************************************************/
#include <reg51.h>

void uart_init(void);
void send_byte(unsigned char dat);
void send_string(unsigned char *str);

// 串口中断接收服务函数
void uart_isr(void) interrupt 4
{
    unsigned char recv;
    if (RI)              // 接收完成标志
    {
        RI = 0;          // 清接收标志
        recv = SBUF;     // 读取接收数据
        send_byte(recv); // 回显(发回上位机)
    }
}

void main(void)
{
    uart_init();
    ES = 1;              // 使能串口中断
    EA = 1;              // 开总中断

    send_string("Hello, AIOTEER!\r\n");

    while (1)
    {
        // 主循环:中断接收处理
    }
}

Proteus 虚拟终端 ​

Proteus 提供 VIRTUAL TERMINAL(虚拟终端) 元件,可模拟电脑串口助手:

  1. 放置 VIRTUAL TERMINAL
  2. 连接:RXD 接单片机 TXD,TXD 接单片机 RXD
  3. 双击虚拟终端,设置波特率 4800、8 数据位、无校验、1 停止位
  4. 运行仿真,即可看到单片机发送的字符串
AT89C51          VIRTUAL TERMINAL
┌──────┐          ┌────────────┐
│ TXD  ├──────────►│ RXD        │
│ RXD  ├───────────│ TXD        │
└──────┘          │ GND        │
                  └────────────┘
                  (波特率 4800)

关键知识点 ​

知识点说明
SCON串口控制寄存器(SM0/SM1 选方式,REN 允许接收)
SBUF发送/接收缓冲寄存器(物理上是两个)
TI发送完成标志
RI接收完成标志
波特率发生器定时器 1 方式 2 常用作波特率发生器
共地通信双方必须共地,否则电平参考不同

波特率与初值对照(12MHz) ​

波特率TH1/TL1(方式2)误差
24000xF30.16%
48000xF3(SMOD=1)0.16%
96000xFD0.16%

12MHz 下 9600 波特率有一定误差但可工作;11.0592MHz 晶振专为串口设计,可精确产生 9600/19200 等标准波特率。

常见问题 ​

Q1:虚拟终端收不到数据?

  • 检查波特率设置是否一致
  • 检查 TXD/RXD 是否交叉连接
  • 检查是否共地

Q2:收到乱码?

  • 波特率不匹配(误差过大)
  • 数据位/停止位设置不一致
  • 建议改用 11.0592MHz 晶振

Q3:发送字符串不完整?

  • 检查发送函数 TI 标志处理
  • 检查字符串是否以 '\0' 结尾

实验任务 ​

  1. 单片机发送字符串"Hello"到虚拟终端
  2. 实现接收回显(收到什么发回什么)
  3. 扩展:用 Proteus 虚拟终端 + 串口控制 LED(收到 '1' 点亮,'0' 熄灭)

考核点 / 验收标准 ​

考核项验收标准分值
串口初始化SCON/TMOD/TH1 等配置正确,波特率准确30
数据发送能发送字符串到虚拟终端25
数据接收能接收并回显数据25
协议理解能说明数据帧格式与波特率含义20

实操要求:现场演示串口收发,收到 '1' 点亮 LED、'0' 熄灭。

aioteer · 物联网专业课程群

💬AI 伴学配置