本文为博主 日月同辉,与我共生,csdn原创首发。希望看完后能对你有所帮助,不足之处请指正!一起交流学习,共同进步!
> 发布人:@日月同辉,与我共生_单片机-CSDN博客
> 欢迎你为独创博主日月同辉,与我共生点赞❤❤❤+关注👍+收藏🌹+评论☺。
系列专栏:CSDN-单片机学习系列🎁
> 我的格言是:“尽最大努力,做最好的自己!💪
版权声明:本文为CSDN博主「日月同辉,与我共生」的原创文章,CSDN独一份。
目录
一、项目设计
1.1功能说明
三台设备(51单片机、串口元件COMPIM、虚拟串口),各自标记为com1、com2、com3。单片机com1发送数据“0”/0x00给com2,com2再发送给com3。此外,虚拟终端设备能接收到单片机com1发送来的数据“0”/0x00。
1.2硬件设计
1.2.1硬件接线原理
两个设备间的连接,遵循设备1发送端TXD接设备2接收端RXD,设备1接收端RXD接设备2发送端TXD。
1.2.2仿真图
由于单片机com1发送的数据,最终由com3接收,而不是com2接收,所以com1与com2的连接无需遵循1.2.1的接线原则。
1.2.3com1、com2和com3
单片机(com1):用到晶振频率fosc=11.0592MHZ。
COMPIM(com2):串口元件。可以调节波特率和数据位数等属性。为了让大家更好地理解,查询法波特率设置为4800bit/s,中断法波特率设置为9600bit/s。
虚拟串口(com3):需要下载虚拟串口软件,将com2与com3这两设备相连接,最后在串口助手看到接收到的结果。
虚拟串口:
串口助手:需要与com2虚拟波特率设置的一样,否则接收到的数据是错误的。在proteus开始调试时,要在串口助手点击打开串口,才能接收到数据,接收到的数据会在接收缓冲区里显示,结果有两种模式,一种是文字模式,另一种是十六进制模式。
1.3计算初值
波特率为4800bit/s,采用工作方式1,初值结果为250,十六进制为0xFA。
波特率为9600bit/s,采用工作方式1,初值结果为253,十六进制为0xFD。
二、查询法
2.1查询法原理
串口发送标志位TI,TI=0,准备发送;TI=1,发送完成。当数据没发送完成前,TI=0,发送完成TI会自动置1,不要忘记将TI清0,以便下次能够继续发送数据。
2.2查询法--初始化
初始化时,要设置寄存器SCON(工作方式、是否多机通信、数据位数),REN一般要接收(置1),初值就是定时初始值TH1/定时重载值TL1,工作方式为方式1(8位异步重载),波特率可变,因为是8位数据传输,所以定时器为定时器T1工作方式为方式2。中断法设置同上。
M0 M1 M2 REN TB8 RB8 TI RI
0 1 0 1 0 0 0 0
void UartInit() //4800bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFA; //设置定时初始值
TH1 = 0xFA; //设置定时重载值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
}
2.3主程序1
语句SBUF='0';是发送数据‘0’,而接收语句是‘0’=SBUF;
发完数据后,TI要清0。
#include <reg51.h>
#include "delay.h"
void UartInit();//串口初始化函数声明
void main()
{
UartInit();//调用串口初始化函数
while(1)
{
SBUF = '0';//发送一帧数据
while(!TI);//等待发送完成(TI会自动置1)
TI=0;//将TI置0
delay(1000);//延时1s
}
}
三、中断法
3.1中断法--初始化
中断法:除了设置SCON、TNOD、初值外,还要打开总中断EA=1,串口中断开关ES=1和定时器启动位TR1=1。
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速,这语句有没有无所谓,默认波特率倍数为1
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFD; //设置定时初始值
TH1 = 0xFD; //设置定时重载值
ET1 = 0; //禁止定时器中断
ES=1;
EA=1;
TR1 = 1; //定时器1开始计时
}
3.2中断服务函数
当发送完成时,TI自动置1,触发一次中断。
void ES_timer() interrupt 4 //当TI置1时,会进入中断服务函数
{
if(TI)
{
TI=0;//TI软件置0
}
}
3.3主程序2
SBUF=0x00;发送数据0x00。
void main()
{
UartInit();//调用串口初始化函数
while(1)
{
SBUF=0x00;//发送数据0x00
delay(2000);//延时2s
}
}
四、项目结果
4.1查询法
由于使用查询法,com1发送字符‘0‘,所以选择文本模式。
虚拟串口终端:如何每发送一个字符后换行呢?下文会讲解!
4.2中断法
由于发送的是十六进制0x00,所以选择HEX模式。
虚拟串口终端:
五、提供完整代码
5.1查询法
#include <reg51.h>
#include "delay.h"
void UartInit();//串口初始化函数声明
void main()
{
UartInit();//调用串口初始化函数
while(1)
{
SBUF = '0';//发送一帧数据
while(!TI);//等待发送完成(TI会自动置1)
TI=0;//将TI置0
delay(1000);//延时1s
}
}
void UartInit() //4800bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFA; //设置定时初始值
TH1 = 0xFA; //设置定时重载值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
}
5.2中断法
#include <reg51.h>
#include "delay.h"
void UartInit();//串口初始化函数声明
void main()
{
UartInit();//调用串口初始化函数
while(1)
{
SBUF=0x00;
delay(2000);//延时2s
}
}
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFD; //设置定时初始值
TH1 = 0xFD; //设置定时重载值
ET1 = 0; //禁止定时器中断
ES=1;
EA=1;
TR1 = 1; //定时器1开始计时
}
void ES_timer() interrupt 4 //当TI置1时,会进入中断服务函数
{
if(TI)
{
TI=0;//TI软件置0
}
}
Hi!我叫不白吃。
下一文将着重讲述printf串口输出重定向的实现及一帧一串数据的发送,亲爱的读者敬请期待,
下一文更精彩!!!
腹有诗书气自华,读书万卷始通神。我叫不白吃,喜欢我的,可以支持我,博主名叫@日月同辉,与我共生https://blog.csdn.net/LIN___IT?type=blog