【51单片机】串口通信(发送与接收)


前言

在嵌入式系统的开发中,串口通信是一种常见且重要的通信方式。它以其简单、稳定的特性在各种应用场景中得到了广泛的使用。本文将介绍51单片机中的串口通信,包括其定义、作用以及在实际应用中的重要性。


串口通信简介

串口通信,顾名思义,是一种串行通信方式,即数据是一位一位地顺序传输的。这与并行通信形成鲜明对比,后者是多位数据同时传输。在51单片机中,串口通信是通过特定的寄存器和引脚来实现的,如SCON寄存器用于设置串口模式,P3.0和P3.1引脚分别用于接收和发送数据。

串口通信的原理

首先,我们需要理解串口是一种串行通信方式,也就是说,数据是一位一位地按顺序传输的。这就像是你在一条单轨铁路上,一辆辆火车依次通过。

当我们要发送数据时,数据会被分解成一个个的二进制位(0或1),然后这些位会一个接一个地通过串口发送出去。这就像是你有一堆火车要发送,你会把它们一个接一个地放到铁轨上,让它们依次出发。

而当我们要接收数据时,串口会一位一位地读取传入的数据,然后把这些位组合起来,形成完整的数据。这就像是你在铁轨的另一端,一辆辆火车依次到达,你会把它们按顺序接收下来,然后组成一列完整的火车。

在这个过程中,还有一些重要的概念,比如波特率。波特率决定了数据传输的速度,也就是说,每秒钟可以传输多少位的数据。这就像是你的火车的速度,速度越快,每秒钟就能运送更多的火车。

总的来说,串口通信就是这样一种一位一位地发送和接收数据的方式,它简单、稳定,被广泛应用在各种电子设备中。

串口通信的作用

串口通信在51单片机中有着广泛的应用。首先,它可以用于单片机与外部设备的通信,如传感器、执行器等。通过串口,单片机可以接收外部设备的数据,或向外部设备发送控制命令。其次,串口通信也可以用于单片机与计算机的通信,这在开发和调试阶段尤其重要。通过串口,开发者可以直接从计算机向单片机发送指令,或从单片机读取运行状态,极大地方便了开发和调试工作。

串口编程的一些概念

  • 波特率:波特率是串口通信中的一个重要概念,它决定了数据传输的速度,单位是bps(比特每秒)。就像火车的速度,波特率越高,数据传输的速度就越快。

  • 数据位:数据位决定了每次传输的数据的大小。常见的数据位有5位、6位、7位和8位。就像火车的车厢数量,数据位越多,每次可以传输的数据就越多。

  • 停止位:停止位用于标记数据传输的结束,常见的停止位有1位和2位。就像火车站,停止位告诉接收端一列火车(也就是一个数据字节)已经到站。

  • 校验位:校验位用于检测数据在传输过程中是否出错。就像火车的检票员,校验位会检查数据是否正确。

仿真图

我们在下面找到Virtual Terminal,他的RXD连接到P3.1,他的TXD连接到P3.0即可
在这里插入图片描述

如何使用串口

初始化串口

初始化串口代码如下:

void UartInit()		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//设置波特率不倍速
	SCON = 0x50;		//设置为8位数据,可变波特率
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFD;			//设定定时初值
	TH1 = 0xFD;			//设定定时器重装值
	TR1 = 1;			//启动定时器1
	ET1 = 0;        	//禁止定时器1中断
	EA=1;				//开启总中断
	ES=1;				//开启串口中断
}

串口模式

51单片机的SCON(Serial Control Register)是串行口控制寄存器,用于控制串行通信的方式选择、接收和发送,指示串口的状态。SCON既可以字节寻址,也可以位寻址,其字节地址为98H,地址位为98H~9FH。

SCON的各个位的功能如下:

  • RI:接收中断标志位,数据接收结束时,标志位会自动置1,需要通过程序将其置0。
  • TI:发送中断标志位,数据发送结束时,标志位会自动置1,需要通过程序将其置0。
  • RB8:存放发送数据的第9位。
  • TB8:存放接收数据的第9位。
  • REN:串行接收允许位,用于控制数据接收的允许和禁止,为1时允许接收,为0时禁止接收。
  • SM2:多机控制位。
  • SM1,SM0:串行工作方式。

波特率配置

TH1和TL1是定时器1的两个寄存器,分别用于存储定时器的高8位和低8位。在51单片机中,定时器1可以被配置为波特率发生器,用于生成串口通信的波特率。

当我们设置 TH1 = 0xFDTL1 = 0xFD 时,实际上是在设置定时器1的溢出时间,从而决定了串口通信的波特率。这里的 0xFD 是256减去所需的计数值,因为定时器是在计数值达到256时溢出的。

例如,如果我们想要设置波特率为9600,晶振频率为11.0592MHz,那么我们可以使用以下公式来计算所需的计数值:

