久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 15995|回復(fù): 39
打印 上一主題 下一主題
收起左側(cè)

51單片機MODBUS程序源碼與ModBusPol(上位機測試軟件)下載

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:404756 發(fā)表于 2018-10-1 22:49 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
MODBUS-51工程版從機,附帶ModBusPol上位機測試軟件




單片機源程序如下:
  1. #include "modbus.h"
  2. #include "resister.h"
  3. /******************數(shù)據(jù)舉例,移植數(shù)據(jù)定義修改區(qū),resister.h也需要修改***********************************/
  4. uint ROdat[3]={1,123,456};          //3個只讀整型
  5. uint RWdat[3]={1,123,456};          //3個可讀可寫整型
  6. float temp=23.4;                                                                         //一個浮點型
  7. long   adc=789654;                                                                        //一個long型
  8. bit    ROstatus0=0;                              //只讀線圈
  9. bit    ROstatus1=1;                              //只讀線圈
  10. bit    RWstatus0=0;                              //可讀可寫線圈
  11. bit    RWstatus1=1;                              //可讀可寫線圈

  12. /********************************************************************
  13. modbus RTU 的C51程序
  14. 單片機AT89C51          11.0592MHZ
  15. 通信波特率 9600 8位數(shù)據(jù) 1位停止位  485通位接口
  16. 單片機控制板地址 localAddr(變量)
  17. 0x01 0x03 0x00 0x00 0x01 0x84 0x0a
  18. **********************************************************************/
  19. uchar LocalAddr = 0x01; //單片機控制板的地址

  20. /***********************************************/
  21. union uf
  22. {
  23. uint x[2];
  24. float y;
  25. }ftemp;

  26. union ul
  27. {
  28. uint x[2];
  29. long y;
  30. }ltemp;

  31. uchar receTimeOut;                //接收超時
  32. uchar sendCount;  //發(fā)送字節(jié)個數(shù)
  33. uchar receCount;    //接收到的字節(jié)個數(shù)
  34. uchar receBuf[50];
  35. uchar sendBuf[50];
  36. bit   bt1ms;       //定時標志位


  37. /* CRC 高位字節(jié)值表 */
  38. uchar code auchCRCHi[] = {
  39. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0/**/,
  40. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  41. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  42. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  43. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  44. 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  45. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  46. 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  47. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  48. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  49. 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  50. 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  51. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  52. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  53. 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  54. 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  55. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  56. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  57. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  58. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  59. 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  60. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  61. 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  62. 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  63. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  64. 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  65. } ;
  66. /* CRC低位字節(jié)值表*/
  67. uchar code auchCRCLo[] = {
  68. 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06/**/,
  69. 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
  70. 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,                   
  71. 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
  72. 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
  73. 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
  74. 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
  75. 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
  76. 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
  77. 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
  78. 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
  79. 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
  80. 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
  81. 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
  82. 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
  83. 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
  84. 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
  85. 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
  86. 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
  87. 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
  88. 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
  89. 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
  90. 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
  91. 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
  92. 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
  93. 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
  94. } ;


  95. //-------------------------------定時器0 1ms 中斷 -------------------------
  96. void timer0_IntProc() interrupt 1
  97. {
  98.         TL0 = 0x66;               
  99.         TH0 = 0xFC;       
  100.     bt1ms = 1;

  101. }

  102. void presetSingleRegister(void);
  103. uint setCoilVal(uint addr,uint tempData);
  104. uint getCoilVal(uint addr,uint *tempData);
  105. uint getRegisterVal(uint addr,uint *tempData);
  106. uint setRegisterVal(uint addr,uint tempData);



  107. //--------------------------------串行中斷程序---------------------------
  108. void comm_IntProc() interrupt 4
  109. {
  110.        if(RI)
  111.         {
  112.              RI = 0;  
  113.                 receTimeOut = 10;    //通訊超時值這個地方很重要        10ms
  114.                 receBuf[receCount] = SBUF;
  115.                         receCount++;          //接收地址偏移寄存器加1                                 
  116.         }
  117.                 if(TI)
  118.                 TI=0;       

  119. }   

  120. //------------------------------------定時處理--------------------------------
  121. void timeProc(void)
  122. {
  123.         if(bt1ms)
  124.         {
  125.            bt1ms = 0;
  126.                if(receTimeOut>0)
  127.                       {
  128.                     receTimeOut--;
  129.             if(receTimeOut==0 && receCount>0)   //判斷通訊接收是否超時
  130.                     {
  131.                         b485Send = 0;    //將485置為接收狀態(tài)                                                                                                                                                              
  132.                         receCount = 0;//      //將接收地址偏移寄存器清零
  133.                             }
  134.                       }
  135.         }
  136. }


  137. //-----------------------------初始化中斷------------------------------------
  138. void InitUartAndTimer0(void)
  139. {
  140.         TMOD= 0x21;    //T0用于定時,T1用于波特
  141.                 TL0 = 0x66;               
  142.                 TH0 = 0xFC;       
  143.         TR0   = 1;        
  144.         ET0   = 1; //開中斷T0
  145.                 //-----------------------------------------------
  146.                 SCON=0x50;
  147.                 TH1=0xfd;
  148.                 TL1=0xfd;
  149.                 TR1=1;
  150.                 EA=1;
  151.                 ES=1;
  152.                 TI=0;   
  153.                 b485Send = 0;      //處于接收


  154. }   
  155. //--------------------------初始化-----------------------------
  156. void initProg(void)
  157. {        
  158.         InitUartAndTimer0();       
  159. }




  160. /***************************CRC校驗碼生成函數(shù) ********************************/
  161. uint crc16(uchar *puchMsg, uint usDataLen)
  162. {
  163. uchar uchCRCHi = 0xFF ; /* 高CRC字節(jié)初始化 */
  164. uchar uchCRCLo = 0xFF ; /* 低CRC 字節(jié)初始化 */
  165. uint uIndex ; /* CRC循環(huán)中的索引 */
  166. while (usDataLen--) /* 傳輸消息緩沖區(qū) */
  167. {
  168.   uIndex = uchCRCHi ^ *puchMsg++ ; /* 計算CRC */
  169.   uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
  170.   uchCRCLo = auchCRCLo[uIndex] ;
  171. }
  172. return (uchCRCLo << 8 | uchCRCHi) ;
  173. }

  174. void uartsends(uchar buff[],uchar len)
  175. {
  176.         uchar i;
  177.         for(i=0;i<len;i++)
  178.         {
  179.                 SBUF=buff[i];
  180.                 while(!TI);
  181.                 TI=0;
  182.         }
  183. }                               
  184. /*******************************串口發(fā)送函數(shù) ********************************/
  185. void Begin_send(void)
  186. {
  187.         b485Send = 1;      //處于發(fā)送
  188.         uartsends(sendBuf,sendCount);
  189.         b485Send = 0;              //發(fā)送完后將485置于接收狀態(tài)
  190.     receCount = 0;   //清接收地址偏移寄存器
  191. }


  192. //fuction:01 讀單個或多個線圈狀態(tài)
  193. void readCoils(void)
  194. {
  195. uint addr;
  196. uint tempAddr;
  197. uint byteCount;
  198. uint  bitCount;
  199. uint crcData;
  200. uint  position;
  201. uint  i,k;
  202. uint tempData;
  203. uchar  exit = 0;
  204. addr = (receBuf[2]<<8) + receBuf[3];
  205. tempAddr = addr;
  206. bitCount = (receBuf[4]<<8) + receBuf[5]; //讀取的位個數(shù)
  207. byteCount = bitCount / 8;    //字節(jié)個數(shù)
  208. if(bitCount%8 != 0)
  209.   byteCount++;      
  210.   for(k=0;k<byteCount;k++)//字節(jié)位置
  211.   {
  212.     position = k + 3;
  213.     sendBuf[position] = 0;
  214.     for(i=0;i<8;i++)
  215.     {
  216.       getCoilVal(tempAddr,&tempData);
  217.       sendBuf[position] |= tempData << i;
  218.       tempAddr++;
  219.       if(tempAddr >= addr+bitCount)//讀完
  220.       {
  221.         exit = 1;
  222.         break;
  223.       }
  224.     }
  225.     if(exit == 1)
  226.     break;
  227.   }
  228.   sendBuf[0] = LocalAddr;
  229.   sendBuf[1] = 0x01;
  230.   sendBuf[2] = byteCount;
  231.   byteCount += 3;
  232.   crcData = crc16(sendBuf,byteCount);
  233.   sendBuf[byteCount] = crcData & 0xff;
  234.   byteCount++;
  235.   sendBuf[byteCount] = crcData >> 8;
  236.   sendCount = byteCount + 1;
  237.   Begin_send();   
  238. }

  239. //fuction:02 讀取線圈輸入(只讀寄存器)狀態(tài)
  240. void readInPutCoils(void)
  241. {
  242. uint addr;
  243. uint tempAddr;
  244. uint byteCount;
  245. uint  bitCount;
  246. uint crcData;
  247. uint  position;
  248. uint  i,k;
  249. uint tempData;
  250. uchar  exit = 0;
  251. addr = (receBuf[2]<<8) + receBuf[3];
  252. tempAddr = addr +10000;        //只讀線圈寄存器偏移地址10000
  253. bitCount = (receBuf[4]<<8) + receBuf[5]; //讀取的位個數(shù)
  254. byteCount = bitCount / 8;    //字節(jié)個數(shù)
  255. if(bitCount%8 != 0)
  256.   byteCount++;      
  257.   for(k=0;k<byteCount;k++)//字節(jié)位置
  258.   {
  259.     position = k + 3;
  260.     sendBuf[position] = 0;
  261.     for(i=0;i<8;i++)
  262.     {
  263.       getCoilVal(tempAddr,&tempData);
  264.       sendBuf[position] |= tempData << i;
  265.       tempAddr++;
  266.       if(tempAddr >= addr+bitCount)//讀完
  267.       {
  268.         exit = 1;
  269.         break;
  270.       }
  271.     }
  272.     if(exit == 1)
  273.     break;
  274.   }
  275.   sendBuf[0] = LocalAddr;
  276.   sendBuf[1] = 0x02;
  277.   sendBuf[2] = byteCount;
  278.   byteCount += 3;
  279.   crcData = crc16(sendBuf,byteCount);
  280.   sendBuf[byteCount] = crcData & 0xff;
  281.   byteCount++;
  282.     sendBuf[byteCount] = crcData >> 8;
  283.   sendCount = byteCount + 1;
  284.   Begin_send();   
  285. }

  286. /********function code : 03,讀取多個寄存器值 ********/

  287. void readRegisters(void)
  288. {
  289.         uint addr;
  290.         uint tempAddr;
  291.         uint crcData;
  292.         uint readCount;
  293.         uint byteCount;
  294.         uint i;
  295.         uint tempData = 0;
  296.         addr = (receBuf[2]<<8) + receBuf[3];
  297.         tempAddr = addr+40000;      //+40000,保持寄存器偏移地址
  298.         readCount = (receBuf[4]<<8) + receBuf[5]; //要讀的個數(shù) ,整型
  299.         byteCount = readCount * 2;                  //每個寄存器內(nèi)容占高,低兩個字節(jié)
  300.         for(i=0;i<byteCount;i+=2,tempAddr++)
  301.         {
  302.               getRegisterVal(tempAddr,&tempData);   
  303.               sendBuf[i+3] = tempData >> 8;        
  304.               sendBuf[i+4] = tempData & 0xff;  
  305.         }
  306.         sendBuf[0] = LocalAddr;
  307.         sendBuf[1] = 3;  //function code : 03
  308.         sendBuf[2] = byteCount;
  309.         byteCount += 3;             //加上前面的地址,功能碼,地址 共3+byteCount個字節(jié)
  310.         crcData = crc16(sendBuf,byteCount);
  311.         sendBuf[byteCount] = crcData & 0xff;   // CRC代碼低位在前
  312.         byteCount++;
  313.         sendBuf[byteCount] = crcData >> 8 ;           //高位在后
  314.         sendCount = byteCount + 1;                        //例如byteCount=49,則sendBuf[]中實際上有49+1個元素待發(fā)
  315.         Begin_send();
  316. }
  317. //fuction 04:讀取輸入寄存器
  318. void readInPutRegisters(void)
  319. {
  320.         uint addr;
  321.         uint tempAddr;
  322.         uint crcData;
  323.         uint readCount;
  324.         uint byteCount;
  325.         uint i;
  326.         uint tempData = 0;
  327.         addr = (receBuf[2]<<8) + receBuf[3];
  328.         tempAddr = addr+30000;  //+輸入寄存器偏移地址:30000
  329.         readCount = (receBuf[4]<<8) + receBuf[5]; //要讀的個數(shù) ,整型
  330.         byteCount = readCount * 2;                  //每個寄存器內(nèi)容占高,低兩個字節(jié)
  331.         for(i=0;i<byteCount;i+=2,tempAddr++)
  332.         {
  333.               getRegisterVal(tempAddr,&tempData);   
  334.               sendBuf[i+3] = tempData >> 8;        
  335.               sendBuf[i+4] = tempData & 0xff;  
  336.         }
  337.         sendBuf[0] = LocalAddr;
  338.         sendBuf[1] = 4;  //function code : 04
  339.         sendBuf[2] = byteCount;
  340.         byteCount += 3;             //加上前面的地址,功能碼,地址 共3+byteCount個字節(jié)
  341.         crcData = crc16(sendBuf,byteCount);
  342.         sendBuf[byteCount] = crcData & 0xff;   // CRC代碼低位在前
  343.         byteCount++;
  344.         sendBuf[byteCount] = crcData >> 8 ;           //高位在后
  345.         sendCount = byteCount + 1;                        //例如byteCount=49,則sendBuf[]中實際上有49+1個元素待發(fā)
  346.         Begin_send();
  347. }
  348.          
  349. //fuction:05 ,強制單個線圈
  350. void forceSingleCoil(void)
  351. {
  352. uint addr;
  353. uint tempAddr;
  354. uint tempData;
  355. uint  onOff;
  356. uchar i;
  357. addr = (receBuf[2]<<8) + receBuf[3];
  358. tempAddr = addr;
  359. onOff = (receBuf[4]<<8) + receBuf[5];
  360. if(onOff == 0xff00)
  361. {
  362.   tempData = 1;//設(shè)為ON
  363. }
  364. else if(onOff == 0x0000)//設(shè)為OFF
  365. {
  366.   tempData = 0;
  367. }
  368. setCoilVal(tempAddr,tempData);
  369. for(i=0;i<receCount;i++)
  370. {
  371.   sendBuf[i] = receBuf[i];
  372. }
  373. sendCount = receCount;
  374. Begin_send();
  375. }

  376. /****************fuction:06設(shè)置單個寄存器ok**********************************************************/

  377. //主機器發(fā)送  地址,功能碼,寄存器高位,寄存器低位,數(shù)據(jù)數(shù)高位, 數(shù)數(shù)低位,CRC低位,CRC高位
  378. //例如設(shè)置D0 發(fā)送,        01      06         00            3F       00                         01                   */
  379. /*********************************************************************************/

  380. void presetSingleRegister(void)
  381. {
  382. uint addr;
  383. uint tempAddr;
  384. uint tempData;
  385. uint crcData;
  386. addr = (receBuf[2]<<8) + receBuf[3];
  387. tempAddr = (addr+40000);
  388. tempData = (receBuf[4]<<8) + receBuf[5];
  389. setRegisterVal(tempAddr,tempData);  
  390. sendBuf[0] = LocalAddr;
  391. sendBuf[1] = 6;    //function code : 16
  392. sendBuf[2] = addr >> 8;  //寄存器地址高位
  393. sendBuf[3] = addr & 0xff;//寄存器地址低位
  394. sendBuf[4] =receBuf[4];
  395. sendBuf[5] =receBuf[5];
  396. crcData = crc16(sendBuf,6);//生成CRC校驗碼
  397. sendBuf[6] = crcData & 0xff;  //CRC代碼低位在前
  398. sendBuf[7] = crcData >> 8;          //高位在后
  399. sendCount = 8;
  400. Begin_send();
  401. }

  402. /********從機響應(yīng)主機問詢函數(shù),function code : 15,強置多線圈值 *********/
  403. //////////////詢問數(shù)據(jù)包格式:
  404. ///////////////////////// receBuf[0] receBuf[1]  receBuf[2]     receBuf[3]   receBuf[4]    receBuf[5]   receBuf[6]  receBuf[7]  receBuf[8] ... receBuf[9]   receBuf[10]
  405. //詢問數(shù)據(jù)格式:receBuf[]={從站地址, 功能碼,  起始地址高位,起始地址低位,寄存器數(shù)高位,寄存器數(shù)低位, 字節(jié)計數(shù),  數(shù)據(jù)高位,  數(shù)據(jù)低位,... 校驗碼低位, 校驗碼高位}
  406. /****************************************************************************/
  407. void forceMultipleCoils(void)
  408. {
  409. uint addr;
  410. uint tempAddr;
  411. uint byteCount;
  412. uint  bitCount;
  413. uint crcData;
  414. uint tempData;
  415. uint  i,k;
  416. uchar  exit = 0;
  417. addr = (receBuf[2]<<8) + receBuf[3];
  418. tempAddr = addr;
  419. bitCount = (receBuf[4]<<8) + receBuf[5];
  420. byteCount = bitCount / 8;    //字節(jié)個數(shù)
  421. if(bitCount%8 != 0)
  422.   byteCount++;     
  423.   for(k=0;k<byteCount;k++)//字節(jié)位置
  424.   {
  425.     for(i=0;i<8;i++)
  426.     {
  427.       tempData = (receBuf[k+3] >>i)&0x01;  
  428.       setCoilVal(tempAddr,tempData);
  429.       tempAddr++;
  430.       if(tempAddr >= addr+bitCount)//讀完
  431.       {
  432.         exit = 1;
  433.         break;
  434.       }
  435.     }
  436.   
  437.     if(exit == 1)
  438.     break;
  439.   }
  440. sendBuf[0] = LocalAddr;
  441. sendBuf[1] = 15;    //function code : 16
  442. sendBuf[2] = addr >> 8;  //寄存器地址高位
  443. sendBuf[3] = addr & 0xff;//寄存器地址低位
  444. sendBuf[4] = bitCount >> 8;//待設(shè)置寄存器數(shù)量高位
  445. sendBuf[5] = bitCount & 0xff;//待設(shè)置寄存器數(shù)量低位
  446. crcData = crc16(sendBuf,6);//生成CRC校驗碼
  447. sendBuf[6] = crcData & 0xff;  //CRC代碼低位在前
  448. sendBuf[7] = crcData >> 8;          //高位在后
  449. sendCount = 8;
  450. Begin_send();
  451. }

  452. /********從機響應(yīng)主機問詢函數(shù),function code : 16,設(shè)置多個寄存器值 *********/
  453. //////////////詢問數(shù)據(jù)包格式:
  454. ///////////////////////// receBuf[0] receBuf[1]  receBuf[2]     receBuf[3]   receBuf[4]    receBuf[5]   receBuf[6]  receBuf[7]  receBuf[8] ... receBuf[9]   receBuf[10]
  455. //詢問數(shù)據(jù)格式:receBuf[]={從站地址, 功能碼,  起始地址高位,起始地址低位,寄存器數(shù)高位,寄存器數(shù)低位, 字節(jié)計數(shù),  數(shù)據(jù)高位,  數(shù)據(jù)低位,... 校驗碼低位, 校驗碼高位}
  456. /****************************************************************************/
  457. void presetMultipleRegisters(void)
  458. {
  459. uint addr;
  460. uint tempAddr;
  461. uint setCount;
  462. uint crcData;
  463. uint tempData;
  464. uchar i;
  465. addr = (receBuf[2]<<8) + receBuf[3];
  466. tempAddr = addr+40000;
  467. setCount = (receBuf[4]<<8) + receBuf[5];
  468. for(i=0;i<setCount;i++,tempAddr++)
  469. {
  470.   tempData = (receBuf[i*2+7]<<8) + receBuf[i*2+8];//待設(shè)置寄存器值
  471.   setRegisterVal(tempAddr,tempData);  
  472. }
  473. sendBuf[0] = LocalAddr;
  474. sendBuf[1] = 16;    //function code : 16
  475. sendBuf[2] = addr >> 8;  //寄存器地址高位
  476. sendBuf[3] = addr & 0xff;//寄存器地址低位
  477. sendBuf[4] = setCount >> 8;//待設(shè)置寄存器數(shù)量高位
  478. sendBuf[5] = setCount & 0xff;//待設(shè)置寄存器數(shù)量低位
  479. crcData = crc16(sendBuf,6);//生成CRC校驗碼
  480. sendBuf[6] = crcData & 0xff;  //CRC代碼低位在前
  481. sendBuf[7] = crcData >> 8;          //高位在后
  482. sendCount = 8;
  483. Begin_send();
  484. }


  485. /*************************查詢uart接收的數(shù)據(jù)包內(nèi)容函數(shù) **************************/
  486. ////函數(shù)功能:叢機根據(jù)串口接收到的數(shù)據(jù)包receBuf[1]里面的內(nèi)容,即function code執(zhí)行相應(yīng)的命令
  487. /********************************************************************************/
  488. void checkComm0Modbus(void)                   //10ms內(nèi)必須響應(yīng)接收數(shù)據(jù)
  489. {
  490. uint crcData;
  491. uint tempData;
  492. uint temp;
  493. if(receCount > 4)                 //如果接收到數(shù)據(jù)
  494. {         
  495.   switch(receBuf[1])
  496.   {
  497. case 1:                                                                //讀取寄存器(一個或多個)
  498.    {         
  499.       if(receCount >= 8)  //從詢問數(shù)據(jù)包格式可知,receCount應(yīng)該等于8        ,接收完成一組數(shù)據(jù)應(yīng)該關(guān)閉接收中斷
  500.         {            
  501.           if(receBuf[0]==LocalAddr)   //核對地址
  502.             {         
  503.               crcData = crc16(receBuf,6);                     //核對校驗碼
  504.               temp=receBuf[7];
  505.               temp=(temp<<8)+receBuf[6];
  506.               if(crcData == temp)
  507.               if(receBuf[1] == 1)
  508.                 {
  509.                 readCoils();                        //讀取線圈輸出狀態(tài)(一個或多個)
  510.                 }
  511.                 receCount = 0;                                                                           
  512.              }       
  513.           
  514.         }      
  515.           break;
  516.       }
  517. case 2:                                                                //讀取寄存器(一個或多個)
  518.    {         
  519.       if(receCount >= 8)  //從詢問數(shù)據(jù)包格式可知,receCount應(yīng)該等于8        ,接收完成一組數(shù)據(jù)應(yīng)該關(guān)閉接收中斷
  520.         {            
  521.           if(receBuf[0]==LocalAddr)   //核對地址
  522.             {         
  523.               crcData = crc16(receBuf,6);                     //核對校驗碼
  524.               temp=receBuf[7];
  525.               temp=(temp<<8)+receBuf[6];
  526.               if(crcData == temp)
  527.               if(receBuf[1] == 2)
  528.                 {
  529.                 readInPutCoils();                        //讀取線圈輸入狀態(tài)(一個或多個)
  530.                 }
  531.                 receCount = 0;                                                                           
  532.              }       
  533.           
  534.         }      
  535.           break;
  536.       }   
  537.    case 3:                                                                //讀取寄存器(一個或多個)
  538.    {         
  539.       if(receCount >= 8)  //從詢問數(shù)據(jù)包格式可知,receCount應(yīng)該等于8        ,接收完成一組數(shù)據(jù)應(yīng)該關(guān)閉接收中斷
  540.         {            
  541.           if(receBuf[0]==LocalAddr)   //核對地址
  542.             {         
  543.               crcData = crc16(receBuf,6);                     //核對校驗碼
  544.               temp=receBuf[7];
  545.               temp=(temp<<8)+receBuf[6];
  546.               if(crcData == temp)
  547.               if(receBuf[1] == 3)
  548.               {
  549.                 readRegisters();                        //讀取保持寄存器(一個或多個)
  550.                }
  551.                 receCount = 0;                                                                           
  552.             }                  
  553.         }      
  554.         break;
  555.    }
  556. case 4:                                                                //讀取寄存器(一個或多個)
  557.    {         
  558.       if(receCount >= 8)  //從詢問數(shù)據(jù)包格式可知,receCount應(yīng)該等于8        ,接收完成一組數(shù)據(jù)應(yīng)該關(guān)閉接收中斷
  559.       {            
  560.           if(receBuf[0]==LocalAddr)   //核對地址
  561.           {         
  562.             crcData = crc16(receBuf,6);                     //核對校驗碼
  563.             temp=receBuf[7];
  564.             temp=(temp<<8)+receBuf[6];
  565.             if(crcData == temp)
  566.             if(receBuf[1] == 4)
  567.               {
  568.               readInPutRegisters();                        //讀取輸入寄存器(一個或多個)
  569.               }
  570.                 receCount = 0;                                                                           
  571.           }       
  572.           
  573.       }      
  574.           break;
  575.     }
  576.    case 5:                                                                //讀取寄存器(一個或多個)
  577.    {         
  578.       if(receCount >= 8)  //從詢問數(shù)據(jù)包格式可知,receCount應(yīng)該等于8        ,接收完成一組數(shù)據(jù)應(yīng)該關(guān)閉接收中斷
  579.       {            
  580.           if(receBuf[0]==LocalAddr)   //核對地址
  581.           {         
  582.             crcData = crc16(receBuf,6);                     //核對校驗碼
  583.             temp=receBuf[7];
  584.             temp=(temp<<8)+receBuf[6];
  585.             if(crcData == temp)
  586.             if(receBuf[1] == 5)
  587.               {
  588.               forceSingleCoil();                        //強置單個線圈 狀態(tài)
  589.               }
  590.                 receCount = 0;                                                                           
  591.           }       
  592.           
  593.       }      
  594.           break;
  595.     }
  596. case 6: if(receCount >= 8)
  597.            {   
  598.              if(receBuf[0]==LocalAddr)
  599.                   {
  600.                     crcData = crc16(receBuf,6);
  601.                     temp=receBuf[7];
  602.                     temp=(temp<<8)+receBuf[6];
  603.                     if(crcData == temp)
  604.                     if(receBuf[1] == 6)
  605.                       {
  606.                           presetSingleRegister();      //預(yù)置單個保持寄存器
  607.                         //  SaveSetupDataToFlash();   //保存設(shè)置數(shù)據(jù)  
  608.                       }
  609.                     receCount = 0;                                                                                                                                         
  610.                  }         
  611.           }
  612.                  break;
  613. case 15://設(shè)置多個線圈
  614.       tempData = receBuf[6];
  615.       tempData += 9; //數(shù)據(jù)個數(shù)
  616.       if(receCount >= tempData)
  617.       {
  618.           if(receBuf[0]==LocalAddr )
  619.             {
  620.                 crcData = crc16(receBuf,tempData-2);
  621.               if(crcData == (receBuf[tempData-1]<<8)+ receBuf[tempData-2])//更改了??
  622.                 {
  623.                   forceMultipleCoils();  
  624.                  // SaveSetupDataToFlash();   //保存設(shè)置數(shù)據(jù)  
  625.                 }
  626.             }
  627.                   receCount = 0;
  628.         }
  629.       break;        
  630.   case 16:                                                //設(shè)置多個寄存器
  631.    {
  632.         tempData = (receBuf[4]<<8) + receBuf[5];                 //設(shè)置寄存器個數(shù)
  633.         tempData = tempData * 2;                                                 //數(shù)據(jù)個數(shù)=        寄存器*2
  634.         tempData += 9;       //從詢問數(shù)據(jù)包格式可知,receCount應(yīng)該等于9+byteCount
  635.         if(receCount >= tempData)
  636.           {         
  637.             if(receBuf[0]==LocalAddr )        //核對地址
  638.                 {         
  639.                   crcData = crc16(receBuf,tempData-2);
  640.                      temp=receBuf[tempData-1];
  641.                   temp=(temp<<8)+receBuf[tempData-2];
  642.                   if(crcData == temp)
  643.                     {  
  644.                     presetMultipleRegisters();  
  645.                     //SaveSetupDataToFlash();   //保存設(shè)置數(shù)據(jù)
  646.                     }
  647.                 }
  648.               receCount = 0;
  649.             }
  650.         break;
  651.       }   
  652.   default: break;  
  653.   }
  654. }
  655. }

  656. ……………………

  657. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
