版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/plm199513100/article/details/79410823
/*
名称:C51单片机之串口
说明:在计算机之间进行通讯的时候,有两种方式,一个是串行通信,一个是并行通信。对于前者适合长距离通信、有一定的纠错能力。对于后者,适合短距离通信,速度较快。
对于C51单片机来说,其内部集成有一个功能很强的全双工通信口。设有两个相互独立的接受、发送缓冲器,可以同时发送数据和接收数据。发送缓冲器只能发送不能读出。接收缓冲器只能接收不能发送,而且两个缓冲器共用一个物理地址(0X99)。在编程时由编译器进行区分。还有,C51单片机的串口有4种工作方式,其中两种波特率时刻变的,另外两种是不可变的。
对于具体的使用来说,首先也是需要进行一系列初始化设置(包括工作方式设置、波特率设置等)。然后可以通过轮询或者中断的方式,检查TI或者RI是否被硬件置1来判断数据是否发送完毕或者有新的数据产生。
还有一点需要说明的是,在串口工作的4中方式中,有两种波特率可变的方式,其波特率设置是根据定时器的溢出来设置的。这么说,从某种程度上说,定时器还可以为串口提供时钟信息。
*/
实验主要代码如下:
int sen_flag = 0,rec_flag = 0;
//串口初始化
void UartInit()
{
//串行口波特率设置:模特率9600(定时器1)
TMOD = 0x20; //定时器1选择工作方式1(8位定时,自动重载)
TL1 = 0xFD; //设置初始值
TH1 = 0xFD;
//串口工作方式设置
SCON = 0x50; // 串行口工作方式1,允许接收
PCON = 0;
TR1 = 1; //启动定时器
ES = 1; //开串行中断
EA = 1; //开总中断
}
//发送一个字符
void SendChar(char c)
{
SBUF = c;
sen_flag = 1; //设置标志位
while(1 == sen_flag ) ; //等待串口发送完毕
//while(0 == TI) ;
}
//发送16进制数据(0-FF)
void SendNum(unsigned char num)
{
unsigned char temp_fir = num&0x0F;
unsigned char temp_sec = num>>4;
if(temp_fir > 9)
temp_fir = temp_fir-10+'A';
else
temp_fir = temp_fir+'0';
if(temp_sec > 9)
temp_sec = temp_sec-10+'A';
else
temp_sec = temp_sec+'0';
SendChar(temp_sec);
SendChar(temp_fir);
}
//发送一个字符串
void SendStr(char * str)
{
while((*str) != '\0')
{
SendChar(*str);
str++;
}
}
//接收一个字节
char RecChar()
{
while(0 == rec_flag ) ; //等待数据
rec_flag = 0; //取消接收标志位
return SBUF;
}
串口中断服务函数如下:
//引进外部变量
extern rec_flag;
extern sen_flag;
void Uart(void) interrupt 4
{
if(1 == TI) //发送中断
{
TI = 0; //发送完一个数据
sen_flag = 0; //取消标志位
}
if(1 == RI) //接收中断
{
RI = 0; //清除中断
rec_flag = 1; //设置接收标志位
}
}