C51学习归纳6 --- UART串口数据通信

        这一部分我认为是十分重要的,没有了数据的传输,我们做的很多事情将是没有意义的。我们一般利用串口做两件事,一是单片机向电脑发送信息,二是单片机接收电脑的信息。

一、UART原理

        TXD:发送信息通道,RXD: 接收信息通道。我发送你接收,所以TXS和RXD相连。GND互连的意义在于有一个共同的低电平的定义,这样在处理数据的时候有了相同的标准,处理才不会出错。

        在芯片上我们连接在P3_0 和P3_1上.

        在串口转换部分,输出RXD-U,TXD-U。然后与主机的RXD,TXD相连。

        我们也发现了这种通信模式的缺点,只能1台设备发送,可以多台设备接收,但不能多发。

        除了UART外我们还有其他的通信方式,如下表:

全双工:通信双方可以在同一时刻互相传输数据
半双工:通信双方可以互相传输数据,但必须分时复用一根数据线
单工:通信只能有一方发送到另一方,不能反向传输
异步:通信双方各自约定通信速率
同步:通信双方靠一根时钟线来约定通信速率
总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)

        我们用这个图 

二、单片机向电脑发送信息

#include <REGX52.H>

/**
  * @brief  串口初始化,4800bps@12.000MHz
  * @param  无
  * @retval 无
  */
void UART_Init()
{
	SCON=0x40;
	PCON |= 0x80;
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

/**
  * @brief  串口发送一个字节数据
  * @param  Byte 要发送的一个字节数据
  * @retval 无
  */
void UART_SendByte(unsigned char Byte)
{
	SBUF=Byte;
	while(TI==0);
	TI=0;
}

        上面是UART的发送和初始化函数。 我们发现UART的使用和定时器1有关。这是因为

         我们要使用定时器定速度的发送接收数据。发送数据后,申请一个发送中断TI,收到数据以后,申请一个接收中断RI。然后转到中断。

         因为TI,RI占用同一个通道,所以进入中断以后,需要判断是接收中断还是发送中断。

        我们先看UART的初始化,我们需要设置PCON,SCON,和定时器的设置。PCON是为了控制串口工作的模式,SCON是为了电源的设置,但是电源控制器的最高位还是串口模式的设置位;定时器是为了产生固定的发送接收频率不产生中断。定时器选取定时器一,运行在模式2,8位自动重装模式上(这是规定),因为自动重载,所以不用每次赋初值。

        我们再看UART的发送数据函数,讲数据放在 SBUF 数据线上,然后当TI = 1的时候发送,发送完后给TI置0;每输入8位,电路自动将TI自动置于1,但是必须软件复位.RI一样。

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

unsigned char Sec;

void main()
{
	UART_Init();			//串口初始化
	while(1)
	{
		UART_SendByte(Sec);	//串口发送一个字节
		Sec++;				//Sec自增
		Delay(1000);		//延时1秒
	}
}

        这里是main函数的逻辑。

三、单片机接收电脑的信息

#include <REGX52.H>

/**
  * @brief  串口初始化,4800bps@12.000MHz
  * @param  无
  * @retval 无
  */
void UART_Init()
{
	SCON=0x50;
	PCON |= 0x80;
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	EA=1;
	ES=1;
}

/**
  * @brief  串口发送一个字节数据
  * @param  Byte 要发送的一个字节数据
  * @retval 无
  */
void UART_SendByte(unsigned char Byte)
{
	SBUF=Byte;
	while(TI==0);
	TI=0;
}

        这里对比前面的代码发现没有任何变化,这是因为我们将接受代码以中断的形式写在了main函数中。

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

void main()
{
	UART_Init();		//串口初始化
	while(1)
	{
		
	}
}

void UART_Routine() interrupt 4
{
	if(RI==1)					//如果接收标志位为1,接收到了数据
	{
		P2=~SBUF;				//读取数据,取反后输出到LED
		UART_SendByte(SBUF);	//将受到的数据发回串口
		RI=0;					//接收标志位清0
	}
}

        进入中断iterrupt 4 以后判断是否是接收中断,将数据取反用LED显示出来,方便检查,然后还可以再将接收到了数据发送出去。记得手动清0。因为接收数据是不确定时间的,所以我们需要利用接收中断执行。

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-06-08 12:08:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-08 12:08:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-08 12:08:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-08 12:08:01       20 阅读

热门阅读

  1. 挣值计算中的典型与非典型

    2024-06-08 12:08:01       8 阅读
  2. Objective-C中分类无法添加实例变量的底层原理

    2024-06-08 12:08:01       10 阅读
  3. android原生TabLayout之自定义指示器效果

    2024-06-08 12:08:01       10 阅读
  4. Redis持久化机制:RDB与AOF的原理和最佳实践

    2024-06-08 12:08:01       10 阅读
  5. 2023 N1CTF Junior pwn 顶级签到

    2024-06-08 12:08:01       9 阅读
  6. C++ 实现Python 列表list 的两种方法

    2024-06-08 12:08:01       8 阅读
  7. flutter 解析json另类封装方式 List<bean>,哈哈哈

    2024-06-08 12:08:01       8 阅读
  8. Linux学习之查看文件内容

    2024-06-08 12:08:01       12 阅读
  9. linux-磁盘空间显示指令

    2024-06-08 12:08:01       9 阅读
  10. 基于截图和模拟点击的自动化压测工具开发(MFC)

    2024-06-08 12:08:01       8 阅读
  11. Git - 创建和应用patch

    2024-06-08 12:08:01       10 阅读
  12. 自动化喷涂生产线方案三

    2024-06-08 12:08:01       10 阅读
  13. 【每日一函数】uname 函数介绍及代码演示

    2024-06-08 12:08:01       8 阅读