标题:
单片机上位机控制下位机显示联合 Proteus仿真程序
[打印本页]
作者:
寄语
时间:
2020-10-21 13:43
标题:
单片机上位机控制下位机显示联合 Proteus仿真程序
还有很多不足的地方,多多包容
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
]Y0(]Y][}GUR@306A[[DKAS.png
(36.36 KB, 下载次数: 47)
下载附件
2020-10-21 13:42 上传
目前程序还无法正常运行,求大神帮忙修改:
矩阵键盘 点阵 上位机 数码管 蜂鸣器联合仿真.zip
(325.64 KB, 下载次数: 15)
2020-10-21 13:43 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
寄语
时间:
2020-10-21 13:50
标题:
RE: 上位机控制下位机显示联合仿真。
主机代码如下,下属还有两个从机代码。
//主机
#include<reg51.h>
#include<string.h>
#define _SUCC_ 0x0f//数据传送成功
#define _ERR_ 0xf0//数据传送失败
unsigned char Table[50]={
0x01, 0x01, 0xd6, 0x93, 0x91, 0xff,0x01,0x01,
0x01, 0x40, 0x4c, 0x66, 0x72, 0x5e,0x4c,0x40,
0xc4, 0xc6, 0xc3, 0xff, 0xff, 0xc0,0xc0,0xc0,
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92,0x82,0xf8};//要发送的数据
unsigned char Table0[8]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92,0x82,0xf8};
unsigned char Buff[50]; //数据缓冲区
unsigned char temp=0xff;
sbit KEY1=P1^0;//开关一号
sbit KEY2=P1^1;//开关二号
//unsigned char addr;
//延时1ms函数
void delay_1ms(unsigned int t)
{
unsigned int x,y;
for(x=t;x>0;x--)
for(y=110;y>0;y--);
}
//缓冲区初始化
void Buff_init()
{
unsigned char i; //将Table里的数据放到缓冲区里
// for(i=0;i<20;i++)
for(i=0;i<50;i++)
{
Buff[i]= Table[i];//将Table里的数据放到Buffp[]里
delay_1ms(100);//延时100ms
}
}
//缓冲区初始化0
void Buff_init0()
{
unsigned char i; //将Table里的数据放到缓冲区里
for(i=0;i<20;i++)
{
Buff[i]= Table0[i];//将Table里的数据放到Buffp[]里
delay_1ms(100);//延时100ms
}
}
//串口初始化函数
void serial_init()
{
TMOD=0x20; //定时器1工作于方式2(00100000)M1=1,M0=0
TH1=0xfd;//定时器赋初值
TL1=0xfd; //波特率为9600
PCON=0;//波特率正常
SCON=0xd0; //串口工作于方式3 11010000
TR1=1; //开启定时器
TI=0;//开启发送数据
RI=0;//开启接受数据
}
//发送数据函数
void SEND_data(unsigned char *Buff)//Buff数据缓冲区
{
unsigned char i;
unsigned char lenth;
unsigned char check;
lenth=strlen(Buff); //计算数据长度
check=lenth;
TI=0; //开启发送
TB8=0; //发送数据帧
SBUF=lenth;//发送数据长度 sbuf:串行口数据缓冲寄存器
while(!TI);//此时ti==0
TI=0;//开启发送
for(i=0;i<lenth;i++) //发送数据
{
check=check^Buff[i];//按位异或,同为一不同为零,
TB8=0;
SBUF=Buff[i]; //将Buff[i]中的数据存入单片机数据缓存区
while(!TI);
TI=0;//开启发送
}
//发送校验字节
TB8=0;
SBUF=check;
while(!TI);
TI=0;
}
//向指定从机地址发送数据
void ADDR_data(unsigned addr)
{
while(temp!=addr) //主机等待从机返回其地址作为应答信号
{
TI=0; //发送从机地址
TB8=1; //发送地址帧
SBUF=addr;
while(!TI);
TI=0;
RI=0;//开始接受数据
while(!RI);
temp=SBUF;
RI=0;
}
temp=_ERR_; //主机等待从机数据接收成功信号
while(temp!=_SUCC_)//当发送成功时
{
SEND_data(Buff);
RI=0;
while(!RI);
temp=SBUF;
RI=0;
}
}
void chushihua()
{
Buff_init();//先进行缓冲区初始化
serial_init();//串口初始化
while(1)
{
if(KEY1==0)//开关一按下
{
delay_1ms(5);//延时5ms确认是否误判
if(KEY1==0) //如果没有误判
{
while(!KEY1);
ADDR_data(0x01);//发送从机地址
}
}
}
}
void chushihua0()
{
Buff_init0();//先进行缓冲区初始化
serial_init();//串口初始化
while(1)
{
if(KEY1==0)//开关一按下
{
delay_1ms(5);//延时5ms确认是否误判
if(KEY1==0) //如果没有误判
{
while(!KEY1);
ADDR_data(0x01);//发送从机地址
}
}
}
}
void main()
{
Buff_init();//先进行缓冲区初始化
serial_init();//串口初始化
while(1)
{
ADDR_data(0x01);//发送从机地址
ADDR_data(0x02);//发送从机地址
}
}
从机1号
//从机
#include<reg51.h>
#include<string.h>
#define addr 0x01//从机1的地址
#define _SUCC_ 0x0f//数据传送成功
#define _ERR_ 0xf0//数据传送失败
sbit k1=P3^2;
sbit k2=P3^3;
sbit k3=P3^4;
sbit D1=P3^5;
sbit D2=P3^6;
sbit D3=P3^7;
unsigned char x;
//延时1ms函数
void delay_1ms(unsigned int t)
{
unsigned int x,y;
for(x=t;x>0;x--)
for(y=110;y>0;y--);
}
unsigned char aa=0xff;//主机与从机之间通信标志
//unsigned char Buff[20];//数据缓冲区
unsigned char Buff[50];//数据缓冲区
//串口初始化函数
void serial_init()
{
TMOD=0x20; //定时器1工作于方式2 波特率为9600
TH1=0xfd;
TL1=0xfd; //定时器初值
PCON=0;
SCON=0xd0; //串口工作于方式3
TR1=1; //开启定时器
TI=0;
RI=0;
}
//接收数据函数
unsigned char RECE_data(unsigned char *Buff)
{
unsigned char i,temp;
unsigned char lenth;
unsigned char check;
RI=0; //开启接收数据(长度)
while(!RI);
if(RB8==1) //若接收到地址帧,则返回0xfe
return 0xfe;
lenth=SBUF;
RI=0; //开启再次接收数据
check=lenth;
for(i=0;i<lenth;i++) //接收数据
{
while(!RI);
if(RB8==1) //若接收到地址帧,则返回0xfe
return 0xfe;
Buff[i]=SBUF;
check=check^(Buff[i]);//按位异或
RI=0;
}
while(!RI); //接收校验字节
if(RB8==1) //若接收到地址帧,则返回0xfe
return 0xfe;
temp=SBUF;
RI=0;
check=temp^check; //将从主机接收到的校验码与自己计算的校验码比对(同为零,不同则大于零)
if(check!=0) //校验码不一致,表明数据接收错误,向主机发送错误信号,函数返回0xff
{
TI=0;
TB8=0;
SBUF=_ERR_; //把错误信号赋值到缓冲区待发送
while(!TI); //发送完毕时跳出循环
TI=0;
return 0xff;
}
TI=0; //校验码一致,表明数据接收正确,向主机发送成功信号,函数返回0x00
TB8=0;
SBUF=_SUCC_;
while(!TI); //发送成功的信号给主机
TI=0;
return 0;
}
const unsigned char CharCode0[8]={0xff,0x81,0x81,0x81,0x81,0x81,0x81,0xff};//P2口代码
unsigned char DispBuff[25]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
void chuang1()
{
static char CurPosi; //定义当前输出位置
D1=0;
P2=Buff[DispBuff[CurPosi]+16]; //输出当前字符显示编码到 P2 口
switch (CurPosi++) //当前输出位置加 1
{
case 0:P1=0x00;break; //P1.0 置低
case 1:P1=0x20;break; //P1.1 置低
case 2:P1=0x40;break; //开一点窗
case 3:P1=0x60;break; //开一半
case 4:P1=0x80;break;//开大半
case 5:P1=0xa0;break; //全关
case 6:P1=0xc0;break; //全开
case 7:P1=0xe0;break;
}
if(CurPosi>7)
CurPosi=0; //当前输出位置大于 7 则重头开始
}
void chuang2()
{
static char CurPosi; //定义当前输出位置
D2=0;
P2=Buff[DispBuff[CurPosi]+8]; //输出当前字符显示编码到 P2 口
switch (CurPosi++) //当前输出位置加 1
{
case 0:P1=0x00;break; //P1.0 置低
case 1:P1=0x20;break; //P1.1 置低
case 2:P1=0x40;break; //开一点窗
case 3:P1=0x60;break; //开一半
case 4:P1=0x80;break;//开大半
case 5:P1=0xa0;break; //全关
case 6:P1=0xc0;break; //全开
case 7:P1=0xe0;break;
}
if(CurPosi>7)
CurPosi=0; //当前输出位置大于 7 则重头开始
}
void chuang3()
{
static char CurPosi; //定义当前输出位
D3=0;
P2=Buff[DispBuff[CurPosi]]; //输出当前字符显示编码到 P2 口
switch (CurPosi++) //当前输出位置加 1
{
case 0:P1=0x00;break; //P1.0 置低
case 1:P1=0x20;break; //P1.1 置低
case 2:P1=0x40;break; //开一点窗
case 3:P1=0x60;break; //开一半
case 4:P1=0x80;break;//开大半
case 5:P1=0xa0;break; //全关
case 6:P1=0xc0;break; //全开
case 7:P1=0xe0;break;
}
if(CurPosi>7)
CurPosi=0; //当前输出位置大于 7 则重头开始
}
//中断函数
void T0_INTProc(void) interrupt 1 //T0 定时中断函数
{
P1=0xff; //关闭所有显示,消隐
TH0=0xec;
TL0=0x78; //重装计数值
TR0=1; //重启计数,为显示下一字符作准备
if(k1==0)
chuang1();
else
D1=1;
if(k2==0)
chuang2();
else
D2=1;
if(k3==0)
chuang3();
else
D3=1;
}
void main()
{
serial_init(); //串口初始化
while(1)
{
SM2=1; //开启接收地址帧
while(aa!=addr) //从机等待主机请求自己的地址
{
RI=0;
while(!RI);
aa=SBUF;
RI=0;
}
TI=0; //一旦被请求,从机返回自己地址作为应答,等待接收数据
TB8=0;
SBUF=addr;
while(!TI);
TI=0;
SM2=0; //接收数据帧
aa=0xff; //从机接收数据,并将数据保存到数据缓冲区
while(aa==0xff)
{
aa=RECE_data(Buff); //接收数据
}
if(aa==0xfe)
continue;
TMOD=0x01; //设定 T0 工作在定时方式 1,16位计数
TH0=0xec; //装入计数值高字节(中断时间)
TL0=0x78; //装入计数值低字节
EA=1; //开总中断
ET0=1; //开 T0 中断
TR0=1; //启动 T0 计数
while(1); //无限循环等待中断发生
}
}
复制代码
从机2号
//从机2
#include<reg51.h>
#include<string.h>
#define addr 0x02//从机1的地址
#define _SUCC_ 0x0f//数据传送成功
#define _ERR_ 0xf0//数据传送失败
unsigned char a;
unsigned char x;
//延时1ms函数
void delay_1ms(unsigned int t)
{
unsigned int x,y;
for(x=t;x>0;x--)
for(y=110;y>0;y--);
}
unsigned char aa=0xff;//主机与从机之间通信标志
unsigned char Buff[50];//数据缓冲区
//串口初始化函数
void serial_init()
{
TMOD=0x20; //定时器1工作于方式2 波特率为9600
TH1=0xfd;
TL1=0xfd; //定时器初值
PCON=0;
SCON=0xd0; //串口工作于方式3
TR1=1; //开启定时器
TI=0;
RI=0;
}
//接收数据函数
unsigned char RECE_data(unsigned char *Buff)
{
unsigned char i,temp;
unsigned char lenth;
unsigned char check;
RI=0; //开启接收数据(长度)
while(!RI);
if(RB8==1) //若接收到地址帧,则返回0xfe
return 0xfe;
lenth=SBUF;
RI=0; //开启再次接收数据
check=lenth;
for(i=0;i<lenth;i++) //接收数据
{
while(!RI);
if(RB8==1) //若接收到地址帧,则返回0xfe
return 0xfe;
Buff[i]=SBUF;
check=check^(Buff[i]);//按位异或
RI=0;
}
while(!RI); //接收校验字节
if(RB8==1) //若接收到地址帧,则返回0xfe
return 0xfe;
temp=SBUF;
RI=0;
check=temp^check; //将从主机接收到的校验码与自己计算的校验码比对(同为零,不同则大于零)
if(check!=0) //校验码不一致,表明数据接收错误,向主机发送错误信号,函数返回0xff
{
TI=0;
TB8=0;
SBUF=_ERR_; //把错误信号赋值到缓冲区待发送
while(!TI); //发送完毕时跳出循环
TI=0;
return 0xff;
}
TI=0; //校验码一致,表明数据接收正确,向主机发送成功信号,函数返回0x00
TB8=0;
SBUF=_SUCC_;
while(!TI); //发送成功的信号给主机
TI=0;
return 0;
}
#define uchar unsigned char//宏定义无符号字符型
#define uint unsigned int //宏定义无符号整型
//定义分别表示8255A各口的变量
volatile unsigned char xdata Aport _at_ 0x8000;
volatile unsigned char xdata Bport _at_ 0x8001;
volatile unsigned char xdata Cport _at_ 0x8002;
volatile unsigned char xdata Ctrlport _at_ 0x8003;
const unsigned char CharCode1[10]= {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92,0x82,0xf8, 0x80,0x90};//晶体管真值码
unsigned char code seg7code[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 };//键盘真值码
unsigned char k;
void delay10ms(void) //延时程序
{
unsigned char i,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);
}
//行扫描获取键盘函数
void Getch ( ) //取键值函数
{
unsigned char X,Y,Z;
Bport=0x0f; //先对P3 置数 行扫描
if(Bport!=0x0f) //判断是否有键按下
{
delay10ms(); //延时,软件去干扰
if(Bport!=0x0f) //确认按键按下
{
X=Bport; //保存行扫描时有键按下时状态
Bport=0xf0; //列扫描
Y=Bport; //保存列扫描时有键按下时状态
Z=X|Y; //取出键值
//获取键盘值函数
switch ( Z ) //判断键值(那一个键按下)
{
case 0x77: k=0; break; //对键值赋值
case 0x7b: k=1; break;
case 0x7d: k=2; break;
case 0x7e: k=3; break;
case 0xb7: k=4; break;
case 0xbb: k=5; break;
/* case 0xbd: k=6; break;
case 0xbe: k=7;
case 0xd7: k=8; break;
case 0xdb: k=9; break;
case 0xdd: k=10;break;
case 0xde: k=11;break;
case 0xe7: k=12;break;
case 0xeb: k=13;break;
case 0xed: k=14;break;
case 0xee: k=15;break;*/
}
}
}
}
void main()
{
serial_init(); //串口初始化
while(1)
{
SM2=1; //开启接收地址帧
while(aa!=addr) //从机等待主机请求自己的地址
{
RI=0;
while(!RI);
aa=SBUF;
RI=0;
}
TI=0; //一旦被请求,从机返回自己地址作为应答,等待接收数据
TB8=0;
SBUF=addr;
while(!TI);
TI=0;
SM2=0; //接收数据帧
aa=0xff; //从机接收数据,并将数据保存到数据缓冲区
while(aa==0xff)
{
aa=RECE_data(Buff); //接收数据
}
if(aa==0xfe)
continue;
while(1){
a=1;
while(a)
{
Bport=0xff;
Getch(); //调用取键值函数
Aport=Buff[k+24]; //查表LED输出
if(k==5)
P1=0x00;
if(P1==0x02)
{
P1=0X01;
a=0;
}
}
}
}
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1