up
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
modbus_constants.h
|
||||||
430
modbus.c
Normal file
430
modbus.c
Normal file
@@ -0,0 +1,430 @@
|
|||||||
|
#include "modbus.h"
|
||||||
|
#define TX_EN GPIO_WriteBit(RS485_GPIO, RS485_GPIO_Pin, Bit_SET);
|
||||||
|
#define TX_DIS GPIO_WriteBit(RS485_GPIO, RS485_GPIO_Pin, Bit_RESET);
|
||||||
|
#define MODBUS_LED_ON GPIO_WriteBit(Modbus_LED, Modbus_LED_Pin, Bit_SET);
|
||||||
|
#define MODBUS_LED_OFF GPIO_WriteBit(Modbus_LED, Modbus_LED_Pin, Bit_RESET);
|
||||||
|
|
||||||
|
static uint8_t buf_ptr = 0;
|
||||||
|
static unsigned char rx_buf_ptr = 0;
|
||||||
|
static unsigned char rx_buf[128];
|
||||||
|
static unsigned char tx_buf[128];
|
||||||
|
|
||||||
|
static uint16_t addr_buf_1 = 0, addr_buf_2 = 0;
|
||||||
|
static uint16_t regs_to_read = 0;
|
||||||
|
static uint16_t CRC16 = 0;
|
||||||
|
static unsigned char crc_buf[300];
|
||||||
|
static unsigned char modbus_id = 0;
|
||||||
|
static uint16_t reg_wr_data = 0;
|
||||||
|
static uint16_t modbus_reg_addr;
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t holding_registers[MAX_HOLDING_REGISTERS];
|
||||||
|
static uint16_t input_registers[MAX_INPUT_REGISTERS];
|
||||||
|
|
||||||
|
static unsigned char rx_flag = 0;
|
||||||
|
static unsigned char timer_state = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t dev_id = DEFAULT_DEVICE_MODBUS_ID;
|
||||||
|
const uint16_t com_dev_id = 247;
|
||||||
|
|
||||||
|
static void (*ModbusUartSendByte)(USART_TypeDef*, unsigned char);
|
||||||
|
static int32_t (*ModbusTcpSendByte)(uint8_t, unsigned char*, uint16_t);
|
||||||
|
static void (*ModbusRIRPoll)(void);
|
||||||
|
static void (*ModbusRHRPoll)(void);
|
||||||
|
static void (*ModbusWSRPoll)(uint16_t, uint16_t);
|
||||||
|
|
||||||
|
void modbus_connect_callback_send_byte(void (*s)(USART_TypeDef*, unsigned char)) {
|
||||||
|
ModbusUartSendByte = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbus_connect_callback_send_buf_tcp(int32_t (*s)(uint8_t, unsigned char*, uint16_t)) {
|
||||||
|
ModbusTcpSendByte = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbus_connect_callback_rir_poll(void (*s)(void)) {
|
||||||
|
ModbusRIRPoll = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbus_connect_callback_rhr_poll(void (*s)(void)) {
|
||||||
|
ModbusRHRPoll = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbus_connect_callback_wsr_poll(void (*s)(uint16_t, uint16_t)) {
|
||||||
|
ModbusWSRPoll = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t modbus_CRC16(unsigned char buf[], uint16_t len)
|
||||||
|
{
|
||||||
|
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> crc16
|
||||||
|
|
||||||
|
uint16_t crc = 0xFFFF;
|
||||||
|
//U8 crc_lsb, crc_msb;
|
||||||
|
for (uint16_t pos = 0; pos < len; pos++) {
|
||||||
|
crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc
|
||||||
|
for (int i = 8; i != 0; i--) { // Loop over each bit
|
||||||
|
if ((crc & 0x0001) != 0) { // If the LSB is set
|
||||||
|
crc >>= 1; // Shift right and XOR 0xA001
|
||||||
|
crc ^= 0xA001;
|
||||||
|
}
|
||||||
|
else // Else LSB is not set
|
||||||
|
crc >>= 1; // Just shift right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, this number has low and high bytes swapped,
|
||||||
|
// so use it accordingly (or swap bytes)
|
||||||
|
// swapping bytes
|
||||||
|
crc = ((crc<<8)&0xff00)|((crc>>8)&0x00ff);
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbus_wsr_answer() {
|
||||||
|
crc_buf[0] = (modbus_id == dev_id) ? dev_id : com_dev_id;
|
||||||
|
crc_buf[1] = (unsigned char) MODBUS_WSR_CMD;
|
||||||
|
crc_buf[2] = (unsigned char) (modbus_reg_addr >> 8);
|
||||||
|
crc_buf[3] = (unsigned char) (modbus_reg_addr & 0xff);
|
||||||
|
crc_buf[4] = (unsigned char) (reg_wr_data >> 8);
|
||||||
|
crc_buf[5] = (unsigned char) (reg_wr_data & 0xff);
|
||||||
|
|
||||||
|
CRC16 = modbus_CRC16(crc_buf, 6);
|
||||||
|
|
||||||
|
switch(CURRENT_OPERATION_MODE) {
|
||||||
|
case 0:
|
||||||
|
TX_EN;
|
||||||
|
ModbusUartSendByte(Modbus_UART, (modbus_id == dev_id) ? dev_id : com_dev_id);
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char)MODBUS_WSR_CMD);
|
||||||
|
ModbusUartSendByte(Modbus_UART, modbus_reg_addr >> 8);
|
||||||
|
ModbusUartSendByte(Modbus_UART, modbus_reg_addr & 0xff);
|
||||||
|
ModbusUartSendByte(Modbus_UART, reg_wr_data >> 8);
|
||||||
|
ModbusUartSendByte(Modbus_UART, reg_wr_data & 0xff);
|
||||||
|
|
||||||
|
ModbusUartSendByte(Modbus_UART, CRC16 >> 8);
|
||||||
|
ModbusUartSendByte(Modbus_UART, CRC16 & 0xff);
|
||||||
|
TX_DIS;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tx_buf[0] = (modbus_id == dev_id) ? dev_id : com_dev_id;
|
||||||
|
tx_buf[1] = MODBUS_WSR_CMD;
|
||||||
|
tx_buf[2] = modbus_reg_addr >> 8;
|
||||||
|
tx_buf[3] = modbus_reg_addr & 0xff;
|
||||||
|
tx_buf[4] = reg_wr_data >> 8;
|
||||||
|
tx_buf[5] = reg_wr_data & 0xff;
|
||||||
|
tx_buf[6] = CRC16 >> 8;
|
||||||
|
tx_buf[7] = CRC16 & 0xff;
|
||||||
|
|
||||||
|
ModbusTcpSendByte(DEFAULT_TCP_MODBUS_SOCKET, tx_buf, 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbus_rir_answer() {
|
||||||
|
buf_ptr = 0;
|
||||||
|
addr_buf_1 = modbus_reg_addr;
|
||||||
|
addr_buf_2 = addr_buf_1;
|
||||||
|
|
||||||
|
crc_buf[0] = (modbus_id == dev_id) ? dev_id : com_dev_id;
|
||||||
|
crc_buf[1] = MODBUS_RIR_CMD;
|
||||||
|
crc_buf[2] = regs_to_read * 2;
|
||||||
|
|
||||||
|
unsigned char cnt = CRC_COUNT_OFFSET;
|
||||||
|
|
||||||
|
for (int i = 0; i < regs_to_read; i++) {
|
||||||
|
crc_buf[cnt++] = (unsigned char)(input_registers[addr_buf_1] >> 8);
|
||||||
|
crc_buf[cnt++] = (unsigned char)(input_registers[addr_buf_1] & 0xff);
|
||||||
|
++addr_buf_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRC16 = modbus_CRC16(crc_buf, regs_to_read * 2 + CRC_COUNT_OFFSET);
|
||||||
|
|
||||||
|
switch(CURRENT_OPERATION_MODE) {
|
||||||
|
case 0:
|
||||||
|
TX_EN;
|
||||||
|
ModbusUartSendByte(Modbus_UART, (modbus_id == dev_id) ? dev_id : com_dev_id);
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char) MODBUS_RIR_CMD);
|
||||||
|
ModbusUartSendByte(Modbus_UART, regs_to_read * 2);
|
||||||
|
|
||||||
|
for (int i = 0; i < regs_to_read; i++) {
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char)(input_registers[addr_buf_2] >> 8));
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char)(input_registers[addr_buf_2] & 0xff));
|
||||||
|
++addr_buf_2;
|
||||||
|
}
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char)(CRC16 >> 8));
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char)(CRC16 & 0xff));
|
||||||
|
TX_DIS;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tx_buf[buf_ptr++] = (modbus_id == dev_id) ? dev_id : com_dev_id;
|
||||||
|
tx_buf[buf_ptr++] = (unsigned char) MODBUS_RIR_CMD;
|
||||||
|
tx_buf[buf_ptr++] = regs_to_read * 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < regs_to_read; i++) {
|
||||||
|
tx_buf[buf_ptr++] = (unsigned char)(input_registers[addr_buf_2] >> 8);
|
||||||
|
tx_buf[buf_ptr++] = (unsigned char)(input_registers[addr_buf_2] & 0xff);
|
||||||
|
++addr_buf_2;
|
||||||
|
}
|
||||||
|
tx_buf[buf_ptr++] = CRC16 >> 8;
|
||||||
|
tx_buf[buf_ptr++] = CRC16 & 0xff;
|
||||||
|
ModbusTcpSendByte(DEFAULT_TCP_MODBUS_SOCKET, tx_buf, buf_ptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbus_rhr_answer() {
|
||||||
|
buf_ptr = 0;
|
||||||
|
addr_buf_1 = modbus_reg_addr;
|
||||||
|
addr_buf_2 = addr_buf_1;
|
||||||
|
|
||||||
|
crc_buf[0] = (modbus_id == dev_id) ? dev_id : com_dev_id;
|
||||||
|
crc_buf[1] = MODBUS_RHR_CMD;
|
||||||
|
crc_buf[2] = regs_to_read * 2;
|
||||||
|
|
||||||
|
unsigned char cnt = CRC_COUNT_OFFSET;
|
||||||
|
|
||||||
|
for (int i = 0; i < regs_to_read; i++) {
|
||||||
|
crc_buf[cnt++] = (unsigned char)(holding_registers[addr_buf_1] >> 8);
|
||||||
|
crc_buf[cnt++] = (unsigned char)(holding_registers[addr_buf_1] & 0xff);
|
||||||
|
++addr_buf_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRC16 = modbus_CRC16(crc_buf, regs_to_read * 2 + CRC_COUNT_OFFSET);
|
||||||
|
|
||||||
|
switch(CURRENT_OPERATION_MODE) {
|
||||||
|
case 0:
|
||||||
|
TX_EN;
|
||||||
|
ModbusUartSendByte(Modbus_UART, (modbus_id == dev_id) ? dev_id : com_dev_id);
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char) MODBUS_RHR_CMD);
|
||||||
|
ModbusUartSendByte(Modbus_UART, regs_to_read * 2);
|
||||||
|
|
||||||
|
for (int i = 0; i < regs_to_read; i++) {
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char)(holding_registers[addr_buf_2] >> 8));
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char)(holding_registers[addr_buf_2] & 0xff));
|
||||||
|
++addr_buf_2;
|
||||||
|
}
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char)(CRC16 >> 8));
|
||||||
|
ModbusUartSendByte(Modbus_UART, (unsigned char)(CRC16 & 0xff));
|
||||||
|
TX_DIS;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tx_buf[buf_ptr++] = (modbus_id == dev_id) ? dev_id : com_dev_id;
|
||||||
|
tx_buf[buf_ptr++] = (unsigned char) MODBUS_RHR_CMD;
|
||||||
|
tx_buf[buf_ptr++] = regs_to_read * 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < regs_to_read; i++) {
|
||||||
|
tx_buf[buf_ptr++] = (unsigned char)(holding_registers[addr_buf_2] >> 8);
|
||||||
|
tx_buf[buf_ptr++] = (unsigned char)(holding_registers[addr_buf_2] & 0xff);
|
||||||
|
++addr_buf_2;
|
||||||
|
}
|
||||||
|
tx_buf[buf_ptr++] = CRC16 >> 8;
|
||||||
|
tx_buf[buf_ptr++] = CRC16 & 0xff;
|
||||||
|
ModbusTcpSendByte(DEFAULT_TCP_MODBUS_SOCKET, tx_buf, buf_ptr);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char modbus_rx_CRC_check(unsigned char modbus_cmd) {
|
||||||
|
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CRC <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
uint16_t CRC16_calc = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
unsigned char ans = 0;
|
||||||
|
|
||||||
|
modbus_reg_addr = (uint16_t)((rx_buf[2] << 8) | rx_buf[3]); // get starting reg addr
|
||||||
|
|
||||||
|
crc_buf[0] = (modbus_id == dev_id) ? dev_id : com_dev_id;
|
||||||
|
crc_buf[2] = (unsigned char)(modbus_reg_addr >> 8);
|
||||||
|
crc_buf[3] = (unsigned char)(modbus_reg_addr & 0x00ff);
|
||||||
|
|
||||||
|
|
||||||
|
switch(modbus_cmd) {
|
||||||
|
case MODBUS_WSR_CMD:
|
||||||
|
reg_wr_data = (rx_buf[4] << 8) | rx_buf[5]; // get data to write into reg
|
||||||
|
|
||||||
|
crc_buf[1] = (unsigned char) MODBUS_WSR_CMD;
|
||||||
|
crc_buf[4] = (unsigned char)(reg_wr_data >> 8);
|
||||||
|
crc_buf[5] = (unsigned char)(reg_wr_data & 0x00ff);
|
||||||
|
break;
|
||||||
|
//----
|
||||||
|
case MODBUS_RHR_CMD:
|
||||||
|
regs_to_read = (rx_buf[4] << 8) | rx_buf[5]; // get number of regs to read
|
||||||
|
|
||||||
|
crc_buf[1] = (unsigned char) MODBUS_RHR_CMD;
|
||||||
|
crc_buf[4] = (unsigned char)(regs_to_read >> 8);
|
||||||
|
crc_buf[5] = (unsigned char)(regs_to_read & 0x00ff);
|
||||||
|
break;
|
||||||
|
//----
|
||||||
|
case MODBUS_RIR_CMD:
|
||||||
|
regs_to_read = (rx_buf[4] << 8) | rx_buf[5]; // get number of regs to read
|
||||||
|
|
||||||
|
crc_buf[1] = (unsigned char) MODBUS_RIR_CMD;
|
||||||
|
crc_buf[4] = (unsigned char)(regs_to_read >> 8);
|
||||||
|
crc_buf[5] = (unsigned char)(regs_to_read & 0x00ff);
|
||||||
|
break;
|
||||||
|
//----
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRC16 = (rx_buf[6] << 8) | rx_buf[7]; // get CRC16 from rx msg
|
||||||
|
CRC16_calc = modbus_CRC16(crc_buf,6); // calc CRC16
|
||||||
|
|
||||||
|
if(CRC16_calc == CRC16)
|
||||||
|
ans = modbus_cmd;
|
||||||
|
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char modbus_get_poll(void)
|
||||||
|
{
|
||||||
|
/// update modbus regs and vars, send answer to master
|
||||||
|
unsigned char rx_cmd_code = 0; // ??? ??????????? ???????rx_cmd_code = 0;
|
||||||
|
// state 1 and 2, transmit end, rx buf has > 7 bytes ?
|
||||||
|
//
|
||||||
|
if ( rx_flag == 1 ) {
|
||||||
|
if( rx_buf_ptr > 7 ) {
|
||||||
|
modbus_id = rx_buf[0]; // get device ID from master msg
|
||||||
|
|
||||||
|
if((modbus_id == dev_id) || (modbus_id == com_dev_id)) {
|
||||||
|
switch(rx_buf[1]) {
|
||||||
|
case MODBUS_RHR_CMD: // ???? ??????? - ?????? R/W ?????????
|
||||||
|
if(modbus_rx_CRC_check(MODBUS_RHR_CMD) == MODBUS_RHR_CMD) {
|
||||||
|
rx_cmd_code = MODBUS_RHR_CMD;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
////-------------------------------------------------------------------
|
||||||
|
case MODBUS_WSR_CMD: // ???? ??????? - ?????? Read-only ?????????
|
||||||
|
if(modbus_rx_CRC_check(MODBUS_WSR_CMD) == MODBUS_WSR_CMD) {
|
||||||
|
rx_cmd_code = MODBUS_WSR_CMD;
|
||||||
|
holding_reg_write(modbus_reg_addr, reg_wr_data); // !!!!
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
////-------------------------------------------------------------------
|
||||||
|
case MODBUS_RIR_CMD:
|
||||||
|
if(modbus_rx_CRC_check(MODBUS_RIR_CMD) == MODBUS_RIR_CMD) {
|
||||||
|
rx_cmd_code = MODBUS_RIR_CMD;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} // switch(rx_buf[1])
|
||||||
|
modbus_reset();
|
||||||
|
} else {
|
||||||
|
modbus_reset();
|
||||||
|
}// if dev_id
|
||||||
|
} else { modbus_reset(); } // if(rx_buf_pos > 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rx_cmd_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
void modbus_reset(void)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 128; i++)
|
||||||
|
rx_buf[i] = 0;
|
||||||
|
|
||||||
|
rx_buf_ptr = 0;
|
||||||
|
rx_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void holding_reg_write(uint16_t red_addr, uint16_t value) {
|
||||||
|
holding_registers[red_addr] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void holding_reg_read(uint16_t red_addr, uint16_t *usr_var_ptr) {
|
||||||
|
*usr_var_ptr = holding_registers[red_addr];
|
||||||
|
}
|
||||||
|
|
||||||
|
void input_reg_read(uint16_t red_addr, uint16_t *usr_var_ptr) {
|
||||||
|
*usr_var_ptr = input_registers[red_addr];
|
||||||
|
}
|
||||||
|
|
||||||
|
void input_reg_write(uint16_t reg_addr, uint16_t value) {
|
||||||
|
input_registers[reg_addr] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t get_wr_reg_addr(void) {
|
||||||
|
return modbus_reg_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t get_wr_reg_val(void) {
|
||||||
|
return reg_wr_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char get_modbus_id(void) {
|
||||||
|
return dev_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_modbus_id(unsigned char newID)
|
||||||
|
{
|
||||||
|
dev_id = newID;
|
||||||
|
modbus_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t RegisterAddr = 0;
|
||||||
|
static uint16_t RegisterValue = 0;
|
||||||
|
|
||||||
|
void modbus_poll(void) {
|
||||||
|
uint8_t mb_get_poll = modbus_get_poll();
|
||||||
|
switch(mb_get_poll) {
|
||||||
|
//////////////////////////// READING INPUTS //////////////////////////
|
||||||
|
case MODBUS_RIR_CMD:
|
||||||
|
MODBUS_LED_ON;
|
||||||
|
ModbusRIRPoll();
|
||||||
|
modbus_rir_answer();
|
||||||
|
MODBUS_LED_OFF;
|
||||||
|
break;
|
||||||
|
//////////////////////////// READING HOLDING //////////////////////////
|
||||||
|
case MODBUS_RHR_CMD:
|
||||||
|
MODBUS_LED_ON;
|
||||||
|
ModbusRHRPoll();
|
||||||
|
modbus_rhr_answer();
|
||||||
|
MODBUS_LED_OFF;
|
||||||
|
break;
|
||||||
|
//////////////////////////// WRITING HOLDING //////////////////////////
|
||||||
|
case MODBUS_WSR_CMD:
|
||||||
|
MODBUS_LED_ON;
|
||||||
|
modbus_wsr_answer();
|
||||||
|
|
||||||
|
RegisterAddr = get_wr_reg_addr(); // get address
|
||||||
|
RegisterValue = get_wr_reg_val(); // get the new value
|
||||||
|
|
||||||
|
ModbusWSRPoll(RegisterAddr, RegisterValue);
|
||||||
|
MODBUS_LED_OFF; // LED toggle
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
}
|
||||||
|
//======================= UART HANDLERS =========================//
|
||||||
|
void Modbus_UART_IRQHandler(void) {
|
||||||
|
if (USART_GetITStatus(Modbus_UART, USART_IT_RXNE) != RESET) {
|
||||||
|
while(USART_GetFlagStatus(Modbus_UART,USART_FLAG_RXNE) == RESET) {}
|
||||||
|
if (rx_buf_ptr < 128) {
|
||||||
|
rx_buf[rx_buf_ptr++] = (unsigned char)Modbus_UART -> DR;
|
||||||
|
} else {
|
||||||
|
Modbus_UART -> DR;
|
||||||
|
}
|
||||||
|
USART_ClearITPendingBit(Modbus_UART, USART_IT_RXNE);
|
||||||
|
|
||||||
|
if (timer_state == 0) {
|
||||||
|
timer_state = 1;
|
||||||
|
Modbus_TIM -> CNT = 0;
|
||||||
|
TIM_Cmd(Modbus_TIM, ENABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modbus_TIM_IRQHandler(void) {
|
||||||
|
if (TIM_GetITStatus(Modbus_TIM, TIM_IT_Update) != RESET)
|
||||||
|
TIM_ClearITPendingBit(Modbus_TIM, TIM_IT_Update);
|
||||||
|
|
||||||
|
TIM_Cmd(Modbus_TIM, DISABLE);
|
||||||
|
timer_state = 0;
|
||||||
|
rx_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//======================== TCP HANDLERS ========================//
|
||||||
|
void Modbus_TCP_Handler(unsigned char* buf, uint8_t size) {
|
||||||
|
for (rx_buf_ptr = 0; rx_buf_ptr < size; rx_buf_ptr++) {
|
||||||
|
rx_buf[rx_buf_ptr] = buf[rx_buf_ptr];
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_flag = 1;
|
||||||
|
}
|
||||||
38
modbus.h
Normal file
38
modbus.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef _MODBUS_H
|
||||||
|
#define _MODBUS_H
|
||||||
|
|
||||||
|
// Includes
|
||||||
|
#include "modbus_constants.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
void Modbus_TCP_Handler(unsigned char*, uint8_t);
|
||||||
|
static unsigned char modbus_rx_buf[128];
|
||||||
|
|
||||||
|
#define CRC_COUNT_OFFSET 3
|
||||||
|
|
||||||
|
#define MODBUS_RHR_CMD (unsigned char)0x03
|
||||||
|
#define MODBUS_RIR_CMD (unsigned char)0x04
|
||||||
|
#define MODBUS_WSR_CMD (unsigned char)0x06
|
||||||
|
|
||||||
|
void modbus_wsr_answer(void);
|
||||||
|
void modbus_rhr_answer(void);
|
||||||
|
unsigned char modbus_get_poll(void);
|
||||||
|
void holding_reg_write(uint16_t, uint16_t);
|
||||||
|
void holding_reg_read(uint16_t, uint16_t*);
|
||||||
|
void input_reg_write(uint16_t, uint16_t);
|
||||||
|
void input_reg_read(uint16_t, uint16_t*);
|
||||||
|
uint16_t get_wr_reg_addr(void);
|
||||||
|
uint16_t get_wr_reg_val(void);
|
||||||
|
unsigned char get_modbus_id(void);
|
||||||
|
void set_modbus_id(unsigned char);
|
||||||
|
|
||||||
|
|
||||||
|
void modbus_connect_callback_send_byte(void (*s)(USART_TypeDef*, unsigned char));
|
||||||
|
void modbus_connect_callback_send_buf_tcp(int32_t (*s)(uint8_t, unsigned char*, uint16_t));
|
||||||
|
void modbus_connect_callback_rir_poll(void (*s)(void));
|
||||||
|
void modbus_connect_callback_rhr_poll(void (*s)(void));
|
||||||
|
void modbus_connect_callback_wsr_poll(void (*s)(uint16_t, uint16_t));
|
||||||
|
void modbus_poll(void);
|
||||||
|
void modbus_reset(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
28
modbus_constants_example.h
Normal file
28
modbus_constants_example.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef _MODBUS_CONSTANTS_H
|
||||||
|
#define _MODBUS_CONSTANTS_H
|
||||||
|
|
||||||
|
#define MAX_HOLDING_REGISTERS 300
|
||||||
|
#define MAX_INPUT_REGISTERS 300
|
||||||
|
|
||||||
|
// MCU Includes
|
||||||
|
|
||||||
|
#include "stm32f4xx.h"
|
||||||
|
#include "stm32f4xx_usart.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Needed Constants
|
||||||
|
|
||||||
|
#define DEFAULT_DEVICE_MODBUS_ID 1
|
||||||
|
#define DEFAULT_TCP_MODBUS_SOCKET 0
|
||||||
|
#define CURRENT_OPERATION_MODE 1 // UART - 0, TCP - 1
|
||||||
|
|
||||||
|
#define RS485_GPIO GPIOB
|
||||||
|
#define RS485_GPIO_Pin GPIO_Pin_6
|
||||||
|
#define Modbus_UART USART2
|
||||||
|
#define Modbus_TIM TIM2
|
||||||
|
#define Modbus_UART_IRQHandler USART2_IRQHandler
|
||||||
|
#define Modbus_TIM_IRQHandler TIM2_IRQHandler
|
||||||
|
#define Modbus_LED GPIOD
|
||||||
|
#define Modbus_LED_Pin GPIO_Pin_2
|
||||||
|
|
||||||
|
#endif
|
||||||
10
readme.txt
Normal file
10
readme.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Modbus Library for slave devices based on STM32 MCU (v5)
|
||||||
|
Supports Modbus RTU and Modbus RTU over TCP modes.
|
||||||
|
|
||||||
|
Original library was written by @ponkin_dmitry
|
||||||
|
|
||||||
|
Single header library which allow you to connect your devices using Modbus protocol.
|
||||||
|
Main configuration takes place in `modbus_constants.h` file.
|
||||||
|
|
||||||
|
Buffer sizes needs to be set via definitions `MAX_HOLDING_REGISTERS` and `MAX_INPUT_REGISTERS`.
|
||||||
|
Create your `modbus_constants.h` header file from example which is in the current repo.
|
||||||
Reference in New Issue
Block a user