Files
ch32v003-ext-board/ch32ext.c

81 lines
2.0 KiB
C

#include <stdio.h>
#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;
}
}
}