这一部分我认为是十分重要的,没有了数据的传输,我们做的很多事情将是没有意义的。我们一般利用串口做两件事,一是单片机向电脑发送信息,二是单片机接收电脑的信息。
一、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; //启动定时器1EA=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; //读取数据,取反后输出到LEDUART_SendByte(SBUF); //将受到的数据发回串口RI=0; //接收标志位清0}
}
进入中断iterrupt 4 以后判断是否是接收中断,将数据取反用LED显示出来,方便检查,然后还可以再将接收到了数据发送出去。记得手动清0。因为接收数据是不确定时间的,所以我们需要利用接收中断执行。