找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9171|回复: 3
打印 上一主题 下一主题
收起左侧

MAX487+51单片机实现RS485通信程序Proteus仿真(实测通过)

  [复制链接]
跳转到指定楼层
楼主
   RS-485总线标准规定了总线接口的电气特性标准即对于2个逻辑状态的定义:正电平在+2V~+6V之间,表示一个逻辑状态;负电平在-2V~-6V之间,则表示另一个逻辑状态;数字信号采用差分传输方式,能够有效减少噪声信号的干扰。RS-485工业总线标准能够有效支持多个分节点和通信距离远,并且对于信息的接收灵敏度较高等特性。在工业通信网络中,RS-485总线一般主要用于与外部各种工业设备进行信息传输和数据交换,所具备的对于噪声的有效抑制能力、高效的数据传输速率与良好的数据传输的可靠性能以及可扩展的通信电缆的长度是其他的许多工业通信标准所无法比拟的。因此,RS-485总线在诸多个领域得到了广泛的应用,比如在工业控制领域、交通的自动化控制领域和现场总线通信网络等。
   RS-485接口的最大传输距离标准值为4000英尺,实际上可达 3000米(理论上的数据,在实际操作中,极限距离仅达1200米左右),另外RS-232-C接口在总线上只允许连接1个收发器,即单站能力。RS485接口在总线上是允许连接多达128个收发器。即具有多站能力,这样用户可以利用单一的RS-485接口方便地建立起设备网络。
本例程为STC89C52+RS485模块组成的“一主两从”模型。从机可拓展多位,修改主、从机地址即可。
本资料包含源文件、仿真程序。实测通过。

MAX487仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

