半成品MODBUS RTU协议+组态王上位机+SHT11 Proteus仿真

2020-01-13 18:39发布

本帖最后由 slzm40 于 2014-7-3 21:17 编辑

  终归是半成品,数据也没做储存,SHT11也没有软件校准,纯读出。只为调MODBUS RTU协议,控制也乱七八糟的。 在这里也学习了有两年之久,发一发顺便有什么错误的地方求指点,以便进步。
   整个东西在Proteus+keil4+组态王6.55+虚拟串口工具仿真出来,程序没做任何数据储存,本机地址上电初始化为0x01,可设置但掉电后重新上电为01,我没有用EEPROM。
  总而言之,完全是做调试用。简单不能再简单了,手上已有SHT11的模块了,打算过些时间做个板子实测下,然后再做软件校准和一些未做完的事(比如数据储存,上位机完善,多机通信,主机板和主机程序)
        功能和协议
          5.jpg (166.97 KB, 下载次数: 0) 下载附件 2014-7-3 21:04 上传
        上MODBUS 的协议解码部份。
  1. void ModbusHandle(void)
  2. {
  3.         INT16U crctemp,crctemp1;
  4.         INT8U addr,readCount,temp,crx;
  5.         INT8U RXBUF[MAX_RXLenth];
  6.         if(UARTMod.fRx)//接收完毕
  7.         {
  8.         crx=UARTMod.Crx;
  9.         memset(RXBUF,00,sizeof(RXBUF));//清空缓冲区
  10.         memcpy(RXBUF,&UARTMod.RxBuffer[0],crx+1);//数据拷贝,这样就可以让UART重新接收数据了
  11.         memset(&UARTMod,00,sizeof(UARTMod));//将UARTMod清空,可重新接收数据
  12.         //UARTMod.fRx=FALSE;//让接收器进行接收
  13.        
  14.         if(RXBUF[0]!=LOCAL_ADD)//不是本机地址返回不处理
  15.                 {
  16.                 return;
  17.                 }
  18.         crctemp=UpdateCRC(&RXBUF[0],crx-2);//CRC校验
  19.         crctemp1=RXBUF[crx-2]<<8|RXBUF[crx-1];
  20.         if((crctemp-crctemp1)!=0)//检验检验是否正确
  21.                 {
  22.                 return;
  23.                 }
  24.         switch(RXBUF[1])//功能码
  25.                 {
  26.                 case 0x01:        //读取输出线圈状态
  27.                                         //slaveADD+funID+  ioADD_H+ioADD_L  +  ioNUM_H+ioNUM_L  +  crc_H+crc_L
  28.                                         //slaveADD+funID+  NUM  +  数据(NUM)  +  crc_H+crc_L       
  29.                                          addr=RXBUF[3];          //获取起始地址
  30.                                             readCount =RXBUF[5];//获取读取线圈个数
  31.                                         if(addr>(OXNum*8-1)||readCount>(OXNum*8-addr)) return;       
  32.                                         //应答处理
  33.                                         UARTMod.TxBuffer[0]=LOCAL_ADD;//地址
  34.                                             UARTMod.TxBuffer[1]=0x01;//功能码
  35.                                            
  36.                                             //因为只设计16个输出线圈,所以
  37.                                             if(readCount>8)  UARTMod.TxBuffer[2]=2; //字节计数
  38.                                          else  UARTMod.TxBuffer[2]=1;
  39.                                          
  40.                                         crctemp=(OX[1]<<8)|OX[0];//输出线圈统一
  41.                                            crctemp=crctemp>>addr;
  42.                                             if(readCount>8)
  43.                                                      {
  44.                                                 UARTMod.TxBuffer[3]=crctemp&0xff;//低
  45.                                                 temp=0xff;
  46.                                                 temp=temp<<(readCount-8);
  47.                                                 temp=~temp;
  48.                                                 crctemp=crctemp>>8;
  49.                                                 crctemp=temp&crctemp;
  50.                                                 UARTMod.TxBuffer[4]=crctemp&0xff;//高
  51.                                                 crctemp=UpdateCRC(&UARTMod.TxBuffer[0],5);
  52.                                                 UARTMod.TxBuffer[5]=crctemp>>8;
  53.                                                 UARTMod.TxBuffer[6]=crctemp&0xff;                                                           
  54.                                                 USART_send_string(7);
  55.                                                      }
  56.                                             else
  57.                                                     {
  58.                                                         temp=0xff;
  59.                                                         temp=temp<<readCount;
  60.                                                         temp=~temp;
  61.                                                         crctemp=crctemp&temp;
  62.                                                         UARTMod.TxBuffer[3]=crctemp&0xff;
  63.                                                         crctemp=UpdateCRC(&UARTMod.TxBuffer[0],4);//发送数据CRC校验
  64.                                                         UARTMod.TxBuffer[4]=crctemp>>8;//校验高8位
  65.                                                         UARTMod.TxBuffer[5]=crctemp&0xff;//校验低8位                                                           
  66.                                                               USART_send_string(6);//发送回应
  67.                                                     }
  68.                                 break;
  69.                 case 0x02:                //读取输入线圈状态
  70.                                                 //slaveADD+funID+  ioADD_H+ioADD_L  +  ioNUM_H+ioNUM_L  +  crc_H+crc_L
  71.                                                 //slaveADD+funID+  NUM  +  数据(NUM)  +  crc_H+crc_L       
  72.                                                  addr=RXBUF[3];          //获取起始地址 (不同于寄存器)
  73.                                                     readCount =RXBUF[5];//获取读取线圈个数
  74.                                                 if(addr>(OXNum*8-1)||readCount>(OXNum*8-addr)) return;       
  75.                                                 //应答处理
  76.                                                 UARTMod.TxBuffer[0]=LOCAL_ADD;//地址
  77.                                                     UARTMod.TxBuffer[1]=0x01;//功能码
  78.                                                     //因为只设计16个线圈,所以
  79.                                                     if(readCount>8)  UARTMod.TxBuffer[2]=2; //字节计数
  80.                                                  else  UARTMod.TxBuffer[2]=1;
  81.                                                  
  82.                                                 crctemp=(IX[1]<<8)|IX[0];//输入线圈统一
  83.                                                    crctemp=crctemp>>addr;
  84.                                                     if(readCount>8)
  85.                                                              {
  86.                                                         UARTMod.TxBuffer[3]=crctemp&0xff;//低
  87.                                                         temp=0xff;
  88.                                                         temp=temp<<(readCount-8);
  89.                                                         temp=~temp;
  90.                                                         crctemp=crctemp>>8;
  91.                                                         crctemp=temp&crctemp;
  92.                                                         UARTMod.TxBuffer[4]=crctemp&0xff;//高
  93.                                                         crctemp=UpdateCRC(&UARTMod.TxBuffer[0],5);
  94.                                                         UARTMod.TxBuffer[5]=crctemp>>8;
  95.                                                         UARTMod.TxBuffer[6]=crctemp&0xff;                                                           
  96.                                                         USART_send_string(7);
  97.                                                              }
  98.                                                     else
  99.                                                             {
  100.                                                                 temp=0xff;
  101.                                                                 temp=temp<<readCount;
  102.                                                                 temp=~temp;
  103.                                                                 crctemp=crctemp&temp;
  104.                                                                 UARTMod.TxBuffer[3]=crctemp&0xff;
  105.                                                                 crctemp=UpdateCRC(&UARTMod.TxBuffer[0],4);//发送数据CRC校验
  106.                                                                 UARTMod.TxBuffer[4]=crctemp>>8;//校验高8位
  107.                                                                 UARTMod.TxBuffer[5]=crctemp&0xff;//校验低8位                                                           
  108.                                                                       USART_send_string(6);//发送回应
  109.                                                             }
  110.                                         break;
  111.                 case 0x03:                //读取保持寄存器
  112.                                                 //slaveADD+funID+datADD_H+dataADD_L+regNUM_H+regNUM_L+crc_H+crc_L
  113.                                                 //slaveADD+funID+2*regNUM+数据(2*regNUM个BYTE)+crc_H+crc_L
  114.                                                 //                                                低地址数据->高地址数据(DAT_H+DAT_L)
  115.                                                 //slaveADD+(funID|0x80)+01(02,03,04)+crc_H+crc_L
  116.                                                 addr=RXBUF[3];          //要读的地址 0~16
  117.                                                 readCount =RXBUF[5];  //要读的个数(16位)
  118.                                                 if(addr>(HoldDataNum-1)||readCount>(HoldDataNum-addr)||readCount>125) return;
  119.                                                 //应答处理
  120.                                                 UARTMod.TxBuffer[0]=LOCAL_ADD;     //目标机地址
  121.                                                 UARTMod.TxBuffer[1]=0x03;          //功能码
  122.                                                 UARTMod.TxBuffer[2]=readCount*2;   //返回字节个数(8位)
  123.                                                 for(temp=0;temp<readCount;temp++)  //低地址数据在前
  124.                                                         {
  125.                                                         UARTMod.TxBuffer[temp*2+3]=(HoldDataReg[temp+addr]>>8)&0xff;//数据高字节在前
  126.                                                         UARTMod.TxBuffer[temp*2+4]=HoldDataReg[temp+addr]&0xff;//数据低字节在前
  127.                                                         }//数据
  128.                                                 crctemp=UpdateCRC(&UARTMod.TxBuffer[0],readCount*2+3);  //求CRC
  129.                                                 UARTMod.TxBuffer[readCount*2+3]=crctemp>>8;
  130.                                                 UARTMod.TxBuffer[readCount*2+4]=crctemp&0xff;                                                            
  131.                                                 USART_send_string(readCount*2+5);
  132.                                 break;
  133.                 case 0x04:                //读取输入寄存器
  134.                                                 //slaveADD+funID+  datADD_H+dataADD_L  +  regNUM_H+regNUM_L   +   crc_H+crc_L
  135.                                                 //slaveADD+funID+2*regNUM+数据(2*regNUM个BYTE)   +   crc_H+crc_L
  136.                                                 //                                                低地址数据->高地址数据(DAT_H+DAT_L)
  137.                                                 //slaveADD+(funID|0x80)+01(02,03,04)+crc_H+crc_L
  138.                                                 addr=RXBUF[3];          //要读的地址 0~HoldDataNum-1
  139.                                                 readCount =RXBUF[5];  //要读的个数(16位)<=125
  140.                                                 if(addr>(InDataNum-1)||readCount>(InDataNum-addr)||readCount>125) return;
  141.                                                 //应答处理
  142.                                                 UARTMod.TxBuffer[0]=LOCAL_ADD;     //目标机地址
  143.                                                 UARTMod.TxBuffer[1]=0x04;          //功能码
  144.                                                 UARTMod.TxBuffer[2]=readCount*2;   //返回字节个数(8位)
  145.                                                 for(temp=0;temp<readCount;temp++)  //低地址数据在前
  146.                                                         {
  147.                                                         UARTMod.TxBuffer[temp*2+3]=(InDataReg[temp+addr]>>8)&0xff;//数据高字节在前
  148.                                                         UARTMod.TxBuffer[temp*2+4]=InDataReg[temp+addr]&0xff;//数据低字节在前
  149.                                                         }//数据
  150.                                                 crctemp=UpdateCRC(&UARTMod.TxBuffer[0],readCount*2+3);  //求CRC
  151.                                                 UARTMod.TxBuffer[readCount*2+3]=crctemp>>8;
  152.                                                 UARTMod.TxBuffer[readCount*2+4]=crctemp&0xff;                                                            
  153.                                                 USART_send_string(readCount*2+5);
  154.                                 break;
  155.                 case 0x05:                //设置单个线圈
  156.                                                 //slaveADD+funID+  ioADD_H+ioADD_L  +  SETVAL_H  +        SETVAL_L +  crc_H+crc_L
  157.                                                 //原报文返回
  158.                                                 addr=RXBUF[3];    //获取起始地址 (不同于寄存器)
  159.                                                 temp=RXBUF[4];    //要设置的状态(0xff为ON,0x00为OFF)
  160.                                                 //以下为设置
  161.                                                 if(temp==0xff)        //置1
  162.                                                 {
  163.                                                         if(addr>=8)
  164.                                                                 {
  165.                                                                 temp=1<<(addr-8);
  166.                                                                 OX[1]=OX[1]|temp;
  167.                                                                 }
  168.                                                         else {
  169.                                                                 temp=1<<addr;
  170.                                                                 OX[0]=OX[0]|temp;
  171.                                                                 }
  172.                                                 }
  173.                                                 else                        //置0
  174.                                                 {
  175.                                                         if(addr>=8)
  176.                                                                 {
  177.                                                                 temp=1<<(addr-8);
  178.                                                                 temp=~temp;
  179.                                                                 OX[1]=OX[1]&temp;
  180.                                                                 }
  181.                                                         else
  182.                                                                 {
  183.                                                                 temp=1<<addr;
  184.                                                                 temp=~temp;
  185.                                                                 OX[0]=OX[0]&temp;
  186.                                                                 }
  187.                                                 }
  188.                                                
  189.                                                 //应答处理,原报文回应
  190.                                                 UARTMod.TxBuffer[0]=LOCAL_ADD;
  191.                                                 UARTMod.TxBuffer[1]=0x05;
  192.                                                 UARTMod.TxBuffer[2]=0x00;
  193.                                                 UARTMod.TxBuffer[3]=addr;
  194.                                                 UARTMod.TxBuffer[4]=RXBUF[4];
  195.                                                 UARTMod.TxBuffer[5]=RXBUF[5];
  196.                                                 UARTMod.TxBuffer[6]=RXBUF[6];
  197.                                                 UARTMod.TxBuffer[7]=RXBUF[7];                                                           
  198.                                                 USART_send_string(8);
  199.                                 break;
  200.                 case 0x06:                //设置单个寄存器
  201.                                                 //slaveADD+funID+  datADD_H+dataADD_L  +  datVAL_H+datVAL_L   +   crc_H+crc_L
  202.                                                 //slaveADD+funID+2*regNUM+数据(2*regNUM个BYTE)   +   crc_H+crc_L
  203.                                                 //                                                低地址数据->高地址数据(DAT_H+DAT_L)
  204.                                                 addr=RXBUF[3];          //要读的地址 0~HoldDataNum-1
  205.                                                 crctemp =RXBUF[4]<<8|RXBUF[5];  //要写的数据
  206.                                                 //以下为设置
  207.                                                 HoldDataReg[addr]=crctemp;
  208.                                                
  209.                                                 //应答处理,原报文回应
  210.                                                 UARTMod.TxBuffer[0]=LOCAL_ADD;
  211.                                                 UARTMod.TxBuffer[1]=0x06;
  212.                                                 UARTMod.TxBuffer[2]=0x00;
  213.                                                 UARTMod.TxBuffer[3]=addr;
  214.                                                 UARTMod.TxBuffer[4]=RXBUF[4];
  215.                                                 UARTMod.TxBuffer[5]=RXBUF[5];
  216.                                                 UARTMod.TxBuffer[6]=RXBUF[6];
  217.                                                 UARTMod.TxBuffer[7]=RXBUF[7];                                                           
  218.                                                 USART_send_string(8);               
  219.                                 break;
  220.                 case 0x0f:                //设置多个线圈
  221.                                 break;
  222.                 case 0x10:                //预置多个寄存器
  223.                                 break;
  224.                 default:                        //返回错误码(不支持功能号)
  225.                                 break;
  226.                 }                 
  227.         }

  228. }
