找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

帖子
查看: 12260|回復(fù): 3
打印 上一主題 下一主題
收起左側(cè)

MAX487+51單片機(jī)實(shí)現(xiàn)RS485通信程序Proteus仿真(實(shí)測(cè)通過)

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
   RS-485總線標(biāo)準(zhǔn)規(guī)定了總線接口的電氣特性標(biāo)準(zhǔn)即對(duì)于2個(gè)邏輯狀態(tài)的定義:正電平在+2V~+6V之間,表示一個(gè)邏輯狀態(tài);負(fù)電平在-2V~-6V之間,則表示另一個(gè)邏輯狀態(tài);數(shù)字信號(hào)采用差分傳輸方式,能夠有效減少噪聲信號(hào)的干擾。RS-485工業(yè)總線標(biāo)準(zhǔn)能夠有效支持多個(gè)分節(jié)點(diǎn)和通信距離遠(yuǎn),并且對(duì)于信息的接收靈敏度較高等特性。在工業(yè)通信網(wǎng)絡(luò)中,RS-485總線一般主要用于與外部各種工業(yè)設(shè)備進(jìn)行信息傳輸和數(shù)據(jù)交換,所具備的對(duì)于噪聲的有效抑制能力、高效的數(shù)據(jù)傳輸速率與良好的數(shù)據(jù)傳輸?shù)目煽啃阅芤约翱蓴U(kuò)展的通信電纜的長(zhǎng)度是其他的許多工業(yè)通信標(biāo)準(zhǔn)所無(wú)法比擬的。因此,RS-485總線在諸多個(gè)領(lǐng)域得到了廣泛的應(yīng)用,比如在工業(yè)控制領(lǐng)域、交通的自動(dòng)化控制領(lǐng)域和現(xiàn)場(chǎng)總線通信網(wǎng)絡(luò)等。
   RS-485接口的最大傳輸距離標(biāo)準(zhǔn)值為4000英尺,實(shí)際上可達(dá) 3000米(理論上的數(shù)據(jù),在實(shí)際操作中,極限距離僅達(dá)1200米左右),另外RS-232-C接口在總線上只允許連接1個(gè)收發(fā)器,即單站能力。RS485接口在總線上是允許連接多達(dá)128個(gè)收發(fā)器。即具有多站能力,這樣用戶可以利用單一的RS-485接口方便地建立起設(shè)備網(wǎng)絡(luò)。
本例程為STC89C52+RS485模塊組成的“一主兩從”模型。從機(jī)可拓展多位,修改主、從機(jī)地址即可。
本資料包含源文件、仿真程序。實(shí)測(cè)通過。

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

