51单片机——UART串口通讯-波特率可选,增添定时器2产生波特率1.1版本

1、优化《51单片机——UART串口通讯-波特率可选,增添定时器2产生波特率1.0》里的代码。

2、原串口中断里的ES去掉了,感觉鸡肋没有鸟用。

3、修改的地方很少哈。

4、特殊备注:当要使用printf()函数的时候需要在函数前面加上2行代码:

ES=0;

TI=1;

xxxx你的代码;

//TI=0;//printf();使用后会自动将TI置0,你不放心的话最好加上TI=0;

ES=1;

#ifndef __UART_H__
#define __UART_H__

// bps4800		1输入
// bps9600		2输入
// bps19200		3输入
// bps57600		4输入
// bps115200	5输入

//串口初始化装载,使用定时器1产生波特率,默认为9600bps
extern void UART_RES_LOAD_T1(unsigned char Mode_n_bps);//4800bps/9600bps/19200bps/57600bps

//串口初始化装载,使用定时器2产生波特率
//串口工作方式1,8位uart且波特率可变,且允许串口接收数据//默认波特率9600bps
extern void UART_RES_LOAD_T2(unsigned char Mode_n_bps);//4800bps/9600bps/19200bps/57600bps//115200bps

//串口发送数据
extern void UART_Send_1Byte_Data(unsigned char DAT);

//串口发送字符串
extern void UART_Send_string(unsigned char* c);

#endif // !__UART_H__
/*
1、串行口控制寄存器SCON(SMO、SM1、REN、TI、RI等)
	SM0	SM1
	0	0	方式0	同步移位串行方式:移位寄存器	波特率是sysclk系统工作时钟频率/12
	0	1	方式1	8位uart,波特率可变				(2smod次方)/32*(定时器1的溢出率)
	1	0	方式2	9位uart							(2smod次方)/64*(sysclk系统工作时钟频率)
	1	1	方式3	9位uart,波特率可变				(2smod次方)/32*(定时器1的溢出率)
2、串行口波特率寄存器PCON(SMOD等默认值波特率不加倍)
3、串行口TX、RX数据缓冲器总线SBUF
4、从机地址掩模寄存器SADEN和从机地址寄存器SADDR
5、串口中断相关寄存器
	中断允许寄存器IE(EA、ES)
	中断优先级寄存器 高IPH(PSH)
	中断优先级寄存器 低IP(PS)
	{
		PSH=0,PS=0时,串口1中断为最低优先级中断(优先级0)
		PSH=0,PS=1时,串口1中断为较低(优先级1)
		PSH=1,PS=0时,串口1中断为较高(优先级2)
		PSH=1,PS=1时,串口1中断为最高(优先级3)
	}
*/
#include <reg52.h>
sfr IPH_    =0xB7;//中断优先级高位寄存器
sfr SADEN_	=0xB9;//从机地址掩码寄存器
sfr SADDR_	=0xA9;//从机地址控制寄存器

//串口初始化装载,使用定时器1产生波特率
//串口工作方式1,8位uart且波特率可变,且允许串口接收数据
//定时器1工作方式2,8位自动重装模式
void UART_RES_LOAD_T1(unsigned char Mode_n_bps)//默认波特率9600bps
{
	SCON = 0x50;//串口工作方式1,8位uart且波特率可变,且允许串口接收数据
	PCON = 0x10;//最高位SMOD=1表示串口工作模式1、2、3下加倍波特率(默认PCON=0x10,波特率不加倍)

	SADEN_ = 0x00;//不使用
	SADDR_ = 0x00;//不使用

	EA = 1;//打开总中断
	ES = 1;//打开串口中断

	//串口1中断优先级0
	IPH_ = 0x00;
	IP = 0x00;
	
	TMOD |= 0x20;//开启定时器T1,并使用工作方式2(8位自动重装)
	switch(Mode_n_bps)
	{
		case 1:	
				TL1 = 250;//计数初值设置波特率4800bps
				TH1 = 250;//装载固定初值,当TL1加满后会自动把TH1的值装载进去
				break;//bps4800
		case 2:
				TL1 = 253;//计数初值设置波特率9600bps
				TH1 = 253;//装载固定初值,当TL1加满后会自动把TH1的值装载进去
				break;//bps9600
		case 3:
				PCON |= 0x80;//SM0D=1,波特率加倍
				TL1 = 253;//计数初值设置波特率19200bps
				TH1 = 253;//装载固定初值,当TL1加满后会自动把TH1的值装载进去
				break;//bps19200
		case 4:
				PCON |= 0x80;//SM0D=1,波特率加倍
				TL1 = 255;//计数初值设置波特率57600bps
				TH1 = 255;//装载固定初值,当TL1加满后会自动把TH1的值装载进去
				break;//bps57600
		default://默认bps9600
				TL1 = 253;//计数初值设置波特率9600bps
				TH1 = 253;//装载固定初值,当TL1加满后会自动把TH1的值装载进去
				break;//bps9600
	}
	ET1 = 0;//禁止定时器1发出中断
	TR1 = 1;//启动定时器1
}

