Compare commits

..

2 Commits

Author SHA1 Message Date
f5210ce050 подправлены внешний вид и коменты 2025-08-31 14:27:25 +03:00
ef623e8b0b +freertos
но надо еще коменты подправить
2025-08-31 13:24:11 +03:00
8 changed files with 1200 additions and 1145 deletions

View File

@ -1,9 +1,13 @@
#include "rs_message.h" #include "rs_message.h"
#include "FreeRTOS.h"
void setup() { void setup() {
// put your setup code here, to run once: // put your setup code here, to run once:
MODBUS_FirstInit(); MODBUS_FirstInit();
//hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, MB_SPEED, 0);
xTaskCreatePinnedToCore(RS_Task, "Modbus", 4096, &hmodbus1, 2, NULL, 1);
Serial.begin(115200); // для отладки Serial.begin(115200); // для отладки
Serial.println("start"); Serial.println("start");
@ -11,9 +15,5 @@ void setup() {
} }
void loop() { void loop() {
// put your main code here, to run repeatedly: //RS_Process(&hmodbus1);
RS_Process(&hmodbus1);
//delay(500);
//Serial.println("start");
//rs_huart.println("start1");
} }

View File

@ -1,4 +1,4 @@
#include "crc_algs.h" #include "modbus/crc_algs.h"
uint32_t CRC_calc; uint32_t CRC_calc;

View File

@ -11,6 +11,9 @@
* *
* @section Функции и макросы * @section Функции и макросы
* *
* ### Инициализация:
* - MODBUS_FirstInit() Инициализация модуля Modbus.
*
* ### Доступ к coils: * ### Доступ к coils:
* - MB_Set_Coil_Local() Установить coil по локальному адресу. * - MB_Set_Coil_Local() Установить coil по локальному адресу.
* - MB_Reset_Coil_Local() Сбросить coil по локальному адресу. * - MB_Reset_Coil_Local() Сбросить coil по локальному адресу.
@ -36,8 +39,6 @@
* - RS_Define_Size_of_RX_Message() Определение размера принимаемого сообщения. * - RS_Define_Size_of_RX_Message() Определение размера принимаемого сообщения.
* - RS_Init() Инициализация UART. * - RS_Init() Инициализация UART.
* *
* ### Инициализация:
* - MODBUS_FirstInit() Инициализация модуля Modbus.
* *
* @section Структура данных Modbus * @section Структура данных Modbus
* *
@ -52,21 +53,27 @@
* @section Инструкция по подключению * @section Инструкция по подключению
* Настройте modbus_config.h дефайны для нужной работы UART * Настройте modbus_config.h дефайны для нужной работы UART
* *
* После для запуска Modbus: * Минимум для запуска Modbus:
* @verbatim * @verbatim
//----------------Прием модбас----------------//
#include "rs_message.h" #include "rs_message.h"
MODBUS_FirstInit(); MODBUS_FirstInit();
void loop() void loop()
{ {
RS_Process(&hmodbus1);(&hmodbus1, &MODBUS_MSG); RS_Process(&hmodbus1);
} }
* @endverbatim * @endverbatim
* Для RTOS:
* @verbatim
#include "rs_message.h"
MODBUS_FirstInit();
xTaskCreatePinnedToCore(RS_Task, "Modbus", 4096, &hmodbus1, 2, NULL, 1);
* @endverbatim
* *
******************************************************************************/ ******************************************************************************/
#include "crc_algs.h" #include "modbus/crc_algs.h"
#include "rs_message.h" #include "modbus/rs_message.h"
uint32_t dbg_temp, dbg_temp2, dbg_temp3; // for debug uint32_t dbg_temp, dbg_temp2, dbg_temp3; // for debug
RS_HandleTypeDef hmodbus1; RS_HandleTypeDef hmodbus1;
@ -87,15 +94,16 @@ void MODBUS_FirstInit(void)
{ {
MB_DevoceInentificationInit(); MB_DevoceInentificationInit();
//-----------SETUP MODBUS------------- //-----------SETUP MODBUS-------------
// set up modbus: MB_RX_Size_NotConst and Timeout enable
hmodbus1.ID = MODBUS_DEVICE_ID; hmodbus1.ID = MODBUS_DEVICE_ID;
hmodbus1.sRS_Timeout = MODBUS_TIMEOUT; hmodbus1.sRS_Timeout = MODBUS_TIMEOUT;
hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT; hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT;
hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst; hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst;
hmodbus1.pMessagePtr = &MODBUS_MSG; hmodbus1.pMessagePtr = &MODBUS_MSG;
hmodbus1.rx_pin = MODBUS_RX_PIN;
hmodbus1.tx_pin = MODBUS_TX_PIN;
hmodbus1.taskDelay = RS_IN_RTOS;
// INIT // INIT
rs_huart.begin(115200, SERIAL_8N1, 8, 9); hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, MODBUS_SPEED, 0);
hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, 0);
RS_EnableReceive(); RS_EnableReceive();
} }
@ -341,14 +349,14 @@ uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg)
shift = 0; // set shift to zero for the next step shift = 0; // set shift to zero for the next step
//-----------READ COILS-------------- //-----------READ COILS--------------
modbus_msg->DATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift; modbus_msg->DWDATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift;
if(ind > 0) if(ind > 0)
modbus_msg->DATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift; modbus_msg->DWDATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift;
} }
// т.к. DATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты // т.к. DWDATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты
for(; ind >= 0; --ind) for(; ind >= 0; --ind)
modbus_msg->DATA[ind] = ByteSwap16(modbus_msg->DATA[ind]); modbus_msg->DWDATA[ind] = ByteSwap16(modbus_msg->DWDATA[ind]);
return 1; return 1;
} }
@ -376,7 +384,7 @@ uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
int i; int i;
for (i = 0; i<modbus_msg->Qnt; i++) for (i = 0; i<modbus_msg->Qnt; i++)
{ {
modbus_msg->DATA[i] = *(pHoldRegs++); modbus_msg->DWDATA[i] = *(pHoldRegs++);
} }
return 1; return 1;
} }
@ -405,9 +413,9 @@ uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg)
for (i = 0; i<modbus_msg->Qnt; i++) for (i = 0; i<modbus_msg->Qnt; i++)
{ {
if(*((int16_t *)pInRegs) > 0) if(*((int16_t *)pInRegs) > 0)
modbus_msg->DATA[i] = (*pInRegs++); modbus_msg->DWDATA[i] = (*pInRegs++);
else else
modbus_msg->DATA[i] = (*pInRegs++); modbus_msg->DWDATA[i] = (*pInRegs++);
} }
return 1; return 1;
} }
@ -509,10 +517,10 @@ uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg)
// get current coils // get current coils
temp_reg = *(coils+ind); temp_reg = *(coils+ind);
// set coils // set coils
setted_coils = ByteSwap16(modbus_msg->DATA[ind]) << start_shift; setted_coils = ByteSwap16(modbus_msg->DWDATA[ind]) << start_shift;
if(ind > 0) if(ind > 0)
{ {
setted_coils |= ((ByteSwap16(modbus_msg->DATA[ind-1]) << start_shift) >> 16); setted_coils |= ((ByteSwap16(modbus_msg->DWDATA[ind-1]) << start_shift) >> 16);
} }
// write coils // write coils
@ -551,7 +559,7 @@ uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg)
//-----------WRITTING REGS----------- //-----------WRITTING REGS-----------
for (int i = 0; i<modbus_msg->Qnt; i++) for (int i = 0; i<modbus_msg->Qnt; i++)
{ {
*(pHoldRegs++) = modbus_msg->DATA[i]; *(pHoldRegs++) = modbus_msg->DWDATA[i];
} }
return 1; return 1;
} }
@ -572,7 +580,7 @@ void MB_WriteObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef
*/ */
uint8_t MB_Read_Device_Identification(RS_MsgTypeDef *modbus_msg) uint8_t MB_Read_Device_Identification(RS_MsgTypeDef *modbus_msg)
{ {
char *mbdata = (char *)modbus_msg->DATA; char *mbdata = (char *)modbus_msg->DWDATA;
unsigned ind = 0; unsigned ind = 0;
switch(modbus_msg->DevId.ReadDevId) switch(modbus_msg->DevId.ReadDevId)
{ {
@ -768,7 +776,7 @@ RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mo
//---------------DATA---------------- //---------------DATA----------------
//-----------[data bytes]------------ //-----------[data bytes]------------
uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA; uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DWDATA;
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
{ // set data { // set data
modbus_uart_buff[ind++] = *tmp_data_addr; modbus_uart_buff[ind++] = *tmp_data_addr;
@ -789,7 +797,7 @@ RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mo
//---------------DATA---------------- //---------------DATA----------------
//-----------[data bytes]------------ //-----------[data bytes]------------
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DWDATA;
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
{ // set data { // set data
if (i%2 == 0) // HI byte if (i%2 == 0) // HI byte
@ -877,7 +885,7 @@ RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modb
MB_DEBUG_PRINT("[MB] Request is invalid (ByteCnt not match DataSize)"); MB_DEBUG_PRINT("[MB] Request is invalid (ByteCnt not match DataSize)");
return RS_PARSE_MSG_ERR; return RS_PARSE_MSG_ERR;
} }
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DWDATA;
for(int i = 0; i < modbus_msg->ByteCnt; i++) // /2 because we transmit 8 bits, not 16 bits for(int i = 0; i < modbus_msg->ByteCnt; i++) // /2 because we transmit 8 bits, not 16 bits
{ // set data { // set data
if (i%2 == 0) if (i%2 == 0)

View File

@ -12,9 +12,8 @@
#ifndef __MODBUS_H_ #ifndef __MODBUS_H_
#define __MODBUS_H_ #define __MODBUS_H_
#include "modbus_config.h" #include "modbus/modbus_config.h"
#include "modbus_data.h" #include "modbus/modbus_data.h"
//#include "settings.h" // for modbus settings
/** /**
* @addtogroup MODBUS_SETTINGS * @addtogroup MODBUS_SETTINGS
@ -22,11 +21,6 @@
* @brief Some defines for modbus * @brief Some defines for modbus
@{ @{
*/ */
/////////////////////////////////////////////////////////////////////
//////////////////////////---SETTINGS---/////////////////////////////
// USER SETTINGS FOR MODBUS IN interface_config.h
//////////////////////////---SETTINGS---/////////////////////////////
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
/////////////////////---USER MESSAGE DEFINES---////////////////////// /////////////////////---USER MESSAGE DEFINES---//////////////////////
@ -141,7 +135,7 @@ typedef struct // RS_MsgTypeDef
uint16_t Qnt; ///< Quantity of modbus data uint16_t Qnt; ///< Quantity of modbus data
uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive
uint16_t DATA[DATA_SIZE]; ///< Modbus Data uint16_t DWDATA[DATA_SIZE]; ///< Modbus Data (Words)
MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command
uint16_t MB_CRC; ///< Modbus CRC uint16_t MB_CRC; ///< Modbus CRC

View File

@ -7,14 +7,25 @@
#ifndef _MODBUS_CONFIG_H_ #ifndef _MODBUS_CONFIG_H_
#define _MODBUS_CONFIG_H_ #define _MODBUS_CONFIG_H_
#define RS_IN_RTOS 20 ///< значение - период таска
// Включить/выключить debug // Включить/выключить debug
#define RS_DEBUG 0 ///< Отладка приема/передачи UART #define RS_DEBUG 1 ///< Отладка приема/передачи UART
#define MODBUS_DEBUG 0 ///< Отладка обработки запросов Modbus #define MODBUS_DEBUG 1 ///< Отладка обработки запросов Modbus
#define MODBUS_ERR_DEBUG 1 ///< Отладка ошибок по CAN #define MODBUS_ERR_DEBUG 1 ///< Отладка ошибок по CAN
// MODBUS PARAMS // MODBUS PARAMS
#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства #define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства
#define MODBUS_TIMEOUT 5000 ///< максимальнйы тайтаут MB в тиках таймера #define MODBUS_TIMEOUT 5000 ///< максимальнйы тайтаут MB в мс
// PERIPH FUNCTIONS AND HANDLERS
#define HUART_TypeDef HardwareSerial
#define rs_huart Serial2 //используемый uart1`
#define MODBUS_SPEED 115200
#define MODBUS_RX_PIN 8
#define MODBUS_TX_PIN 9
// STRING OBJECTS MODBUS // STRING OBJECTS MODBUS
#define MODBUS_VENDOR_NAME "NIO PRIBOR" #define MODBUS_VENDOR_NAME "NIO PRIBOR"
@ -25,9 +36,6 @@
#define MODBUS_MODEL_NAME "Arduino" #define MODBUS_MODEL_NAME "Arduino"
#define MODBUS_USER_APPLICATION_NAME "" #define MODBUS_USER_APPLICATION_NAME ""
// PERIPH FUNCTIONS AND HANDLERS
#define rs_huart Serial1 //используемый uart
#define HUART_TypeDef HardwareSerial
/** /**
* @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей) * @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей)

View File

@ -135,7 +135,7 @@ extern MB_DataStructureTypeDef MB_DATA;
typedef struct typedef struct
{ {
unsigned length; unsigned length;
char *name; const char *name;
}MB_DeviceObjectTypeDef; }MB_DeviceObjectTypeDef;
/** /**
* @brief Структура для объектов Modbus * @brief Структура для объектов Modbus

View File

@ -1,50 +1,71 @@
/** /**
************************************************************************** **************************************************************************
* @file rs_message.cpp * @file rs_message.cpp
* @brief Модуль для реализации протоколов по RS/UART (Arduino). * @brief Модуль для работы с протоколами RS/UART на Arduino.
**************************************************************************\ **************************************************************************
* @details * @details
* Данный модуль реализует основные функции для приема и передачи сообщений * Данный модуль обеспечивает приём и передачу сообщений по протоколу RS
* по протоколу RS через UART. Реализована обработка приёма и передачи данных, * через UART на платформах Arduino. Поддерживаются два режима работы:
* управление состояниями RS, а также функции для инициализации и управления * - обычный (Arduino loop);
* периферией Arduino Serial. * - FreeRTOS (через StreamBuffer и отдельную задачу RS_Task).
* *
* Реализованы следующие функции: * Основные возможности:
* - RS_Init() инициализация структуры RS и привязка к Serial-порту. * - Инициализация и управление структурой RS_HandleTypeDef.
* - RS_Abort() остановка работы RS/UART с очисткой флагов и структур. * - Обработка приёма байтов, сборка пакетов и определение их длины.
* - RS_Handle_Transmit_Start() запуск передачи данных. * - Разбор полученных сообщений и формирование ответов.
* - RS_Process() обработка входящих данных (вызов в loop()). * - Управление состояниями приёма и передачи (флаги RX/TX, busy/free).
* - Таймаут приёма и аварийная остановка передачи/приёма.
* *
* В модуле также определён буфер RS_Buffer[] для хранения принимаемых/передаваемых данных. * Предоставляемые функции:
* - RS_Init() инициализация структуры RS и Serial порта.
* - RS_Abort() остановка работы RS/UART, очистка флагов.
* - RS_Handle_Transmit_Start() подготовка и отправка сообщения.
* - RS_Process() основной цикл обработки (Arduino loop).
* - RS_Process_Byte() обработка одного принятого байта (для FreeRTOS).
* - RS_UART_RX_Handler() ISR-приём данных UART (FreeRTOS).
* - RS_Task() FreeRTOS задача обработки UART.
* *
* Пользователь должен определить функции: * Пользователь должен реализовать слабые функции:
* - RS_Response() формирование ответа на принятое сообщение. * - RS_Response() формирование ответа на сообщение.
* - RS_Collect_Message() подготовка сообщения для передачи. * - RS_Collect_Message() заполнение буфера перед передачей.
* - RS_Parse_Message() разбор принятого сообщения. * - RS_Parse_Message() разбор принятого пакета.
* - RS_Define_Size_of_RX_Message() определение размера входящих данных. * - RS_Define_Size_of_RX_Message() определение длины ожидаемого пакета.
*
* Буфер для приёма/передачи: RS_Buffer[MSG_SIZE_MAX].
* *
* @note * @note
* Для корректной работы требуется вызывать RS_Process() в основном цикле программы. * - В режиме Arduino loop необходимо вызывать RS_Process() в основном цикле.
* UART используется через стандартный Arduino Stream API (write(), read(), available()). * - В режиме FreeRTOS требуется определить макрос RS_IN_RTOS,
* создать задачу RS_Task и подключить RS_UART_RX_Handler() к ISR UART.
* - UART используется через стандартный Arduino Stream API (write, read, available).
* *
@verbatim * Пример использования (Arduino loop):
//-------------------Функции-------------------// * @verbatim
Functions: users RS_HandleTypeDef hRS;
- RS_Parse_Message Разбор принятого сообщения RS_MsgTypeDef msg;
- RS_Collect_Message Заполнение структуры сообщения и буфера hRS.pMessagePtr = &msg;
- RS_Response Ответ на сообщение RS_Init(&hRS, &Serial, 115200, NULL);
- RS_Define_Size_of_RX_Message Определение размера принимаемых данных
Functions: general void loop() {
- RS_Init Инициализация структуры RS и привязка Serial RS_Process(&hRS);
- RS_Abort Остановка приёма/передачи }
- RS_Handle_Transmit_Start Запуск передачи сообщения * @endverbatim
- RS_Process Обработка приёма сообщений (в loop) * Пример использования с RTOS:
* @verbatim
RS_HandleTypeDef hRS;
RS_MsgTypeDef msg;
hRS.pMessagePtr = &msg;
RS_Init(&hRS, &Serial, 115200, NULL);
@endverbatim xTaskCreate(RS_Task, "RS_Task", 256, &hRS, 1, NULL);
*************************************************************************/ //...
void eventSerial() {
RS_UART_RX_Handler(&hmodbus1);
}
* @endverbatim
**************************************************************************/
#include "rs_message.h" #include "modbus/rs_message.h"
uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer
@ -56,15 +77,16 @@ uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer
* @param SerialPort - указатель на структуру с настройками UART. * @param SerialPort - указатель на структуру с настройками UART.
* @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер. * @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер.
* @return RS_RES - статус о состоянии RS после инициализации. * @return RS_RES - статус о состоянии RS после инициализации.
* @note Инициализация перефирии и структуры для приема-передачи по RS. * @note Инициализация периферии и структуры для приема-передачи по RS.
*/ */
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint8_t *pRS_BufferPtr) { RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint32_t baudRate, uint8_t *pRS_BufferPtr) {
if (!hRS || !SerialPort) { if (!hRS || !SerialPort) {
RS_DEBUG_PRINT("[RS] Init error: null handler or port"); RS_DEBUG_PRINT("[RS] Init error: null handler or port");
return RS_ERR; return RS_ERR;
} }
hRS->huart = SerialPort; hRS->huart = SerialPort;
hRS->baudRate = baudRate;
hRS->pBufferPtr = pRS_BufferPtr ? pRS_BufferPtr : RS_Buffer; hRS->pBufferPtr = pRS_BufferPtr ? pRS_BufferPtr : RS_Buffer;
hRS->RS_STATUS = RS_OK; hRS->RS_STATUS = RS_OK;
RS_Set_Free(hRS); RS_Set_Free(hRS);
@ -78,6 +100,8 @@ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint8
RS_Set_Busy(hRS); RS_Set_Busy(hRS);
RS_Set_RX_Flags(hRS); RS_Set_RX_Flags(hRS);
hRS->huart->begin(hRS->baudRate, SERIAL_8N1, hRS->rx_pin, hRS->tx_pin);
RS_DEBUG_PRINT("[RS] Initialized successfully"); RS_DEBUG_PRINT("[RS] Initialized successfully");
return RS_OK; return RS_OK;
} }
@ -91,7 +115,7 @@ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint8
- ABORT_RX_TX: Отмена приема и передачи по ЮАРТ, - ABORT_RX_TX: Отмена приема и передачи по ЮАРТ,
- ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры. - ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры.
* @return RS_RES - статус о состоянии RS после аборта. * @return RS_RES - статус о состоянии RS после аборта.
* @note В Arduino аппаратный UART (Serial) не отключается физически, * @details В Arduino аппаратный UART (Serial) не отключается физически,
* т.к. стандартный API HardwareSerial не даёт прямого доступа * т.к. стандартный API HardwareSerial не даёт прямого доступа
* к регистрах UART. RS_Abort лишь очищает внутренние флаги * к регистрах UART. RS_Abort лишь очищает внутренние флаги
* и структуры, имитируя "отключение". * и структуры, имитируя "отключение".
@ -125,7 +149,7 @@ RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode) {
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения. * @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации передачи. * @return RS_RES - статус о состоянии RS после инициализации передачи.
* @note Определяет отвечать ли на команду или нет. * @details Определяет отвечать ли на команду или нет.
*/ */
RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{ {
@ -159,18 +183,31 @@ RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *
return RS_OK; return RS_OK;
} }
#ifdef RS_IN_RTOS
/** /**
* @brief Main RS processing function. * @brief Задача обработки UART приёма (FreeRTOS).
* @param pvParameters - указатель на RS_HandleTypeDef (передаётся при создании задачи).
* @details Вызывает функцию обработки приема UART по протоколу.
*/
void RS_Task(void *pvParameters) {
RS_HandleTypeDef *hRS = (RS_HandleTypeDef *)pvParameters;
uint8_t rxBuf[64];
for (;;) {
RS_Process(hRS);
vTaskDelay(pdMS_TO_TICKS(hRS->taskDelay));
}
}
#endif // RS_IN_RTOS
/**
* @brief Основная функция обработки RS (вариант без FreeRTOS).
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @return None. * @note Используется в Arduino loop(), если проект без FreeRTOS.
* @note Функция должна вызываться в основном цикле (loop()). * @details Выполняет проверку таймаутов, обработку поступающих байт из UART
* Выполняет проверку таймаутов, обработку поступающих байт из UART * по протоколу
* и вызов пользовательских функций:
* - RS_Define_Size_of_RX_Message() для определения размера пакета;
* - RS_Parse_Message() для разбора принятого сообщения;
* - RS_Response() для ответа, если сообщение адресовано текущему устройству.
* В случае таймаута выполняется RS_Abort() с режимом ABORT_RX.
*/ */
void RS_Process(RS_HandleTypeDef *hRS) void RS_Process(RS_HandleTypeDef *hRS)
{ {
@ -255,7 +292,7 @@ void RS_Process(RS_HandleTypeDef *hRS)
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения. * @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о результате ответа на комманду. * @return RS_RES - статус о результате ответа на комманду.
* @note Обработка принятой комманды и ответ на неё. * @details Обработка принятой комманды и ответ на неё.
*/ */
__attribute__((weak)) RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) { return RS_ERR; }
@ -265,7 +302,7 @@ __attribute__((weak)) RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_Msg
* @param RS_msg - указатель на структуру сообщения. * @param RS_msg - указатель на структуру сообщения.
* @param msg_uart_buff - указатель на буффер UART. * @param msg_uart_buff - указатель на буффер UART.
* @return RS_RES - статус о результате заполнения буфера. * @return RS_RES - статус о результате заполнения буфера.
* @note Заполнение буффера UART из структуры сообщения. * @details Заполнение буффера UART из структуры сообщения.
*/ */
__attribute__((weak)) RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; }
@ -275,7 +312,7 @@ __attribute__((weak)) RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS,
* @param RS_msg - указатель на структуру сообщения. * @param RS_msg - указатель на структуру сообщения.
* @param msg_uart_buff - указатель на буффер UART. * @param msg_uart_buff - указатель на буффер UART.
* @return RS_RES - статус о результате заполнения структуры. * @return RS_RES - статус о результате заполнения структуры.
* @note Заполнение структуры сообщения из буффера UART. * @details Заполнение структуры сообщения из буффера UART.
*/ */
__attribute__((weak)) RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; }
@ -284,6 +321,6 @@ __attribute__((weak)) RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, R
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия.
* @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия.
* @note Определение сколько байтов надо принять по протоколу. * @details Определение сколько байтов надо принять по протоколу.
*/ */
__attribute__((weak)) RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size) { return RS_ERR; }

View File

@ -21,7 +21,7 @@
*************************************************************************/ *************************************************************************/
#ifndef __RS_LIB_H_ #ifndef __RS_LIB_H_
#define __RS_LIB_H_ #define __RS_LIB_H_
#include "modbus.h" #include "modbus/modbus.h"
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
////////////////////////////---DEFINES---//////////////////////////// ////////////////////////////---DEFINES---////////////////////////////
@ -148,9 +148,14 @@ typedef struct // RS_HandleTypeDef
uint8_t ID; ///< ID of RS "channel" uint8_t ID; ///< ID of RS "channel"
RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct
uint8_t *pBufferPtr; ///< pointer to message buffer uint8_t *pBufferPtr; ///< pointer to message buffer
#ifdef RS_IN_RTOS
uint16_t taskDelay; ///< freertos buffer
#endif
uint32_t RS_Message_Size; ///< size of whole message, not only data uint32_t RS_Message_Size; ///< size of whole message, not only data
/* HANDLERS and SETTINGS */ /* HANDLERS and SETTINGS */
uint8_t tx_pin; ///< Transmit pin
uint8_t rx_pin; ///< Receive pin
HUART_TypeDef *huart; ///< handler for used uart HUART_TypeDef *huart; ///< handler for used uart
RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef
uint16_t sRS_Timeout; ///< setting: timeout in ms uint16_t sRS_Timeout; ///< setting: timeout in ms
@ -187,9 +192,12 @@ RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *r
//-------------------------GENERAL FUNCTIONS------------------------- //-------------------------GENERAL FUNCTIONS-------------------------
/*-----------------Should be called from main code-----------------*/ /*-----------------Should be called from main code-----------------*/
/* Задача обработки UART приёма (FreeRTOS) */
void RS_Task(void *pvParameters);
/* Основная функция обработки RS */
void RS_Process(RS_HandleTypeDef *hRS); void RS_Process(RS_HandleTypeDef *hRS);
/* Initialize UART and handle RS stucture */ /* Initialize UART and handle RS stucture */
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *huart, uint8_t *pRS_BufferPtr); RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint32_t baudRate, uint8_t *pRS_BufferPtr);
/* Abort RS/UART */ /* Abort RS/UART */
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode); RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode);
/* Handle for starting transmit */ /* Handle for starting transmit */