Freertos mit separaten Task-Datei

Beispiel mit einem Modbus-Task …

------------------------------------------------------------------
Struktur:
------------------------------------------------------------------
Core/
├── Src/
│   ├── freertos.c               <- HAL-generiert (belassen)
│   ├── modbus_task.c            <- deine Datei
├── Inc/
│   ├── freertos.h               <- HAL-generiert (belassen)
│   ├── modbus_task.h            <- dein Header
------------------------------------------------------------------
modbus_task.h:
------------------------------------------------------------------
#ifndef INC_MODBUS_TASK_H_
#define INC_MODBUS_TASK_H_

#include "main.h"

void modbus_task(void *argument);


#endif /* INC_MODBUS_TASK_H_ */
------------------------------------------------------------------
modbus_task.c;
------------------------------------------------------------------
#include "modbus_task.h"
#include "usart.h"
#include "config.h"
#include "analog_helper.h" // für analoge Werte ...
#include "gpio.h"
#include "cmsis_os.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>

UART_HandleTypeDef huart4;

#define MODBUS_BUF_LEN 256

static uint8_t rx_buffer[MODBUS_BUF_LEN];
static uint8_t tx_buffer[MODBUS_BUF_LEN];
static uint16_t rx_index = 0;

extern I2C_HandleTypeDef hi2c2;

static uint16_t modbus_crc16(uint8_t *buf, uint16_t len)
{
    uint16_t crc = 0xFFFF;
    for(uint16_t pos = 0; pos < len; pos++)
    {
        crc ^= (uint16_t)buf[pos];
        for(uint8_t i = 0; i < 8; i++)
        {
            if((crc & 0x0001) != 0)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else crc >>= 1;
        }
    }
    return crc;
}

static void modbus_send(uint8_t *buf, uint16_t len)
{
    HAL_UART_Transmit(&huart4, buf, len, HAL_MAX_DELAY);
}