//串口初始化装载,使用定时器2产生波特率
//串口工作方式1,8位uart且波特率可变,且允许串口接收数据
void UART_RES_LOAD_T2(unsigned char Mode_n_bps)//默认波特率9600bps
{
	SCON = 0x50;//串口工作方式1,8位uart且波特率可变,且允许串口接收数据
	T2CON |= 0x30;//定时器2用作串口波特率发生器且16位自动重装模式

	SADEN_ = 0x00;//不使用,默认值
	SADDR_ = 0x00;//不使用。默认值

	EA = 1;//打开总中断
	ES = 1;//打开串口中断

	//串口1中断优先级0
	IPH_ = 0x00;//默认值
	IP = 0x00;//默认值

	//T2MOD = 0x02;//T2OE :T2 输出允许位,当 T2OE=1 的时候,允许时钟输出到 P1.0。(仅对80C54 / 80C58 有效)
					//DCEN:向下计数允许位。 DCEN = 1 是允许 T2 向下计数,否则向上计数。
	switch (Mode_n_bps)
	{
		case 1:
			TL2 = 0xb8;//计数初值设置波特率4800bps
			TH2 = 0xff;//装载固定初值
			RCAP2L = 0xb8;
			RCAP2H = 0xff;
			break;//bps4800
		case 2:
			TL2 = 0xdc;//计数初值设置波特率9600bps
			TH2 = 0xff;//装载固定初值
			RCAP2L = 0xdc;
			RCAP2H = 0xff;
			break;//bps9600
		case 3:
			TL2 = 0xee;//计数初值设置波特率19200bps
			TH2 = 0xff;//装载固定初值
			RCAP2L = 0xee;
			RCAP2H = 0xff;
			break;//bps19200
		case 4:
			TL2 = 0xfa;//计数初值设置波特率57600bps
			TH2 = 0xff;//装载固定初值
			RCAP2L = 0xfa;
			RCAP2H = 0xff;
			break;//bps57600
		case 5:
			TL2 = 0xfd;//计数初值设置波特率115200bps
			TH2 = 0xff;//装载固定初值
			RCAP2L = 0xfd;
			RCAP2H = 0xff;
			break;//bps115200
		default://默认bps9600
			TL2 = 0xdc;//计数初值设置波特率9600bps
			TH2 = 0xff;//装载固定初值
			RCAP2L = 0xdc;
			RCAP2H = 0xff;
			break;//bps9600
	}
	TR2 = 1;//启动定时器2
}
//串口发送数据
void UART_Send_1Byte_Data(unsigned char DAT)
{
	ES = 0;//要发送数据了,先关闭串口中断服务
	TI = 0;//准备发送数据
	SBUF = DAT;
	while (!TI);//判断是否发送完成TI=1?
	TI = 0;//软件清除发送完成的标志位
	ES = 1;//发送完成了,开启串口中断服务
}
//串口发送字符串
void UART_Send_string(unsigned char *c)
{
	while (*c != '\0')
	{
		UART_Send_1Byte_Data(*c++);//带*c表示的是值,c表示的是地址
	}
}

//串口中断函数,中断号4
//单片机串口只缓存1字节8位数据
void UART(void) interrupt 4
{
	/*if (TI) //发送标志位  
	{
		TI = 0;//此处注释掉是因为不需要在串口中断函数里发送数据。
		//使用printf()/puts()/putchar()(stdio.h)的时候,需要ES=0;TI=1;printf();最后ES=1。
	}*/
	if (RI)	 //接收标志位
	{
		if((SBUF=='\r')|| (SBUF == '\n'))//当接收到换行或者左对齐的时候
		{
			UART_Send_string("\r\n");//执行左对齐并换行
		}
		else
		UART_Send_1Byte_Data(SBUF);//把串口接收到的值在重新发送回去
		RI = 0;
	}
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

金丝草

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

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

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

打赏作者

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

抵扣说明:

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

余额充值