#include "modbus_block_host.hpp" #include "modbus_basic.hpp" using namespace iflytop; #define PRV_DEBUG 0 ModbusBlockHost::ModbusBlockHost() {} ModbusBlockHost::~ModbusBlockHost() {} extern "C" { void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {} } void ModbusBlockHost::initialize(UART_HandleTypeDef *huart) { this->huart = huart; m_modbus_lock.init(); } void ModbusBlockHost::cleanRxBuff() { // HAL_StatusTypeDef status; do { status = HAL_UART_Receive(huart, rxbuff, 1, 1); } while (status == HAL_OK); } void ModbusBlockHost::uarttx(uint8_t *buff, size_t len) { ZASSERT(len < sizeof(txbuff)); #if PRV_DEBUG printf("uart_tx:\n"); for (size_t i = 0; i < len; i++) { printf("%02x ", buff[i]); } printf("\n"); #endif // HAL_UART_Transmit(huart, buff, len, 1000); HAL_UART_DMAStop(huart); HAL_StatusTypeDef ret = HAL_UART_Transmit_DMA(huart, buff, len); ZASSERT(ret == HAL_OK); // 等待DMA传输完成 while (true) { if (HAL_UART_GetState(huart) == HAL_UART_STATE_READY) break; } return; } bool ModbusBlockHost::uartrx(uint8_t *buff, size_t len, int overtimems) { HAL_StatusTypeDef status; ZASSERT(len < sizeof(rxbuff)); status = HAL_UART_Receive_DMA(huart, buff, len); if (status != HAL_OK) { return false; } for (size_t i = 0; i < overtimems; i++) { osDelay(3); if (HAL_UART_GetState(huart) == HAL_UART_STATE_READY) { #if PRV_DEBUG if (status == HAL_OK) { printf("uart_rx:"); for (size_t i = 0; i < len; i++) { printf("%02x ", buff[i]); } printf("\n"); } #endif return true; } } #if PRV_DEBUG printf("uart_rx timeout\n"); #endif HAL_UART_Abort(huart); HAL_UART_DMAStop(huart); return false; } bool ModbusBlockHost::readReg03(uint8_t slaveAddr, uint16_t regAddr, uint16_t *regVal, int overtimems) { zlock_guard lck(m_modbus_lock); txbuff[0] = slaveAddr; txbuff[1] = 0x03; txbuff[2] = regAddr >> 8; txbuff[3] = regAddr & 0xff; txbuff[4] = 0x00; txbuff[5] = 0x01; modbus_pack_crc_to_packet(txbuff, 6 + 2); cleanRxBuff(); uarttx(txbuff, 6 + 2); bool status; status = uartrx(rxbuff, 5 + 2, overtimems); if (!status) { return false; } if (!modbus_checkcrc16(rxbuff, 7)) { ZLOGE("ModbusBlockHost", "crc error"); return false; } *regVal = (((uint16_t)(rxbuff[3])) << 8) | rxbuff[4]; return true; } // static const char *hex2str(uint8_t *buff, size_t len) { // static char str[100]; // for (size_t i = 0; i < len; i++) { // sprintf(str + i * 2, "%02x", buff[i]); // } // return str; // } bool ModbusBlockHost::readReg03Muti(uint8_t slaveAddr, uint16_t regAddr, uint16_t *regVal, int regNum, int overtimems) { zlock_guard lck(m_modbus_lock); txbuff[0] = slaveAddr; txbuff[1] = 0x03; txbuff[2] = regAddr >> 8; txbuff[3] = regAddr & 0xff; txbuff[4] = 0x00; txbuff[5] = regNum; modbus_pack_crc_to_packet(txbuff, 6 + 2); cleanRxBuff(); uarttx(txbuff, 6 + 2); bool status; // 14*2 = 28 status = uartrx(rxbuff, 5 + regNum * 2, overtimems); if (!status) { return false; } if (!modbus_checkcrc16(rxbuff, 5 + regNum * 2)) { ZLOGE("ModbusBlockHost", "crc error"); return false; } for (int i = 0; i < regNum; i++) { regVal[i] = ((uint16_t)(rxbuff[3 + i * 2]) << 8) | rxbuff[4 + i * 2]; // int16_t val = regVal[i] ; // ZLOGI("RX", "%d", val); } return true; } bool ModbusBlockHost::writeReg06(uint8_t slaveAddr, uint16_t regAddr, uint16_t regVal, int overtimems) { zlock_guard lck(m_modbus_lock); txbuff[0] = slaveAddr; txbuff[1] = 0x06; txbuff[2] = regAddr >> 8; txbuff[3] = regAddr & 0xff; txbuff[4] = regVal >> 8; txbuff[5] = regVal & 0xff; modbus_pack_crc_to_packet(txbuff, 6 + 2); cleanRxBuff(); uarttx(txbuff, 6 + 2); bool status; status = uartrx(rxbuff, 8, overtimems); if (status && modbus_checkcrc16(rxbuff, 8)) { return true; } return false; } bool ModbusBlockHost::writeReg10(uint8_t slaveAddr, uint16_t regAddr, uint16_t regVal, int overtimems) { zlock_guard lck(m_modbus_lock); txbuff[0] = slaveAddr; txbuff[1] = 0x10; txbuff[2] = regAddr >> 8; txbuff[3] = regAddr & 0xff; txbuff[4] = 0x00; txbuff[5] = 0x01; txbuff[6] = 0x02; // 字节数 txbuff[7] = regVal >> 8; txbuff[8] = regVal & 0xff; modbus_pack_crc_to_packet(txbuff, 9 + 2); cleanRxBuff(); uarttx(txbuff, 9 + 2); bool status; status = uartrx(rxbuff, 8, overtimems); if (status && modbus_checkcrc16(rxbuff, 8)) { return true; } return false; }