STC89C52单片机 串口通信

串口初始化
void UARTInit()
{
	EA = 1;	//打开总中断
	ES = 1; //打开串口中断
	SM0 = 0;	SM1 = 1;//串口工作方式1,8位UART波特率可变
	REN = 1;//串口允许接收
	TR1 = 1;//启动定时器1
	TMOD |= 0x20;//定时器1,工作模式2 8位自动重装
	TH1 = 0xfd;   // 根据下面的公式计算得到
	TL1 = 0xfd; //设置比特率9600
}

在这里插入图片描述
例如:计算9600的波特率

SMOD在没有设置的情况下,默认为0.
SMOD = 0
所以2的0次方为1
2^0 = 1
在这里插入图片描述

晶震频率计算:fosc = 11.0592 兆赫兹 = 11.0592 x 1000000 = 11059200赫兹

11059200 ÷ 9600 = 1152 得到波特率公式的被除数

根据公式
1152 ÷ 32 = 36

36 ÷ 12 = 3

256 - T初 = 256 - 3 = 253

在这里插入图片描述

将 253 转换为16进制得到 0xFD

TH1 = 0xFD;
TL1 = 0xFD; 设置波特率9600

串口中断
void UART() interrupt 4 {
	if(RI)//判断接收是否完成
	{
		num = SBUF;//读SBUF,读出串口接收到的数据
		RI = 0;//软件清零接收标志位	
	}
	if(TI)//判断是否发送完成
		TI = 0;//清零发送完成标志位	
} 
串口工作方式1,8位UART比特率9600
#include <reg52.h>
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选
uchar num;//数码管显示的值

//共阴数码管段选表0-9
uchar code SMGduan[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};
//数码管位选码
uchar code SMGwei[] = {0xfe, 0xfd, 0xfb};

/*====================================
函数	:display(uchar i)
参数	:i 显示数值,取值范围0-255
返回值	:无
描述	:三位共阴数码管动态显示
====================================*/
void display(uchar i)
{
	static uchar wei; 		
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = SMGwei[wei];
	WE = 0;//锁存位选数据
	switch(wei)
	{
		case 0: DU = 1; P0 = SMGduan[i / 100]; DU = 0; break;
		case 1: DU = 1; P0 = SMGduan[i % 100 / 10]; DU = 0; break;	
		case 2: DU = 1; P0 = SMGduan[i % 10]; DU = 0; break;		
	}
	wei++;
	if(wei == 3)
		wei = 0;
}
//定时器0初始化
void timer0Init()
{
	EA = 1;	//打开总中断
	ET0 = 1;//打开定时器0中断
	TR0 = 1;	 //启动定时器0
	REN = 1;//允许串口接收
	TMOD |= 0X01; //定时器工作模式1,16位定时模式
	TH0 = 0xED;
	TL0 = 0xFF; //定时5ms
}
//串口初始化
void UARTInit()
{
	EA = 1;	//打开总中断
	ES = 1; //打开串口中断
	SM0 = 0;	SM1 = 1;//串口工作方式1,8位UART波特率可变
	REN = 1;//串口允许接收
	TR1 = 1;//启动定时器1
	TMOD |= 0x20;//定时器1,工作模式2 8位自动重装
	TH1 = 0xfd;
	TL1 = 0xfd;//设置比特率9600
}
void main()//main函数自身会循环
{	
	timer0Init();//定时器0初始化
	UARTInit();//串口初始化
	while(1);	
} 

//定时器0中断函数
void timer0() interrupt 1
{
	TH0 = 0xED;
	TL0 = 0xFF; //定时5ms
	display(num); //数码管显示函数	
}
//串口中断函数
void UART() interrupt 4 {
	if(RI)//判断接收是否完成
	{
		num = SBUF;//读SBUF,读出串口接收到的数据
		RI = 0;//软件清零接收标志位	
	}
	if(TI)//判断是否发送完成
		TI = 0;//清零发送完成标志位	
} 

通过串口发送数据前需要进行的设置
在右边的菜单栏找到串口助手然后

  • 第一步让COM号保持一致
  • 第二步波特率设置为9600
  • 第三步打开串口
  • 第四步发送和接收格式选择HEX格式
    在这里插入图片描述

在这里插入图片描述

修改串口中断中的函数,实现接收缓冲区数据
//串口中断函数
void UART() interrupt 4
{
	uchar temp;
	if(RI)//判断接收是否完成
	{
		num = SBUF;//读SBUF,读出串口接收到的数据
		RI = 0;//软件清零接收标志位	
		temp = num;//
		SBUF = temp;//写SBUF,把要发送的数据送给发送缓存器
	}
	if(TI)//判断是否发送完成
		TI = 0;//清零发送完成标志位	
} 

对代码修改后可以通过
在这里插入图片描述

串口助手选择文本模式接收和发送数据

在这里插入图片描述
ASCII码规定了不同字符是用哪个整数去表示,所以其它字母或数字对应的值可以通过ASCII表查看。


通过串口发送字符串
puts()函数和printf()函数
void main()
{
	UARTInit(); //串口初始化
	while(1)
	{
		TI = 1;
		puts("Hello Wolrd!");   // 使用puts函数
		while(!TI);
		TI = 0;
		delay(1000);
	}	
}
void main()
{
	UARTInit(); //串口初始化
	while(1)
	{
		TI = 1;
		printf("Hello Wolrd!");   // 使用printf函数
		while(!TI);
		TI = 0;
		delay(1000);
	}	
}

注:puts()函数和printf()函数区别是

  • puts函数会执行换行操作
  • printf函数不会执行换行操作

打开串口助手选择对应COM号,设置波特率9600接收格式选择【文本格式】。

#include <reg52.h>
#include <stdio.h>  // 打印字符串需要调用 stdio.h 库

#define uint unsigned int
#define uchar unsigned char

//毫秒级延时函数定义
void delay(uint z)
{
	uint x,y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0 ; y--); 		
} 

//串口初始化
void UARTInit()
{
	SM0 = 0;	SM1 = 1;//串口工作方式1,8位UART波特率可变
	TR1 = 1;//启动定时器1
	TMOD |= 0x20;//定时器1,工作模式2 8位自动重装
	TH1 = 0xfd;
	TL1 = 0xfd;//设置比特率9600
}

void main()
{
	UARTInit(); //串口初始化
	while(1)
	{
		TI = 1;
		puts("Hello Wolrd!");   // 每次打印都会换行   支持中文打印 
		while(!TI);
		TI = 0;
		delay(1000);
	}	
}

在这里插入图片描述

注:

  • 使用printf()函数puts()函数需要引入头文件#include <stdio.h>
  • 使用printf()函数puts()函数前都应软件置位TI = 1;
    如果没有软件置位TI = 1,则会一直处于等待状态,while(!TI)一直在循环中。
  • 9
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值