概要
本次实验对51单片机的串口进行了双机通信的仿真,实现了51单片机的简单双机通信;现对本次仿真的结构及实现的功能做简要的介绍,
本次仿真主要构成:主机U1-MASTER、从机U2-SLAVE、以及LED显示部分(第一部分显示主机接收到的信息、第二部分显示从机接收到的信号);
实现的功能:主机通过串口发送信息给从机,从机接收到信息后通过从机旁边LED显示;从机通过串口发送信息给主机,主机收到后通过旁边LED显示。
简单的通信协议:通信双方均选用9600波特的传输速率,系统的主频为11.0952MHz,主机的呼叫号为0,即主机地址;从机的呼叫号为1,即从机地址,发送的数据以$为结束符号;通信时发送的数据为两部分,一是通信对象,二是内容。
仿真实图
1、主机部分:
2、从机部分:
3、仿真效果图
程序
1、主机程序
uart.c
#include "uart.h"
u8 RXstart; //开始接收
u16 RXData; //接收数据位
u16 temp[10] = {0}; //数组接收
int j = 0;
//串口初始化,定时器1模式2,波特率为9600bps,晶振频率11.592MHz
void UartInit()
{
SCON = 0XD0; //串口模式3,主从+波特率可变,允许接收,清空收发中断标志位
//主机SM2不置位,从机SM2要置位
TMOD = 0x20; //设置定时器1为模式2,8位自动重装载模式
TH1 = 0xfd; //波特率计算式:[256-(K*Fosc)/(384*BaudeRate)]h
TL1 = 0XFD;
TR1 = 1; //开定时器1中断
REN = 1; //允许串口接收
PCON &= 0X7F; //禁止波特率倍增K=1;
ES = 1; //开串口中断
EA = 1; //开总中断
}
//主机数据发送函数以$结束,主机先发地址TB8=1,后发数据TB8=0;
void UartSendData(u8 addr,u8 *str)
{
TB8 = 1; //发送地址
SBUF = addr; //通过SBUF发送出去
while(!TI); //判断是否发送成功,成功发送TI被置1,要手动复位
TI = 0; //复位
TB8 = 0; //发送数据
while(*str != '\0') //发送数组
{
SBUF = (*str);
while(!TI); //判断是否发送完一组数据
TI = 0;
str++;
}
}
//主机接收数据,串口中断服务函数
void UartRData() interrupt 4 //串口中断服务函数
{
ES = 0; //关闭串口中断
if(RI) //再判断是否接收到数据,接收到数据RI会被置1
{
RXData = SBUF; //接收数据
if(RXData == MasterAddr0) //判断是否呼叫本机
{
RXstart = 1; //开始接收数据
SM2 = 0; //配置为接收数据模式
j = 0;
}
if(RXstart) //判断是否接收过本地址
{
if(RXData != '$') //判断是否接收到数据结束标志$
{
temp[j] = RXData; //没有接收到结束标志$,正常保存数据
j++;
}
else //接收到数据结束标志$
{
RXstart = 0; //数据接收结束
SM2 = 1; //重新配置为只接收地址,下次发送TB8=1才中断
j = 0;
}
}
}
RI = 0; //清除接收中断标志位
ES = 1; // 开串口中断
}
uart.h
#ifndef __UART_H
#define __UART_H
#include "reg52.h"
#ifndef u16
#define u16 unsigned int
#endif
#ifndef u8
#define u8 unsigned char
#endif
#define MasterAddr0 0 //主机号/地址
extern u16 temp[10]; //数组接收
void UartInit();
void UartSendData(u8 addr,u8 *str);
void UartRData();
#endif
main.c
#include "reg52.h"
#include "uart.h"
//从机地址SlaveAddr:0~9
#define SlaveAddr1 1 //从机号(地址)
extern u16 temp[10]; //数组接收
#define LED P0
void delay(u16 i);
void main()
{
u8 i;
UartInit();
while(1)
{
UartSendData(SlaveAddr1,"168$");
for(i=0;i<10;i++)
{
LED = temp[i];
delay(50000);
}
}
}
void delay(u16 i)
{
while(i--);
}
2、从机程序
uart.c
#include "uart.h"
u8 RXData; //接收数据
u8 RXstart; //接收标志
u16 temp[10] = {0}; //数据缓存
int j;
//串口初始化函数,定时器1模式2,波特率9600bps,晶振频率11.0592MHz
void UartInit()
{
SCON = 0XF0; //串口模式3,SM2接收地址,允许接收EN,清空收发标志
TMOD = 0X20; //定时器1模式2,8位重装载模式
TH1 = 0XFD;
TL1 = 0XFD;
TR1 = 1; //开定时器中断1
PCON &= 0X7F; //波特率不倍增
ES = 1; //开串口中断
EA = 1; //开总中断
}
//从机发送函数,从机发送给主机的数据帧要以字符‘0’开头,标识这是发给主机的
void SendData(u8 addr,u8 *str)
{
TB8 = 1;//发送地址
SBUF = addr; //通过SBUF发送出去
while(!TI); //判断是否发送成功
TI = 0; //清除发送中断标志位
TB8 = 0; //发送数据
while(*str != '\0') //发送数组
{
SBUF = (*str);
while(!TI);
TI = 0;
str++;
}
}
//从机数据接收函数,$是结束标志
void ReData() interrupt 4 //串口中断服务函数
{
ES = 0; //关闭串口中断
if(RI) //再判断是否接收到数据
{
RXData = SBUF;
if(RXstart) //判断是否接收过本地址
{
if(RXData != '\$') //判断是否接收到结束标志$
{
temp[j] = RXData; //没有接收到$,正常接收数据
j++;
}
else
{
RXstart = 0; //本次接收结束
SM2 = 1; //重新配置为只接收地址,下次发送TB8=1才中断
j = 0;
}
}
if(RXData == SlaveAddr) //判断是否呼叫本机,地址范围:000-254(00-FE)
{
RXstart = 1; //开始接收数据
SM2 = 0; //配置为接收数据模式
j = 0;
}
}
RI = 0; //清除接收中断标志位
ES = 1; //重开串口中断
}
uart.h
#ifndef __UART_H
#define __UART_H
#include "reg52.h"
#ifndef u16
#define u16 unsigned int
#endif
#ifndef u8
#define u8 unsigned char
#endif
#define SlaveAddr 1 //从机号/地址
extern u16 temp[10]; //数据缓存
void UartInit();
void SendData(u8 addr,u8 *str);
void ReData();
#endif
main.c
#include "reg52.h"
#include "uart.h"
#define MasterAddr0 0 //主机号(地址)
extern u16 temp[10]; //数据缓存
#define LED P0
void delay(u16 i);
void main()
{
u8 i;
UartInit();
while(1)
{
for(i=0;i<10;i++)
{
LED = temp[i];
delay(50000);
}
SendData(MasterAddr0,"2$");
}
}
void delay(u16 i)
{
while(i--);
}
知识链接
1、串口相关寄存器
SCON串口控制寄存器;
TCON定时器控制寄存器
TMOD定时器/计数器模式控制寄存器
PCON电源控制寄存器
IE中断使用寄存器
SCON串口控制寄存器
SM0、SM1:串口工作方式控制位
SM2:多机通信控制位(方式2、3),1允许,0不允许
REN:允许/禁止串行接收控制位
TB8:要发送的第9位数据,由软件清零,多机通信中地址(1)或数据(0)标志位
RB8:接收到的第九位数据
TI:发送中断请求标志位,软件复位
RI:接收中断请求标志位,软件复位
TCON定时器控制寄存器
TF1:定时器/计数器1溢出标志
TR1:定时器1运行控制位,软件控制
TF0:定时器/计数器0溢出标志
TR0:定时器0运行控制位,软件控制
IE1:外部中断1使能位
IT1:外部中断1触发方式控制位
IE0:外部中断0使能位
IT0:外部中断0触发方式控制位
TMOD定时器/计数器模式控制寄存器
GATE:定时器1门控制位
C/T:计数器/定时器1选择位
M1、M0:定时器计数器1模式控制位
后四位为定时器0相关位
PCON电源控制寄存器
SMOD:波特率选择位,1加倍,0不加倍
IE中断使能寄存器
EA:总中断允许位
ES:串口中断允许位
ET1:定时器1溢出中断允许位
EX1:外部中断1中断位允许
ET0:定时器0溢出中断允许位
EX0:外部中断0中断位允许文章来源:https://www.toymoban.com/news/detail-791799.html
总结
这一个拖了好久,一直没整,原因就不多说了,归纳了一下:还是要多尝试,试错的成本可能不低,但错过机会的成本更高,所以还是要多去尝试,不管结果如何。试过总是还是有机会的,没试过就一定没机会。
感觉还不是很熟悉,还是要多看多练习,多总结。文章来源地址https://www.toymoban.com/news/detail-791799.html
到了这里,关于【PROTEUS-51单片机串口通信仿真】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!