这次我们讲的是单片机的串口通信,有一点点复杂

一、串口通信:单片机世界的"对话艺术"

想象两个单片机需要交流信息,它们需要一种共同语言——这就是串口通信(UART)。作为最古老的通信协议之一,UART至今仍是嵌入式系统的首选通信方式,广泛应用于:

  • 🔌 单片机与PC通信(调试/数据上传)

  • 📱 蓝牙/WiFi模块控制

  • 🌡️ 传感器数据采集(温湿度、GPS等)

  • 🤖 多机分布式系统


二、串口通信核心原理

1. 数据传输格式

          1帧数据 (10-11位)
┌───┬───────┬───────┬───────┬───┬───┐
│起 │ 数据位0│ 数据位1│ ...  │停 │空闲│
│始 │(LSB)  │       │      │止 │状态│
│位0│       │       │      │位1│   │
└───┴───────┴───────┴───────┴───┴───┘
  • 波特率:通信速度(如9600、115200bps)

  • 数据位:5-9位(通常8位)

  • 校验位:奇/偶/无校验(错误检测)

  • 停止位:1-2位(帧结束标志)

2. 电平标准对比
类型 电压范围 传输距离 常用场景
TTL 0-5V <1m 板级设备间通信
RS232 ±3~±15V 15m PC串口
RS485 ±1.5~±6V 1200m 工业现场总线

三、硬件连接全解析

1. 单片机与PC通信

        +-----------------+          +-----------------+
        |    AT89C51      |          |      PC         |
        |                 |          |                 |
        |   P3.0(RXD)─────┼───>──────┼─RXD (DB9针2)    |
        |   P3.1(TXD)◄────┼────<─────┼─TXD (DB9针3)    |
        |                 |          |                 |
        |       GND───────┼───────┬──┼─GND (DB9针5)    |
        +-----------------+       │  +-----------------+
                                  │
                                  ▼
                           MAX232电平转换芯片

注意:必须使用MAX232/CH340等芯片转换TTL↔RS232电平

2. 多机通信(RS485总线)

         +---------+     双绞线      +---------+
         | 主机    |◄---A/B线----►| 从机1   |
         |         |               |         |
         | MAX485  |               | MAX485  |
         |  DE─────┼───控制线─────►│ DE      |
         +---------+               +---------+
             ▲                         ▲
             │                         │
         +---------+               +---------+
         | 从机2   |               | 从机N   |
         +---------+               +---------+

优势:抗干扰强、支持128节点、长距离传输


四、51单片机串口编程实战

1. 初始化配置(11.0592MHz晶振)

#include <reg52.h>

void UART_Init() {
    // 波特率9600
    TMOD |= 0x20;    // 定时器1模式2(8位自动重装)
    TH1 = 0xFD;      // 波特率计算:256 - (Fosc/12/32/波特率)
    TL1 = 0xFD;
    TR1 = 1;         // 启动定时器1
    
    SCON = 0x50;     // 模式1(8位UART),允许接收
    ES = 1;          // 使能串口中断
    EA = 1;          // 全局中断使能
}
2. 数据发送函数

void UART_SendByte(unsigned char dat) {
    SBUF = dat;         // 数据写入发送缓冲器
    while(!TI);         // 等待发送完成
    TI = 0;             // 清除发送中断标志
}

void UART_SendString(char *str) {
    while(*str != '\0') {
        UART_SendByte(*str++);
    }
}
3. 中断接收程序

unsigned char rx_buffer[50];
unsigned char rx_index = 0;

void UART_ISR() interrupt 4 {
    if(RI) {                   // 接收中断
        RI = 0;                // 清除标志
        unsigned char ch = SBUF;
        
        if(ch == '\n') {       // 回车结束符
            rx_buffer[rx_index] = '\0';
            process_command(rx_buffer); // 处理命令
            rx_index = 0;
        } else if(rx_index < 49) {
            rx_buffer[rx_index++] = ch;
        }
    }
}

五、多机通信协议设计

1. Modbus RTU协议帧格式

