|
|
|
@@ -4,9 +4,25 @@ |
|
|
|
#include "os.h" |
|
|
|
#include "app_cfg.h" |
|
|
|
#include "sys_cfg.h" |
|
|
|
#include "string.h" |
|
|
|
#include "modbus.h" |
|
|
|
|
|
|
|
extern OS_EVENT* ModbusReceived; /*接收到modbus请求报文*/ |
|
|
|
extern OS_EVENT* ModbusAssembled; /*modbus响应帧组装完成*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*0x270F+1=K10000*/ |
|
|
|
uint8_t ModbusCoil[1250]; /*10000/8=1250*/ |
|
|
|
uint16_t ModbusReg[10000]; |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
/*USART接收空闲中断*/ |
|
|
|
void USART1_IRQHandler(void) |
|
|
|
@@ -73,12 +89,303 @@ void ModbusSend(uint8_t *txBuf, uint16_t len) |
|
|
|
/*modbus协议帧解析任务*/ |
|
|
|
void AppTaskModbusParse (void *p_arg) |
|
|
|
{ |
|
|
|
INT8U err; |
|
|
|
MODBUS_FRAME frame; |
|
|
|
uint16_t rxLen; |
|
|
|
uint8_t rxBuf[256]; |
|
|
|
|
|
|
|
while(1) |
|
|
|
{ |
|
|
|
OSTimeDly(OS_TICKS_PER_SEC); |
|
|
|
OSSemPend(ModbusReceived, 0, &err); |
|
|
|
|
|
|
|
rxLen = ModbusRxLen; |
|
|
|
|
|
|
|
memcpy(rxBuf, ModbusRxBuf, rxLen); |
|
|
|
|
|
|
|
frame.crc = ((uint16_t)(rxBuf[rxLen - 1])) | ((uint16_t)rxBuf[rxLen - 2] << 8); |
|
|
|
if(ChcekCrc16(frame.crc, rxBuf, rxLen) != 0) |
|
|
|
{ |
|
|
|
/****************************crc错误处理******************************/ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
frame.slaveAddres = rxBuf[0]; |
|
|
|
if(frame.slaveAddres != SLAVE_ADDRES) |
|
|
|
{ |
|
|
|
/*****************************从机地址错误处理************************/ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
frame.func = rxBuf[1]; |
|
|
|
frame.opeAddres = ((uint16_t)rxBuf[2] << 8) | ((uint16_t)rxBuf[3]); |
|
|
|
frame.opeNum = ((uint16_t)rxBuf[4] << 8) | ((uint16_t)rxBuf[5]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(frame.func) |
|
|
|
{ |
|
|
|
case 0x01:/*读线圈*/ |
|
|
|
ModbusReadCoil(frame.opeAddres, frame.opeNum); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 0x03:/*读寄存器*/ |
|
|
|
ModbusReadReg(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); |
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 0x10:/*写多个寄存器*/ |
|
|
|
frame.wNum = rxBuf[6]; |
|
|
|
memcpy(frame.wData, &rxBuf[7], frame.wNum); |
|
|
|
|
|
|
|
ModbusWriteReg(frame.opeAddres, frame.opeNum, frame.wData); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default:/*功能码错误*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
ModbusSend(ModbusTxBuf, ModbusTxLen); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t ModbusReadCoil(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(addres > 0x270F || (addres + num) > 0x270F) |
|
|
|
{ |
|
|
|
/********************地址超限处理*****************/ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t ModbusWriteCoil(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(addres > 0x270F || (addres + num) > 0x270F) |
|
|
|
{ |
|
|
|
/********************地址超限处理*****************/ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
|
if(readVal != 0) |
|
|
|
{ |
|
|
|
ModbusCoil[byteIndI] |= writeVal; |
|
|
|
} |
|
|
|
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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t ModbusReadReg(uint16_t addres, uint16_t num) |
|
|
|
{ |
|
|
|
uint8_t index; |
|
|
|
uint8_t readValH; |
|
|
|
uint8_t readValL; |
|
|
|
uint8_t dataLen; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(addres > 0x270F || (addres + num) > 0x270F) |
|
|
|
{ |
|
|
|
/********************地址错误处理*****************/ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
dataLen = num * 2; |
|
|
|
for(uint16_t i = 0; i < num; i++) |
|
|
|
{ |
|
|
|
index = 3 + (i * 2); |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t ModbusWriteReg(uint16_t addres, uint16_t num, uint8_t *data) |
|
|
|
{ |
|
|
|
uint8_t index; |
|
|
|
|
|
|
|
uint8_t writeValH; |
|
|
|
uint8_t writeValL; |
|
|
|
uint16_t writeVal; |
|
|
|
|
|
|
|
|
|
|
|
if(addres > 0x270F || (addres + num) > 0x270F) |
|
|
|
{ |
|
|
|
/********************地址错误处理*****************/ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(uint16_t i = 0; i < num; i++) |
|
|
|
{ |
|
|
|
index = i * 2; |
|
|
|
|
|
|
|
writeValH = data[index]; |
|
|
|
writeValL = data[index + 1]; |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
uint16_t Crc16(const uint8_t *data, uint16_t length); |
|
|
|
|
|
|
|
void AddCrc16(uint8_t *data, uint16_t length) |
|
|
|
{ |
|
|
|
uint16_t crc16 = Crc16(data, length); |
|
|
|
|
|
|
|
/*低前高后*/ |
|
|
|
data[length] = (uint8_t)(crc16 & 0x00FF); |
|
|
|
data[length + 1] = (uint8_t)(crc16 >> 8); |
|
|
|
} |
|
|
|
|
|
|
|
/*crc16校验*/ |
|
|
|
uint16_t Crc16(const uint8_t *data, uint16_t length) |
|
|
|
{ |
|
|
|
uint16_t crc; |
|
|
|
uint16_t byteInd; |
|
|
|
uint8_t bitInd; |
|
|
|
|
|
|
|
crc = 0xFFFFu; |
|
|
|
for (byteInd = 0u; byteInd < length; byteInd++) |
|
|
|
{ |
|
|
|
crc ^= (uint16_t)data[byteInd]; |
|
|
|
for (bitInd = 0u; bitInd < 8u; bitInd++) |
|
|
|
{ |
|
|
|
if ((crc & 0x0001u) != 0u) |
|
|
|
{ |
|
|
|
crc >>= 1; |
|
|
|
crc ^= 0xA001u; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
crc >>= 1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return crc; |
|
|
|
} |
|
|
|
|
|
|
|
/*crc16检查*/ |
|
|
|
int8_t ChcekCrc16(uint16_t recCrc16, uint8_t *data, uint16_t length) |
|
|
|
{ |
|
|
|
uint16_t crc16 = Crc16(data, (length - 2)); |
|
|
|
|
|
|
|
if(recCrc16 == crc16) |
|
|
|
{ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |