找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2058|回复: 1
收起左侧

单片机上位机控制下位机显示联合 Proteus仿真程序

[复制链接]
ID:756334 发表于 2020-10-21 13:43 | 显示全部楼层 |阅读模式
还有很多不足的地方,多多包容
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
]Y0(]Y][}GUR@306A[[DKAS.png

目前程序还无法正常运行,求大神帮忙修改:
矩阵键盘 点阵 上位机 数码管 蜂鸣器联合仿真.zip (325.64 KB, 下载次数: 15)
回复

使用道具 举报

ID:756334 发表于 2020-10-21 13:50 | 显示全部楼层

RE: 上位机控制下位机显示联合仿真。

主机代码如下,下属还有两个从机代码。
//主机
  1. #include<reg51.h>
  2. #include<string.h>

  3. #define _SUCC_   0x0f//数据传送成功
  4. #define _ERR_    0xf0//数据传送失败
  5. unsigned char Table[50]={
  6.                                                  0x01, 0x01, 0xd6, 0x93, 0x91, 0xff,0x01,0x01,
  7.                                                  0x01, 0x40, 0x4c, 0x66, 0x72, 0x5e,0x4c,0x40,
  8.                                                  0xc4, 0xc6, 0xc3, 0xff, 0xff, 0xc0,0xc0,0xc0,
  9.                                                  0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92,0x82,0xf8};//要发送的数据

  10. unsigned char Table0[8]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92,0x82,0xf8};
  11. unsigned char Buff[50];  //数据缓冲区
  12. unsigned char temp=0xff;
  13. sbit KEY1=P1^0;//开关一号
  14. sbit KEY2=P1^1;//开关二号
  15. //unsigned char addr;                                                                                                                                          

  16. //延时1ms函数
  17. void delay_1ms(unsigned int t)
  18. {
  19.         unsigned int x,y;
  20.         for(x=t;x>0;x--)
  21.           for(y=110;y>0;y--);
  22. }
  23. //缓冲区初始化
  24. void Buff_init()
  25. {
  26.         unsigned char i;    //将Table里的数据放到缓冲区里
  27. //        for(i=0;i<20;i++)
  28.          for(i=0;i<50;i++)
  29.         {
  30.           Buff[i]= Table[i];//将Table里的数据放到Buffp[]里
  31.           delay_1ms(100);//延时100ms
  32.         }
  33. }

  34. //缓冲区初始化0
  35. void Buff_init0()
  36. {
  37.         unsigned char i;    //将Table里的数据放到缓冲区里
  38.         for(i=0;i<20;i++)  
  39.         {
  40.           Buff[i]= Table0[i];//将Table里的数据放到Buffp[]里
  41.           delay_1ms(100);//延时100ms
  42.         }
  43. }

  44. //串口初始化函数
  45. void serial_init()
  46. {
  47.         TMOD=0x20; //定时器1工作于方式2(00100000)M1=1,M0=0
  48.         TH1=0xfd;//定时器赋初值  
  49.         TL1=0xfd; //波特率为9600
  50.         PCON=0;//波特率正常
  51.         SCON=0xd0;  //串口工作于方式3  11010000
  52.         TR1=1;  //开启定时器
  53.         TI=0;//开启发送数据
  54.         RI=0;//开启接受数据
  55. }
  56. //发送数据函数
  57. void SEND_data(unsigned char *Buff)//Buff数据缓冲区
  58. {
  59.         unsigned char i;
  60.         unsigned char lenth;
  61.         unsigned char check;
  62.         lenth=strlen(Buff);   //计算数据长度
  63.         check=lenth;
  64.         
  65.         TI=0;       //开启发送
  66.         TB8=0;      //发送数据帧
  67.         SBUF=lenth;//发送数据长度   sbuf:串行口数据缓冲寄存器
  68.         while(!TI);//此时ti==0
  69.         TI=0;//开启发送
  70.                  
  71.         for(i=0;i<lenth;i++)  //发送数据
  72.         {
  73.           check=check^Buff[i];//按位异或,同为一不同为零,
  74.           TB8=0;
  75.           SBUF=Buff[i]; //将Buff[i]中的数据存入单片机数据缓存区  
  76.           while(!TI);
  77.           TI=0;//开启发送
  78.         }
  79.         //发送校验字节
  80.         TB8=0;      
  81.         SBUF=check;   
  82.         while(!TI);
  83.         TI=0;     
  84. }
  85. //向指定从机地址发送数据
  86. void ADDR_data(unsigned addr)
  87. {
  88.         while(temp!=addr) //主机等待从机返回其地址作为应答信号
  89.         {
  90.           TI=0;    //发送从机地址
  91.           TB8=1;    //发送地址帧
  92.           SBUF=addr;
  93.           while(!TI);
  94.           TI=0;
  95.          
  96.           RI=0;//开始接受数据
  97.           while(!RI);
  98.           temp=SBUF;
  99.           RI=0;
  100.         }
  101.         
  102.         temp=_ERR_;   //主机等待从机数据接收成功信号
  103.         while(temp!=_SUCC_)//当发送成功时
  104.         {
  105.           SEND_data(Buff);
  106.           RI=0;
  107.           while(!RI);
  108.           temp=SBUF;
  109.           RI=0;
  110.         }
  111. }


  112. void chushihua()
  113. {
  114.         Buff_init();//先进行缓冲区初始化
  115.         serial_init();//串口初始化
  116.         while(1)
  117.         {
  118.           if(KEY1==0)//开关一按下
  119.           {
  120.                    delay_1ms(5);//延时5ms确认是否误判
  121.                    if(KEY1==0)        //如果没有误判
  122.                    {
  123.                     while(!KEY1);
  124.                     ADDR_data(0x01);//发送从机地址
  125.                    }
  126.           }
  127.         }
  128. }



  129. void chushihua0()
  130. {
  131.         Buff_init0();//先进行缓冲区初始化
  132.         serial_init();//串口初始化
  133.         while(1)
  134.         {
  135.           if(KEY1==0)//开关一按下
  136.           {
  137.                    delay_1ms(5);//延时5ms确认是否误判
  138.                    if(KEY1==0)        //如果没有误判
  139.                    {
  140.                     while(!KEY1);
  141.                     ADDR_data(0x01);//发送从机地址
  142.                    }
  143.           }
  144.         }
  145. }

  146.       
  147. void main()
  148. {
  149.         Buff_init();//先进行缓冲区初始化
  150.         serial_init();//串口初始化
  151.         while(1)
  152.         {
  153.         ADDR_data(0x01);//发送从机地址
  154.         ADDR_data(0x02);//发送从机地址
  155.         }
  156. }
  157. 从机1号
  158. //从机
  159. #include<reg51.h>
  160. #include<string.h>

  161. #define addr     0x01//从机1的地址
  162. #define _SUCC_   0x0f//数据传送成功
  163. #define _ERR_    0xf0//数据传送失败


  164. sbit k1=P3^2;
  165. sbit k2=P3^3;
  166. sbit k3=P3^4;

  167. sbit D1=P3^5;
  168. sbit D2=P3^6;
  169. sbit D3=P3^7;

  170. unsigned char x;
  171. //延时1ms函数
  172. void delay_1ms(unsigned int t)
  173. {
  174.         unsigned int x,y;
  175.         for(x=t;x>0;x--)
  176.           for(y=110;y>0;y--);
  177. }



  178. unsigned char aa=0xff;//主机与从机之间通信标志
  179. //unsigned char Buff[20];//数据缓冲区
  180. unsigned char Buff[50];//数据缓冲区

  181. //串口初始化函数
  182. void serial_init()
  183. {
  184.         TMOD=0x20; //定时器1工作于方式2          波特率为9600
  185.         TH1=0xfd;  
  186.         TL1=0xfd; //定时器初值
  187.         PCON=0;
  188.         SCON=0xd0;  //串口工作于方式3
  189.         TR1=1;  //开启定时器
  190.         TI=0;
  191.         RI=0;
  192. }
  193. //接收数据函数
  194. unsigned char RECE_data(unsigned char *Buff)
  195. {
  196.         unsigned char i,temp;
  197.         unsigned char lenth;
  198.         unsigned char check;
  199.         
  200.         RI=0;     //开启接收数据(长度)
  201.         while(!RI);
  202.         if(RB8==1)    //若接收到地址帧,则返回0xfe
  203.           return 0xfe;
  204.         lenth=SBUF;
  205.         RI=0; //开启再次接收数据   
  206.         
  207.         check=lenth;
  208.         for(i=0;i<lenth;i++) //接收数据
  209.         {
  210.           while(!RI);
  211.           if(RB8==1)   //若接收到地址帧,则返回0xfe
  212.            return 0xfe;
  213.           Buff[i]=SBUF;   
  214.           check=check^(Buff[i]);//按位异或
  215.           RI=0;
  216.         }

  217.         while(!RI);    //接收校验字节
  218.         if(RB8==1)    //若接收到地址帧,则返回0xfe
  219.           return 0xfe;
  220.         temp=SBUF;
  221.         RI=0;
  222.               
  223.         check=temp^check;  //将从主机接收到的校验码与自己计算的校验码比对(同为零,不同则大于零)
  224.         if(check!=0)   //校验码不一致,表明数据接收错误,向主机发送错误信号,函数返回0xff
  225.         {
  226.           TI=0;
  227.           TB8=0;
  228.           SBUF=_ERR_; //把错误信号赋值到缓冲区待发送
  229.           while(!TI); //发送完毕时跳出循环
  230.           TI=0;
  231.           return 0xff;
  232.         }
  233.         TI=0;           //校验码一致,表明数据接收正确,向主机发送成功信号,函数返回0x00
  234.         TB8=0;
  235.         SBUF=_SUCC_;
  236.         while(!TI);                 //发送成功的信号给主机
  237.         TI=0;
  238.         return 0;
  239. }
  240. const unsigned char CharCode0[8]={0xff,0x81,0x81,0x81,0x81,0x81,0x81,0xff};//P2口代码
  241. 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};
  242. void chuang1()
  243. {
  244. static char CurPosi;    //定义当前输出位置
  245. D1=0;
  246. P2=Buff[DispBuff[CurPosi]+16]; //输出当前字符显示编码到 P2 口
  247.         switch (CurPosi++)     //当前输出位置加 1   
  248.         {
  249.                 case 0:P1=0x00;break;   //P1.0 置低   
  250.                 case 1:P1=0x20;break; //P1.1 置低   
  251.                 case 2:P1=0x40;break;   //开一点窗   
  252.                 case 3:P1=0x60;break;    //开一半
  253.                 case 4:P1=0x80;break;//开大半
  254.                 case 5:P1=0xa0;break;         //全关
  255.                 case 6:P1=0xc0;break;        //全开
  256.                 case 7:P1=0xe0;break;
  257.         }   
  258.         if(CurPosi>7)  
  259.         CurPosi=0;   //当前输出位置大于 7 则重头开始
  260.         
  261. }
  262. void chuang2()
  263. {
  264. static char CurPosi;    //定义当前输出位置
  265. D2=0;
  266. P2=Buff[DispBuff[CurPosi]+8]; //输出当前字符显示编码到 P2 口
  267.         switch (CurPosi++)     //当前输出位置加 1   
  268.         {
  269.                 case 0:P1=0x00;break;   //P1.0 置低   
  270.                 case 1:P1=0x20;break; //P1.1 置低   
  271.                 case 2:P1=0x40;break;   //开一点窗   
  272.                 case 3:P1=0x60;break;    //开一半
  273.                 case 4:P1=0x80;break;//开大半
  274.                 case 5:P1=0xa0;break;         //全关
  275.                 case 6:P1=0xc0;break;        //全开
  276.                 case 7:P1=0xe0;break;
  277.         }   
  278.         if(CurPosi>7)  
  279.         CurPosi=0;   //当前输出位置大于 7 则重头开始
  280.         
  281. }
  282. void chuang3()
  283. {
  284. static char CurPosi;    //定义当前输出位
  285. D3=0;
  286. P2=Buff[DispBuff[CurPosi]]; //输出当前字符显示编码到 P2 口
  287.         switch (CurPosi++)     //当前输出位置加 1   
  288.         {
  289.                 case 0:P1=0x00;break;   //P1.0 置低   
  290.                 case 1:P1=0x20;break; //P1.1 置低   
  291.                 case 2:P1=0x40;break;   //开一点窗   
  292.                 case 3:P1=0x60;break;    //开一半
  293.                 case 4:P1=0x80;break;//开大半
  294.                 case 5:P1=0xa0;break;         //全关
  295.                 case 6:P1=0xc0;break;        //全开
  296.                 case 7:P1=0xe0;break;
  297.         }   
  298.         if(CurPosi>7)  
  299.         CurPosi=0;   //当前输出位置大于 7 则重头开始

  300. }
  301. //中断函数
  302. void  T0_INTProc(void)  interrupt  1   //T0 定时中断函数
  303. {
  304.         P1=0xff;       //关闭所有显示,消隐
  305.          
  306.         TH0=0xec;     
  307.         TL0=0x78;        //重装计数值   
  308.         TR0=1;     //重启计数,为显示下一字符作准备  
  309. if(k1==0)  
  310. chuang1();
  311. else
  312. D1=1;               
  313. if(k2==0)
  314. chuang2();
  315. else
  316. D2=1;
  317. if(k3==0)  
  318. chuang3();
  319. else
  320. D3=1;
  321. }
  322. void main()
  323. {
  324.         serial_init();          //串口初始化
  325.         while(1)
  326.         {
  327.           SM2=1;            //开启接收地址帧
  328.           while(aa!=addr)  //从机等待主机请求自己的地址
  329.           {
  330.                    RI=0;
  331.                    while(!RI);
  332.                    aa=SBUF;
  333.                    RI=0;
  334.           }
  335.         
  336.           TI=0;     //一旦被请求,从机返回自己地址作为应答,等待接收数据
  337.           TB8=0;
  338.           SBUF=addr;
  339.           while(!TI);
  340.           TI=0;
  341.         
  342.           SM2=0;                  //接收数据帧
  343.           aa=0xff;                                    //从机接收数据,并将数据保存到数据缓冲区
  344.           while(aa==0xff)
  345.           {
  346.                    aa=RECE_data(Buff);                //接收数据
  347.           }
  348.           if(aa==0xfe)
  349.            continue;
  350.                 TMOD=0x01;      //设定 T0 工作在定时方式 1,16位计数  
  351.                 TH0=0xec;     //装入计数值高字节(中断时间)  
  352.                 TL0=0x78;      //装入计数值低字节  
  353.                 EA=1;    //开总中断  
  354.                 ET0=1;       //开 T0 中断  
  355.                 TR0=1;       //启动 T0 计数  
  356.                 while(1);      //无限循环等待中断发生
  357.                
  358.         }
  359. }
