29
project/Core/Inc/modbus_tcp.h
Normal file
29
project/Core/Inc/modbus_tcp.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* @file modbus_tcp.h
|
||||||
|
*
|
||||||
|
* @brief TCP Modbus handler
|
||||||
|
* @date Nov 6, 2023
|
||||||
|
* @author Obe
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INC_MODBUS_H_
|
||||||
|
#define INC_MODBUS_H_
|
||||||
|
|
||||||
|
#define MODBUSPORT 502 // 502 is the default
|
||||||
|
|
||||||
|
|
||||||
|
#include <tcp.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "lcd_api.h"
|
||||||
|
#include "llfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void modbus_init
|
||||||
|
* @brief Initializes the modbus tcp
|
||||||
|
*/
|
||||||
|
void modbus_init(void);
|
||||||
|
|
||||||
|
#endif /* INC_MODBUS_H_ */
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "lcd_api.h"
|
#include "lcd_api.h"
|
||||||
#include "mqtt_application.h"
|
#include "mqtt_application.h"
|
||||||
#include "tftp.h"
|
#include "tftp.h"
|
||||||
|
#include "modbus_tcp.h"
|
||||||
#include "UDP_broadcast.h"
|
#include "UDP_broadcast.h"
|
||||||
|
|
||||||
/* USER CODE END Includes */
|
/* USER CODE END Includes */
|
||||||
@@ -134,7 +135,9 @@ int main(void)
|
|||||||
|
|
||||||
/* Initialize the tftp server */
|
/* Initialize the tftp server */
|
||||||
tftp_server_init();
|
tftp_server_init();
|
||||||
|
|
||||||
|
/* Initialize Modbus*/
|
||||||
|
modbus_init();
|
||||||
|
|
||||||
/* Initialize the MQTT application */
|
/* Initialize the MQTT application */
|
||||||
mqtt_application_init();
|
mqtt_application_init();
|
||||||
|
|||||||
162
project/Core/Src/modbus_tcp.c
Normal file
162
project/Core/Src/modbus_tcp.c
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/**
|
||||||
|
* @file modbus_tcp.c
|
||||||
|
*
|
||||||
|
* @brief TCP Modbus handler
|
||||||
|
* @date Nov 6, 2023
|
||||||
|
* @author Obe
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Includes
|
||||||
|
#include "modbus_tcp.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
// Defines
|
||||||
|
#define MAX_REG REG_LENGTH
|
||||||
|
#define EXTENSION_LENGTH 4
|
||||||
|
#define TEXT_LENGTH 200
|
||||||
|
#define MULTIPLE_REG 0x10
|
||||||
|
#define REG_LENGTH 428
|
||||||
|
#define START_DATA 28
|
||||||
|
#define MODBUS_MODE 7
|
||||||
|
|
||||||
|
#define REG_COLOR_B_RED 14
|
||||||
|
#define REG_COLOR_B_GREEN 16
|
||||||
|
#define REG_COLOR_B_BLUE 18
|
||||||
|
|
||||||
|
#define REG_COLOR_F_RED 20
|
||||||
|
#define REG_COLOR_F_GREEN 22
|
||||||
|
#define REG_COLOR_F_BLUE 24
|
||||||
|
|
||||||
|
#define REG_IMAGE_NR 26
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
static char* TAG = "Modbus_TCP"; // Tag used in logs
|
||||||
|
|
||||||
|
static struct tcp_pcb* modbus_pcb;
|
||||||
|
uint8_t registers[MAX_REG];
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
static err_t modbus_incoming_data(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err);
|
||||||
|
static err_t modbus_accept(void* arg, struct tcp_pcb* pcb, err_t err);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn static err_t modbus_incoming_data(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||||
|
* @brief Function that's called when there is a new request on port 502.
|
||||||
|
* It handles the incoming data from QModMaster
|
||||||
|
*/
|
||||||
|
static err_t modbus_incoming_data(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) {
|
||||||
|
uint8_t counter;
|
||||||
|
char text[TEXT_LENGTH];
|
||||||
|
uint32_t result_background = 0xff000000;
|
||||||
|
uint32_t text_foreground_color = 0xff000000;
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
|
||||||
|
// Putting underscores in the whole array
|
||||||
|
memset(text, '_', TEXT_LENGTH);
|
||||||
|
text[TEXT_LENGTH - 1] = '\0';
|
||||||
|
|
||||||
|
if (p != NULL) {
|
||||||
|
LOG_INFO(TAG, "data is valid\n");
|
||||||
|
// Process the modbus data
|
||||||
|
tcp_recved(pcb, p->tot_len);
|
||||||
|
|
||||||
|
// Putting the buffer in the register array
|
||||||
|
for (uint16_t i = 0; i < p->tot_len && i < MAX_REG; i++) {
|
||||||
|
registers[i] = ((uint*)p->payload)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (registers[MODBUS_MODE] == MULTIPLE_REG) {
|
||||||
|
// Check if it's a Modbus Write Multiple Registers request (0x10)
|
||||||
|
LOG_INFO(TAG, "in writing multiple register mode\n");
|
||||||
|
|
||||||
|
LOG_INFO(TAG, "Background R:%d G:%d B:%d\nForeground: R:%d G:%d B:%d\nImage Nr: %d",
|
||||||
|
registers[REG_COLOR_B_RED], registers[REG_COLOR_B_GREEN], registers[REG_COLOR_B_BLUE],
|
||||||
|
registers[REG_COLOR_F_RED], registers[REG_COLOR_F_GREEN], registers[REG_COLOR_F_BLUE],
|
||||||
|
registers[REG_IMAGE_NR]);
|
||||||
|
|
||||||
|
counter = 0;
|
||||||
|
for (int i = START_DATA; i < REG_LENGTH; i++) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
text[counter] = registers[i];
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result_background |= ((uint32_t)registers[REG_COLOR_B_RED]) << 16;
|
||||||
|
result_background |= ((uint32_t)registers[REG_COLOR_B_GREEN]) << 8;
|
||||||
|
result_background |= (uint32_t)registers[REG_COLOR_B_BLUE];
|
||||||
|
|
||||||
|
text_foreground_color |= ((uint32_t)registers[REG_COLOR_F_RED]) << 16;
|
||||||
|
text_foreground_color |= ((uint32_t)registers[REG_COLOR_F_GREEN]) << 8;
|
||||||
|
text_foreground_color |= (uint32_t)registers[REG_COLOR_F_BLUE];
|
||||||
|
|
||||||
|
// Processing the image index
|
||||||
|
size_t number_of_files = llfs_file_count(); // How many files that there are
|
||||||
|
|
||||||
|
if (number_of_files > 0) {
|
||||||
|
llfs_file_t file_list[number_of_files];
|
||||||
|
number_of_files = llfs_file_list(file_list, number_of_files, NULL);
|
||||||
|
|
||||||
|
lcd_clear_text();
|
||||||
|
lcd_clear_images();
|
||||||
|
lcd_stop_all_gifs();
|
||||||
|
|
||||||
|
lcd_display_text(text, 10, 10, text_foreground_color, result_background, LCD_FONT24);
|
||||||
|
|
||||||
|
if (number_of_files < registers[REG_IMAGE_NR]) {
|
||||||
|
lcd_display_text("FILE NOT IN FILESYSTEM", 10, 75, LCD_RED, LCD_BLACK, LCD_FONT24);
|
||||||
|
} else {
|
||||||
|
const char* ext = strrchr(file_list[registers[REG_IMAGE_NR] - 1].name, '.');
|
||||||
|
if (ext == NULL) {
|
||||||
|
LOG_CRIT(TAG, "No valid extension found");
|
||||||
|
} else if (strcmp(ext, ".gif") == 0) {
|
||||||
|
lcd_draw_gif_from_fs(file_list[registers[REG_IMAGE_NR] - 1].name, 0, 75);
|
||||||
|
} else if (strcmp(ext, ".bmp") == 0) {
|
||||||
|
lcd_draw_img_from_fs(file_list[registers[REG_IMAGE_NR] - 1].name, 0, 75);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LOG_INFO(TAG, "not in writing multiple register mode!!!\n");
|
||||||
|
}
|
||||||
|
} else if (err == ERR_OK) {
|
||||||
|
tcp_close(pcb); // When everything was ok close the TCP connection
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn static err_t modbus_accept(void *arg, struct tcp_pcb *pcb, err_t err)
|
||||||
|
* @brief Sets the function that's being called when theirs incoming data
|
||||||
|
*/
|
||||||
|
static err_t modbus_accept(void* arg, struct tcp_pcb* pcb, err_t err) {
|
||||||
|
LWIP_UNUSED_ARG(arg);
|
||||||
|
LWIP_UNUSED_ARG(err);
|
||||||
|
|
||||||
|
// Sets the priority of a connection.
|
||||||
|
tcp_setprio(pcb, TCP_PRIO_MIN);
|
||||||
|
|
||||||
|
// Sets which function is being called when new data arrives
|
||||||
|
tcp_recv(pcb, modbus_incoming_data);
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void modbus_init
|
||||||
|
* @brief Initializes the modbus tcp
|
||||||
|
*/
|
||||||
|
void modbus_init(void) {
|
||||||
|
LOG_INFO(TAG, "Initializing\n");
|
||||||
|
// Creating a new tcp pcb
|
||||||
|
modbus_pcb = tcp_new();
|
||||||
|
|
||||||
|
// Bind the modbus_pcb to port 502
|
||||||
|
tcp_bind(modbus_pcb, IP_ADDR_ANY, MODBUSPORT);
|
||||||
|
|
||||||
|
modbus_pcb = tcp_listen(modbus_pcb);
|
||||||
|
// Set callback function for incoming connections
|
||||||
|
tcp_accept(modbus_pcb, modbus_accept);
|
||||||
|
LOG_INFO(TAG, "initialized\n");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user