[经验分享] 嵌入式单片机---串口通信及相关通信技术

[复制链接]
1732|2
Zuocidian 发表于 2025-9-6 13:18 | 显示全部楼层 |阅读模式
一、通信方式分类
(一)按数据传输线路数量划分:串行通信与并行通信




(二)按数据传输方向划分:单工、半双工、全双工通信




二、串口通信(UART)核心知识
(一)串口通信定义
通常指“异步串口通信(UART)”,是串行通信的一种,通过1根发送线(TX)和1根接收线(RX)实现双向数据传输,靠“波特率同步”,广泛用于短距离设备交互(如单片机与电脑、传感器与控制器),属于异步串行全双工通信方式。

(二)串口通信时序
串口通信空闲时数据线为高电平,数据以“帧”为单位传输,1帧包含4个固定部分,时序顺序如下:

        空闲时为高电平

起始位:帧的开始标志,必为低电平(持续1个“位时间”,$ \text{位时间} = \frac{1}{\text{波特率}} $),用于通知接收端“即将传数据”;
数据位:实际传输的二进制数据,通常为5~8位(最常用8位,即1个字节),按“低位在前(LSB)、高位在后(MSB)”传输;
校验位(可选):用于检错,分奇校验(数据位+校验位总“1”的个数为奇数)、偶校验(总“1”的个数为偶数)、无校验(省略);
停止位:帧的结束标志,为高电平,用于接收端确认1帧结束,以保证下一个字节发送前的起始位能够表现出来。




(三)串口通信速率
速率决定因素:串口通信速率由“波特率(Baud Rate)”决定,波特率指“每秒传输的信号变化次数”(对串口而言,通常1个信号变化对应1位数据,因此 $ \text{波特率} \approx \text{每秒传输的位数} $,即bps),且收发双方必须设置相同的波特率,否则会因“位时间不匹配”导致数据传输错误。
常见波特率(单位:bps):1200、2400、4800、9600(常用)、115200等。
三、同步通信与异步通信




串口通信归属:串口通信(UART)属于异步通信,无需时钟线,靠起始/停止位和约定波特率实现数据同步。

四、常见电平标准(TTL、RS232、RS485)
三者是串口通信的“电平标准”(定义“0”和“1”对应的电压范围),核心差异是“电压范围”“传输距离”和“抗干扰能力”:




五、USB相关
USB(通用串行总线)是一种常用的串行通信接口,具有即插即用、支持热插拔、传输速率较高、可同时为外部设备供电等特点,广泛应用于电脑与外部设备(如U盘、鼠标、键盘、手机等)的连接与数据传输,其通信方式为串行通信,支持全双工传输。

六、51单片机串口通信相关代码
(一)头文件引用
#include <reg52.h>  
#include <stdio.h>  
#include <string.h>  
#include "delay.h"  


(二)串口初始化函数
void init_uart(void)  
{  
    unsigned char t;  
    t = SCON;  
    t &= ~(3 << 6);  
    t |= (1 << 6) | (1 << 4);  
    SCON = t;  

    PCON |= (1 << 7);  

    t = TMOD;  
    t &= ~(3 << 4);  
    t |= (2 << 4);  
    t &= ~(3 << 6);  
    TMOD = t;  
    TH1 = 204;  
    TL1 = 204;  
    TCON |= (1 << 6);  

    IE |= (1 << 7) | (1 << 4);  
}  



(三)单个字符发送函数
void send_char(char ch)  
{  
    SBUF = ch;  
    while((SCON & (1 << 1)) == 0);  
    SCON &= ~(1 << 1);  
}  


(四)缓冲区发送函数
void send_buffer(const char *p, int len)  
{  
    while(len--)  
    {  
        send_char(*p++);  
    }  
}  


(五)串口中断服务函数
void uart_handler(void) interrupt 4  
{  
    if((SCON & (1 << 0)) != 0)  
    {  
        P2 = SBUF;  
        SCON &= ~(1 << 0);  
    }  
}  


(六)全局变量定义
xdata char recv_buffer[64];  
int pos = 0;  


(七)主函数
int main(void)  
{  
    int i = 1;  
    int n = 10;  

    char *p = (char *) &p;  
    xdata char buffer[32];  
    init_uart();  

    while(1)  
    {  
        n = sizeof(int);  
        sprintf(buffer, "int size  =  %d\n", n);  
        send_buffer(buffer, strlen(buffer));  

        n = sizeof(char);  
        sprintf(buffer, "char size  =  %d\n", n);  
        send_buffer(buffer, strlen(buffer));  

        n = sizeof(short);  
        sprintf(buffer, "short size  =  %d\n", n);  
        send_buffer(buffer, strlen(buffer));  

        n = sizeof(double);  
        sprintf(buffer, "double size  =  %d\n", n);  
        send_buffer(buffer, strlen(buffer));  

        n = sizeof(long);  
        sprintf(buffer, "long size  =  %d\n", n);  
        send_buffer(buffer, strlen(buffer));  

        n = sizeof(char *);  
        sprintf(buffer, "char * size  =  %d\n", n);  
        send_buffer(buffer, strlen(buffer));  

        delay(0x9FFF);  
    }  

    return 0;  
}  


————————————————
版权声明:本文为CSDN博主「眰恦ゞLYF」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_69590097/article/details/151229299

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
不想起床喵星人 发表于 2025-9-29 12:31 | 显示全部楼层
串口通信的时序图非常清晰,帮助我理解了数据是如何一步步传输的。
迷雾隐者 发表于 2025-9-29 20:04 | 显示全部楼层
能否提供更多关于如何调试这部分代码的技巧?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

240

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部