本帖最后由 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 的协议解码部份。
- void ModbusHandle(void)
- {
- INT16U crctemp,crctemp1;
- INT8U addr,readCount,temp,crx;
- INT8U RXBUF[MAX_RXLenth];
- if(UARTMod.fRx)//接收完毕
- {
- crx=UARTMod.Crx;
- memset(RXBUF,00,sizeof(RXBUF));//清空缓冲区
- memcpy(RXBUF,&UARTMod.RxBuffer[0],crx+1);//数据拷贝,这样就可以让UART重新接收数据了
- memset(&UARTMod,00,sizeof(UARTMod));//将UARTMod清空,可重新接收数据
- //UARTMod.fRx=FALSE;//让接收器进行接收
-
- if(RXBUF[0]!=LOCAL_ADD)//不是本机地址返回不处理
- {
- return;
- }
- crctemp=UpdateCRC(&RXBUF[0],crx-2);//CRC校验
- crctemp1=RXBUF[crx-2]<<8|RXBUF[crx-1];
- if((crctemp-crctemp1)!=0)//检验检验是否正确
- {
- return;
- }
- switch(RXBUF[1])//功能码
- {
- case 0x01: //读取输出线圈状态
- //slaveADD+funID+ ioADD_H+ioADD_L + ioNUM_H+ioNUM_L + crc_H+crc_L
- //slaveADD+funID+ NUM + 数据(NUM) + crc_H+crc_L
- addr=RXBUF[3]; //获取起始地址
- readCount =RXBUF[5];//获取读取线圈个数
- if(addr>(OXNum*8-1)||readCount>(OXNum*8-addr)) return;
- //应答处理
- UARTMod.TxBuffer[0]=LOCAL_ADD;//地址
- UARTMod.TxBuffer[1]=0x01;//功能码
-
- //因为只设计16个输出线圈,所以
- if(readCount>8) UARTMod.TxBuffer[2]=2; //字节计数
- else UARTMod.TxBuffer[2]=1;
-
- crctemp=(OX[1]<<8)|OX[0];//输出线圈统一
- crctemp=crctemp>>addr;
- if(readCount>8)
- {
- UARTMod.TxBuffer[3]=crctemp&0xff;//低
- temp=0xff;
- temp=temp<<(readCount-8);
- temp=~temp;
- crctemp=crctemp>>8;
- crctemp=temp&crctemp;
- UARTMod.TxBuffer[4]=crctemp&0xff;//高
- crctemp=UpdateCRC(&UARTMod.TxBuffer[0],5);
- UARTMod.TxBuffer[5]=crctemp>>8;
- UARTMod.TxBuffer[6]=crctemp&0xff;
- USART_send_string(7);
- }
- else
- {
- temp=0xff;
- temp=temp<<readCount;
- temp=~temp;
- crctemp=crctemp&temp;
- UARTMod.TxBuffer[3]=crctemp&0xff;
- crctemp=UpdateCRC(&UARTMod.TxBuffer[0],4);//发送数据CRC校验
- UARTMod.TxBuffer[4]=crctemp>>8;//校验高8位
- UARTMod.TxBuffer[5]=crctemp&0xff;//校验低8位
- USART_send_string(6);//发送回应
- }
- break;
- case 0x02: //读取输入线圈状态
- //slaveADD+funID+ ioADD_H+ioADD_L + ioNUM_H+ioNUM_L + crc_H+crc_L
- //slaveADD+funID+ NUM + 数据(NUM) + crc_H+crc_L
- addr=RXBUF[3]; //获取起始地址 (不同于寄存器)
- readCount =RXBUF[5];//获取读取线圈个数
- if(addr>(OXNum*8-1)||readCount>(OXNum*8-addr)) return;
- //应答处理
- UARTMod.TxBuffer[0]=LOCAL_ADD;//地址
- UARTMod.TxBuffer[1]=0x01;//功能码
- //因为只设计16个线圈,所以
- if(readCount>8) UARTMod.TxBuffer[2]=2; //字节计数
- else UARTMod.TxBuffer[2]=1;
-
- crctemp=(IX[1]<<8)|IX[0];//输入线圈统一
- crctemp=crctemp>>addr;
- if(readCount>8)
- {
- UARTMod.TxBuffer[3]=crctemp&0xff;//低
- temp=0xff;
- temp=temp<<(readCount-8);
- temp=~temp;
- crctemp=crctemp>>8;
- crctemp=temp&crctemp;
- UARTMod.TxBuffer[4]=crctemp&0xff;//高
- crctemp=UpdateCRC(&UARTMod.TxBuffer[0],5);
- UARTMod.TxBuffer[5]=crctemp>>8;
- UARTMod.TxBuffer[6]=crctemp&0xff;
- USART_send_string(7);
- }
- else
- {
- temp=0xff;
- temp=temp<<readCount;
- temp=~temp;
- crctemp=crctemp&temp;
- UARTMod.TxBuffer[3]=crctemp&0xff;
- crctemp=UpdateCRC(&UARTMod.TxBuffer[0],4);//发送数据CRC校验
- UARTMod.TxBuffer[4]=crctemp>>8;//校验高8位
- UARTMod.TxBuffer[5]=crctemp&0xff;//校验低8位
- USART_send_string(6);//发送回应
- }
- break;
- case 0x03: //读取保持寄存器
- //slaveADD+funID+datADD_H+dataADD_L+regNUM_H+regNUM_L+crc_H+crc_L
- //slaveADD+funID+2*regNUM+数据(2*regNUM个BYTE)+crc_H+crc_L
- // 低地址数据->高地址数据(DAT_H+DAT_L)
- //slaveADD+(funID|0x80)+01(02,03,04)+crc_H+crc_L
- addr=RXBUF[3]; //要读的地址 0~16
- readCount =RXBUF[5]; //要读的个数(16位)
- if(addr>(HoldDataNum-1)||readCount>(HoldDataNum-addr)||readCount>125) return;
- //应答处理
- UARTMod.TxBuffer[0]=LOCAL_ADD; //目标机地址
- UARTMod.TxBuffer[1]=0x03; //功能码
- UARTMod.TxBuffer[2]=readCount*2; //返回字节个数(8位)
- for(temp=0;temp<readCount;temp++) //低地址数据在前
- {
- UARTMod.TxBuffer[temp*2+3]=(HoldDataReg[temp+addr]>>8)&0xff;//数据高字节在前
- UARTMod.TxBuffer[temp*2+4]=HoldDataReg[temp+addr]&0xff;//数据低字节在前
- }//数据
- crctemp=UpdateCRC(&UARTMod.TxBuffer[0],readCount*2+3); //求CRC
- UARTMod.TxBuffer[readCount*2+3]=crctemp>>8;
- UARTMod.TxBuffer[readCount*2+4]=crctemp&0xff;
- USART_send_string(readCount*2+5);
- break;
- case 0x04: //读取输入寄存器
- //slaveADD+funID+ datADD_H+dataADD_L + regNUM_H+regNUM_L + crc_H+crc_L
- //slaveADD+funID+2*regNUM+数据(2*regNUM个BYTE) + crc_H+crc_L
- // 低地址数据->高地址数据(DAT_H+DAT_L)
- //slaveADD+(funID|0x80)+01(02,03,04)+crc_H+crc_L
- addr=RXBUF[3]; //要读的地址 0~HoldDataNum-1
- readCount =RXBUF[5]; //要读的个数(16位)<=125
- if(addr>(InDataNum-1)||readCount>(InDataNum-addr)||readCount>125) return;
- //应答处理
- UARTMod.TxBuffer[0]=LOCAL_ADD; //目标机地址
- UARTMod.TxBuffer[1]=0x04; //功能码
- UARTMod.TxBuffer[2]=readCount*2; //返回字节个数(8位)
- for(temp=0;temp<readCount;temp++) //低地址数据在前
- {
- UARTMod.TxBuffer[temp*2+3]=(InDataReg[temp+addr]>>8)&0xff;//数据高字节在前
- UARTMod.TxBuffer[temp*2+4]=InDataReg[temp+addr]&0xff;//数据低字节在前
- }//数据
- crctemp=UpdateCRC(&UARTMod.TxBuffer[0],readCount*2+3); //求CRC
- UARTMod.TxBuffer[readCount*2+3]=crctemp>>8;
- UARTMod.TxBuffer[readCount*2+4]=crctemp&0xff;
- USART_send_string(readCount*2+5);
- break;
- case 0x05: //设置单个线圈
- //slaveADD+funID+ ioADD_H+ioADD_L + SETVAL_H + SETVAL_L + crc_H+crc_L
- //原报文返回
- addr=RXBUF[3]; //获取起始地址 (不同于寄存器)
- temp=RXBUF[4]; //要设置的状态(0xff为ON,0x00为OFF)
- //以下为设置
- if(temp==0xff) //置1
- {
- if(addr>=8)
- {
- temp=1<<(addr-8);
- OX[1]=OX[1]|temp;
- }
- else {
- temp=1<<addr;
- OX[0]=OX[0]|temp;
- }
- }
- else //置0
- {
- if(addr>=8)
- {
- temp=1<<(addr-8);
- temp=~temp;
- OX[1]=OX[1]&temp;
- }
- else
- {
- temp=1<<addr;
- temp=~temp;
- OX[0]=OX[0]&temp;
- }
- }
-
- //应答处理,原报文回应
- UARTMod.TxBuffer[0]=LOCAL_ADD;
- UARTMod.TxBuffer[1]=0x05;
- UARTMod.TxBuffer[2]=0x00;
- UARTMod.TxBuffer[3]=addr;
- UARTMod.TxBuffer[4]=RXBUF[4];
- UARTMod.TxBuffer[5]=RXBUF[5];
- UARTMod.TxBuffer[6]=RXBUF[6];
- UARTMod.TxBuffer[7]=RXBUF[7];
- USART_send_string(8);
- break;
- case 0x06: //设置单个寄存器
- //slaveADD+funID+ datADD_H+dataADD_L + datVAL_H+datVAL_L + crc_H+crc_L
- //slaveADD+funID+2*regNUM+数据(2*regNUM个BYTE) + crc_H+crc_L
- // 低地址数据->高地址数据(DAT_H+DAT_L)
- addr=RXBUF[3]; //要读的地址 0~HoldDataNum-1
- crctemp =RXBUF[4]<<8|RXBUF[5]; //要写的数据
- //以下为设置
- HoldDataReg[addr]=crctemp;
-
- //应答处理,原报文回应
- UARTMod.TxBuffer[0]=LOCAL_ADD;
- UARTMod.TxBuffer[1]=0x06;
- UARTMod.TxBuffer[2]=0x00;
- UARTMod.TxBuffer[3]=addr;
- UARTMod.TxBuffer[4]=RXBUF[4];
- UARTMod.TxBuffer[5]=RXBUF[5];
- UARTMod.TxBuffer[6]=RXBUF[6];
- UARTMod.TxBuffer[7]=RXBUF[7];
- USART_send_string(8);
- break;
- case 0x0f: //设置多个线圈
- break;
- case 0x10: //预置多个寄存器
- break;
- default: //返回错误码(不支持功能号)
- break;
- }
- }
- }
复制代码
最后还是上附件吧。
顺便问下,我有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 上传
点击文件名下载附件
软件部份
谢了,做试验用还是可以的
一周热门 更多>