|
|
|
@@ -1,28 +1,31 @@ |
|
|
|
#include "stm32f4xx.h" |
|
|
|
#include "hardware.h" |
|
|
|
#include "ucos_ii.h" |
|
|
|
#include "os.h" |
|
|
|
#include "app_cfg.h" |
|
|
|
#include "sys_cfg.h" |
|
|
|
#include "string.h" |
|
|
|
#include "modbus.h" |
|
|
|
|
|
|
|
extern OS_EVENT* ModbusReceived; /*接收到modbus请求报文*/ |
|
|
|
|
|
|
|
|
|
|
|
uint8_t ModbusErr; |
|
|
|
/*0x270F + 1 = K10000 */ |
|
|
|
uint8_t ModbusCoil[1250]; /*10000/8=1250*/ |
|
|
|
uint16_t ModbusReg[10000]; |
|
|
|
uint8_t ModbusErr; |
|
|
|
|
|
|
|
uint8_t ModbusRxBuf[MODBUS_RX_BUF_SIZE]; /*接收数组*/ |
|
|
|
uint16_t ModbusRxLen = 0; /*接收数据长度*/ |
|
|
|
uint8_t ModbusTxBuf[MODBUS_TX_BUF_SIZE]; /*发送数组*/ |
|
|
|
uint16_t ModbusTxLen = 0; /*发送数据长度*/ |
|
|
|
|
|
|
|
|
|
|
|
uint8_t ModbusErrReply(uint8_t func, uint8_t err); |
|
|
|
uint16_t Crc16(const uint8_t *data, uint16_t length); |
|
|
|
void AddCrc16(uint8_t *data, uint16_t length); |
|
|
|
int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length); |
|
|
|
uint8_t ModbusReadCoil(uint16_t addres, uint16_t num); |
|
|
|
uint8_t ModbusWriteCoil(uint16_t addres, uint16_t num, uint8_t *data); |
|
|
|
uint8_t ModbusReadReg(uint16_t addres, uint16_t num); |
|
|
|
uint8_t ModbusWriteReg(uint16_t addres, uint16_t num, uint8_t *data); |
|
|
|
uint8_t ModbusReadCoils(uint16_t addres, uint16_t num); |
|
|
|
uint8_t ModbusWriteCoils(uint16_t addres, uint16_t num, uint8_t *data); |
|
|
|
uint8_t ModbusReadRegs(uint16_t addres, uint16_t num); |
|
|
|
uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data); |
|
|
|
uint8_t ModbusWriteReg(uint16_t addres, uint8_t *data); |
|
|
|
uint8_t ModbusWriteCoil(uint16_t addres, uint8_t *data); |
|
|
|
|
|
|
|
|
|
|
|
/*USART接收空闲中断*/ |
|
|
|
@@ -91,7 +94,7 @@ void ModbusSend(uint8_t *txBuf, uint16_t len) |
|
|
|
/*modbus协议帧解析任务*/ |
|
|
|
void AppTaskModbusParse (void *p_arg) |
|
|
|
{ |
|
|
|
INT8U err; |
|
|
|
OS_ERR err; |
|
|
|
MODBUS_FRAME frame; |
|
|
|
uint16_t rxLen; |
|
|
|
uint8_t rxBuf[256]; |
|
|
|
@@ -106,10 +109,11 @@ void AppTaskModbusParse (void *p_arg) |
|
|
|
memcpy(rxBuf, ModbusRxBuf, rxLen); |
|
|
|
|
|
|
|
/*拼接crc校验码(高前低后),接收到的数据帧crc校验码是低前高后*/ |
|
|
|
frame.crc = ((uint16_t)(rxBuf[rxLen - 1])) | ((uint16_t)rxBuf[rxLen - 2] << 8); |
|
|
|
frame.crc = ((uint16_t)(rxBuf[rxLen - 2])) | ((uint16_t)rxBuf[rxLen - 1] << 8); |
|
|
|
if(ChcekCrc16(frame.crc, rxBuf, rxLen) != 0) |
|
|
|
{ |
|
|
|
/*crc校验错误,直接丢弃*/ |
|
|
|
ModbusErr = ERR_CRC; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -117,6 +121,7 @@ void AppTaskModbusParse (void *p_arg) |
|
|
|
if(frame.slaveAddres != SLAVE_ADDRES) |
|
|
|
{ |
|
|
|
/*从机地址错误,直接丢弃*/ |
|
|
|
ModbusErr = ERR_SLAVE_ADDRES; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -128,41 +133,38 @@ void AppTaskModbusParse (void *p_arg) |
|
|
|
switch(frame.func) |
|
|
|
{ |
|
|
|
case 0x01:/*读线圈*/ |
|
|
|
ModbusReadCoil(frame.opeAddres, frame.opeNum); |
|
|
|
ModbusErr = ModbusReadCoils(frame.opeAddres, frame.opeNum); |
|
|
|
break; |
|
|
|
|
|
|
|
case 0x03:/*读寄存器*/ |
|
|
|
ModbusReadReg(frame.opeAddres, frame.opeNum); |
|
|
|
ModbusErr = ModbusReadRegs(frame.opeAddres, frame.opeNum); |
|
|
|
break; |
|
|
|
|
|
|
|
case 0x0F:/*写多个线圈*/ |
|
|
|
frame.wNum = rxBuf[6]; |
|
|
|
memcpy(frame.wData, &rxBuf[7], frame.wNum); |
|
|
|
|
|
|
|
ModbusWriteCoil(frame.opeAddres, frame.opeNum, frame.wData); |
|
|
|
ModbusErr = ModbusWriteCoils(frame.opeAddres, frame.opeNum, frame.wData); |
|
|
|
break; |
|
|
|
|
|
|
|
case 0x10:/*写多个寄存器*/ |
|
|
|
frame.wNum = rxBuf[6]; |
|
|
|
memcpy(frame.wData, &rxBuf[7], frame.wNum); |
|
|
|
|
|
|
|
ModbusWriteReg(frame.opeAddres, frame.opeNum, frame.wData); |
|
|
|
ModbusErr = ModbusWriteRegs(frame.opeAddres, frame.opeNum, frame.wData); |
|
|
|
break; |
|
|
|
|
|
|
|
// case 0x05:/*写单个线圈*/ |
|
|
|
// ModbusWriteCoil(frame.opeAddres, 1, frame.wData); |
|
|
|
|
|
|
|
// break; |
|
|
|
|
|
|
|
// case 0x06:/*写单个寄存器*/ |
|
|
|
case 0x05:/*写单个线圈*/ |
|
|
|
memcpy(frame.wData, &rxBuf[4], 2); |
|
|
|
ModbusErr = ModbusWriteCoil(frame.opeAddres, frame.wData); |
|
|
|
break; |
|
|
|
|
|
|
|
// ModbusWriteReg(frame.opeAddres, 1, frame.wData); |
|
|
|
// break; |
|
|
|
case 0x06:/*写单个寄存器*/ |
|
|
|
memcpy(frame.wData, &rxBuf[4], 2); |
|
|
|
ModbusErr = ModbusWriteReg(frame.opeAddres, frame.wData); |
|
|
|
break; |
|
|
|
|
|
|
|
default:/*功能码错误*/ |
|
|
|
ModbusErr = ERR_FUNC; |
|
|
|
ModbusErrReply(frame.func, ERR_FUNC); |
|
|
|
|
|
|
|
ModbusErr = ModbusErrReply(frame.func, ERR_FUNC); |
|
|
|
break; |
|
|
|
} |
|
|
|
/*启动发送*/ |
|
|
|
@@ -170,7 +172,7 @@ void AppTaskModbusParse (void *p_arg) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t ModbusReadCoil(uint16_t addres, uint16_t num) |
|
|
|
uint8_t ModbusReadCoils(uint16_t addres, uint16_t num) |
|
|
|
{ |
|
|
|
uint16_t byteIndI; /*字节索引*/ |
|
|
|
uint8_t bitIndI; /*位索引*/ |
|
|
|
@@ -186,13 +188,11 @@ uint8_t ModbusReadCoil(uint16_t addres, uint16_t num) |
|
|
|
/*操作地址超限*/ |
|
|
|
if(addres > 0x270F || (addres + (num - 1)) > 0x270F) |
|
|
|
{ |
|
|
|
ModbusErr = ERR_OPE_ADDRES; |
|
|
|
return ModbusErrReply(0x01, ERR_OPE_ADDRES); |
|
|
|
} |
|
|
|
/*操作数量超限*/ |
|
|
|
if(num == 0 || num > 2000) |
|
|
|
{ |
|
|
|
ModbusErr = ERR_DATA; |
|
|
|
return ModbusErrReply(0x01, ERR_DATA); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -229,9 +229,11 @@ uint8_t ModbusReadCoil(uint16_t addres, uint16_t num) |
|
|
|
ModbusTxBuf[2] = dataLen; /*响应帧返回数据字节数*/ |
|
|
|
AddCrc16(ModbusTxBuf, 3 + dataLen); |
|
|
|
ModbusTxLen = 5 + dataLen; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t ModbusWriteCoil(uint16_t addres, uint16_t num, uint8_t *data) |
|
|
|
uint8_t ModbusWriteCoils(uint16_t addres, uint16_t num, uint8_t *data) |
|
|
|
{ |
|
|
|
uint16_t byteIndI; |
|
|
|
uint8_t bitIndI; |
|
|
|
@@ -244,13 +246,11 @@ uint8_t ModbusWriteCoil(uint16_t addres, uint16_t num, uint8_t *data) |
|
|
|
/*操作地址超限*/ |
|
|
|
if(addres > 0x270F || (addres + (num - 1)) > 0x270F) |
|
|
|
{ |
|
|
|
ModbusErr = ERR_OPE_ADDRES; |
|
|
|
return ModbusErrReply(0x0F, ERR_OPE_ADDRES); |
|
|
|
} |
|
|
|
/*操作数量超限*/ |
|
|
|
if(num == 0 || num > 1968) |
|
|
|
{ |
|
|
|
ModbusErr = ERR_DATA; |
|
|
|
return ModbusErrReply(0x0F, ERR_DATA); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -267,46 +267,46 @@ uint8_t ModbusWriteCoil(uint16_t addres, uint16_t num, uint8_t *data) |
|
|
|
/*将写入值移位到要写入的位*/ |
|
|
|
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; |
|
|
|
} |
|
|
|
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 ModbusReadReg(uint16_t addres, uint16_t num) |
|
|
|
uint8_t ModbusReadRegs(uint16_t addres, uint16_t num) |
|
|
|
{ |
|
|
|
uint8_t index; |
|
|
|
uint8_t readValH; |
|
|
|
uint8_t readValL; |
|
|
|
uint8_t dataLen; |
|
|
|
|
|
|
|
|
|
|
|
/*操作地址超限*/ |
|
|
|
if(addres > 0x270F || (addres + (num - 1)) > 0x270F) |
|
|
|
{ |
|
|
|
ModbusErr = ERR_OPE_ADDRES; |
|
|
|
return ModbusErrReply(0x03, ERR_OPE_ADDRES); |
|
|
|
} |
|
|
|
/*操作数量超限*/ |
|
|
|
if(num == 0 || num > 125) |
|
|
|
{ |
|
|
|
ModbusErr = ERR_DATA; |
|
|
|
return ModbusErrReply(0x03, ERR_DATA); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -326,9 +326,11 @@ uint8_t ModbusReadReg(uint16_t addres, uint16_t num) |
|
|
|
ModbusTxBuf[2] = dataLen; |
|
|
|
AddCrc16(ModbusTxBuf, 3 + dataLen); |
|
|
|
ModbusTxLen = 5 + dataLen; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t ModbusWriteReg(uint16_t addres, uint16_t num, uint8_t *data) |
|
|
|
uint8_t ModbusWriteRegs(uint16_t addres, uint16_t num, uint8_t *data) |
|
|
|
{ |
|
|
|
uint8_t index; |
|
|
|
|
|
|
|
@@ -339,17 +341,14 @@ uint8_t ModbusWriteReg(uint16_t addres, uint16_t num, uint8_t *data) |
|
|
|
/*操作地址超限*/ |
|
|
|
if(addres > 0x270F || (addres + (num - 1)) > 0x270F) |
|
|
|
{ |
|
|
|
ModbusErr = ERR_OPE_ADDRES; |
|
|
|
return ModbusErrReply(0x10, ERR_OPE_ADDRES); |
|
|
|
} |
|
|
|
/*操作数量超限*/ |
|
|
|
if(num == 0 || num > 123) |
|
|
|
{ |
|
|
|
ModbusErr = ERR_DATA; |
|
|
|
return ModbusErrReply(0x10, ERR_DATA); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(uint16_t i = 0; i < num; i++) |
|
|
|
{ |
|
|
|
index = i * 2; |
|
|
|
@@ -372,9 +371,95 @@ uint8_t ModbusWriteReg(uint16_t addres, uint16_t num, uint8_t *data) |
|
|
|
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(addres > 0x270F) |
|
|
|
{ |
|
|
|
return ModbusErrReply(0x0F, 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] = 0x0F; |
|
|
|
/*操作地址*/ |
|
|
|
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(addres > 0x270F) |
|
|
|
{ |
|
|
|
return ModbusErrReply(0x10, 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] = 0x10; |
|
|
|
/*操作地址*/ |
|
|
|
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; |
|
|
|
|