串口通信


串口通信

硬件电路

电平标准

TTL:+5V表示1,0V表示0

1665028662515

异步:A发了1s的1和1s的0,那B就可以连续两次0.5s发1和两次0.5s的0

串口参数及时序图

检验位(9位)

奇校验

//收:0000 0011 1
//发:0000 0011 1
//但是如果是0000 1010 1就也会补1,排错率不高
//收:1110 0000 0
//发:1100 0000 0
//这时就是错误的,说明数据出了问题

串口模式图

中间圈起来那块是控制波特率的

发送寄存器: X=SBUF

接收寄存器:SBUF=X

通信初实现

16位定时器/计时器8位自动重装载的区别

就是十六位记的数多,但每次都需要自己写的代码赋初值,浪费时间。双八位就是将十六位分开,一个计数,另一个存放初值,每次计数完成后AR会自动将值赋给CNT,不用代码处理,比较快,但只有八位所以记的数少了。

上代码

#include <REGX52.H>
#include "Delay.h"

void UART_Init()//4800bps@11.0592MHz
{
	//串口部分
	SCON = 0x40;		//8位数据,可变波特率
	PCON &= 0x7F;	
	//定时器1部分,T1是串口专用的定时器
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xFA;		//设定定时初值
	TH1 = 0xFA;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

void UART_SendByte(unsigned char Byte)
{
	SBUF=Byte;//SBUF写入,被赋值
	while(TI==0);//本来TI=0,但是在数据传输完成之后串口会自动将1赋给TI,因此需要软件进行复位。
	TI=0;//软件复位
	
}

void main()
{
	UART_Init();
	UART_SendByte(0x11);
	while(1)
	{
		
	}
}

①串口部分SCON(serial control)&PCON(power control)

SCON = 0x40;		//8位数据,可变波特率
PCON &= 0x7F;	
SM0&SM1

REN给0/1都可以

SM2,TB8,RB8跟模式1无关,给0

就是发送结束后,硬件给T1置1,表示发送完了,然后请求中断的时候TI=0,必须用软件复位是指要人为在软件中使TI=1

TI=0 —-发送—完毕——硬件—> T1=1 —请求中断—> TI=1 —主机响应中断——软件复位> TI=0

TI最开始为0

对RI的理解和TI一样

所以SCON=0100 0000 —> 0x40

②PCON,用波特率计算搞出来的

定时器部分

要改为定时器1

TMOD &= 0x0F;    & 0000 1111		
TMOD |= 0x20;    | 0010 0000

小小问题

当我把下面这串

void main()
{
	UART_Init();
	UART_SendByte(0x11);
	while(1)
	{
		
	}
}

改成

void main()
{
	UART_Init();
	while(1)
	{
		UART_SendByte(0x11);		
	}
}

当为0x11时正常且不断输出11,当为0x66时异常且不断输出96,是因为波特率的误差,此时我们让它翻慢点就可以正常输出了(让他稳定点)

void main()
{
	UART_Init();
	while(1)
	{
		UART_SendByte(0x11);
        Delay(1);//让他慢慢翻
	}
}

串口和中断系统

我们要启用串口中断,而不是定时器中断,定时器中断是到点了就中断,串口中断是有数据过来中断,所以要配置定时器不中断即ET1等于0,然后开启串口中断

中断服务函数

模板

void UART_Rountine() interrupt 4//中断服务子函数
{
	if(RI==1)
	{
		
		RI=0;
	}
}

例子

void UART_Rountine() interrupt 4//中断服务子函数
{
	if(RI==1)//区分发送和接收,发送和接收都会触发中断
			 //而且二者占用同一个通道,写这个是为了判断,然后把发送和接受分开
	{
		P2=~SBUF;
		UART_SendByte(SBUF);
		RI=0;
	}
}

算波特率

TL1 = 0xFA;		//设定定时初值
TH1 = 0xFA;		//设定定时器重装值

FA—16转10—> 250

那么一个TL1/TH1对应8byte,也就是256,定时器每隔256-250=6µs溢出一次(每计6个数就溢出一次),11.0529MHz晶振对应12T模式下的0.924µs计数一次

溢出的频率=0.924/6=0.154MHz

0.154MHz/16=0.009625MHz

0.009625×1000×1000=9625?应该是接近4800的才对………up主用的12MHz来算,算到了4807


文章作者: WB
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WB !
  目录