MODBUS-51工程版從機.rar (3.71 MB, 下載次數(shù): 779)



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

使用道具 舉報

沙發(fā)
ID:1 發(fā)表于 2018-10-1 23:10 | 只看該作者
補全原理圖或者詳細說明一下電路連接即可獲得100+黑幣
回復(fù)

使用道具 舉報

板凳
ID:199427 發(fā)表于 2018-10-2 08:39 | 只看該作者
謝謝樓主提供的源碼!請問樓主,該源碼在硬件上測試過嗎?
回復(fù)

使用道具 舉報

地板
ID:237723 發(fā)表于 2018-10-2 08:50 | 只看該作者
挺不錯 學(xué)習(xí)學(xué)習(xí)!
回復(fù)

使用道具 舉報

5#
ID:25103 發(fā)表于 2018-10-4 19:38 | 只看該作者

謝謝樓主提供的源碼!謝謝!!
回復(fù)

使用道具 舉報

6#
ID:188720 發(fā)表于 2018-10-20 15:25 | 只看該作者
有沒有51單片機做主機的例程?
回復(fù)

使用道具 舉報

7#
ID:3802 發(fā)表于 2019-1-8 17:56 | 只看該作者
好資料,51黑有你更精彩!!!
回復(fù)

使用道具 舉報

