51单片机串口通信基础教程:从代码出发理解通信原理

51单片机串口通信基础教程:从代码出发理解通信原理

一、引言

想象我们生活在一个由各种小机器人组成的世界里,每个小机器人都有自己的任务和功能。为了让这些小机器人之间能够交流信息,我们需要一种通信方式。在51单片机的世界里,串口通信就像是小机器人之间的“电话线路”,通过它,单片机可以和其他设备(比如电脑)进行信息的传递。今天,我们就来详细解读一段51单片机串口通信的代码,看看这个“电话线路”是如何搭建和工作的。

二、代码整体功能概述

这段代码的主要功能是让51单片机通过串口与其他设备进行通信。单片机初始化串口后,先发送两个字节的数据 0x5a ,之后进入一个无限循环,等待接收其他设备发送的数据。一旦接收到数据,就将数据加1后再发送回去。

三、代码详细解读

1. 头文件和特殊寄存器定义

#include "reg52.h"
sfr AUXR=0x8e;
  • #include "reg52.h":这就像是我们打开了一个工具箱,reg52.h 这个头文件里包含了很多51单片机常用的工具(寄存器定义),我们在代码里可以直接使用这些工具。
  • sfr AUXR=0x8eAUXR 是一个特殊的寄存器,就好比是工具箱里一个比较特殊的工具。我们通过 sfr 关键字给它指定了地址 0x8e,这样我们就可以使用这个特殊工具来完成一些特定的任务。

2. 变量定义

unsigned char urdat;

urdat 就像是一个小盒子,用来存放从串口接收到的数据。unsigned char 表示这个盒子只能存放无符号的单字节数据。

3. 数据发送函数 SendByte

void SendByte(unsigned char dat)
{
    SBUF = dat;
    while(TI==0);
    TI=0;
}
  • SBUF = dat;SBUF 是串口的数据缓冲区,就像是一个快递包裹箱。我们把要发送的数据 dat 放到这个包裹箱里,准备寄出去。
  • while(TI==0);TI 是发送中断标志位,就像是快递的发货通知。当 TI 为0时,说明包裹还没发出去,我们就一直等着,直到包裹发出去(TI 变为1)。
  • TI=0;:包裹发出去后,我们把发货通知清零,为下一次发货做准备。

4. 延时函数 Delay10ms

void Delay10ms()		//@11.0592MHz
{
    unsigned char i, j;
    i = 108;
    j = 145;
    do
    {
        while (--j);
    } while (--i);
}

这个延时函数就像是一个倒计时器。在单片机的世界里,有时候我们需要等一段时间再做下一步操作。这里通过嵌套的循环,让单片机空转一段时间,大约是10毫秒。ij 的值是根据单片机的晶振频率 11.0592MHz 计算出来的,就像是倒计时器的刻度。

5. 串口初始化函数 UartInit

void UartInit(void)		//9600bps@11.0592MHz
{
    SCON = 0x50;		//8位数据,可变波特率
    AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
    AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
    TL1 = 0xE0;		//设定定时初值
    TH1 = 0xFE;		//设定定时初值
    ET1 = 0;		//禁止定时器1中断
    TR1 = 1;		//启动定时器1
    ES=1;
    EA=1;
}

这个函数就像是在搭建“电话线路”。

  • SCON = 0x50;SCON 是串口控制寄存器,就像是电话的拨号盘。我们把它设置为 0x50,表示使用8位数据、可变波特率的通信模式。
  • AUXR |= 0x40;AUXR &= 0xFE;AUXR 就像是电话线路的总开关,这里我们通过设置它来选择定时器1作为时钟源和波特率发生器。
  • TMOD &= 0x0F;TMOD 是定时器模式寄存器,就像是定时器的模式选择按钮。我们把它设置为让定时器1工作在16位自动重装模式。
  • TL1 = 0xE0;TH1 = 0xFE;TL1TH1 是定时器1的初值寄存器,就像是定时器的初始刻度。我们给它们赋初值,是为了得到我们想要的波特率(这里是9600bps)。
  • ET1 = 0;:禁止定时器1中断,就像是把定时器的闹钟关掉,我们不需要它发出中断信号。
  • TR1 = 1;:启动定时器1,就像是按下定时器的启动按钮。
  • ES=1;EA=1;ES 是串口中断允许位,EA 是全局中断允许位。我们把它们都设置为1,就像是打开了电话的铃声开关,允许串口接收到数据时发出中断信号。

6. 串口中断服务函数 ServiceUart

void ServiceUart() interrupt 4
{
    if(RI==1)
    {
        RI=0;
        urdat=SBUF;
        SendByte(urdat+1);
    }
}

这个函数就像是当电话铃声响起(串口接收到数据)时,我们要做的事情。

  • if(RI==1)RI 是接收中断标志位,就像是电话的来电指示灯。当 RI 为1时,说明有电话打进来(接收到数据)。
  • RI=0;:把来电指示灯熄灭,为下一次来电做准备。
  • urdat=SBUF;:把接收到的数据从数据缓冲区 SBUF 里取出来,放到我们之前准备好的小盒子 urdat 里。
  • SendByte(urdat+1);:把小盒子里的数据加1,然后通过 SendByte 函数再发送回去,就像是接电话后回复对方一个修改后的信息。

7. 主函数 main

void main()
{
    UartInit();
    Delay10ms();//用来延迟使得方便用串口工具显示出0x5a
    SendByte(0x5a);
    SendByte(0x5a);
    while(1);
}

主函数就像是整个程序的指挥官。

  • UartInit();:调用串口初始化函数,搭建好“电话线路”。
  • Delay10ms();:延时10毫秒,就像是给对方一点准备时间,方便对方的串口工具显示我们要发送的数据。
  • SendByte(0x5a);SendByte(0x5a);:发送两个字节的数据 0x5a,就像是给对方打个招呼。
  • while(1);:进入无限循环,就像是指挥官一直在等待新的任务(等待串口接收到新的数据)。

四、逻辑图

开始
调用UartInit初始化串口
调用Delay10ms延时10ms
调用SendByte发送0x5a
再次调用SendByte发送0x5a
进入无限循环等待
串口接收到数据
RI是否为1
RI清0
读取数据到urdat
调用SendByte发送urdat+1

这个逻辑图清晰地展示了程序的执行流程。从开始初始化串口,到发送数据,再到进入无限循环等待接收数据,一旦接收到数据就进行处理并回复,形成了一个完整的串口通信流程。

通过以上的解读和逻辑图,相信你对51单片机的串口通信有了更深入的理解。现在你可以试着修改代码,实现更多有趣的功能,比如发送不同的数据、处理更复杂的信息等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值