复制代码

最后还是上附件吧。顺便问下,我有CC1101的两个无线模块,无线通信协议目前用哪种。或有没相关资料学习下
Humiture.pdf (55.11 KB, 下载次数: 76) 2014-7-3 21:16 上传 点击文件名下载附件
原理图


HumitureControl组态.zip (124.28 KB, 下载次数: 90) 2014-7-3 21:09 上传 点击文件名下载附件
组态王上位机部份


software.zip (248.17 KB, 下载次数: 87) 2014-7-3 21:09 上传 点击文件名下载附件
软件部份


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
12条回答
yklstudent
1楼-- · 2020-01-14 15:21
看起来好高端的组态王 mark
cqfeiyu
2楼-- · 2020-01-14 19:52
slzm40 发表于 2014-7-5 13:56
我在网上找的。好像只有破解65000个点。版本6.55,做了个小监控软件,监控温湿度已经有一个多星期了, ...

谢了,做试验用还是可以的
cqfeiyu
3楼-- · 2020-01-14 22:17
Modbus 还是建议用FreeModbus稳定
mdcao
4楼-- · 2020-01-15 01:43
hyf88
5楼-- · 2020-01-15 04:29
 精彩回答 2  元偷偷看……
hyf88
6楼-- · 2020-01-15 06:57
楼主继续完善弄成成品吧

一周热门 更多>