- чуть переделаны некоторые дефайны для универсализации - смена направления сделана через указател на функцию, а не глобальный дефайн - добавлен бета осцилограф модбас - некоторый рефакторинг
145 lines
5.0 KiB
C
145 lines
5.0 KiB
C
/**
|
||
*******************************************************************************
|
||
* @file modbus_oscil.c
|
||
* @brief Модуль для реализации осциллографа через MODBUS.
|
||
*******************************************************************************
|
||
* @details
|
||
* Файл содержит реализацию функций для работы с буфером осциллографа.
|
||
*
|
||
* @section oscil_functions Функции
|
||
* - MB_Oscil_Init() — Инициализация структуры осциллографа
|
||
* - MB_Oscil_Add() — Добавление данных в буфер
|
||
* - MB_Oscil_UpdateTail() — Обновление указателя Tail
|
||
******************************************************************************/
|
||
#include "modbus_oscil.h"
|
||
|
||
#ifdef MODBUS_ENABLE_OSCIL
|
||
|
||
|
||
|
||
/**
|
||
* @brief Инициализация структуры осциллографа
|
||
* @param oscil Указатель на структуру осциллографа
|
||
* @param BufferSize Размер буфера в Modbus регистрах (max 125)
|
||
* @param NumbOfChannels Количество каналов (должно быть четным)
|
||
* @param SampleTime Период дискретизации
|
||
* @return HAL Status
|
||
*/
|
||
HAL_StatusTypeDef MB_Oscil_Init(MB_OscilTypeDef *oscil, uint8_t BufferSize, uint8_t NumbOfChannels, uint16_t SampleTime)
|
||
{
|
||
if(!oscil || (BufferSize >= MbData_size) || (NumbOfChannels > 15) || !SampleTime)
|
||
return HAL_ERROR;
|
||
|
||
if(NumbOfChannels % 2 != 0)
|
||
return HAL_ERROR;
|
||
|
||
oscil->Config.BufferSize = BufferSize;
|
||
oscil->Config.NumbOfChannels = NumbOfChannels;
|
||
oscil->Config.SampleTime = SampleTime;
|
||
oscil->Config.LastTick = 0;
|
||
oscil->Preamble.Head = 0;
|
||
oscil->Preamble.Tail = 0;
|
||
oscil->Config.Overrun = 0;
|
||
|
||
return HAL_OK;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief Инициализация структуры осциллографа
|
||
* @param oscil Указатель на структуру осциллографа
|
||
* @param BufferSize Размер буфера в Modbus регистрах (max 125)
|
||
* @param NumbOfChannels Количество каналов (должно быть четным)
|
||
* @param SampleTime Период дискретизации
|
||
* @return HAL Status
|
||
*/
|
||
HAL_StatusTypeDef MB_Oscil_Set_SampleTime(MB_OscilTypeDef *oscil, uint16_t SampleTime)
|
||
{
|
||
if(!oscil || !SampleTime)
|
||
return HAL_ERROR;
|
||
|
||
oscil->Config.SampleTime = SampleTime;
|
||
return HAL_OK;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief Добавление данных всех каналов в буфер
|
||
* @param oscil Указатель на структуру осциллографа
|
||
* @param Data Массив с данными каналов (длина = NumbOfChannels)
|
||
* @return HAL Status
|
||
*/
|
||
HAL_StatusTypeDef MB_Oscil_Add(MB_OscilTypeDef *oscil, uint8_t *Data)
|
||
{
|
||
if(!oscil || !Data)
|
||
return HAL_ERROR;
|
||
|
||
if(local_time() - oscil->Config.LastTick < oscil->Config.SampleTime)
|
||
return HAL_BUSY;
|
||
|
||
oscil->Config.LastTick = local_time();
|
||
|
||
uint8_t head_max = oscil->Config.BufferSize * 2;
|
||
uint8_t start_pos = oscil->Preamble.Head;
|
||
uint8_t channels = oscil->Config.NumbOfChannels;
|
||
uint8_t tail = oscil->Preamble.Tail;
|
||
|
||
// Пишем данные
|
||
for(uint8_t i = 0; i < channels; i++)
|
||
{
|
||
uint8_t write_pos = (start_pos + i) % head_max;
|
||
oscil->Data[write_pos] = Data[i];
|
||
}
|
||
|
||
// Новое положение Head
|
||
uint8_t new_head = (start_pos + channels) % head_max;
|
||
|
||
// Проверяем, есть ли непрочитанные данные (Tail != Head)
|
||
// if(tail != start_pos) {
|
||
// Если есть непрочитанные данные, проверяем не перетерли ли мы их
|
||
if(start_pos < new_head) {
|
||
// Линейный случай
|
||
if(tail > start_pos && tail <= new_head) {
|
||
oscil->Preamble.Tail = (new_head + 1) % head_max;
|
||
oscil->Config.Overrun = 1;
|
||
}
|
||
} else if(start_pos > new_head) {
|
||
// Кольцевой случай (было переполнение)
|
||
if(tail > start_pos || tail <= new_head) {
|
||
oscil->Preamble.Tail = (new_head + 1) % head_max;
|
||
oscil->Config.Overrun = 1;
|
||
}
|
||
}
|
||
// }
|
||
oscil->Preamble.Head = new_head;
|
||
|
||
return HAL_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief Обновление указателя Tail
|
||
* @param oscil Указатель на структуру осциллографа
|
||
* @return HAL Status
|
||
*
|
||
* @details Вызывается после того, как данные были прочитаны через Modbus.
|
||
* Tail устанавливается на следующий байт за Head.
|
||
*/
|
||
HAL_StatusTypeDef MB_Oscil_UpdateTail(MB_OscilTypeDef *oscil)
|
||
{
|
||
if(!oscil)
|
||
return HAL_ERROR;
|
||
|
||
// Сдвигаем Tail на следующий байт за Head
|
||
uint8_t head_max = oscil->Config.BufferSize * 2;
|
||
oscil->Preamble.Tail = oscil->Preamble.Head;
|
||
|
||
if(oscil->Preamble.Tail >= head_max)
|
||
oscil->Preamble.Tail = 0;
|
||
|
||
oscil->Config.Overrun = 0;
|
||
|
||
return HAL_OK;
|
||
}
|
||
|
||
|
||
#endif //MODBUS_ENABLE_OSCIL
|