8#
ID:514327 發(fā)表于 2019-4-17 10:25 | 只看該作者
值得借鑒
回復(fù)

使用道具 舉報

9#
ID:578008 發(fā)表于 2019-7-25 14:32 | 只看該作者
紅燒魚頭 發(fā)表于 2018-10-20 15:25
有沒有51單片機做主機的例程?

現(xiàn)在有了碼?
回復(fù)

使用道具 舉報

10#
ID:57896 發(fā)表于 2019-7-25 21:31 | 只看該作者
其實這個資料很不錯的
回復(fù)

使用道具 舉報

11#
ID:111310 發(fā)表于 2019-7-26 11:32 | 只看該作者
我想看看學(xué)習(xí),不知道能不能下載下來
回復(fù)

使用道具 舉報

12#
ID:531445 發(fā)表于 2019-7-31 17:01 | 只看該作者
這個資料很不錯的
回復(fù)

使用道具 舉報

13#
ID:593904 發(fā)表于 2019-8-22 06:12 來自手機 | 只看該作者
學(xué)習(xí)資料很好
回復(fù)

使用道具 舉報

14#
ID:384870 發(fā)表于 2019-9-5 06:51 | 只看該作者
謝謝分享,我測試一下
回復(fù)

使用道具 舉報

15#
ID:514317 發(fā)表于 2019-9-5 08:17 | 只看該作者
這個有點復(fù)雜    還弄不清楚
回復(fù)

