#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请求报文*/ /*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) { OSIntEnter(); /*进入中断*/ uint32_t temp; uint16_t rxLenRemain; if(USART_GetITStatus(USART1, USART_IT_IDLE) == SET) { /*在计算数据长度之前先关闭DMA接收通道,防止计算过程中DMA继续转运数据*/ DMA_Cmd(DMA2_Stream2, DISABLE); /*清除IDLE中断标志位*/ temp = USART1->SR; temp = USART1->DR; (void)temp; /*清除传输已经完成TCIF2、传输已经完成一半HTIF2标志位*/ DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2 | DMA_FLAG_HTIF2); /*计算数据长度*/ rxLenRemain = DMA_GetCurrDataCounter(DMA2_Stream2); ModbusRxLen = MODBUS_RX_BUF_SIZE - rxLenRemain; if(ModbusRxLen != 0) { OSSemPost(ModbusReceived); } /*重新指定接收地址*/ DMA_MemoryTargetConfig(DMA2_Stream2, (uint32_t)ModbusRxBuf, DMA_Memory_0); /*重启DMA*/ DMA_SetCurrDataCounter(DMA2_Stream2, MODBUS_RX_BUF_SIZE); DMA_Cmd(DMA2_Stream2, ENABLE); } OSIntExit(); /*退出中断*/ } /*modbus响应帧发送*/ void ModbusSend(uint8_t *txBuf, uint16_t len) { /*先关闭DMA发送通道*/ DMA_Cmd(DMA2_Stream7, DISABLE); /*等待DMA关闭*/ while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE); /*清除传输已经完成TCIF7、传输已经完成一半HTIF7、FIFO错误FEIF7标志位*/ DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_FEIF7 | DMA_FLAG_HTIF7 | DMA_FLAG_TCIF7); /*配置发送地址和长度*/ DMA_MemoryTargetConfig(DMA2_Stream7, (uint32_t)txBuf, DMA_Memory_0); DMA_SetCurrDataCounter(DMA2_Stream7, len); /*启动 DMA 发送*/ DMA_Cmd(DMA2_Stream7, ENABLE); } /*modbus协议帧解析任务*/ void AppTaskModbusParse (void *p_arg) { INT8U err; MODBUS_FRAME frame; uint16_t rxLen; uint8_t rxBuf[256]; while(1) { 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; } }