波特率可以理解为切割数据的大小,当你想要传输相应大小的数据的时候,接收方也应该接受这个大小,不然会导致数据错误。
串口模式图
SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器。 地址相同,意思就是当修改SBUF里的数据的时候,这两个寄存器的数据都会修改。
TI可以理解为发送标记位,每次发送一个数据之后,TI都由硬件控制变为1,然后进入中断程序,之后必须使用软件复位。RI类似,为接收标记位。
这个地方是连接到了SCON,控制的话,需要给ES赋1,EA 赋1,优先级直接给低优先级。接下来还是先看看SCON部分的原理图。
因为我们只是简单的通信,并且使用的是8位UART,所以SM0赋0,SM1赋1就行, SM2也可以赋0,我们首先写一个发送的程序,所以REN先赋值0,TB8,RB8赋0就行,TI,RI在前面接受过了,就不再赘述,又因为我们需要使用计时器1来进行自动重装,所以要对之前的代码做一些修改,具体如下所示。
void UART_Init() //4800bps@11.0592MHz
{
SCON = 0x40; //8位数据,可变波特率,不可接收
PCON &= 0x7F; //波特率不倍速
//计时器1
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
//这两个其实是在设置波特率
TL1 = 0xFA; //设置定时初始值
TH1 = 0xFA; //设置定时重载值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //定时器1开始计时
EA = 1; //使能赋值
ES = 1;
}
我们来看一下具体代码:
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
//void UartInit(void) //4800bps@11.0592MHz
//{
// PCON &= 0x7F; //波特率不倍速
// SCON = 0x50; //8位数据,可变波特率
// TMOD &= 0x0F; //设置定时器模式
// TMOD |= 0x20; //设置定时器模式
// TL1 = 0xFA; //设置定时初始值
// TH1 = 0xFA; //设置定时重载值
// ET1 = 0; //禁止定时器1中断
// TR1 = 1; //定时器1开始计时
//}
unsigned char Sec;
void main(){
UART_Init();
while(1)
{
UART_SendByte(Sec);
Sec++;
Delay(1000);
}
}
#include <REGX52.H>
/**
* @brief 串口初始化,4800bps@11.0592MHz
* @param 无
* @retval 无
*/
void UART_Init() //4800bps@11.0592MHz
{
SCON = 0x40; //8位数据,可变波特率
PCON &= 0x7F; //波特率不倍速
//计时器1
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFA; //设置定时初始值
TH1 = 0xFA; //设置定时重载值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
}
/**
* @brief 串口发送一个字节数据
* @param Byte 要发送的一个字节数据
* @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
SBUF = Byte;
while(TI == 0);
TI = 0;
}
运行结果如下所示:
https://live.csdn.net/v/embed/210913
串口
接下来,我们升级一下,通过电脑来控制LED灯,具体代码如下所示:
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
//void UartInit(void) //4800bps@11.0592MHz
//{
// PCON &= 0x7F; //波特率不倍速
// SCON = 0x50; //8位数据,可变波特率
// TMOD &= 0x0F; //设置定时器模式
// TMOD |= 0x20; //设置定时器模式
// TL1 = 0xFA; //设置定时初始值
// TH1 = 0xFA; //设置定时重载值
// ET1 = 0; //禁止定时器1中断
// TR1 = 1; //定时器1开始计时
//}
unsigned char Sec;
void main(){
UART_Init();
while(1)
{
}
}
void UART_Routine() interrupt 4
{
if(RI = 1)
{
P2 = SBUF;
UART_SendByte(SBUF);
RI = 0;
}
}
#include <REGX52.H>
/**
* @brief 串口初始化,4800bps@11.0592MHz
* @param 无
* @retval 无
*/
void UART_Init() //4800bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率,可接收
PCON &= 0x7F; //波特率不倍速
//计时器1
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFA; //设置定时初始值
TH1 = 0xFA; //设置定时重载值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
EA = 1; //使能中断
ES = 1;
}
/**
* @brief 串口发送一个字节数据
* @param Byte 要发送的一个字节数据
* @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
SBUF = Byte;
while(TI == 0);
TI = 0;
}
/**串口中断函数模板
void UART_Routine() interrupt 4
{
if(RI = 1)
{
P2 = SBUF;
UART_SendByte(SBUF);
RI = 0;
}
}
*/
运行结果如下所示(电脑端没拍出来),就是通过给单片机发送数据,来控制LED的亮灭,大家可以自己尝试。
https://live.csdn.net/v/embed/213795
串口通信