代碼片段(主機(jī))
  1. #include<reg51.h>
  2. #include<string.h>
  3. #include "lcd.h"
  4. #define _SUCC_   0x0f//數(shù)據(jù)傳送成功
  5. #define _ERR_    0xf0//數(shù)據(jù)傳送失敗
  6. unsigned char aa=0xff;//主機(jī)與從機(jī)之間通信標(biāo)志
  7. unsigned char temp=0xff;
  8. unsigned char Buff[20];//數(shù)據(jù)緩沖區(qū)
  9. unsigned char recive[6];     //用于保存從機(jī)發(fā)送的數(shù)據(jù)
  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. //延時(shí)1ms函數(shù)
  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. //串口初始化函數(shù)
  26. void init()
  27. {
  28.      TMOD=0x20; //定時(shí)器1工作于方式2
  29.      TH1=0xfd;  
  30.      TL1=0xfd; //波特率為9600
  31.      PCON=0;
  32.      SCON=0xd0;  //串口工作于方式3
  33.      TR1=1;  //開啟定時(shí)器
  34.      TI=0;
  35.      RI=0;
  36. }


  37. //發(fā)送數(shù)據(jù)函數(shù)
  38. void SEND_data(unsigned char *Buff)
  39. {
  40.      unsigned char i,lenth,check;
  41.      lenth=strlen(Buff);      //計(jì)算數(shù)據(jù)長(zhǎng)度
  42.      check=lenth;
  43.      TI=0;         //發(fā)送數(shù)據(jù)長(zhǎng)度
  44.      TB8=0;       //發(fā)送數(shù)據(jù)幀
  45.      SBUF=lenth;
  46.      while(!TI);
  47.      TI=0;
  48.          
  49.      for(i=0;i<lenth;i++)  //發(fā)送數(shù)據(jù)
  50.     {
  51.         check=check^Buff[i];
  52.         TB8=0;
  53.         SBUF=Buff[i];      
  54.         while(!TI);
  55.         TI=0;
  56.     }
  57.       TB8=0;      //發(fā)送校驗(yàn)字節(jié)
  58.       SBUF=check;   
  59.       while(!TI);
  60.       TI=0;     
  61. }

  62. //接收數(shù)據(jù)函數(shù)
  63. unsigned char RECE_data(unsigned char *Buff)
  64. {
  65.      unsigned char i;
  66.      unsigned char lenth;
  67.      unsigned char check;
  68.      RI=0;     //接收數(shù)據(jù)長(zhǎng)度
  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++) //接收數(shù)據(jù)
  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);    //接收校驗(yàn)字節(jié)
  88.      if(RB8==1)    //若接收到地址幀,則返回0xfe
  89.      return 0xfe;
  90.      temp=SBUF;
  91.      RI=0;
  92.      check=temp^check;  //將從主機(jī)接收到的校驗(yàn)碼與自己計(jì)算的校驗(yàn)碼比對(duì)
  93.      if(check!=0)   //校驗(yàn)碼不一致,表明數(shù)據(jù)接收錯(cuò)誤,向主機(jī)發(fā)送錯(cuò)誤信號(hào),函數(shù)返回0xff
  94.      {
  95.         TI=0;
  96.         TB8=0;
  97.         SBUF=_ERR_;
  98.         while(!TI);
  99.         TI=0;
  100.         return 0xff;
  101.      }
  102.      TI=0;           //校驗(yàn)碼一致,表明數(shù)據(jù)接收正確,向主機(jī)發(fā)送成功信號(hào),函數(shù)返回0x00
  103.      TB8=0;
  104.      SBUF=_SUCC_;         
  105.      while(!TI);
  106.      TI=0;
  107.      return 0;
  108. }                 

  109. //發(fā)送從機(jī)地址
  110. void ADDR_data(unsigned addr)
  111. {
  112. while(temp!=addr) //主機(jī)等待從機(jī)返回其地址作為應(yīng)答信號(hào)
  113. {
  114.   TI=0;    //發(fā)送從機(jī)地址
  115.   TB8=1;    //發(fā)送地址幀
  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);//發(fā)送從機(jī)地址
  137.       temp=_ERR_;   //主機(jī)等待從機(jī)數(shù)據(jù)接收成功信號(hào)
  138.       while(temp!=_SUCC_)
  139.       {
  140.           unsigned char Buff[]={0xfe};
  141.           SEND_data(Buff);//發(fā)送數(shù)據(jù)
  142.           RI=0;
  143.           while(!RI);
  144.           temp=SBUF;
  145.           RI=0;
  146.       }
  147.       SM2=0;       //接收數(shù)據(jù)幀
  148.       aa=0xff;    //從機(jī)接收數(shù)據(jù),并將數(shù)據(jù)保存到數(shù)據(jù)緩沖區(qū)
  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_;   //主機(jī)等待從機(jī)數(shù)據(jù)接收成功信號(hào)
  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_;   //主機(jī)等待從機(jī)數(shù)據(jù)接收成功信號(hào)
  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;       //接收數(shù)據(jù)幀
  200.         aa=0xff;    //從機(jī)接收數(shù)據(jù),并將數(shù)據(jù)保存到數(shù)據(jù)緩沖區(qū)
  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_;   //主機(jī)等待從機(jī)數(shù)據(jù)接收成功信號(hào)
  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_;   //主機(jī)等待從機(jī)數(shù)據(jù)接收成功信號(hào)
  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_;   //主機(jī)等待從機(jī)數(shù)據(jù)接收成功信號(hào)
  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_;   //主機(jī)等待從機(jī)數(shù)據(jù)接收成功信號(hào)
  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_;   //主機(jī)等待從機(jī)數(shù)據(jù)接收成功信號(hào)
  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. }
復(fù)制代碼

51hei.png (6.3 KB, 下載次數(shù): 210)

51hei.png

RS485多機(jī)通信-1602顯示從機(jī)信息.zip

180.8 KB, 下載次數(shù): 242, 下載積分: 黑幣 -5

評(píng)分

參與人數(shù) 1黑幣 +30 收起 理由
admin + 30 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏10 分享淘帖 頂2 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:928052 發(fā)表于 2021-6-8 11:48 | 只看該作者
正在做RS485,希望有幫助。
回復(fù)

使用道具 舉報(bào)

板凳
ID:1037582 發(fā)表于 2022-6-30 16:13 | 只看該作者
不明白定時(shí)器方式2存在的意義是什么啊
回復(fù)

使用道具 舉報(bào)

地板
ID:496636 發(fā)表于 2022-7-1 07:50 來(lái)自觸屏版 | 只看該作者
hbkjdxsh 發(fā)表于 2022-6-30 16:13
不明白定時(shí)器方式2存在的意義是什么啊

自動(dòng)重載定時(shí)器模式,如果是模式0,1溢出后需要在中斷程序中手工添加賦初值語(yǔ)句。如果是模式2,系統(tǒng)直接把THx的值賦給TLx
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表