使用道具 舉報

16#
ID:149389 發(fā)表于 2019-9-7 09:05 來自手機 | 只看該作者
很好的參考資料
回復(fù)

使用道具 舉報

17#
ID:608128 發(fā)表于 2019-9-7 11:23 | 只看該作者
很完整,很有用,值得參考
回復(fù)

使用道具 舉報

18#
ID:428400 發(fā)表于 2019-9-28 19:46 | 只看該作者
這個資料好!謝謝
回復(fù)

使用道具 舉報

19#
ID:500625 發(fā)表于 2019-11-15 11:11 | 只看該作者
感謝分享
回復(fù)

使用道具 舉報

20#
ID:602896 發(fā)表于 2019-11-23 16:37 | 只看該作者
很好找了好久啊
回復(fù)

使用道具 舉報

21#
ID:33452 發(fā)表于 2019-12-4 08:29 | 只看該作者
很好找了好久啊
回復(fù)

使用道具 舉報

22#
ID:748018 發(fā)表于 2020-5-14 19:21 來自手機 | 只看該作者
謝謝樓主的分享
回復(fù)

使用道具 舉報

23#
ID:611470 發(fā)表于 2020-5-14 19:40 來自手機 | 只看該作者
資料很好,感謝分享
回復(fù)

使用道具 舉報

