/** * @file MODBUS_S_LOW_ATY.c * * @param Project DEVICE_GENERAL_ATY_LIB * * @author ATY * * @copyright * - Copyright 2017 - 2023 MZ-ATY * - This code follows: * - MZ-ATY Various Contents Joint Statement - * * https://mengze.top/MZ-ATY_VCJS * - CC 4.0 BY-NC-SA - * * https://creativecommons.org/licenses/by-nc-sa/4.0/ * - Your use will be deemed to have accepted the terms of this statement. * * @brief Familiar functions of modbus for all device * * @note 4 byte per reg, save float or uint32 * * @version * - 1_01_221029 > ATY * -# Preliminary version, first Release * - 1_02_240120 > ATY * -# add multy addr and channel * -# add lock ******************************************************************************** */ #ifndef __MODBUS_S_LOW_ATY_C #define __MODBUS_S_LOW_ATY_C #include "MODBUS_S_LOW_ATY.h" /******************************* For user *************************************/ /******************************************************************************/ /** * @brief modbus process * @param buf * @param len * @param dev * @return uint8_t * @note only make 03/06/10 function code, others will return err 01 */ uint8_t Modbus_Process(uint8_t* buf, uint8_t len, struct MODBUS_S_LOW_ATY_Dev* dev) { uint8_t sendBuf[(MODBUS_REG_HOLDING_SIZE * 2) + 4] = {0x00}; uint16_t sendBufSize = 4; __ATY_LOCK(dev); sendBuf[0] = buf[0]; sendBuf[1] = buf[1]; if(buf[0] == dev->addr){ // check addr if(len < 4){ // check buf min size sendBuf[1] = buf[1] + 0x80; sendBuf[2] = 0x02; sendBufSize = 6; } else if(CheckCrc16Modbus(buf, len)){ // check crc sendBuf[1] = buf[1] + 0x80; sendBuf[2] = 0x08; sendBufSize = 6; } else{ switch(buf[1]) // check function code { // case MODBUS_FUNC_READ_COILS:{break; } // case MODBUS_FUNC_READ_DISCRETE_INPUTS:{break; } case MODBUS_FUNC_READ_HOLDING_REGISTERS:{ uint16_t i = 0, startAddr = 0, regCount = 0; startAddr = ((buf[2] << 8) + buf[3]); regCount = ((buf[4] << 8) + buf[5]); if(startAddr + regCount - 1 > MODBUS_REG_HOLDING_SIZE){ sendBuf[1] = buf[1] + 0x80; sendBuf[2] = 0x02; sendBufSize = 6; break; } sendBuf[2] = regCount * 2; sendBufSize += 1; for(i = 0; i < regCount; i++){ if(dev->bigEndian){ sendBuf[2 + (i * 2) + 1] = dev->mbRegs[startAddr + i]; sendBuf[2 + (i * 2) + 2] = dev->mbRegs[startAddr + i] >> 8; } else{ sendBuf[2 + (i * 2) + 1] = dev->mbRegs[startAddr + i] >> 8; sendBuf[2 + (i * 2) + 2] = dev->mbRegs[startAddr + i]; } sendBufSize += 2; } break; } // case MODBUS_FUNC_READ_INPUT_REGISTERS:{break; } // case MODBUS_FUNC_WRITE_SINGLE_COIL:{break; } case MODBUS_FUNC_WRITE_SINGLE_HOLDING_REGISTERS:{ uint16_t startAddr = 0; startAddr = (((uint16_t)buf[2] << 8) + (uint16_t)buf[3]); if(startAddr >= MODBUS_REG_HOLDING_SIZE){ sendBuf[1] = buf[1] + 0x80; sendBuf[2] = 0x02; sendBufSize = 6; break; } if(dev->bigEndian){ dev->mbRegs[startAddr] = buf[4] + buf[5] << 8; } else{ dev->mbRegs[startAddr] = buf[4] << 8 + buf[5]; } sendBuf[2] = startAddr >> 8; sendBuf[3] = startAddr; if(dev->bigEndian){ sendBuf[4] = dev->mbRegs[startAddr]; sendBuf[5] = dev->mbRegs[startAddr] >> 8; } else{ sendBuf[4] = dev->mbRegs[startAddr] >> 8; sendBuf[5] = dev->mbRegs[startAddr]; } sendBufSize += 4; dev->setFlag = 1; break; } case MODBUS_FUNC_WRITE_MULTY_HOLDING_REGISTERS:{ uint16_t i = 0, startAddr = 0, regCount = 0; startAddr = ((buf[2] << 8) + buf[3]); regCount = ((buf[4] << 8) + buf[5]); if(startAddr + regCount - 1 > MODBUS_REG_HOLDING_SIZE){ sendBuf[1] = buf[1] + 0x80; sendBuf[2] = 0x02; sendBufSize = 6; break; } for(i = 0; i < regCount; i++) { if(dev->bigEndian){ dev->mbRegs[startAddr + i] = (buf[6 + (i * 2) + 1]) + (buf[6 + (i * 2) + 2] << 8); } else{ dev->mbRegs[startAddr + i] = (buf[6 + (i * 2) + 1] << 8) + (buf[6 + (i * 2) + 2]); } } sendBuf[2] = startAddr >> 8; sendBuf[3] = startAddr; sendBuf[4] = regCount >> 8; sendBuf[5] = regCount; sendBufSize += 4; dev->setFlag = 1; break; } default:{ sendBuf[1] = buf[1] + 0x80; sendBuf[2] = 0x01; sendBufSize = 6; break; } } } sendBuf[sendBufSize - 2] = GenCrc16ModbusHL(sendBuf, sendBufSize - 2, 1); sendBuf[sendBufSize - 1] = GenCrc16ModbusHL(sendBuf, sendBufSize - 2, 0); dev->uartSendBytes(sendBuf, sendBufSize); } __ATY_UNLOCK(dev); return 0; } /** * @brief * * @param floatBuf * @param dev */ void UpdateMbRegsFromFloat(float* floatBuf, struct MODBUS_S_LOW_ATY_Dev* dev) { union mbFloatChange mbFloatChange_u = {0}; uint8_t i = 0; for(i = 0; i < (uint8_t)(MODBUS_REG_HOLDING_SIZE / 2); i++){ mbFloatChange_u.f_t = floatBuf[i]; if(dev->bigEndian){ dev->mbRegs[i * 2] = (mbFloatChange_u.u8_t[0] << 8) + mbFloatChange_u.u8_t[1]; dev->mbRegs[(i * 2) + 1] = (mbFloatChange_u.u8_t[2] << 8) + mbFloatChange_u.u8_t[3]; } else{ dev->mbRegs[i * 2] = (mbFloatChange_u.u8_t[3] << 8) + mbFloatChange_u.u8_t[2]; dev->mbRegs[(i * 2) + 1] = (mbFloatChange_u.u8_t[1] << 8) + mbFloatChange_u.u8_t[0]; } } } /** * @brief * * @param floatBuf * @param dev */ void TransMbRegsToFloat(float* floatBuf, struct MODBUS_S_LOW_ATY_Dev* dev) { union mbFloatChange mbFloatChange_u = {0}; uint8_t i = 0; for(i = 0; i < (uint8_t)(MODBUS_REG_HOLDING_SIZE / 2); i++){ if(dev->bigEndian){ mbFloatChange_u.u8_t[0] = (uint8_t)(dev->mbRegs[i * 2] >> 8); mbFloatChange_u.u8_t[1] = (uint8_t)(dev->mbRegs[i * 2]); mbFloatChange_u.u8_t[2] = (uint8_t)(dev->mbRegs[(i * 2) + 1] >> 8); mbFloatChange_u.u8_t[3] = (uint8_t)(dev->mbRegs[(i * 2) + 1]); } else{ mbFloatChange_u.u8_t[3] = (uint8_t)(dev->mbRegs[i * 2] >> 8); mbFloatChange_u.u8_t[2] = (uint8_t)(dev->mbRegs[i * 2]); mbFloatChange_u.u8_t[1] = (uint8_t)(dev->mbRegs[(i * 2) + 1] >> 8); mbFloatChange_u.u8_t[0] = (uint8_t)(dev->mbRegs[(i * 2) + 1]); } floatBuf[i] = mbFloatChange_u.f_t; } } #endif /* __MODBUS_S_LOW_ATY_C */ /************************************ etc *************************************/ /* init */ // // mb // uint8_t MODBUS1_UART(uint8_t* buf, uint8_t len){ // UartSendBytes(buf, len, &HW_UART_ATY_Dev_3); // return 0; // } // struct MODBUS_S_LOW_ATY_Dev MODBUS_S_LOW_ATY_Dev_1 = { // .addr = 0x01, // .size = MODBUS_REG_HOLDING_SIZE, // .mbRegs = {0}, // .uartSendBytes = MODBUS1_UART, // .lock = _ATY_UNLOCKED, // .debugEnable = 0, // .LOG = printf // }; /* use */ // void UartReceiveProcess_User_3(void) // { // if((HW_UART_ATY_Dev_3.rx[0] == 'O' // && HW_UART_ATY_Dev_3.rx[1] == 'K' // && HW_UART_ATY_Dev_3.rx[2] == '?')) // UartSendStr("OK!", &HW_UART_ATY_Dev_3); // Modbus_Process(HW_UART_ATY_Dev_3.rx, HW_UART_ATY_Dev_3.rxCount, &MODBUS_S_LOW_ATY_Dev_1); // } // // 100ms cycle // { // UpdateMbRegsFromFloat(mbG, &MODBUS_S_LOW_ATY_Dev_1); // } /******************************************************************************/ /******************************** End Of File *********************************/