找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5614|回复: 3
收起左侧

stc11f60xe单片机modbus(RTU)从站源程序可与plc组态王通信

[复制链接]
ID:76127 发表于 2015-4-8 21:14 | 显示全部楼层 |阅读模式
晶振12M 波特率9200 可与组态王通信 组态王IO设备选择西门子S7-200 MODBUS(RTU)或支持MODBUS 协义的PLC
编译器为KEIL3
单片机型号:STC11F60XE
  1. #include<reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. #define _irol_(a,b) (a<<b)|(a>>16-b)
  5. #define BIT(A) (1<<A )
  6. #define D0 DW0[0]
  7. #define D1 DW0[1]
  8. #define D2 DW0[2]
  9. #define D3 DW0[3]
  10. #define D4 DW0[4]
  11. #define D5 DW0[5]
  12. #define D6 DW0[6]
  13. #define D7 DW0[7]
  14. #define D8 DW0[8]
  15. #define D9 DW0[9]
  16. #define D10 DW0[10]
  17. #define D11 DW0[11]
  18. #define D12 DW0[12]
  19. #define D13 DW0[13]
  20. #define D14 DW0[14]
  21. #define D15 DW0[15]
  22. #define D16 DW0[16]
  23. #define D17 DW0[17]
  24. #define D18 DW0[18]
  25. #define D19 DW0[19]
  26. #define D20 DW0[20]
  27. #define D21 DW0[21]
  28. #define D22 DW0[22]
  29. #define D23 DW0[23]
  30. #define D24 DW0[24]
  31. #define D25 DW0[25]
  32. #define D26 DW0[26]
  33. #define D27 DW0[27]
  34. #define D28 DW0[28]
  35. #define D29 DW0[29]
  36. #define D30 DW0[30]
  37. #define D31 DW0[31]
  38. unsigned long bdata  M00=0xAAAADCBA;
  39. unsigned int idata DW0[32]={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,25,26,27,28,29,30} ;//_at_ 0x0000

  40. /*sbit p10=P1^0;
  41. sbit p11=P1^1; */
  42. sbit p12=P1^2;
  43. sbit p13=P1^3;
  44. sbit p14=P1^4;

  45. uchar ac;
  46. uchar at;//结束接收计时;
  47. uint b;
  48. uchar *p;
  49. uchar uartR[80]={2};//接收缓冲区;
  50. bit fcbz;//启动发送标志,发送结束需清零;
  51. bit fcz;//发送中标志位;
  52. uchar fc;//发送数据个数;
  53. uchar fc1;//发送数据现在数;
  54. bit a1;//数据接收中标志位;
  55. bit a2;//数据接收结束标志位;
  56. bit crc1;//crc校验正确位;1有效;
  57. sfr BRT=0X9C;
  58. sfr AUXR1=0XA2;
  59. sfr AUXR=0X8E;
  60. uchar code suzhu[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f};

  61. sbit P07=P0^7;
  62. void delay(uint a) //延时函数;
  63. {
  64.   while(a--);
  65. }
  66. void time0() interrupt 1 //定时器0中断服务程序,用于提供通信接收空闲结束时钟等;
  67. {
  68.     TH0=0XFE;
  69. TL0=0X0C;
  70. if(a1)
  71. {
  72. at++;
  73. if(at>=100)  //50毫秒无数据流,完成接收;
  74. {a1=0;
  75.   a2=1;
  76.   at=0;
  77. }
  78. }
  79. if(M00&BIT(0))
  80. {
  81. b++;
  82. if(b==1000)
  83. {
  84.     b=0;
  85.   if(M00&BIT(1))M00&=~BIT(1);
  86.   else M00|=BIT(1);
  87. }
  88. if(M00&BIT(1))P07=!P07;
  89. else P07=1;
  90. }
  91. else P07=1;
  92. }
  93. void uartinit() //串口初始化;
  94. {
  95.   SCON=0X50;
  96.   PCON = 0x80;
  97.   AUXR=0X15;
  98.   BRT=217;
  99.   EA=1;
  100.   ES=1;
  101. }
  102. uint crc16(unsigned char *p,A) //调用时把校验数据首地址送给指针p,校验数据个数送给A;
  103. {
  104. uint code pp[256]={0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
  105.          0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
  106.          0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
  107.          0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
  108.          0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
  109.          0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
  110.          0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
  111.          0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
  112.          0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
  113.          0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
  114.          0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
  115.          0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
  116.          0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
  117.          0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
  118.          0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
  119.          0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
  120.          0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
  121.          0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
  122.          0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
  123.          0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
  124.          0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
  125.          0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
  126.          0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
  127.          0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
  128.          0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
  129.          0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
  130.          0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
  131.          0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
  132.          0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
  133.          0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
  134.          0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
  135.          0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040};
  136. uchar i;
  137. uint arc, crc;
  138. crc=0xffff;
  139. for (i=0;i<A;i++ )
  140.     {
  141.    arc= (p[i]^crc)&0x00ff;
  142.      crc=_irol_(crc,8);
  143.      crc= crc & 0x00ff;
  144.      crc= crc^pp[arc];
  145.      }
  146.    return(crc);
  147. }

  148. void modbus1(unsigned char *p,unsigned long M00) //功能码1(读线圈)处理函数;
  149. {
  150.   unsigned int A,B;
  151.   unsigned char i,y,u;

  152.   B=p[4];
  153.   B=B<<8|p[5];//取线圈个数;
  154.   A=p[2];
  155.   A=A<<8|p[3]; //取线圈地址;
  156.   if(B>0&&B<33)
  157.   {
  158.   if(A>=0&&A+B<33)
  159.   {
  160.   fc=B/8;
  161.   for(i=0;i<fc;i++)
  162.   {
  163.     u=0;
  164.   for(y=0;y<8;y++)
  165.   {
  166.    u>>=1;
  167.    if((M00>>A)&0x01 )u|=0x80;
  168.    A++;
  169.    }
  170.    p[i+3]=u;
  171.   }   
  172.   if(B%8)
  173.   {
  174.   fc+=1;
  175.   u=0;
  176.   for(y=0;y<B%8;y++)
  177.   {
  178.    if((M00>>A)&0x01 )u|=0x01<<y;
  179.    A++;  
  180.   }
  181.    p[fc+2]=u;
  182.    }
  183.   p[2]=fc;
  184.   fc+=3;
  185.   }
  186.   else
  187.   {
  188.    p[1]=0x81;
  189.    p[2]=0x02;
  190.    fc=3;
  191.   }
  192.   }
  193.   else
  194.   {
  195.    p[1]=0x81;
  196.    p[2]=0x03;
  197.    fc=3;
  198.   }
  199. }
  200. void modbus2(unsigned char *p,unsigned long M00)//功能码2(读输入离散)处理函数;
  201. {
  202.   unsigned int A,B;
  203.   unsigned char i,y,u;

  204.   B=p[4];
  205.   B=B<<8|p[5];//取IO离散个数;
  206.   A=p[2];
  207.   A=A<<8|p[3];//取IO离散地址;
  208.   if(B>0&&B<33)
  209.   {
  210.   if(A>=0&&A+B<33)
  211.   {
  212.   fc=B/8;
  213.   for(i=0;i<fc;i++)
  214.   {
  215.   u=0;
  216.   for(y=0;y<8;y++)
  217.   {
  218.    u>>=1;
  219.    if((M00>>A)&0x01 )u|=0x80;
  220.    A++;
  221.    }
  222.    p[i+3]=u;
  223.   }   
  224.   if(B%8)
  225.   {
  226. fc+=1;
  227. u=0;
  228.   for(y=0;y<B%8;y++)
  229.   {
  230.    if((M00>>A)&0x01 )u|=0x01<<y;
  231.    A++;   
  232.   }
  233.   
  234.   p[fc+2]=u;
  235.    }
  236.   p[2]=fc;
  237.   fc+=3;
  238.   }
  239.   else
  240.   {
  241.    p[1]=0x82;
  242.    p[2]=0x02;
  243.    fc=3;
  244.   }
  245.   }
  246.   else
  247.   {
  248.    p[1]=0x82;
  249.    p[2]=0x03;
  250.    fc=3;
  251.   }
  252. }
  253. void modbus3(unsigned char *p,unsigned int *p0)//功能码3(读保持寄存器)处理函数;
  254. {
  255.   unsigned int A,B;
  256.   unsigned char i;
  257.   unsigned int *p1;
  258.   p1=p+3;
  259.   B=p[4];
  260.   B=B<<8|p[5]; //取保持寄存器数量;
  261.   A=p[2];
  262.   A=A<<8|p[3];//取保持寄存器地址;
  263.   if(B>0&&B<33)
  264.   {
  265.   if(A>=0&&A+B<33)
  266.   {
  267.   for(i=0;i<B;i++)
  268.   {
  269.    p1[i]=p0[A+i];
  270.   }
  271.   p[2]=B*2;
  272.   fc=B*2+3;

  273.   }
  274.   else
  275.   {
  276.    p[1]=0x83;
  277.    p[2]=0x02;
  278.    fc=3;
  279.   }
  280.   }
  281.   else
  282.   {
  283.    p[1]=0x83;
  284.    p[2]=0x03;
  285.    fc=3;
  286.   }
  287. }
  288. void modbus4(unsigned char *p,unsigned int *p0 ) //功能码4(读输入寄存器)处理函数;
  289. {
  290.   unsigned int A,B;
  291.   unsigned char i;
  292.   unsigned int *p1;
  293.   p1=p+3;
  294.   B=p[4];
  295.   B=B<<8|p[5]; //取输入寄存器个数;
  296.   A=p[2];
  297.   A=A<<8|p[3]; //取输入寄存器地址;
  298.   if(B>0&&B<33)
  299.   {
  300.   if(A>=0&&A+B<33)
  301.   {
  302.   for(i=0;i<B;i++)
  303.   {
  304.    p1[i]=p0[A+i];
  305.   }
  306.   p[2]=B*2;
  307.   fc=B*2+3;
  308.   }
  309.   else
  310.   {
  311.    p[1]=0x84;
  312.    p[2]=0x02;
  313.    fc=3;
  314.   }
  315.   }
  316.   else
  317.   {
  318.    p[1]=0x84;
  319.    p[2]=0x03;
  320.    fc=3;
  321.   }
  322. }
  323. void modbus5(unsigned char *p,unsigned long *p1)//功能码5(写单个线圈)处理函数;
  324. {
  325.   unsigned int A,B,i;
  326.   B=p[4];
  327.   B=B<<8|p[5];//取线圈状态;
  328.   A=p[2];
  329.   A=A<<8|p[3];//取线圈地址;
  330.   if(B==0X0000||B==0XFF00)
  331.   {
  332.   if(A>=0&&A<32)
  333.   {
  334.    i=1;
  335.    if(B==0XFF00)
  336.    {
  337.     p1[0]|=i<<A;
  338.    }
  339.    else M00&=~(i<<A);
  340.    fc=6;
  341.   }
  342.   else
  343.   {
  344.    p[1]=0x85;
  345.    p[2]=0x02;
  346.    fc=3;
  347.   }
  348.   }
  349.   else
  350.   {
  351.    p[1]=0x85;
  352.    p[2]=0x03;
  353.    fc=3;
  354.   }
  355. }
  356. void modbus6(unsigned char *p,unsigned int *p1)//功能码6(写单个寄存器)处理函数;
  357. {
  358.   unsigned int A,B;
  359.   B=p[4];
  360.   B=B<<8|p[5];//取寄存器值;
  361.   A=p[2];
  362.   A=A<<8|p[3];//取寄存器地址;
  363.   if(B>=0X00||B<=0XFFFF)
  364.   {
  365.   if(A>=0&&A<32)
  366.   {
  367.    p1[A]=B;
  368.    fc=6;
  369.   }
  370.   else
  371.   {
  372.    p[1]=0x86;
  373.    p[2]=0x02;
  374.    fc=3;
  375.   }
  376.   }
  377.   else
  378.   {
  379.    p[1]=0x86;
  380.    p[2]=0x03;
  381.    fc=3;
  382.   }
  383. }
  384. void modbus15(unsigned char *p,unsigned long *M00)//功能码15(写多个线圈)处理函数;
  385. {
  386.   unsigned int A,B;
  387.   unsigned char i,y,u;
  388.   unsigned long l;

  389.   B=p[4];
  390.   B=B<<8|p[5]; //取线圈个数;
  391.   A=p[2];
  392.   A=A<<8|p[3];//取线圈地址;
  393.   if(B>0&&B<33)
  394.   {
  395.   if(A>=0&&A+B<33)
  396.   {
  397.   l=1;
  398.   fc=B/8;
  399.   for(i=0;i<fc;i++)
  400.   {
  401.   u=p[i+7];
  402.   for(y=0;y<8;y++)
  403.   {
  404.    if((u>>y)&0x01 )M00[0]|=l<<A;
  405.    else M00[0]&=~(l<<A);
  406.    A++;
  407.    }
  408.   }   
  409.   if(B%8)
  410.   {
  411. if(fc)
  412. {
  413. fc+=1;
  414. u=p[fc+6];
  415. }
  416. else  u=p[7];
  417.   for(y=0;y<B%8;y++)
  418.   {
  419.    if((u>>y)&0x01 )M00[0]|=l<<A;
  420.    else M00[0]&=~(l<<A);
  421.    A++;
  422.   }
  423.   }
  424.   fc=6;
  425.   p14=0;
  426.   }
  427.   else
  428.   {
  429.    p[1]=0x8F;
  430.    p[2]=0x02;
  431.    fc=3;
  432.   }
  433. }
  434.   else
  435.   {
  436.    p[1]=0x8F;
  437.    p[2]=0x03;
  438.    fc=3;
  439.   }
  440. }
  441. void modbus16(unsigned char *p,unsigned int *p1)
  442. {
  443.   unsigned int A,B;
  444.   unsigned int *p0;
  445.   p0=p+7;
  446.   B=p[4];
  447.   B=B<<8|p[5];//取寄存器数量;
  448.   A=p[2];
  449.   A=A<<8|p[3];//取寄存器地址;
  450.   if(B>0&&B<33)
  451.   {
  452.   if(A>=0&&A+B<33)
  453.   {
  454.    p1+=A;
  455.   while(B--)
  456.    {
  457.     p1[0]=p0[0];
  458.     p1++;
  459. p0++;
  460.    }  
  461.    fc=6;
  462.   }
  463.   else
  464.   {
  465.    p[1]=0x90;
  466.    p[2]=0x02;
  467.    fc=3;
  468.    fcbz=1;
  469.    }
  470.   }
  471.   else
  472.   {
  473.    p[1]=0x90;
  474.    p[2]=0x03;
  475.    fc=3;
  476.    fcbz=1;
  477.   }
  478. }
  479. /*void modbus23(unsigned char *p,unsigned int *p1)
  480. {
  481.   unsigned int A,B,AW,BW;
  482.   unsigned int *p0;
  483. // unsigned char u;
  484.   B=p[4];
  485.   B=B<<8|p[5];//取读寄存器数量;
  486.   A=p[2];
  487.   A=A<<8|p[8]; //取读寄存器地址;
  488.   BW=p[8];
  489.   BW=BW<<8|p[9];//取写寄存器数量;
  490.   AW=p[6];
  491.   AW=AW<<8|p[7]; //取写寄存器地址;
  492. if(B>0&&B<33&&BW>0&&BW<33)
  493. {
  494. if(A>=0&&A+B<33&&AW>=0&&AW+BW<33)
  495. {
  496. unsigned char i;
  497.   p1+=AW;
  498.   p0=p+11;
  499.     do
  500.    {
  501.     p1[0]=p0[0];
  502.     p1++;
  503. p0++;
  504.    }while(BW--);
  505.   ////////////////////c=(B&0X00FF)*2;
  506.   p0=p+3;
  507.   p1=p1-AW-BW;
  508.   p1+=A;
  509.     for(i=0;i<B;i++)
  510.   {
  511.    p1[i]=p0[A+i];
  512.   }
  513.   }
  514.   else
  515. {
  516.    p[1]=0x97;
  517.    p[2]=0x02;
  518.    fc=3;
  519. }
  520. }
  521. else
  522. {
  523.    p[1]=0x97;
  524.    p[2]=0x03;
  525.    fc=3;
  526. }
  527.   }*/
  528. void modata(uchar *p,ac)
  529. {
  530. unsigned int a,b;
  531.   p13=0;
  532.   a=p[ac];
  533.   a=(a<<8)|p[ac-1];
  534.   b=crc16(p,ac-1);
  535.   if(a!=b)goto pp;
  536.   p12=0;
  537.   fcbz=1;
  538.   switch(p[1]) //功能码判断与服务函数调用;
  539.   {
  540.   case 1: //读线圈;
  541.   modbus1(uartR, M00);
  542.   break;
  543.   case 2://读输入离散;
  544.   modbus2(uartR, M00);
  545.   break;
  546.   case 3://读保持寄存器;
  547.   modbus3(uartR,DW0);
  548.   break;
  549.   case 4://读输入寄存器;
  550.   modbus4(uartR,DW0);
  551.   break;
  552.   case 5://写单个线圈;
  553.   modbus5(uartR, &M00);
  554.   break;
  555.   case 6://写单个数据寄存器;
  556.   modbus6(uartR, DW0);
  557.   break;
  558.   case 15://写多个连续线圈;
  559.   modbus15(uartR,&M00);
  560.   break;
  561.   case 16://写多个连续寄存器;
  562.   modbus16(uartR,DW0);
  563.   break;
  564. // case 23://读写寄存器;
  565. // modbus23(uartR,DW0);
  566.   break;
  567.   default:
  568.    p[1]+=0x80;
  569.    p[2]=0x01;
  570.    fc=3;
  571.   }
  572. pp:;
  573. }
  574.   modbushy(unsigned char *p ,a)//通讯回应;
  575. {
  576.   unsigned int b;
  577.   b=crc16(p,a);
  578.   p[a]=b;
  579.   a+=1;
  580.   p[a]=b>>8;
  581.   fc=a;
  582.   SBUF=p[0];
  583. }

  584. void uart() interrupt 4 //串口中断函数;
  585. {
  586.   uchar ua;
  587.   if(RI)
  588.   {
  589.    RI=0;
  590.    ua=SBUF;
  591.    if(!a1)
  592.    {
  593.     if(ua==2)
  594. {a1=1;
  595.   ac=0;
  596.   at=0;
  597.   uartR[0]=ua;
  598.   }
  599.    }
  600.    else
  601.    {
  602.    RI=0;
  603.    ac++;
  604.    uartR[ac]=ua;
  605.    at=0; //清零结束接收计时器;
  606.    }
  607.    }
  608.   else
  609.   {
  610.    TI=0;
  611.   if(fc--)
  612.    {
  613.     fc1++;
  614. SBUF=uartR[fc1];
  615.    }
  616.    else fc1=0,fc=0;
  617.   }
  618. }
  619. void sumaguan(uint c)
  620. {
  621.   P2|=0x0f;
  622.   P1=suzhu[c%10];
  623.   P2&=~1;
  624.   delay(300);
  625.   P2|=0x0f;
  626.   P1=suzhu[c%100/10];
  627.   P2&=~4;
  628.   delay(300);
  629.   P2|=0x0f;
  630.   P1=suzhu[c%1000/100];
  631.   //if(b1)P1&=~0x80;
  632.   P2&=~2;
  633.   delay(300);
  634.   P2|=0x0f;
  635.   P1=suzhu[c/1000];
  636.   P2&=~8;
  637. delay(300);
  638. }

  639. void main()
  640. {
  641.     TH0=0XFE;
  642. TL0=0X0C;
  643.   TMOD=0X01;
  644. TR0=1;
  645. EA=1;
  646. ET0=1;
  647. uartinit();
  648. while(1)
  649. {  
  650.   if(!(M00&BIT(0)))M00&=~BIT(1);
  651.     //sumaguan(D1);
  652.     if(a2)modata(uartR,ac),a2=0;
  653.     if(fcbz)modbushy(uartR ,fc),fcbz=0;
  654. }
  655. }
复制代码



回复

使用道具 举报

ID:82719 发表于 2015-6-11 18:50 | 显示全部楼层
你好,请问有51单片机modbus协议的程序吗?
回复

使用道具 举报

ID:428400 发表于 2019-9-17 19:59 | 显示全部楼层
谢谢分享!
回复

使用道具 举报

ID:428400 发表于 2019-9-28 19:35 | 显示全部楼层
有例子吗,大神?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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