Migrated to a new HAL version; FW now works; Adress is 38, board type is 12

This commit is contained in:
Anton Mukhin
2024-07-25 16:25:03 +03:00
parent 7da825917f
commit 07be2f747f
12 changed files with 4757 additions and 16 deletions

269
Core/Src/modbus_logic.c Normal file
View File

@@ -0,0 +1,269 @@
/*
* modbus_logic.c
*
* Created on: Jul 25, 2024
* Author: User
*/
#include <stdint.h>
#include "main.h"
#include "modbus_logic.h"
extern UART_HandleTypeDef huart1;
extern DMA_HandleTypeDef hdma_usart1_rx;
uint8_t recv_buffer[BUFFERS_SIZE];
uint8_t send_buffer[BUFFERS_SIZE];
uint16_t bytes_to_send = 0;
//uint16_t last_rx_time = 0xFFFF;
enum recv_state cmd_receiving = RECV_IDLE;
enum send_state cmd_sending = SEND_IDLE;
uint16_t tranfer_errors_count;
extern uint16_t led_time_act;
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if (huart->Instance == USART1)
{
if (recv_buffer[5] != BOARD_ADRESS)
{
cmd_receiving = RECV_ERROR;
return;
}
// Check function code
if (recv_buffer[6] == 3 || recv_buffer[6] == 4 || recv_buffer[6] == 6)
{
if(Size==MODBUS_HEADER_SIZE)cmd_receiving = RECV_READ_COMPLETE;
return;
}
else if (recv_buffer[6] == 0x10)
{
uint16_t pdu_size = *((uint16_t*)(recv_buffer + 2));
uint16_t remaining_size = pdu_size - (MODBUS_HEADER_SIZE - 4) + 2;
if (remaining_size + MODBUS_HEADER_SIZE == Size)
cmd_receiving = RECV_READ_COMPLETE;
else
{
cmd_receiving = RECV_ERROR;
tranfer_errors_count++;
}
return;
}
else
{
tranfer_errors_count++;
cmd_receiving = RECV_ERROR;
return;
}
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
cmd_sending = SEND_IDLE;
TXEN_OFF;
}
}
void modbus_loop_iterate()
{
if (cmd_sending == SEND_IDLE)
{
if (cmd_receiving == RECV_ERROR)
{
cmd_receiving = RECV_IDLE;
}
if (cmd_receiving == RECV_IDLE)
{
if(HAL_UARTEx_ReceiveToIdle_DMA(&huart1, recv_buffer, BUFFERS_SIZE)==HAL_OK)
{
cmd_receiving = RECV_READ_HEADER;
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
}
}
else if (cmd_receiving == RECV_READ_COMPLETE)
{
process_incoming_packet();
cmd_receiving = RECV_IDLE;
}
}
else if (cmd_sending == SEND_BUSY && bytes_to_send != 0)
{
TXEN_ON;
HAL_UART_Transmit_DMA(&huart1, send_buffer, bytes_to_send);
bytes_to_send = 0;
}
}
static uint16_t checksum(int size)
{
uint16_t index;
uint16_t checksum = 0;
for (index = 0; index < size; index++)
checksum += send_buffer[index];
return checksum;
}
void process_incoming_packet()
{
uint8_t source;
uint8_t dest;
uint8_t func_code;
uint16_t checksum_recv;
uint16_t transaction_id;
uint16_t pdu_size;
uint16_t checksum_real;
uint16_t response_pdu_length;
uint16_t address;
uint8_t write_result;
uint16_t size;
uint16_t i;
led_time_act=100;
dest = recv_buffer[5];
if(dest!=BOARD_ADRESS)return;
transaction_id = *((uint16_t*)(recv_buffer));
pdu_size = *((uint16_t*)(recv_buffer + 2));
if (pdu_size + 6 > BUFFERS_SIZE)
{
tranfer_errors_count++;
return;
}
source = recv_buffer[4];
func_code = recv_buffer[6];
//checksum_recv = *((uint16_t*)(recv_buffer + 4 + pdu_size));
checksum_recv = recv_buffer[4 + pdu_size];
checksum_recv += ((uint16_t)recv_buffer[5 + pdu_size])<<8;
checksum_real = 0;
for (i = 0; i < 4 + pdu_size; i++)
checksum_real += recv_buffer[i];
if (checksum_recv != checksum_real)
{
tranfer_errors_count++;
return;
}
// Prepare response header
*(uint16_t*)(send_buffer) = transaction_id;
send_buffer[4] = BOARD_ADRESS;
send_buffer[5] = source;
response_pdu_length = 0;
if ((func_code == 3 || func_code == 4) && pdu_size == 7) // Read holding/input registers
{
uint16_t start_address = *((uint16_t*)(recv_buffer + 7));
uint16_t quantity = *((uint16_t*)(recv_buffer + 9));
if (quantity > MAX_REGS_PER_QUERY)
{
tranfer_errors_count++;
return;
}
response_pdu_length = 2 * quantity + 1 + 3;
send_buffer[6] = func_code;
send_buffer[7] = 0; // bytes counter
for (address = start_address; address < start_address + quantity; address++)
{
uint16_t value;
uint8_t read_result = read_register(address, &value);
if (read_result != 0)
{
send_buffer[6] = func_code + 0x80;
send_buffer[7] = read_result;
response_pdu_length = 4;
break;
}
send_buffer[7] += 2;
*((uint16_t*)(&(send_buffer[8 + 2 * (address - start_address)]))) = value;
}
}
else if (func_code == 6 && pdu_size == 7) // Write holding register
{
uint16_t address = *((uint16_t*)(recv_buffer + 7));
uint16_t value = *((uint16_t*)(recv_buffer + 9));
response_pdu_length = 7;
send_buffer[6] = func_code;
write_result = write_register(address, value);
if (write_result == 0)
{
//*((uint16_t*)(send_buffer + 7)) = address;
send_buffer[7] = (uint8_t)(address&0x00FF);
send_buffer[8] = (uint8_t)((address&0xFF00)>>8);
//*((uint16_t*)(send_buffer + 9)) = value;
send_buffer[9] = (uint8_t)(value&0x00FF);
send_buffer[10] = (uint8_t)((value&0xFF00)>>8);
}
else
{
response_pdu_length = 4;
send_buffer[6] = 0x86;
send_buffer[7] = write_result;
}
}
else if (func_code == 0x10) // Write multiple registers
{
uint16_t start_address = *((uint16_t*)(recv_buffer + 7));
uint16_t quantity = *((uint16_t*)(recv_buffer + 9));
uint8_t byte_count = recv_buffer[11];
if (pdu_size != 3 + 5 + quantity * 2 || quantity * 2 != byte_count)
{
tranfer_errors_count++;
return;
}
response_pdu_length = 7;
send_buffer[6] = func_code;
//*((uint16_t*)(send_buffer + 7)) = start_address;
send_buffer[7] = (uint8_t)(start_address&0x00FF);
send_buffer[8] = (uint8_t)((start_address&0xFF00)>>8);
//*((uint16_t*)(send_buffer + 9)) = quantity;
send_buffer[9] = (uint8_t)(quantity&0x00FF);
send_buffer[10] = (uint8_t)((quantity&0xFF00)>>8);
for (address = start_address; address < start_address + quantity; address++)
{
uint16_t value = *((uint16_t*)(recv_buffer + 12u + 2u * (address - start_address)));
write_result = write_register(address, value);
if (write_result != 0)
{
response_pdu_length = 4;
send_buffer[6] = 0x90;
send_buffer[7] = write_result;
break;
}
}
}
else
{
tranfer_errors_count++;
return;
}
//*((uint16_t*)(send_buffer + 2)) = response_pdu_length;
send_buffer[2] = (uint8_t)(response_pdu_length&0x00FF);
send_buffer[3] = (uint8_t)((response_pdu_length&0xFF00)>>8);
size = 4 + response_pdu_length;
//*((uint16_t*)(send_buffer + size)) = checksum(size);
uint16_t s = checksum(size);
send_buffer[size] = (uint8_t)(s&0x00FF);
send_buffer[size+1] = (uint8_t)((s&0xFF00)>>8);
if (cmd_sending == SEND_IDLE)
{
bytes_to_send = size + 2;
cmd_sending = SEND_BUSY;
}
else
{
tranfer_errors_count++;
}
}