串口通信
一、串口介绍
-
串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
-
单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。
-
51单片机内部自带UART (Universal Asynchronous ReceiverTransmitter,通用异步收发器),可实现单片机的串口通信
二、硬件电路
-
简单双向串口通信有两根通信线(发送端TXD和接收端RXD)
-
TXD与RXD要交叉连接
-
当只需单向的数据传输时,可以直接一根通信线
-
当电平标准不一致时,需要加电平转换芯片
三、电平标准
电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
-
TTL电平:+5V表示1,0V表示0
-
RS232电平:-3--15V表示1,+3-+15V表示0
-
RS485电平:两线压差+2~+6V表示1,-2--6V表示0(差分信号)
(单片机经常使用TTL电平)
四、51单片机的UART
-
STC89C52有1个UART
-
STC89C52的UART有四种工作模式:
模式0:同步移位寄存器
模式1:8位UART,波特率可变(常用)
模式2:9位UART,波特率固定
模式3:9位UART,波特率可变
五、串口参数及时序图
-
波特率:串口通信的速率(发送和接收各数据位的间隔时间)
-
检验位:用于数据验证
-
停止位:用于数据帧间隔
-
就位数据格式的时候多了一位检验位
六、串口模式图
七、代码示例
串口初始化 (UartInit
函数)
这个函数用于初始化8051单片机的串口(UART),以便以特定的波特率(这里是4800bps)进行通信。它做了以下几件事情:
-
设置波特率倍速位:
PCON |= 0x80;
这行代码使能了波特率倍速位(SMOD),这通常用于提高波特率的精度或实现更高的波特率。 -
配置串口控制寄存器:
SCON = 0x50;
这行代码设置了串口的工作模式,这里选择的是模式1(8位数据位,可变波特率)。 -
定时器配置:为了生成正确的波特率,需要配置定时器1。这里首先清除定时器1的模式位(
TMOD &= 0x0F;
),然后设置为8位自动重装模式(TMOD |= 0x20;
)。TL1 = 0xF4;
和TH1 = 0xF4;
设置了定时器的初始值和重装值,这些值是根据系统时钟频率(11.0592MHz)和波特率(4800bps)计算得出的。 -
启动定时器并启用串口中断:
TR1 = 1;
启动定时器1,EA=1;
和ES=1;
分别启用全局中断和串口中断。
串口发送字节 (Uart_SendByte
函数)
这个函数用于通过串口发送一个字节的数据。它简单地将要发送的字节写入到串口缓冲寄存器(SBUF
),然后等待发送完成(TI
标志位被硬件置1)。发送完成后,它手动清除TI
标志位,以便进行下一次发送。
串口中断处理函数模板
这个部分提供了一个串口中断处理函数的模板,但并未完全实现。在8051单片机中,串口中断通常用于接收数据。中断处理函数通过检查RI
(接收中断标志位)来确定是否有数据接收完成。如果RI
为1,表示有数据接收完成,可以读取SBUF
寄存器中的数据,并清除RI
标志位以准备接收下一个字节。
#include <REGX52.H>
void UartInit(void) //4800bps@11.0592MHz
{
PCON |= 0x80; //使能波特率倍速位SMOD
SCON = 0x50; //8位数据,可变波特率
//AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T
//AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xF4; //设定定时初值
TH1 = 0xF4; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA=1;
ES=1;
}
/*******************************************************************************
函数名程: void Uart_SendByte(unsigned char Byte)
函数功能: 串口发送一个字节数据
参数列表: Byte 要发送的字节
返回值 : 无
*******************************************************************************/
void Uart_SendByte(unsigned char Byte)
{
SBUF=Byte;
while(TI==0);//发送完一个字节之后,会自动置1,跳出循环
TI=0;//打开进行下一次通讯,复位。
}
/*串口中断函数模板
void uart() interrupt 4
{
if(RI==1)
{
RI=0;
}
}
通常可以通过stc-isp进行选择,如图所示
主函数代码
-
头文件和函数定义:
-
REGX52.H
:这通常是一个包含8051寄存器定义的头文件,但具体实现可能因编译器或单片机型号而异。 -
Delay.h
,Timer0.h
,Timer1.h
,Uart.h
:这些头文件在代码中被包含,但它们的实现没有给出。这些文件应该包含定时器0、定时器1、串口通信和延迟函数的声明。 -
UartInit()
和Uart_SendByte(unsigned char Byte)
函数在Uart.h
中声明,并在其他地方实现。
-
-
main函数:
-
初始化了串口,但之后进入了一个空的无限循环。在这个循环中,没有实际的处理逻辑,但串口中断将处理接收到的数据。
-
-
串口中断处理函数:
-
中断服务例程(ISR)
uart()
使用了interrupt 4
,这是8051中用于串口中断的标准中断号。 -
当串口接收到数据时(
RI==1
),它首先通过P2=~SBUF;
将接收到的数据(存储在SBUF
中)取反后输出到P2端口,这假设P2端口连接了LED灯或其他显示设备。 -
然后,它通过
Uart_SendByte(SBUF);
将接收到的数据(未取反)发送回电脑。 -
最后,它清除了接收中断标志
RI=0;
以准备下一次接收。
-
#include <REGX52.H>
#include <stdio.h>
#include "Delay.h"
#include "Timer0.h"
#include "Timer1.h"
#include "Uart.h"
typedef unsigned int u16;
typedef unsigned char u8;
void main()
{
UartInit();
while(1)
{
}
}
//电脑和单片机互相通信,
void uart() interrupt 4
{
if(RI==1)
{
P2=~SBUF;//取反是为了让1为亮0为灭
Uart_SendByte(SBUF);//发送到电脑端
RI=0;
}
}