24#
ID:381027 發(fā)表于 2020-5-21 16:50 | 只看該作者
這個程序下載到單片機上直接通過485通信就可以和上位機的主站通信了嗎?那主站要怎么設(shè)置啊。
回復(fù)

使用道具 舉報

25#
ID:768413 發(fā)表于 2020-6-3 14:40 | 只看該作者
很不錯的學(xué)習(xí)資料
回復(fù)

使用道具 舉報

26#
ID:348695 發(fā)表于 2020-6-25 12:06 | 只看該作者
謝謝樓主提供的源碼!
回復(fù)

使用道具 舉報

27#
ID:564550 發(fā)表于 2020-11-13 20:33 | 只看該作者
正在搞焊接的通訊板,借樓主資源 多謝!~
回復(fù)

使用道具 舉報

28#
ID:81560 發(fā)表于 2020-12-7 03:37 | 只看該作者
正需要這個資料,非常感謝!
回復(fù)

使用道具 舉報

29#
ID:220936 發(fā)表于 2021-1-20 19:41 | 只看該作者
好資料,感謝樓主分享,不知在工程上能否使用
回復(fù)

使用道具 舉報

30#
ID:898951 發(fā)表于 2021-3-31 15:13 | 只看該作者
不知道 能不能驗證
回復(fù)

