#include #include "ch32v003fun.h" #include "modbus.h" #include "rs485.h" #include "shift_reg.h" #include "simple_eeprom.h" #include "state_manager.h" #include "systick.h" #define SLAVE_ADDRESS 0x01 #define MAX_MODBUS_FRAME 16 #define NUM_REGISTERS 1 #define FRAME_TIMEOUT_MS 4 // 3.5 char times at 9600 baud (~1.042ms per char) static uint16_t holding_registers[NUM_REGISTERS]; static void handle_modbus_frame(uint8_t* rx_buffer, uint16_t rx_count) { uint8_t response[MAX_MODBUS_FRAME]; uint16_t response_len; uint8_t result; result = modbus_process_message(rx_buffer, rx_count, SLAVE_ADDRESS, holding_registers, NUM_REGISTERS); if (result == MODBUS_ERROR_NONE) { shift_reg_write(holding_registers[0]); save_state(holding_registers[0]); response_len = modbus_create_response(response, SLAVE_ADDRESS, MODBUS_FC_WRITE_SINGLE_REGISTER, 0, holding_registers[0]); } else { response_len = modbus_create_error_response( response, SLAVE_ADDRESS, MODBUS_FC_WRITE_SINGLE_REGISTER, result); } rs485_send(response, response_len); } int main(void) { uint8_t rx_buffer[MAX_MODBUS_FRAME]; uint16_t rx_count = 0; uint32_t last_byte_time = 0; SystemInit(); systick_init(); shift_reg_init(); rs485_init(UART_BRR); // restore last saved state holding_registers[0] = load_state(); shift_reg_write(holding_registers[0]); while (1) { if (!rs485_available()) { continue; } uint32_t current_time = millis(); // check for frame timeout if (rx_count > 0 && (current_time - last_byte_time) > FRAME_TIMEOUT_MS) { rx_count = 0; } rx_buffer[rx_count++] = rs485_read(); last_byte_time = current_time; // process complete frame if (rx_count >= 8) { handle_modbus_frame(rx_buffer, rx_count); rx_count = 0; } // buffer overflow protection if (rx_count >= MAX_MODBUS_FRAME) { rx_count = 0; } } }