┌─────┬─────┬─────┬───────────┬───────────┐
│地址 │功能码│数据长度│   数据区    │  CRC校验  │
├─────┼─────┼─────┼───────────┼───────────┤
│1字节│1字节│1字节│ N字节      │  2字节     │
└─────┴─────┴─────┴───────────┴───────────┘
2. 从机响应处理

void process_modbus(unsigned char addr) {
    if(addr != MY_ADDRESS) return; // 非本机地址
    
    switch(rx_buffer[1]) {         // 功能码
        case 0x03: // 读寄存器
            unsigned char reg_addr = rx_buffer[2];
            unsigned char reg_val = read_register(reg_addr);
            // 构建响应帧
            tx_buffer[0] = MY_ADDRESS;
            tx_buffer[1] = 0x03;
            tx_buffer[2] = reg_val;
            tx_buffer[3] = calc_crc(tx_buffer, 3);
            UART_SendBytes(tx_buffer, 4);
            break;
            
        case 0x06: // 写寄存器
            // 实现代码...
    }
}

六、常见问题及解决方案

1. 数据乱码问题

原因排查

  1. 波特率不匹配(误差>3%)

  2. 晶振频率偏差(换11.0592MHz)

  3. 地线未连接(必须共地)

解决方案

// 精确波特率计算工具:https://www.keil.com/products/c51/baudrate.asp
2. 数据丢失问题

优化策略

  1. 增加接收缓冲区

  2. 提升中断优先级

    IP |= 0x10; // 设置串口高优先级
  3. 使用硬件流控(RTS/CTS)

3. 长距离通信干扰

抗干扰设计

         +--------------+
         |   单片机     |
         |     TX  ────────┬─► 22Ω电阻
         |          │      │
         |          ▼      ▼
         |       SN75176  ◄─── 120Ω终端电阻
         |          │      │
         | A ───────┴──────┘
         | B ───────┬──────┐
         +----------│------│--------+
                    ▼      ▼
                双绞线 (A/B线反向)

七、进阶应用:无线串口通信

1. ESP8266 WiFi透传

// AT指令配置示例
UART_SendString("AT+CWMODE=1\r\n");   // 设为STA模式
UART_SendString("AT+CWJAP=\"SSID\",\"PWD\"\r\n"); // 连接WiFi
UART_SendString("AT+CIPSTART=\"TCP\",\"192.168.1.100\",8080\r\n"); // TCP连接
UART_SendString("AT+CIPMODE=1\r\n");  // 透传模式
2. 手机APP监控界面

图表

代码

下载

渲染失败


八、调试技巧与工具

1. 必备调试工具
工具 用途
串口助手 数据收发/波形显示
逻辑分析仪 精确解析通信时序
USB-TTL PC与单片机直连
RS485测试仪 总线故障定位
2. 调试代码片段

// 发送测试图案(0x00~0xFF)
void UART_SendTestPattern() {
    for(unsigned char i=0; i<255; i++) {
        UART_SendByte(i);
        delay_ms(10);
    }
}

// 用示波器检查:
//  1. 波特率是否准确
//  2. 数据位/停止位是否合规

九、完整项目示例:环境监测系统

// 主程序框架
void main() {
    UART_Init();
    DHT11_Init();
    
    while(1) {
        float temp = DHT11_ReadTemp();
        float humi = DHT11_ReadHumi();
        
        // 通过串口发送JSON数据
        printf("{\"temp\":%.1f,\"humi\":%.1f}\r\n", temp, humi);
        
        delay_ms(5000);
    }
}

// PC端接收结果:
{"temp":25.5,"humi":60.2}

十、未来趋势:高速串行通信

技术 速率 特点 应用场景
UART <10Mbps 简单易用 低速控制
SPI >100Mbps 全双工,需4线 存储器/屏幕
I2C 3.4Mbps 两线制,地址寻址 传感器
USB 480Mbps 即插即用 外围设备
LVDS >1Gbps 差分信号 高清视频

源码下载GitHub工程
扩展阅读:《嵌入式网络那些事》


结语:串口通信是单片机工程师的"必修课",掌握其原理与实战技巧,能为你打开物联网世界的大门。欢迎在评论区分享你的串口调试经验!同学们加油哈哈哈!!

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