使用道具 舉報

31#
ID:307784 發(fā)表于 2022-3-15 07:16 來自手機 | 只看該作者
好資料,可以測試下
回復(fù)

使用道具 舉報

32#
ID:77589 發(fā)表于 2023-6-26 17:36 | 只看該作者
好資料,51黑有你更精彩!!!
回復(fù)

使用道具 舉報

33#
ID:166646 發(fā)表于 2023-7-12 11:51 | 只看該作者
很好的資料,謝謝
回復(fù)

使用道具 舉報

34#
ID:216265 發(fā)表于 2023-8-11 15:05 | 只看該作者
不錯,謝謝樓主提供的從機代碼
回復(fù)

使用道具 舉報

35#
ID:143914 發(fā)表于 2023-9-6 21:31 來自手機 | 只看該作者
感謝大佬,剛接觸modbus,受益匪淺
回復(fù)

使用道具 舉報

36#
ID:933601 發(fā)表于 2023-11-9 20:26 | 只看該作者
感謝樓主無私開源
回復(fù)

使用道具 舉報

37#
ID:636442 發(fā)表于 2024-1-3 15:25 | 只看該作者
感謝技術(shù)資料分享。很有參考用處。
回復(fù)

使用道具 舉報

38#
ID:50577 發(fā)表于 2025-1-16 15:55 | 只看該作者
#include "modbus.h" #include "resister.h"這兩個庫在哪里去了
回復(fù)