复制代码

从机2号
//从机2
  1. #include<reg51.h>
  2. #include<string.h>

  3. #define addr     0x02//从机1的地址
  4. #define _SUCC_   0x0f//数据传送成功
  5. #define _ERR_    0xf0//数据传送失败
  6. unsigned char a;
  7. unsigned char x;
  8. //延时1ms函数
  9. void delay_1ms(unsigned int t)
  10. {
  11.         unsigned int x,y;
  12.         for(x=t;x>0;x--)
  13.           for(y=110;y>0;y--);
  14. }
  15. unsigned char aa=0xff;//主机与从机之间通信标志
  16. unsigned char Buff[50];//数据缓冲区

  17. //串口初始化函数
  18. void serial_init()
  19. {
  20.         TMOD=0x20; //定时器1工作于方式2          波特率为9600
  21.         TH1=0xfd;  
  22.         TL1=0xfd; //定时器初值
  23.         PCON=0;
  24.         SCON=0xd0;  //串口工作于方式3
  25.         TR1=1;  //开启定时器
  26.         TI=0;
  27.         RI=0;
  28. }
  29. //接收数据函数
  30. unsigned char RECE_data(unsigned char *Buff)
  31. {
  32.         unsigned char i,temp;
  33.         unsigned char lenth;
  34.         unsigned char check;
  35.         
  36.         RI=0;     //开启接收数据(长度)
  37.         while(!RI);
  38.         if(RB8==1)    //若接收到地址帧,则返回0xfe
  39.           return 0xfe;
  40.         lenth=SBUF;
  41.         RI=0; //开启再次接收数据   
  42.         
  43.         check=lenth;
  44.         for(i=0;i<lenth;i++) //接收数据
  45.         {
  46.           while(!RI);
  47.           if(RB8==1)   //若接收到地址帧,则返回0xfe
  48.            return 0xfe;
  49.           Buff[i]=SBUF;   
  50.           check=check^(Buff[i]);//按位异或
  51.           RI=0;
  52.         }

  53.         while(!RI);    //接收校验字节
  54.         if(RB8==1)    //若接收到地址帧,则返回0xfe
  55.           return 0xfe;
  56.         temp=SBUF;
  57.         RI=0;
  58.               
  59.         check=temp^check;  //将从主机接收到的校验码与自己计算的校验码比对(同为零,不同则大于零)
  60.         if(check!=0)   //校验码不一致,表明数据接收错误,向主机发送错误信号,函数返回0xff
  61.         {
  62.           TI=0;
  63.           TB8=0;
  64.           SBUF=_ERR_; //把错误信号赋值到缓冲区待发送
  65.           while(!TI); //发送完毕时跳出循环
  66.           TI=0;
  67.           return 0xff;
  68.         }
  69.         TI=0;           //校验码一致,表明数据接收正确,向主机发送成功信号,函数返回0x00
  70.         TB8=0;
  71.         SBUF=_SUCC_;
  72.         while(!TI);                 //发送成功的信号给主机
  73.         TI=0;
  74.         return 0;
  75. }
  76. #define uchar unsigned char//宏定义无符号字符型
  77. #define uint unsigned int  //宏定义无符号整型

  78. //定义分别表示8255A各口的变量
  79. volatile unsigned char xdata Aport _at_ 0x8000;
  80. volatile unsigned char xdata Bport _at_ 0x8001;
  81. volatile unsigned char xdata Cport _at_ 0x8002;
  82. volatile unsigned char xdata Ctrlport _at_ 0x8003;
  83. const unsigned char CharCode1[10]= {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92,0x82,0xf8, 0x80,0x90};//晶体管真值码
  84. unsigned char code seg7code[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 };//键盘真值码
  85. unsigned char k;


  86. void delay10ms(void) //延时程序
  87. {
  88.         unsigned char i,j;
  89.         for(i=20;i>0;i--)
  90.         for(j=248;j>0;j--);
  91. }

  92. //行扫描获取键盘函数     
  93. void Getch ( )        //取键值函数
  94. {
  95. unsigned char X,Y,Z;
  96. Bport=0x0f; //先对P3 置数 行扫描
  97. if(Bport!=0x0f) //判断是否有键按下
  98.         {
  99.         delay10ms(); //延时,软件去干扰
  100.         if(Bport!=0x0f) //确认按键按下
  101.                 {
  102.                 X=Bport; //保存行扫描时有键按下时状态
  103.                 Bport=0xf0; //列扫描
  104.                 Y=Bport;    //保存列扫描时有键按下时状态
  105.                 Z=X|Y; //取出键值

  106. //获取键盘值函数
  107. switch ( Z ) //判断键值(那一个键按下)
  108.                         {
  109.                                 case 0x77: k=0; break; //对键值赋值
  110.                                 case 0x7b: k=1; break;
  111.                                 case 0x7d: k=2; break;
  112.                                 case 0x7e: k=3; break;
  113.                                 case 0xb7: k=4; break;
  114.                                 case 0xbb: k=5; break;
  115.                                 /*  case 0xbd: k=6; break;
  116.                                 case 0xbe: k=7;
  117.                                 case 0xd7: k=8; break;
  118.                                 case 0xdb: k=9; break;
  119.                                 case 0xdd: k=10;break;
  120.                                 case 0xde: k=11;break;
  121.                                 case 0xe7: k=12;break;
  122.                                 case 0xeb: k=13;break;
  123.                                 case 0xed: k=14;break;
  124.                                 case 0xee: k=15;break;*/
  125.                         }
  126.                  }
  127.         }
  128. }
  129. void main()
  130. {
  131.         serial_init();          //串口初始化
  132.         while(1)
  133.         {
  134.           SM2=1;            //开启接收地址帧
  135.           while(aa!=addr)  //从机等待主机请求自己的地址
  136.           {
  137.                    RI=0;
  138.                    while(!RI);
  139.                    aa=SBUF;
  140.                    RI=0;
  141.           }
  142.         
  143.           TI=0;     //一旦被请求,从机返回自己地址作为应答,等待接收数据
  144.           TB8=0;
  145.           SBUF=addr;
  146.           while(!TI);
  147.           TI=0;
  148.         
  149.           SM2=0;                  //接收数据帧
  150.           aa=0xff;                                    //从机接收数据,并将数据保存到数据缓冲区
  151.           while(aa==0xff)
  152.           {
  153.                    aa=RECE_data(Buff);                //接收数据
  154.           }
  155.           if(aa==0xfe)
  156.            continue;
  157.         while(1){
  158.         a=1;
  159.         while(a)
  160.         {
  161.                 Bport=0xff;
  162.                 Getch();             //调用取键值函数
  163.                 Aport=Buff[k+24]; //查表LED输出

  164.                                 if(k==5)
  165.                                 P1=0x00;
  166.                                 if(P1==0x02)
  167.                                 {
  168.                                 P1=0X01;
  169.                                 a=0;
  170.                                 }
  171.                   }
  172.         }
  173.                
  174.         }
  175. }
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表