static void modbus_handle_request(uint8_t *buf, uint16_t len)
{
    if(len < 4) return;

    uint8_t id = buf[0];
    uint8_t func = buf[1];

    if(id != g_config.modbus_slave_id) return;

    uint16_t crc_calc = modbus_crc16(buf, len-2);
    uint16_t crc_recv = buf[len-2] | (buf[len-1] << 8);

    if(crc_calc != crc_recv) return;

    uint16_t addr = (buf[2] << 8) | buf[3];
    uint16_t count = (buf[4] << 8) | buf[5];

    uint16_t response_len = 0;

    switch(func)
    {
        case 1: // Read Coils (Dout lesen)
        {
            tx_buffer[0] = id;
            tx_buffer[1] = func;
            tx_buffer[2] = 1;

            uint8_t val = 0;
            val |= HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3) ? (1<<0) : 0;
            val |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4) ? (1<<1) : 0;
            val |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5) ? (1<<2) : 0;
            val |= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) ? (1<<3) : 0;
            val |= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) ? (1<<4) : 0;
            val |= HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_15) ? (1<<5) : 0;
            val |= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10) ? (1<<6) : 0;

            tx_buffer[3] = val;

            response_len = 4;
            break;
        }

        case 2: // Read Discrete Inputs (Din lesen)
        {
            tx_buffer[0] = id;
            tx_buffer[1] = func;
            tx_buffer[2] = 2;

            uint16_t val = 0;
            val |= HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) ? (1<<0) : 0;
            val |= HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) ? (1<<1) : 0;
            val |= HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_5) ? (1<<2) : 0;
            val |= HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_6) ? (1<<3) : 0;
            val |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0) ? (1<<4) : 0;
            val |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1) ? (1<<5) : 0;
            val |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_2) ? (1<<6) : 0;
            val |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_3) ? (1<<7) : 0;
            val |= HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) ? (1<<8) : 0;
            val |= HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) ? (1<<9) : 0;
            val |= HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) ? (1<<10) : 0;

            tx_buffer[3] = val >> 8;
            tx_buffer[4] = val & 0xFF;

            response_len = 5;
            break;
        }

        case 3: // Read Holding Registers (Aout lesen, float)
        case 4: // Read Input Registers (Ain lesen, float)
        {
            tx_buffer[0] = id;
            tx_buffer[1] = func;
            tx_buffer[2] = count * 4;

            float values[5] = {0};

            if(func == 3)
            {
                uint16_t aout[4];
                analog_read_outputs(aout, 4);
                for(int i=0;i<4;i++) values[i] = (float)aout[i];
            }
            else
            {
                int32_t ain[5];
                analog_read_inputs(ain, 5);
                for(int i=0;i<5;i++) values[i] = (float)ain[i];
            }

            for(uint16_t i = 0; i < count; i++)
            {
                if(i >= 5) break;
                uint32_t fval;
                memcpy(&fval, &values[i], sizeof(float));
                tx_buffer[3+i*4+0] = (fval >> 24) & 0xFF;
                tx_buffer[3+i*4+1] = (fval >> 16) & 0xFF;
                tx_buffer[3+i*4+2] = (fval >> 8)  & 0xFF;
                tx_buffer[3+i*4+3] = fval & 0xFF;
            }

            response_len = 3 + count * 4;
            break;
        }

        case 5: // Write Single Coil (DO setzen)
        {
            uint16_t val = (buf[4] << 8) | buf[5];
            if(addr == 0)
                HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, (val ? GPIO_PIN_SET : GPIO_PIN_RESET));
            else if(addr == 1)
                HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, (val ? GPIO_PIN_SET : GPIO_PIN_RESET));
            else if(addr == 2)
                HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, (val ? GPIO_PIN_SET : GPIO_PIN_RESET));
            else if(addr == 3)
                HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, (val ? GPIO_PIN_SET : GPIO_PIN_RESET));
            else if(addr == 4)
                HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, (val ? GPIO_PIN_SET : GPIO_PIN_RESET));
            else if(addr == 5)
                HAL_GPIO_WritePin(GPIOE, GPIO_PIN_15, (val ? GPIO_PIN_SET : GPIO_PIN_RESET));
            else if(addr == 6)
                HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, (val ? GPIO_PIN_SET : GPIO_PIN_RESET));

            memcpy(tx_buffer, buf, 6);
            response_len = 6;
            break;
        }

        case 16: // Write Multiple Registers (Aout schreiben, float)
        {
            uint8_t bytecount = buf[6];
            float values[4] = {0};

            for(uint16_t i=0; i < count; i++)
            {
                if(i >= 4) break;
                uint32_t fval = (buf[7+i*4+0] << 24) |
                                (buf[7+i*4+1] << 16) |
                                (buf[7+i*4+2] << 8) |
                                buf[7+i*4+3];
                memcpy(&values[i], &fval, sizeof(float));
            }

            // Optional: analog_write_outputs(values);

            tx_buffer[0] = id;
            tx_buffer[1] = func;
            tx_buffer[2] = buf[2];
            tx_buffer[3] = buf[3];
            tx_buffer[4] = buf[4];
            tx_buffer[5] = buf[5];

            response_len = 6;
            break;
        }

        default:
        {
            tx_buffer[0] = id;
            tx_buffer[1] = func | 0x80;
            tx_buffer[2] = 0x01;
            response_len = 3;
            break;
        }
    }

    uint16_t crc = modbus_crc16(tx_buffer, response_len);
    tx_buffer[response_len++] = crc & 0xFF;
    tx_buffer[response_len++] = crc >> 8;

    modbus_send(tx_buffer, response_len);
}

void modbus_task(void *argument)
{
    HAL_UART_Receive_IT(&huart4, &rx_buffer[rx_index], 1);

    for(;;)
    {
        osDelay(10);

        static uint32_t last_index = 0;
        static uint32_t last_tick = 0;

        if(rx_index != last_index)
        {
            last_index = rx_index;
            last_tick = HAL_GetTick();
        }

        if((HAL_GetTick() - last_tick) > 5 && rx_index > 0)
        {
            modbus_handle_request(rx_buffer, rx_index);
            rx_index = 0;
            memset(rx_buffer, 0, sizeof(rx_buffer));
            HAL_UART_Receive_IT(&huart4, &rx_buffer[rx_index], 1);
        }
    }
}
------------------------------------------------------------------
Hinzufügen in der freertos.c;
------------------------------------------------------------------
...
#include "modbus_task.h"
...
osThreadId_t modbusTaskHandle;
const osThreadAttr_t modbusTask_attributes = {
  .name = "modbusTask",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 512 * 4
};
...
//innerhalb von void MX_FREERTOS_Init(void) hinter dem ersten Task-Handle ...
modbusTaskHandle = osThreadNew(modbus_task, NULL, &modbusTask_attributes); // hinzufügen
...

Tags:

Comments

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Search


Categories


Recent Posts


Tags