本帖最后由 garett 于 2014-8-2 17:15 编辑
MODBUS通讯协议。本人写了接收程序。大家一起来验证下。看看有没有什么问题个需要更改的地方。
求交流啊啊啊啊啊。每个功能的具体函数。都暂时控制的。因为还没想清楚用数组还是什么别的方法来控制。
/*获取StartAddr的第i个8位数据 不够补零*/
u8 GetByteData(u16 StartAdd,u16 i);
/*获取StartAddr的第i个数据*/
u16 GetData(u16 StartAdd,u16 i);
/*从StateAddr写入value 8位数据*/
void WriteForceState(u16 StateAddr,u8 value);
/*写寄存器值*/
void WriteRegister(u16 RegAddr,u16 RegData);
工程文件:
MODBUS_VER_1.0.zip
(991.87 KB, 下载次数: 2)
= =大家一起来纠错啊~~还有说说自己的看法啊。。求交流。。
- #define SlaveID 0x01 //主机地址
- #define ReadCoilState 1 //读取线圈状态
- #define ReadInputState 2 //读取输入状态
- #define ReadHoldRegister 3 //读取保持寄存器
- #define ReadInputRegister 4 //读取输入寄存器
- #define ForceSingleCoilOutputState 5 //强制写单线圈输出状态
- #define PresetSingleRegister 6 //预设(写)单寄存器
- #define CommIndexSlaveID 0 //地址
- #define CommIndexFunction 1 //功能码
- #define CommIndexStartAddrH 2 //起始地址高位
- #define CommIndexStartAddrL 3 //起始地址低位
- #define CommIndexForceState 4 //强制状态
- #define CommIndexDataH 4 //数据高位
- #define CommIndexDataL 5 //数据低位
- #define MaxRegisterLen 20 //寄存器最大长度
- #define MaxDataLen 30 //数据最大长度
- u8 CommIndexLength=0; //通信指针长度 在UART接收时设置
- u8 CommIndexEnd=0xff; //通信指针结束 在UART接收时设置
- u8 SendBuf[MaxDataLen]=0; //发送缓冲区
- u8 ReceiveBuf[MaxDataLen]=0; //接收缓冲区
- //接收处理
- void DisposeReceive(void)
- {
- u16 CRC16Temp; //CRC校验临时存储变量
- if(ReceiveBuf[CommIndexSlaveID]==SlaveID) //如果接收到的数据地址为从机地址
- {
- /*计算发送来的数据的CRC校验码*/
- CRC16Temp=GetCRC16(ReceiveBuf,CommIndexLength);
- /*验证计算出来的CRC校验值是否与缓冲区校验值相等*/
- if(CRC16Temp==((u16)ReceiveBuf[CommIndexEnd-1]<<8|(u16)ReceiveBuf[CommIndexEnd]))
- { /*CRC校验正确,数据无误*/
- switch(ReceiveBuf[CommIndexFunction])
- {
- case ReadCoilState: //1:读取线圈状态
- ReadCoil();
- break;
- case ReadInputState: //2:读取输入状态
- ReadInput();
- break;
- case ReadHoldRegister: //3读取保存寄存器
- ReadHoldReg();
- break;
- case ReadInputRegister: //4读取输入寄存器
- ReadInputReg();
- break;
- case ForceSingleCoilOutputState: //5强制写单线圈输出状态
- ForceSingleCoil();
- break;
- case PresetSingleRegister: //6预设(写)单寄存器
- PresetSingleReg();
- break;
- default:
- break;
- }
- }
- else //CRC校验错误
- {
- RequestRetry(); //请求主机重发指令
- }
- }
- }
- /*
- *功能码:0x01 读取线圈状态
- *发送:[硬件地址][01][起始地址高][起始地址低][总位数高][总位数低][CRC低][CRC高]
- *返回:[硬件地址][01][ 字节数 ][ 位状态1 ][位状态2 ][位状态n ][CRC低][CRC高]
- */
- void ReadCoil(void)
- {
- u16 StartAdd,BitNum,CRC16Temp,i;
- u8 CommIndexNum;
- StartAdd=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
- BitNum=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];
- BitNum=BitNum/8;
- if(BitNum%8!=0)
- BitNum++;
- SendBuf[CommIndexNum++]=SlaveID;
- SendBuf[CommIndexNum++]=ReadCoilState;
- SendBuf[CommIndexNum++]=(u8)BitNum;
- /*获取X位状态*/
- for(i=0;i<BitNum;i++)
- {
- /*获取StartAdd的第i个8位数据 不够补0*/
- SendBuf[CommIndexNum++]=GetByteData(StartAdd,i);
- }
- CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
- SendBuf[CommIndexNum++]=(u8)CRC16Temp>>8;
- SendBuf[CommIndexNum++]=(u8)CRC16Temp;
- //从SendBuf发送CommIndexNum个8位的返回数据
- Uart1_Send(SendBuf,CommIndexNum);
- //结束 清除缓冲区
- memset(SendBuf,0,sizeof(SendBuf));
- }
- /*
- *功能码:0x02 读取输入状态
- *发送:[硬件地址][02][起始地址高][起始地址低][总位数高][总位数低][CRC低][CRC高]
- *返回:[硬件地址][02][ 字节数 ][ 位状态1 ][位状态2 ][位状态n ][CRC低][CRC高]
- */
- void ReadInput(void)
- {
- u16 StartAdd,BitNum,CRC16Temp,i;
- u8 CommIndexNum=0;
- StartAdd=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
- BitNum=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];
- BitNum=BitNum/8;
- if(BitNum%8!=0)
- BitNum++;
- SendBuf[CommIndexNum++]=SlaveID;
- SendBuf[CommIndexNum++]=ReadInputState;
- SendBuf[CommIndexNum++]=(u8)BitNum;
- /*获取X位状态*/
- for(i=0;i<BitNum;i++)
- {
- /*获取StartAdd的第i个8位数据 不够补0*/
- SendBuf[CommIndexNum++]=GetByteData(StartAdd,i);
- }
- CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
- SendBuf[CommIndexNum++]=(u8)CRC16Temp>>8;
- SendBuf[CommIndexNum++]=(u8)CRC16Temp;
- //从SendBuf发送CommIndexNum个8位的返回数据
- Uart1_Send(SendBuf,CommIndexNum);
- //结束 清除缓冲区
- memset(SendBuf,0,sizeof(SendBuf));
- }
- /*
- *功能码:0x03 读取保持寄存器
- *发送:[硬件地址][03][起始地址高][起始地址低][总寄存器数高][总寄存器数低][ CRC低 ][ CRC高 ]
- *返回:[硬件地址][03][ 字节数 ][寄存器0高 ][ 寄存器0低 ][ 寄存器1高 ][ 寄存器1低 ][ 寄存器n高 ][ 寄存器n低 ][ CRC低 ][ CRC高 ]
- */
- void ReadHoldReg(void)
- {
- u16 StartAdd,RegLen,i,DataTemp,CRC16Temp;
- u8 CommIndexNum=0;
- //获取起始地址
- StartAdd=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
- //获取读取长度
- RegLen=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];
- SendBuf[CommIndexNum++]=SlaveID;
- SendBuf[CommIndexNum++]=ReadHoldRegister;
- SendBuf[CommIndexNum++]=(u8)(RegLen*2);
- for(i=0;i<RegLen;i++)
- {
- /*获取16位数据并返回赋给[寄存器n高][寄存器n低]*/
- DataTemp=GetData(StartAdd,i);
- SendBuf[CommIndexNum++] = (u8)(DataTemp>>8);
- SendBuf[CommIndexNum++] = (u8)(DataTemp&0x00ff);
- }
- CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
- SendBuf[CommIndexNum++]=(u8)(CRC16Temp>>8);
- SendBuf[CommIndexNum++]=(u8)(CRC16Temp&0x00ff);
- //从SendBuf发送CommIndexNum个8位的返回数据
- Uart1_Send(SendBuf,CommIndexNum);
- //结束 清除缓冲区
- memset(SendBuf,0,sizeof(SendBuf));
- }
- /*
- *功能码:0x04 读取输入寄存器
- *发送:[硬件地址][04][起始地址高][起始地址低][总寄存器数高][总寄存器数低][ CRC低 ][ CRC高 ]
- *返回:[硬件地址][04][ 字节数 ][寄存器0高 ][ 寄存器0低 ][ 寄存器1高 ][ 寄存器1低 ][ 寄存器n高 ][ 寄存器n低 ][ CRC低 ][ CRC高 ]
- */
- void ReadInputReg(void)
- {
- u16 StartAdd,RegLen,i,DataTemp,CRC16Temp;
- u8 CommIndexNum=0;
- //获取起始地址
- StartAdd=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
- //获取读取长度
- RegLen=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];
- SendBuf[CommIndexNum++]=SlaveID;
- SendBuf[CommIndexNum++]=ReadHoldRegister;
- SendBuf[CommIndexNum++]=(u8)(RegLen*2);
- for(i=0;i<RegLen;i++)
- {
- /*获取16位数据并返回赋给[寄存器n高][寄存器n低]*/
- DataTemp=GetData(StartAdd,i);
- SendBuf[CommIndexNum++] = (u8)(DataTemp>>8);
- SendBuf[CommIndexNum++] = (u8)(DataTemp&0x00ff);
- }
- CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
- SendBuf[CommIndexNum++]=(u8)(CRC16Temp>>8);
- SendBuf[CommIndexNum++]=(u8)(CRC16Temp&0x00ff);
- //串口发送返回数据
- Uart1_Send(SendBuf,CommIndexNum);
- //结束 清除缓冲区
- memset(SendBuf,0,sizeof(SendBuf));
- }
- /*
- *功能码:0x05 强制(写)单线圈(输出状态)
- *发送:[硬件地址][05][线圈地址高][线圈地址低][ 强制状态 ][ CRC低 ][ CRC高 ]
- *返回:[硬件地址][05][线圈地址高][线圈地址低][ 强制状态 ][ CRC低 ][ CRC高 ]
- */
- void ForceSingleCoil(void)
- {
- u16 CoilAddr,CRC16Temp;
- u8 ForceState,CommIndexNum=0;
- CoilAddr=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
- ForceState=ReceiveBuf[CommIndexForceState];
- //从CoilAddr写入ForceState 8位数据
- WriteForceState(CoilAddr,ForceState);
- SendBuf[CommIndexNum++]=SlaveID;
- SendBuf[CommIndexNum++]=ForceSingleCoilOutputState;
- SendBuf[CommIndexNum++]=(u8)CoilAddr>>8;
- SendBuf[CommIndexNum++]=(u8)CoilAddr&0x00ff;
- SendBuf[CommIndexNum++]=ForceState;
- CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
- SendBuf[CommIndexNum++]=(u8)(CRC16Temp>>8);
- SendBuf[CommIndexNum++]=(u8)(CRC16Temp&0x00ff);
- //串口发送返回数据
- Uart1_Send(SendBuf,CommIndexNum);
- //结束 清除缓冲区
- memset(SendBuf,0,sizeof(SendBuf));
- }
- /*
- *功能码:0x06 预设(写)单寄存器
- *发送:[硬件地址][06][寄存器地址高][寄存器地址低][寄存器值高][寄存器值低][ CRC低 ][ CRC高 ]
- *返回:[硬件地址][06][寄存器地址高][寄存器地址低][寄存器值高][寄存器值低][ CRC低 ][ CRC高 ]
- */
- void PresetSingleReg(void)
- {
- u16 RegAddr,RegData,CRC16Temp;
- u8 CommIndexNum=0;
- RegAddr=(u16)ReceiveBuf[CommIndexStartAddrH]<<8|(u16)ReceiveBuf[CommIndexStartAddrL];
- RegData=(u16)ReceiveBuf[CommIndexDataH]<<8|(u16)ReceiveBuf[CommIndexDataL];
- /*写寄存器值*/
- WriteRegister(RegAddr,RegData);
- SendBuf[CommIndexNum++]=SlaveID;
- SendBuf[CommIndexNum++]=PresetSingleRegister;
- SendBuf[CommIndexNum++]=(u8)RegAddr>>8;
- SendBuf[CommIndexNum++]=(u8)RegAddr&0x00ff;
- SendBuf[CommIndexNum++]=(u8)RegData>>8;
- SendBuf[CommIndexNum++]=(u8)RegData&0x00ff;
- CRC16Temp=GetCRC16(SendBuf,CommIndexNum-1);
- SendBuf[CommIndexNum++]=(u8)(CRC16Temp>>8);
- SendBuf[CommIndexNum++]=(u8)(CRC16Temp&0x00ff);
- //串口发送返回数据
- Uart1_Send(SendBuf,CommIndexNum);
- //结束 清除缓冲区
- memset(SendBuf,0,sizeof(SendBuf));
- }
- /*
- *CRC校验错误 请求主机重发指令
- */
- void RequestRetry(void)
- {
- }
|
|