|
- #include "stm32f4xx.h"
- #include "ucos_ii.h"
- #include "os.h"
- #include "string.h"
- #include "modbus_parse.h"
- #include "modbus_rec_send.h"
-
- extern OS_EVENT* ModbusWriteFlash; /*接收到modbus写入coil请求报文*/
- extern OS_EVENT* ModbusConnect; /*已接收到modbus正确报文*/
-
- uint8_t ModbusErr;
- /*0x270F + 1 = K10000 */
- uint8_t ModbusCoil[1250]; /*10000/8=1250*/
- uint16_t ModbusReg[10000];
-
- /*附加功能:页寄存器*/
- uint16_t ModbusExtPage[1] = {0}; /*设置地址为0xFFFE*/
- uint16_t ModbusExtReg[1]; /*地址映射为0x10000*/
- /*附加功能:读取所有单数个寄存器*/
- uint16_t ModbusExtOdd[1] = {0}; /*设置地址为0xFFFF*/
-
- uint8_t ModbusRxBuf[MODBUS_RX_BUF_SIZE]; /*接收数组*/
- uint16_t ModbusRxLen = 0; /*接收数据长度*/
- uint8_t ModbusTxBuf[MODBUS_TX_BUF_SIZE]; /*发送数组*/
- uint16_t ModbusTxLen = 0; /*发送数据长度*/
-
-
- /*modbus协议帧解析任务*/
- void AppTaskModbusParse (void *p_arg)
- {
- OS_ERR err;
- MODBUS_FRAME frame;
- uint16_t rxLen;
- uint8_t rxBuf[256];
-
- while(1)
- {
- /*无限期等待接收到数据帧信号量*/
- OSSemPend(ModbusReceived, 0, &err);
-
- /*数据接收,防止下一帧覆盖*/
- rxLen = ModbusRxLen;
- if(rxLen > MODBUS_RX_BUF_SIZE)
- {
- rxLen = 0;
- }
- memcpy(rxBuf, ModbusRxBuf, rxLen);
-
- /*帧分解*/
- frame.slaveAddres = rxBuf[0];
- frame.func = rxBuf[1];
- frame.crc = ((uint16_t)(rxBuf[rxLen - 2])) | ((uint16_t)rxBuf[rxLen - 1] << 8);
- frame.opeAddres = ((uint16_t)rxBuf[2] << 8) | ((uint16_t)rxBuf[3]);
- frame.opeNum = ((uint16_t)rxBuf[4] << 8) | ((uint16_t)rxBuf[5]);
-
- /*crc校验判断*/
- if(ChcekCrc16(frame.crc, rxBuf, rxLen) != 0)
- {
- /*crc校验错误,直接丢弃*/
- ModbusErr = ERR_CRC;
- continue;
- }
- /*从机地址判断*/
- if(frame.slaveAddres != SLAVE_ADDRES)
- {
- /*从机地址错误,直接丢弃*/
- ModbusErr = ERR_SLAVE_ADDRES;
- continue;
- }
- /*释放正确接收信号量*/
- OSSemPost(ModbusConnect);
-
- /*功能码分类*/
- switch(frame.func)
- {
- case 0x01:/*读线圈*/
- ModbusErr = ModbusReadCoils(frame.opeAddres, frame.opeNum);
- break;
-
- case 0x03:/*读寄存器*/
- ModbusErr = ModbusReadRegs(frame.opeAddres, frame.opeNum);
- break;
-
- case 0x0F:/*写多个线圈*/
- frame.wNum = rxBuf[6];
- if(frame.wNum != ((frame.opeNum + 7) / 8))
- {
- ModbusErr = ModbusErrReply(0x0F, ERR_DATA);
- }
- else
- {
- memcpy(frame.wData, &rxBuf[7], frame.wNum);
- ModbusErr = ModbusWriteCoils(frame.opeAddres, frame.opeNum, frame.wData);
- }
- break;
-
- case 0x10:/*写多个寄存器*/
- frame.wNum = rxBuf[6];
- if(frame.wNum != (frame.opeNum * 2))
- {
- ModbusErr = ModbusErrReply(0x10, ERR_DATA);
- }
- else
- {
- memcpy(frame.wData, &rxBuf[7], frame.wNum);
- ModbusErr = ModbusWriteRegs(frame.opeAddres, frame.opeNum, frame.wData);
- }
- break;
-
- case 0x05:/*写单个线圈*/
- memcpy(frame.wData, &rxBuf[4], 2);
- ModbusErr = ModbusWriteCoil(frame.opeAddres, frame.wData);
- break;
-
- case 0x06:/*写单个寄存器*/
- memcpy(frame.wData, &rxBuf[4], 2);
- ModbusErr = ModbusWriteReg(frame.opeAddres, frame.wData);
- break;
-
- default:/*功能码错误*/
- ModbusErr = ERR_FUNC;
- ModbusErr = ModbusErrReply(frame.func, ERR_FUNC);
- break;
- }
- /*发送响应帧*/
- ModbusSend(ModbusTxBuf, ModbusTxLen);
-
- if(ModbusErr == 0 && (frame.func == 0x0F || frame.func == 0x10
- || frame.func == 0x05 || frame.func == 0x06))
- {
- /*释放写FLASH信号量*/
- OSSemPost(ModbusWriteFlash);
- }
- }
- }
-
- uint8_t ModbusReadCoils(uint16_t addres, uint16_t num)
- {
- uint16_t byteIndI; /*字节索引*/
- uint8_t bitIndI; /*位索引*/
- uint16_t byteIndO;
- uint8_t bitIndO;
-
- uint8_t dataLen; /*响应帧返回字节数*/
-
- uint8_t index; /*发送数组索引*/
- uint8_t readVal; /*读取到的形式值*/
- uint8_t writeVal; /*写入的形式值*/
-
- if(ModbusRxLen < 8)
- {
- return ModbusErrReply(0x01, ERR_DATA);
- }
- /*操作地址超限*/
- if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
- {
- return ModbusErrReply(0x01, ERR_OPE_ADDRES);
- }
- /*操作数量超限*/
- if(num == 0 || num > 2000)
- {
- return ModbusErrReply(0x01, ERR_DATA);
- }
-
- /*不能num/8+1,当为8的整数时会多一个*/
- dataLen = (num + 7) / 8;
-
- /*清零发送数组*/
- memset(&ModbusTxBuf[3], 0, 253);
-
- for(uint16_t i = 0; i < num; i++)
- {
- byteIndO = i / 8;
- bitIndO = i % 8;
-
- byteIndI = (addres + i) / 8;
- bitIndI = (addres + i) % 8;
-
- /*位掩码读取线圈值*/
- readVal = ModbusCoil[byteIndI] & ((uint8_t)1 << bitIndI);
-
- /*读取到的值为0则不进行操作*/
- if(readVal != 0)
- {
- index = 3 + byteIndO;
- /*将读取到的值移位到要写入的位*/
- writeVal = (uint8_t)1u << bitIndO;
-
- ModbusTxBuf[index] |= writeVal;
- }
- }
-
- ModbusTxBuf[0] = SLAVE_ADDRES; /*从机地址*/
- ModbusTxBuf[1] = 0x01; /*功能码*/
- ModbusTxBuf[2] = dataLen; /*响应帧返回数据字节数*/
- AddCrc16(ModbusTxBuf, 3 + dataLen);
- ModbusTxLen = 5 + dataLen;
-
- return 0;
- }
-
- uint8_t ModbusWriteCoils(uint16_t addres, uint16_t num, uint8_t *data)
- {
- uint16_t byteIndI;
- uint8_t bitIndI;
- uint16_t byteIndO;
- uint8_t bitIndO;
-
- uint8_t readVal;
- uint8_t writeVal;
-
- if(ModbusRxLen < 10)
- {
- return ModbusErrReply(0x0F, ERR_DATA);
- }
- /*操作地址超限*/
- if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
- {
- return ModbusErrReply(0x0F, ERR_OPE_ADDRES);
- }
- /*操作数量超限*/
- if(num == 0 || num > 1968)
- {
- return ModbusErrReply(0x0F, ERR_DATA);
- }
-
- for(uint16_t i = 0; i < num; i++)
- {
- byteIndI = (addres + i) / 8;
- bitIndI = (addres + i) % 8;
-
- byteIndO = i / 8;
- bitIndO = i % 8;
-
- /*位掩码读取要写入的值*/
- readVal = data[byteIndO] & ((uint8_t)1 << bitIndO);
- /*将写入值移位到要写入的位*/
- writeVal = (uint8_t)1 << bitIndI;
-
- /*对应位写入1*/
- if(readVal != 0)
- {
- ModbusCoil[byteIndI] |= writeVal;
- }
- /*对应位写入0*/
- else
- {
- ModbusCoil[byteIndI] &= (~writeVal);
- }
- }
- ModbusTxBuf[0] = SLAVE_ADDRES;
- ModbusTxBuf[1] = 0x0F;
- /*操作地址*/
- ModbusTxBuf[2] = (uint8_t)(addres >> 8);
- ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
- /*成功写入的数量*/
- ModbusTxBuf[4] = (uint8_t)(num >> 8);
- ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
- AddCrc16(ModbusTxBuf, 6);
- ModbusTxLen = 8;
-
- return 0;
- }
-
- uint8_t ModbusReadRegs(uint16_t addres, uint16_t num)
- {
- uint8_t index;
- uint8_t readValH;
- uint8_t readValL;
- uint8_t dataLen;
-
- if(ModbusRxLen < 8)
- {
- return ModbusErrReply(0x03, ERR_DATA);
- }
- /*操作地址超限*/
- if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
- {
- if(addres == 0xFFFF && num == 1)
- {
- ;
- }
- else
- {
- return ModbusErrReply(0x03, ERR_OPE_ADDRES);
- }
- }
- /*操作数量超限*/
- if(num == 0 || num > 125)
- {
- return ModbusErrReply(0x03, ERR_DATA);
- }
-
- dataLen = num * 2;
- /*附加功能:读取0x10000寄存器*/
- if(ModbusExtPage[0] == 1 && addres == 0x0000)
- {
- /*将16位寄存器值拆分为两个8位*/
- readValH = (uint8_t)(ModbusExtReg[0] >> 8);
- readValL = (uint8_t)(ModbusExtReg[0] & 0x00FF);
-
- ModbusTxBuf[3] = readValH;
- ModbusTxBuf[4] = readValL;
- }
- else
- {
- for(uint16_t i = 0; i < num; i++)
- {
- index = 3 + (i * 2);
- /*将16位寄存器值拆分为两个8位*/
- readValH = (uint8_t)(ModbusReg[addres + i] >> 8);
- readValL = (uint8_t)(ModbusReg[addres + i] & 0x00FF);
-
- ModbusTxBuf[index] = readValH;
- ModbusTxBuf[index + 1] = readValL;
- }
- }
-
- ModbusTxBuf[0] = SLAVE_ADDRES;
- ModbusTxBuf[1] = 0x03;
- ModbusTxBuf[2] = dataLen;
- AddCrc16(ModbusTxBuf, 3 + dataLen);
- ModbusTxLen = 5 + dataLen;
-
- return 0;
- }
-
- uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data)
- {
- uint8_t index;
-
- uint8_t writeValH;
- uint8_t writeValL;
- uint16_t writeVal;
-
- if(ModbusRxLen < 11)
- {
- return ModbusErrReply(0x10, ERR_DATA);
- }
- /*操作地址超限*/
- if(addres > 0x270F || (addres + (num - 1)) > 0x270F)
- {
- if((addres == 0xFFFE || addres == 0xFFFF) && num == 1)
- {
- ;
- }
- else
- {
- return ModbusErrReply(0x10, ERR_OPE_ADDRES);
- }
- }
- /*操作数量超限*/
- if(num == 0 || num > 123)
- {
- return ModbusErrReply(0x10, ERR_DATA);
- }
-
- /*附加功能:读取0x10000寄存器*/
- if(addres == 0xFFFE && num == 1)
- {
- writeValH = data[0];
- writeValL = data[1];
-
- /*将要写入两个8位值拼接为16位*/
- writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
- ModbusExtPage[0] = writeVal;
- }
- /*附加功能:读取大量奇数寄存器*/
- else if(addres == 0xFFFF && num == 1)
- {
- writeValH = data[0];
- writeValL = data[1];
-
- /*将要写入两个8位值拼接为16位*/
- writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
- ModbusExtOdd[0] = writeVal;
- }
- /*正常功能*/
- else
- {
- for(uint16_t i = 0; i < num; i++)
- {
- index = i * 2;
-
- writeValH = data[index];
- writeValL = data[index + 1];
-
- /*将要写入两个8位值拼接为16位*/
- writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
- ModbusReg[addres + i] = writeVal;
- }
- }
-
- ModbusTxBuf[0] = SLAVE_ADDRES;
- ModbusTxBuf[1] = 0x10;
- /*操作地址*/
- ModbusTxBuf[2] = (uint8_t)(addres >> 8);
- ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
- /*成功写入数量*/
- ModbusTxBuf[4] = (uint8_t)(num >> 8);
- ModbusTxBuf[5] = (uint8_t)(num & 0x00FF);
- AddCrc16(ModbusTxBuf, 6);
- ModbusTxLen = 8;
-
- return 0;
- }
-
- uint8_t ModbusWriteCoil(uint16_t addres, uint8_t *data)
- {
- uint16_t byteIndI;
- uint8_t bitIndI;
-
- uint16_t readVal;
- uint8_t writeVal;
-
- if(ModbusRxLen < 8)
- {
- return ModbusErrReply(0x05, ERR_DATA);
- }
- /*操作地址超限*/
- if(addres > 0x270F)
- {
- return ModbusErrReply(0x05, ERR_OPE_ADDRES);
- }
-
- byteIndI = addres / 8;
- bitIndI = addres % 8;
-
- /*位掩码读取要写入的值*/
- readVal = ((uint16_t)data[0] << 8) | ((uint16_t)data[1] & 0x00FF);
- /*将写入值移位到要写入的位*/
- writeVal = (uint8_t)1 << bitIndI;
-
- /*置on*/
- if(readVal == 0xFF00)
- {
- ModbusCoil[byteIndI] |= writeVal;
- }
- /*置off*/
- else if(readVal == 0x0000)
- {
- ModbusCoil[byteIndI] &= (~writeVal);
- }
- else
- {
- return ModbusErrReply(0x05, ERR_DATA);
- }
-
- ModbusTxBuf[0] = SLAVE_ADDRES;
- ModbusTxBuf[1] = 0x05;
- /*操作地址*/
- ModbusTxBuf[2] = (uint8_t)(addres >> 8);
- ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
- /*成功写入*/
- ModbusTxBuf[4] = data[0];
- ModbusTxBuf[5] = data[1];
- AddCrc16(ModbusTxBuf, 6);
- ModbusTxLen = 8;
-
- return 0;
- }
-
- uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data)
- {
- uint8_t writeValH;
- uint8_t writeValL;
- uint16_t writeVal;
-
- if(ModbusRxLen < 8)
- {
- return ModbusErrReply(0x06, ERR_DATA);
- }
- /*操作地址超限*/
- if(addres > 0x270F)
- {
- return ModbusErrReply(0x06, ERR_OPE_ADDRES);
- }
-
- writeValH = data[0];
- writeValL = data[1];
- /*将要写入两个8位值拼接为16位*/
- writeVal = ((uint16_t)writeValH << 8) | ((uint16_t)writeValL & 0x00FF);
- ModbusReg[addres] = writeVal;
-
- ModbusTxBuf[0] = SLAVE_ADDRES;
- ModbusTxBuf[1] = 0x06;
- /*操作地址*/
- ModbusTxBuf[2] = (uint8_t)(addres >> 8);
- ModbusTxBuf[3] = (uint8_t)(addres & 0x00FF);
- /*成功写入*/
- ModbusTxBuf[4] = writeValH;
- ModbusTxBuf[5] = writeValL;
- AddCrc16(ModbusTxBuf, 6);
- ModbusTxLen = 8;
-
- return 0;
- }
-
-
-
- uint8_t ModbusErrReply(uint8_t func, uint8_t err)
- {
- ModbusTxBuf[0] = SLAVE_ADDRES;
- ModbusTxBuf[1] = func | 0x80;
- ModbusTxBuf[2] = err;
- AddCrc16(ModbusTxBuf, 3);
- ModbusTxLen = 5;
-
- return err;
- }
|