代码片段(主机)
  1. #include<reg51.h>
  2. #include<string.h>
  3. #include "lcd.h"
  4. #define _SUCC_   0x0f//数据传送成功
  5. #define _ERR_    0xf0//数据传送失败
  6. unsigned char aa=0xff;//主机与从机之间通信标志
  7. unsigned char temp=0xff;
  8. unsigned char Buff[20];//数据缓冲区
  9. unsigned char recive[6];     //用于保存从机发送的数据
  10. sbit KEY1=P1^3;
  11. sbit KEY2=P1^2;
  12. sbit KEY3=P1^1;
  13. sbit KEY4=P1^0;
  14. sbit KEY5=P3^2;
  15. sbit KEY6=P3^3;

  16. //sbit KEY5=P1^4;
  17. //sbit KEY6=P1^5;
  18. //延时1ms函数
  19. void delay_1ms(unsigned int i)
  20. {
  21.      unsigned int x,y;
  22.      for(x=i;x>0;x--)
  23.          for(y=110;y>0;y--);
  24. }
  25. //串口初始化函数
  26. void init()
  27. {
  28.      TMOD=0x20; //定时器1工作于方式2
  29.      TH1=0xfd;  
  30.      TL1=0xfd; //波特率为9600
  31.      PCON=0;
  32.      SCON=0xd0;  //串口工作于方式3
  33.      TR1=1;  //开启定时器
  34.      TI=0;
  35.      RI=0;
  36. }


  37. //发送数据函数
  38. void SEND_data(unsigned char *Buff)
  39. {
  40.      unsigned char i,lenth,check;
  41.      lenth=strlen(Buff);      //计算数据长度
  42.      check=lenth;
  43.      TI=0;         //发送数据长度
  44.      TB8=0;       //发送数据帧
  45.      SBUF=lenth;
  46.      while(!TI);
  47.      TI=0;
  48.          
  49.      for(i=0;i<lenth;i++)  //发送数据
  50.     {
  51.         check=check^Buff[i];
  52.         TB8=0;
  53.         SBUF=Buff[i];      
  54.         while(!TI);
  55.         TI=0;
  56.     }
  57.       TB8=0;      //发送校验字节
  58.       SBUF=check;   
  59.       while(!TI);
  60.       TI=0;     
  61. }

  62. //接收数据函数
  63. unsigned char RECE_data(unsigned char *Buff)
  64. {
  65.      unsigned char i;
  66.      unsigned char lenth;
  67.      unsigned char check;
  68.      RI=0;     //接收数据长度
  69.      while(!RI);
  70.      if(RB8==1)
  71.      {
  72.          RI = 0;   
  73.          return 0xfe;  //若接收到地址帧,则返回0xfe
  74.      }
  75.      lenth=SBUF;
  76.      RI=0;     
  77.      check=lenth;
  78.      for(i=0;i<lenth;i++) //接收数据
  79.     {
  80.         while(!RI);
  81.         if(RB8==1)   //若接收到地址帧,则返回0xfe
  82.         return 0xfe;
  83.         Buff[i]=SBUF;   
  84.         check=check^(Buff[i]);
  85.         RI=0;
  86.     }
  87.      while(!RI);    //接收校验字节
  88.      if(RB8==1)    //若接收到地址帧,则返回0xfe
  89.      return 0xfe;
  90.      temp=SBUF;
  91.      RI=0;
  92.      check=temp^check;  //将从主机接收到的校验码与自己计算的校验码比对
  93.      if(check!=0)   //校验码不一致,表明数据接收错误,向主机发送错误信号,函数返回0xff
  94.      {
  95.         TI=0;
  96.         TB8=0;
  97.         SBUF=_ERR_;
  98.         while(!TI);
  99.         TI=0;
  100.         return 0xff;
  101.      }
  102.      TI=0;           //校验码一致,表明数据接收正确,向主机发送成功信号,函数返回0x00
  103.      TB8=0;
  104.      SBUF=_SUCC_;         
  105.      while(!TI);
  106.      TI=0;
  107.      return 0;
  108. }                 

  109. //发送从机地址
  110. void ADDR_data(unsigned addr)
  111. {
  112. while(temp!=addr) //主机等待从机返回其地址作为应答信号
  113. {
  114.   TI=0;    //发送从机地址
  115.   TB8=1;    //发送地址帧
  116.   SBUF=addr;
  117.   while(!TI);
  118.   TI=0;
  119.   
  120.   RI=0;
  121.   while(!RI);
  122.   temp=SBUF;
  123.   RI=0;
  124. }
  125. }

  126. void keyscan()
  127. {
  128.   
  129.   if(KEY1==0)
  130.   {
  131.      LcdWriteCom(0x01);  //清屏
  132.      delay_1ms(5);
  133.      if(KEY1==0)
  134.     {
  135.       while(!KEY1);
  136.       ADDR_data(0x01);//发送从机地址
  137.       temp=_ERR_;   //主机等待从机数据接收成功信号
  138.       while(temp!=_SUCC_)
  139.       {
  140.           unsigned char Buff[]={0xfe};
  141.           SEND_data(Buff);//发送数据
  142.           RI=0;
  143.           while(!RI);
  144.           temp=SBUF;
  145.           RI=0;
  146.       }
  147.       SM2=0;       //接收数据帧
  148.       aa=0xff;    //从机接收数据,并将数据保存到数据缓冲区
  149.       while(aa==0xff)
  150.       {
  151.           aa=RECE_data(Buff);
  152.           P0 = 0xff;
  153.       }
  154.       P0 = 0xfe;
  155.       recive[0] = Buff[0];
  156.       recive[1] = Buff[1];
  157.       recive[2] = Buff[2];
  158.      
  159.     }
  160.   }

  161.   if(KEY2==0)
  162.   {
  163.      LcdWriteCom(0x01);  //清屏
  164.      delay_1ms(5);
  165.      if(KEY2==0)
  166.      {
  167.         while(!KEY2);
  168.         ADDR_data(0x01);
  169.         temp=_ERR_;   //主机等待从机数据接收成功信号
  170.         while(temp!=_SUCC_)
  171.        {
  172.           unsigned char Buff[]={0xff};
  173.           SEND_data(Buff);
  174.           RI=0;
  175.           while(!RI);  
  176.           RI=0;
  177.           temp=SBUF;
  178.        }
  179.      }
  180.   }

  181.   if(KEY3==0)
  182.   {
  183.      LcdWriteCom(0x01);  //清屏
  184.      delay_1ms(5);
  185.      if(KEY3==0)
  186.      {
  187.          while(!KEY3);
  188.          ADDR_data(0x02);
  189.          temp=_ERR_;   //主机等待从机数据接收成功信号
  190.          while(temp!=_SUCC_)
  191.         {
  192.            unsigned char Buff[]={0xfe};
  193.            SEND_data(Buff);
  194.            RI=0;
  195.            while(!RI);
  196.            temp=SBUF;
  197.            RI=0;
  198.         }
  199.         SM2=0;       //接收数据帧
  200.         aa=0xff;    //从机接收数据,并将数据保存到数据缓冲区
  201.         while(aa==0xff)
  202.         {
  203.             aa=RECE_data(Buff);
  204.             P0 = 0xff;
  205.         }
  206.         P0 = 0xfe;
  207.         /*
  208.         recive[3] = Buff[0];
  209.         recive[4] = Buff[1];
  210.         recive[5] = Buff[2];
  211.         */
  212.         recive[0] = Buff[0];
  213.         recive[1] = Buff[1];
  214.         recive[2] = Buff[2];
  215.      }
  216.   }

  217.   if(KEY4==0)
  218.   {
  219.       LcdWriteCom(0x01);  //清屏
  220.       delay_1ms(5);
  221.       if(KEY4==0)
  222.      {
  223.          while(!KEY4);
  224.          ADDR_data(0x02);
  225.           temp=_ERR_;   //主机等待从机数据接收成功信号
  226.          while(temp!=_SUCC_)
  227.         {
  228.              unsigned char Buff[]={0xff};
  229.              SEND_data(Buff);
  230.              RI=0;
  231.              while(!RI);
  232.              temp=SBUF;
  233.              RI=0;
  234.         }
  235.      }
  236.   }
  237.   if(KEY5==0)
  238.   {
  239.       LcdWriteCom(0x01);  //清屏
  240.       delay_1ms(5);
  241.       if(KEY5==0)
  242.      {
  243.          while(!KEY5);
  244.          ADDR_data(0x01);
  245.           temp=_ERR_;   //主机等待从机数据接收成功信号
  246.          while(temp!=_SUCC_)
  247.         {
  248.              unsigned char Buff[]={0xff};
  249.              SEND_data(Buff);
  250.              RI=0;
  251.              while(!RI);
  252.              temp=SBUF;
  253.              RI=0;
  254.         }
  255.          ADDR_data(0x02);
  256.           temp=_ERR_;   //主机等待从机数据接收成功信号
  257.          while(temp!=_SUCC_)
  258.         {
  259.              unsigned char Buff[]={0xff};
  260.              SEND_data(Buff);
  261.              RI=0;
  262.              while(!RI);
  263.              temp=SBUF;
  264.              RI=0;
  265.         }
  266.      }
  267.   }
  268.   if(KEY6==0)
  269.   {
  270.       LcdWriteCom(0x01);  //清屏
  271.       delay_1ms(5);
  272.       if(KEY6==0)
  273.      {
  274.          while(!KEY6);
  275.          ADDR_data(0x01);
  276.           temp=_ERR_;   //主机等待从机数据接收成功信号
  277.          while(temp!=_SUCC_)
  278.         {
  279.              unsigned char Buff[]={0xff};
  280.              SEND_data(Buff);
  281.              RI=0;
  282.              while(!RI);
  283.              temp=SBUF;
  284.              RI=0;
  285.         }
  286.          ADDR_data(0x02);
  287.           temp=_ERR_;   //主机等待从机数据接收成功信号
  288.          while(temp!=_SUCC_)
  289.         {
  290.              unsigned char Buff[]={0xff};
  291.              SEND_data(Buff);
  292.              RI=0;
  293.              while(!RI);
  294.              temp=SBUF;
  295.              RI=0;
  296.         }
  297.      }
  298.   }

  299. }      
  300. void main()
  301. {
  302.      init();
  303.      LcdInit();             //初始化LCD1602
  304.      LcdWriteCom(0x01);
  305.      while(1)
  306.      {
  307.         keyscan();
  308.         LcdWriteData(recive[0]);
  309.         LcdWriteData(recive[1]);
  310.         LcdWriteData(recive[2]);
  311.         /*
  312.         LcdWriteData(recive[3]);
  313.         LcdWriteData(recive[4]);
  314.         LcdWriteData(recive[5]);
  315.         */
  316.         LcdWriteCom(0x80);
  317.      }
  318. }
复制代码

51hei.png (6.3 KB, 下载次数: 148)

51hei.png

RS485多机通信-1602显示从机信息.zip

180.8 KB, 下载次数: 204, 下载积分: 黑币 -5

评分

参与人数 1黑币 +30 收起 理由
admin + 30 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏7 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:928052 发表于 2021-6-8 11:48 | 只看该作者
正在做RS485,希望有帮助。
回复

使用道具 举报

板凳
ID:1037582 发表于 2022-6-30 16:13 | 只看该作者
不明白定时器方式2存在的意义是什么啊
回复

使用道具 举报

地板
ID:496636 发表于 2022-7-1 07:50 来自手机 | 只看该作者
hbkjdxsh 发表于 2022-6-30 16:13
不明白定时器方式2存在的意义是什么啊

自动重载定时器模式,如果是模式0,1溢出后需要在中断程序中手工添加赋初值语句。如果是模式2,系统直接把THx的值赋给TLx
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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