使用道具 舉報

39#
ID:277290 發(fā)表于 2025-1-18 08:19 | 只看該作者
很好的MODBUS學(xué)習(xí)資料,感謝分享!
回復(fù)

使用道具 舉報

40#
ID:1126676 發(fā)表于 2025-2-11 09:33 | 只看該作者
感謝樓主的分享! 大概看了一下。值得大家下載研究
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 国产高清在线观看 | 福利视频三区 | 美女久久视频 | 午夜网址 | 精品欧美一区免费观看α√ | 亚洲精品三级 | 欧美国产日本一区 | 日韩一级免费电影 | 欧洲精品一区 | 国产精品久久久久久妇女 | 欧美2区 | 伊人免费视频二 | 国产一级片网站 | 日本不卡一区 | 成人精品鲁一区一区二区 | 久草精品在线 | 69视频在线播放 | 精品综合视频 | 精品视频 免费 | 欧美a级成人淫片免费看 | 欧美13videosex性极品 | 中文字幕一区二区三区不卡 | 免费久久视频 | 狠狠综合久久av一区二区小说 | 亚洲精品国产电影 | 免费在线一区二区三区 | 国产成人在线观看免费 | av毛片 | 亚洲第一免费播放区 | 人人看人人射 | 黄色一级大片在线免费看产 | 成人精品鲁一区一区二区 | 日韩精品一区二区三区 | 日本色高清| 97超级碰碰 | 4h影视| 国产乱码高清区二区三区在线 | 中文字幕一区二区三区乱码在线 | 国产欧美在线 | 亚洲乱码一区二区三区在线观看 | 国产免费一区二区 |