计数值 = 晶振频率 32 × 波特率 计数值 = \frac{晶振频率}{32 \times 波特率} 计数值=32×波特率晶振频率

将11.0592MHz和9600代入公式,我们可以得到计数值大约为3。然后我们用256减去这个计数值,得到253,对应的十六进制数就是FD。所以我们设置 TH1 = 0xFDTL1 = 0xFD

发送与接收

发送

我们可以通过把数据给SBUF寄存器,他就会给我们发送出去,我们可以通过他来实现发送函数

发送函数代码如下:

void Uartsend(unsigned char byte) //定义一个函数,用于发送一个字节的数据
{
	SBUF = byte; //将要发送的数据(byte)写入到发送缓冲区(SBUF)
	while(TI == 0); //等待数据发送完成,发送完成后,硬件会将TI置1
	TI = 0; //数据发送完成后,通过软件将TI清零
}

接收

接收,我们使用中断来接收,接收到的数据存储在SBUF寄存器里面
串口的接收在函数后面加interrupt 4即可,表示这个接收中断使用他

void UART_ISR() interrupt 4 //定义一个中断服务程序,用于处理串口中断,中断号为4
{
	if(RI==1) //如果接收中断标志位RI为1,表示接收到数据
	{
		Uartsend(SBUF); //调用Uartsend函数,将接收到的数据(存储在SBUF中)发送出去
		RI=0; //数据发送完成后,通过软件将接收中断标志位RI清零
	}
}

示例代码

#include <REGX52.H>
void UartInit()		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//??????
	SCON = 0x50;		//8???,?????
	TMOD &= 0x0F;		//?????1???
	TMOD |= 0x20;		//?????1?8???????
	TL1 = 0xFD;			//??????
	TH1 = 0xFD;			//????????		
	TR1 = 1;			//?????1
	ET1 = 0;        	//?????1??
	EA=1;				//????? 
	ES=1;				//??????
}
void Uartsend(unsigned char byte)//??
{
	SBUF=byte;//??????????SBUF
	//??????????TI=1;?????????
	while(TI==0);
	TI=0;//????
}
void UART_ISR() interrupt 4//??????
{
	if(RI==1)//????
	{
		Uartsend(SBUF);//????????????
		RI=0;//????
	}
}
int main()
{
	UartInit();
	
	while(1)
	{
		Uartsend(0x00);
	}
}

总结

总的来说,串口通信在51单片机中扮演着重要的角色。它以其简单、稳定的特性,为单片机提供了与外部世界交流的桥梁。无论是在硬件控制,还是在软件开发和调试中,串口通信都是不可或缺的一部分。因此,深入理解和熟练掌握串口通信,对于每一个嵌入式开发者来说,都是非常重要的。希望本文能帮助你对51单片机的串口通信有更深入的理解。

  • 30
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
51单片机串口通信需要通过串口通信模块来实现,常用的串口通信模块有MAX232、PL2303等。 下面是51单片机串口通信接收发送的基本步骤: 1. 设置串口通信的波特率、数据位、校验位和停止位等参数。 2. 使能串口接收中断,当有数据到达时,中断服务程序会被触发。 3. 在中断服务程序中读取串口接收寄存器中的数据,并进行相应的处理。 4. 发送数据时,将要发送的数据存储到串口发送寄存器中,等待发送完成。 5. 检查发送是否完成,如果未完成,则等待发送完成后再进行下一次发送。 下面是一个简单的示例程序,演示了如何在51单片机上进行串口通信接收发送: ```c #include <reg52.h> #include <stdio.h> #define BAUDRATE 9600 #define FOSC 11059200L #define TIMER 12 sbit LED = P2^0; void init_uart(); void uart_send(unsigned char dat); void uart_send_string(unsigned char *str); void uart_receive() interrupt 4; void main() { LED = 0; init_uart(); while(1) { uart_send_string("Hello, world!\r\n"); delay(1000); } } void init_uart() { TMOD &= 0x0F; TMOD |= 0x20; TH1 = TL1 = -(FOSC/12/BAUDRATE); TR1 = 1; SM0 = 0; SM1 = 1; EA = 1; ES = 1; } void uart_send(unsigned char dat) { SBUF = dat; while(!TI); TI = 0; } void uart_send_string(unsigned char *str) { while(*str) { uart_send(*str++); } } void uart_receive() interrupt 4 { unsigned char dat; if(RI) { RI = 0; dat = SBUF; if(dat == '1') { LED = !LED; } } } ``` 在上面的程序中,我们使用了一个单片机上的LED作为输出,每隔1秒钟向串口发送一条消息。同时,当接收到的数据为字符“1”时,反转LED的状态。 注意,上面的程序中使用了定时器来控制串口通信的波特率,需要根据实际的硬件参数进行调整。另外,由于串口通信是异步通信,需要在发送接收时进行一定的时间延迟,以确保数据的正确传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人才程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值