Добавлена терминалка от андрея, +проект вынесен в отдельную папку
This commit is contained in:
555
py_project/Core/Dallas/dallas_tools.c
Normal file
555
py_project/Core/Dallas/dallas_tools.c
Normal file
@@ -0,0 +1,555 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file dallas_tools.c
|
||||
* @brief Драйвер для работы с датчиками температуры DS18B20
|
||||
* @author MicroTechnics (microtechnics.ru)
|
||||
******************************************************************************
|
||||
@details
|
||||
Этот файл содержит реализацию функций для работы с датчиком DS18B20
|
||||
через интерфейс 1-Wire. Он предоставляет функции для чтения и записи
|
||||
конфигурации, выполнения измерений и обработки полученных данных.
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/* Includes ----------------------------------------------------------------*/
|
||||
|
||||
#include "dallas_tools.h"
|
||||
#include "string.h"
|
||||
|
||||
|
||||
/* Declarations and definitions --------------------------------------------*/
|
||||
DALLAS_HandleTypeDef hdallas1;
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Функция для нахождения нового датчика на место потерянного
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_ReplaceLostedSensor(DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
result = Dallas_IsConnected(sensor);
|
||||
|
||||
if(sensor->isLost)
|
||||
{
|
||||
if(DS18B20_Search(sensor->hdallas->ds_devices, sensor->hdallas->onewire) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
if(sensor->Init.init_func(sensor->hdallas, sensor) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY; // датчик не потерян
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Функция для иниицализации нового датчика в структуре
|
||||
* @param hdallas Указатель на хендл для общения с датчиками
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_AddNewSensors(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
sensor->hdallas = hdallas;
|
||||
|
||||
result = sensor->Init.init_func(hdallas, sensor);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Инициализирует структуру датчика по ROM
|
||||
* @param hdallas Указатель на хендл для общения с датчиками
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_SensorInitByROM(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
uint8_t ROM[8] = {0};
|
||||
ROM[0] = (sensor->Init.InitParam >> (7*8)) & 0xFF;
|
||||
ROM[1] = (sensor->Init.InitParam >> (6*8)) & 0xFF;
|
||||
ROM[2] = (sensor->Init.InitParam >> (5*8)) & 0xFF;
|
||||
ROM[3] = (sensor->Init.InitParam >> (4*8)) & 0xFF;
|
||||
ROM[4] = (sensor->Init.InitParam >> (3*8)) & 0xFF;
|
||||
ROM[5] = (sensor->Init.InitParam >> (2*8)) & 0xFF;
|
||||
ROM[6] = (sensor->Init.InitParam >> (1*8)) & 0xFF;
|
||||
ROM[7] = (sensor->Init.InitParam >> (0*8)) & 0xFF;
|
||||
|
||||
if(DS18B20_IsValidAddress(ROM) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
uint8_t comparebytes = DALLAS_ROM_SIZE;
|
||||
int ROM_ind = 0;
|
||||
for(int i = 0; i < hdallas->onewire->RomCnt; i++)
|
||||
{
|
||||
comparebytes = DALLAS_ROM_SIZE;
|
||||
for(int rom_byte = 0; rom_byte < DALLAS_ROM_SIZE; rom_byte++)
|
||||
{
|
||||
if(hdallas->ds_devices->DevAddr[i][rom_byte] == ROM[rom_byte])
|
||||
comparebytes--;
|
||||
}
|
||||
if(comparebytes == 0)
|
||||
{
|
||||
ROM_ind = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Проверка присутствует ли выбранный датчик на линии */
|
||||
if(comparebytes == 0)
|
||||
{
|
||||
|
||||
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices->DevAddr[ROM_ind]);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Инициализирует структуру датчика по пользовательским байтам
|
||||
* @param hdallas Указатель на хендл для общения с датчиками
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_SensorInitByUserBytes(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
uint8_t UserByte1 = sensor->Init.InitParam & 0xFF;
|
||||
uint8_t UserByte2 = sensor->Init.InitParam >> 8;
|
||||
uint8_t UserByte3 = (sensor->Init.InitParam >> 16) & 0xFF;
|
||||
uint8_t UserByte4 = (sensor->Init.InitParam >> 16) >> 8;
|
||||
uint8_t UserByte12Cmp = 0;
|
||||
uint8_t UserByte34Cmp = 0;
|
||||
|
||||
for(int i = 0; i < hdallas->onewire->RomCnt; i++)
|
||||
{
|
||||
/* Проверка присутствует ли выбранный датчик на линии */
|
||||
result = DS18B20_ReadScratchpad(hdallas->onewire, (uint8_t *)&hdallas->ds_devices->DevAddr[i], (uint8_t *)&hdallas->scratchpad);
|
||||
if (result != HAL_OK)
|
||||
return result;
|
||||
|
||||
/* Сравнение UserByte1 и UserByte2, если они не равны нулю */
|
||||
if((sensor->Init.InitParam & 0xFFFF) != NULL)
|
||||
{
|
||||
if( (hdallas->scratchpad.tHighRegister == UserByte1) &&
|
||||
(hdallas->scratchpad.tLowRegister == UserByte2))
|
||||
{
|
||||
UserByte12Cmp = 1;
|
||||
}
|
||||
}/* Если сравнение UserByte1 и UserByte2 не выбрано, то считаем что они совпадают */
|
||||
else
|
||||
{
|
||||
UserByte12Cmp = 1;
|
||||
}
|
||||
/* Сравнение UserByte3 и UserByte4, если они не равны нулю */
|
||||
if((sensor->Init.InitParam & 0xFFFF0000) != NULL)
|
||||
{
|
||||
if( (hdallas->scratchpad.UserByte3 == UserByte3) &&
|
||||
(hdallas->scratchpad.UserByte4 == UserByte4))
|
||||
{
|
||||
UserByte34Cmp = 1;
|
||||
}
|
||||
}/* Если сравнение UserByte3 и UserByte4 не выбрано, то считаем что они одинаковые */
|
||||
else
|
||||
{
|
||||
UserByte34Cmp = 1;
|
||||
}
|
||||
/* Если нашли нужный датчик - завершаем поиск */
|
||||
if(UserByte12Cmp && UserByte34Cmp)
|
||||
{
|
||||
// sensor->isInitialized = 1;
|
||||
// sensor->Init.init_func = (HAL_StatusTypeDef (*)())Dallas_SensorInitByUserBytes;
|
||||
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices->DevAddr[i]);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
sensor->sensROM = 0;
|
||||
/* Возвращаем ошибку если не нашли */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Инициализирует структуру датчика по порядковому номеру
|
||||
* @param hdallas Указатель на хендл для общения с датчиками
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
* @details Порядковый номер датчика в списке найденных.
|
||||
* Т.е. каким по счету этот датчик был найден
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_SensorInitByInd(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices->DevAddr[sensor->Init.InitParam]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Инициализирует датчик для работы
|
||||
* @param hdallas Указатель на хендл для общения с датчиками
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @param ROM ROM датчика, который надо инициализировать
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_SensorInit(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor, uint8_t (*ROM)[DALLAS_ROM_SIZE])
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
if(hdallas == 0)
|
||||
return HAL_ERROR;
|
||||
|
||||
sensor->hdallas = hdallas;
|
||||
sensor->sensROM = 0;
|
||||
sensor->sensROM = *(uint64_t *)(ROM);
|
||||
// for(int i = 0; i < DALLAS_ROM_SIZE; i++)
|
||||
// sensor->sensROM |= ((uint64_t)(*ROM)[i] << (56 - 8*i));
|
||||
|
||||
/* Проверка присутствует ли выбранный датчик на линии */
|
||||
result = Dallas_ReadScratchpad(sensor);
|
||||
if (result == HAL_OK)
|
||||
{
|
||||
/* Установка разрешения */
|
||||
result = DS18B20_SetResolution(hdallas->onewire, (uint8_t *)ROM, sensor->Init.Resolution);
|
||||
if (result == HAL_OK)
|
||||
{
|
||||
sensor->isInitialized = 1;
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->isInitialized = 0;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->isInitialized = 0;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Деинициализирует структуру датчика
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_SensorDeInit(DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
memset(&sensor->f, 0, sizeof(sensor->f));
|
||||
sensor->isConnected = 0;
|
||||
sensor->isInitialized = 0;
|
||||
sensor->isLost = 0;
|
||||
sensor->temperature = 0;
|
||||
sensor->sensROM = 0;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Запускает измерение температуры на всех датчиках
|
||||
* @param hdallas Указатель на хендл для общения с датчиками
|
||||
* @param waitCondition Условие ожидания завершения преобразования
|
||||
* @param dallas_delay_ms Время ожидания окончания конверсии
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_StartConvertTAll(DALLAS_HandleTypeDef *hdallas, DALLAS_WaitConvertionTypeDef waitCondition, uint8_t dallas_delay_ms)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
uint8_t rxDummyData;
|
||||
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
// Отправка команды начала преобразования температуры
|
||||
result = DS18B20_StartConvTAll(hdallas->onewire);
|
||||
if(result != HAL_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
// // Проверка что преобразование началось
|
||||
// if(OneWire_ReadBit(onewire) == 1)
|
||||
// return HAL_ERROR;
|
||||
|
||||
// Ожидание завершения преобразования, путем проверки шины
|
||||
if (waitCondition == DALLAS_WAIT_BUS)
|
||||
{
|
||||
result = DS18B20_WaitForEndConvertion(hdallas->onewire);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Ожидание завершения преобразования, путем задержки
|
||||
if (waitCondition == DALLAS_WAIT_DELAY)
|
||||
{
|
||||
uint32_t delayValueMs = 0;
|
||||
|
||||
switch (dallas_delay_ms)
|
||||
{
|
||||
case DALLAS_CONFIG_9_BITS:
|
||||
delayValueMs = DALLAS_DELAY_MS_9_BITS;
|
||||
break;
|
||||
|
||||
case DALLAS_CONFIG_10_BITS:
|
||||
delayValueMs = DALLAS_DELAY_MS_10_BITS;
|
||||
break;
|
||||
|
||||
case DALLAS_CONFIG_11_BITS:
|
||||
delayValueMs = DALLAS_DELAY_MS_11_BITS;
|
||||
break;
|
||||
|
||||
case DALLAS_CONFIG_12_BITS:
|
||||
delayValueMs = DALLAS_DELAY_MS_12_BITS;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
HAL_Delay(delayValueMs);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Измеряет температуру на датчике
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @param waitCondition Условие ожидания завершения преобразования
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_ConvertT(DALLAS_SensorHandleTypeDef *sensor, DALLAS_WaitConvertionTypeDef waitCondition)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
uint8_t rxDummyData;
|
||||
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor->isInitialized == 0)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Проверка присутствует ли выбранный датчик на линии */
|
||||
result = Dallas_IsConnected(sensor);
|
||||
if (result != HAL_OK)
|
||||
return result;
|
||||
|
||||
// Отправка команды начала преобразования температуры
|
||||
result = DS18B20_StartConvT(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM);
|
||||
if(result != HAL_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Ожидание завершения преобразования, путем проверки шины
|
||||
if (waitCondition == DALLAS_WAIT_BUS)
|
||||
{
|
||||
result = DS18B20_WaitForEndConvertion(sensor->hdallas->onewire);
|
||||
if(result == HAL_TIMEOUT)
|
||||
{
|
||||
sensor->f.timeout_convertion_cnt++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Ожидание завершения преобразования, путем задержки
|
||||
if (waitCondition == DALLAS_WAIT_DELAY)
|
||||
{
|
||||
uint32_t delayValueMs = 0;
|
||||
|
||||
switch (sensor->hdallas->scratchpad.ConfigRegister)
|
||||
{
|
||||
case DALLAS_CONFIG_9_BITS:
|
||||
delayValueMs = DALLAS_DELAY_MS_9_BITS;
|
||||
break;
|
||||
|
||||
case DALLAS_CONFIG_10_BITS:
|
||||
delayValueMs = DALLAS_DELAY_MS_10_BITS;
|
||||
break;
|
||||
|
||||
case DALLAS_CONFIG_11_BITS:
|
||||
delayValueMs = DALLAS_DELAY_MS_11_BITS;
|
||||
break;
|
||||
|
||||
case DALLAS_CONFIG_12_BITS:
|
||||
delayValueMs = DALLAS_DELAY_MS_12_BITS;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
HAL_Delay(delayValueMs);
|
||||
}
|
||||
|
||||
/* Не считываем температуру, если не выбрано ожидание окончания преобразования */
|
||||
if(waitCondition != DALLAS_WAIT_NONE)
|
||||
{
|
||||
result = Dallas_ReadTemperature(sensor);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Читает измеренную датчиком температуру
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_ReadTemperature(DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor->isInitialized == 0)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Проверка присутствует ли выбранный датчик на линии */
|
||||
result = Dallas_IsConnected(sensor);
|
||||
if (result != HAL_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
result = DS18B20_CalcTemperature(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, (uint8_t *)&sensor->hdallas->scratchpad, &sensor->temperature);
|
||||
|
||||
if (result != HAL_OK)
|
||||
{
|
||||
sensor->f.read_temperature_err_cnt++;
|
||||
return result;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Проверяет подключен ли датчик (чтение scratchpad)
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_IsConnected(DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
result = Dallas_ReadScratchpad(sensor);
|
||||
|
||||
if (result == HAL_OK)
|
||||
{
|
||||
sensor->isConnected = 1;
|
||||
sensor->isLost = 0;
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->temperature = 0;
|
||||
if(sensor->isConnected == 1)
|
||||
{
|
||||
sensor->f.disconnect_cnt++;
|
||||
}
|
||||
sensor->isLost = 1;
|
||||
sensor->isConnected = 0;
|
||||
|
||||
// Dallas_ReplaceLostedSensor(sensor);
|
||||
return HAL_BUSY; // использую busy, чтобы отличать ситуацию от HAL_ERROR
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Записывает пользовательские байты
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @param UserBytes12 Пользовательские байты 1 и 2
|
||||
* @param UserBytes34 Пользовательские байты 3 и 4
|
||||
* @param UserBytesMask Маска, какие байты записывать, а какие нет
|
||||
* @retval HAL Status
|
||||
* @details старший байт - UserByte4/UserByte2, младший - UserByte3/UserByte1.
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_WriteUserBytes(DALLAS_SensorHandleTypeDef *sensor, uint16_t UserBytes12, uint16_t UserBytes34, uint8_t UserBytesMask)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
if(sensor->isInitialized == 0)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Проверка присутствует ли выбранный датчик на линии */
|
||||
result = Dallas_IsConnected(sensor);
|
||||
if (result != HAL_OK)
|
||||
return result;
|
||||
|
||||
result = DS18B20_WriteUserBytes(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, UserBytes12, UserBytes34, UserBytesMask);
|
||||
if (result != HAL_OK)
|
||||
{
|
||||
sensor->f.write_err_cnt++;
|
||||
return result;
|
||||
}
|
||||
result = Dallas_ReadScratchpad(sensor);
|
||||
if (result != HAL_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
HAL_StatusTypeDef Dallas_ReadScratchpad(DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
return DS18B20_ReadScratchpad(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, (uint8_t *)&sensor->hdallas->scratchpad);
|
||||
}
|
||||
148
py_project/Core/Dallas/dallas_tools.h
Normal file
148
py_project/Core/Dallas/dallas_tools.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file dallas_tools.h
|
||||
* @brief Драйвер датчиков температуры DALLAS
|
||||
******************************************************************************
|
||||
* Этот файл предоставляет объявления и определения для работы с датчиками
|
||||
* температуры DS18B20. Он включает структуры данных, макросы и прототипы
|
||||
* функций для инициализации, чтения температуры
|
||||
* и управления датчиками.
|
||||
*
|
||||
* Работа с датчиками ведётся через протокол OneWire.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef DALLAS_TOOLS_H
|
||||
#define DALLAS_TOOLS_H
|
||||
|
||||
|
||||
|
||||
/* Includes -----------------------------------------------------------------*/
|
||||
#include "ds18b20_driver.h"
|
||||
#include "onewire.h"
|
||||
|
||||
/* Определения пользовательских байтов для записи чтения */
|
||||
#define DALLAS_USER_BYTE_1 (1<<0) ///< Первый пользовательский байт
|
||||
#define DALLAS_USER_BYTE_2 (1<<1) ///< Второй пользовательский байт
|
||||
#define DALLAS_USER_BYTE_3 (1<<2) ///< Третий пользовательский байт
|
||||
#define DALLAS_USER_BYTE_4 (1<<3) ///< Четвёртый пользовательский байт
|
||||
|
||||
#define DALLAS_USER_BYTE_12 (DALLAS_USER_BYTE_1|DALLAS_USER_BYTE_2) ///< Первые два байта
|
||||
#define DALLAS_USER_BYTE_34 (DALLAS_USER_BYTE_3|DALLAS_USER_BYTE_4) ///< Вторые два байта
|
||||
#define DALLAS_USER_BYTE_ALL (DALLAS_USER_BYTE_12|DALLAS_USER_BYTE_34) ///< Все пользовательские байты
|
||||
|
||||
/* Declarations and definitions ---------------------------------------------*/
|
||||
#define DALLAS_ROM_SIZE 8
|
||||
|
||||
#define DALLAS_CONFIG_9_BITS 0x1F
|
||||
#define DALLAS_CONFIG_10_BITS 0x3F
|
||||
#define DALLAS_CONFIG_11_BITS 0x5F
|
||||
#define DALLAS_CONFIG_12_BITS 0x7F
|
||||
|
||||
#define DALLAS_DELAY_MS_9_BITS 94
|
||||
#define DALLAS_DELAY_MS_10_BITS 188
|
||||
#define DALLAS_DELAY_MS_11_BITS 375
|
||||
#define DALLAS_DELAY_MS_12_BITS 750
|
||||
#define DALLAS_DELAY_MS_MAX DALLAS_DELAY_MS_12_BITS
|
||||
|
||||
/** @brief Структура Scratchpad датчика DALLAS */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t TemperatureLSB; ///< Младший байт температуры
|
||||
uint8_t TemperatureMSB; ///< Старший байт температуры
|
||||
uint8_t tHighRegister; ///< Верхний температурный порог
|
||||
uint8_t tLowRegister; ///< Нижний температурный порог
|
||||
uint8_t ConfigRegister; ///< Конфигурационный регистр
|
||||
uint8_t reserved; ///< Зарезервировано
|
||||
uint8_t UserByte3; ///< Пользовательский байт 3
|
||||
uint8_t UserByte4; ///< Пользовательский байт 4
|
||||
uint8_t ScratchpadCRC; ///< Контрольная сумма
|
||||
}DALLAS_ScratchpadTypeDef;
|
||||
|
||||
/** @brief Структура флагов ошибок датчиков DALLAS */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t disconnect_cnt; ///< Счетчик отключений датчика
|
||||
uint8_t read_temperature_err_cnt; ///< Счетчик ошибок чтения температуры
|
||||
uint8_t timeout_convertion_cnt; ///< Счетчик ошибок таймаута конвертации
|
||||
uint8_t write_err_cnt; ///< Счетчик других ошибок
|
||||
}DALLAS_FlagsTypeDef;
|
||||
|
||||
|
||||
/** @brief Структура инициализации датчика DALLAS */
|
||||
typedef struct __packed
|
||||
{
|
||||
uint64_t InitParam; ///< Параметр для инициализации: ROM/UserBytes/Индекс
|
||||
uint8_t Resolution; ///< Разрешение датчика
|
||||
HAL_StatusTypeDef (*init_func)(); ///< Функция инициализации
|
||||
} DALLAS_InitStructTypeDef;
|
||||
|
||||
|
||||
|
||||
/** @brief Cтруктура обработчика DALLAS для общения с датчиком*/
|
||||
typedef struct
|
||||
{
|
||||
OneWire_t *onewire;
|
||||
DS18B20_Drv_t *ds_devices;
|
||||
DALLAS_ScratchpadTypeDef scratchpad;
|
||||
}DALLAS_HandleTypeDef;
|
||||
extern DALLAS_HandleTypeDef hdallas1;
|
||||
|
||||
/** @brief Основная структура обработчика датчика DALLAS */
|
||||
typedef struct
|
||||
{
|
||||
unsigned isConnected:1; ///< Флаг соединения
|
||||
unsigned isInitialized:1; ///< Флаг инициализации
|
||||
unsigned isLost:1; ///< Флаг потери связи
|
||||
|
||||
DALLAS_HandleTypeDef *hdallas;
|
||||
uint64_t sensROM; ///< ROM-код датчика
|
||||
|
||||
float temperature; ///< Текущая температура
|
||||
|
||||
DALLAS_InitStructTypeDef Init; ///< Структура инициализации
|
||||
DALLAS_FlagsTypeDef f; ///< Флаги
|
||||
} DALLAS_SensorHandleTypeDef;
|
||||
|
||||
|
||||
|
||||
/** @brief Варианты ожидания окончания конверсии */
|
||||
typedef enum
|
||||
{
|
||||
DALLAS_WAIT_NONE = 0x00, ///< Без ожидания окончания конверсии
|
||||
DALLAS_WAIT_BUS = 0x01, ///< Ожидание окончания конверсии по шине (опрос датчиков - чтение бита)
|
||||
DALLAS_WAIT_DELAY = 0x02, ///< Без ожидания окончания через задержку (максимальная задержка для заданной разрядности)
|
||||
} DALLAS_WaitConvertionTypeDef;
|
||||
|
||||
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
|
||||
/* Функция для нахождения нового датчика на место потерянного */
|
||||
HAL_StatusTypeDef Dallas_ReplaceLostedSensor(DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Функция для иниицализации нового датчика в структуре */
|
||||
HAL_StatusTypeDef Dallas_AddNewSensors(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Инициализирует структуру датчика по ROM */
|
||||
HAL_StatusTypeDef Dallas_SensorInitByROM(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Инициализирует структуру датчика по пользовательским байтам */
|
||||
HAL_StatusTypeDef Dallas_SensorInitByUserBytes(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Инициализирует структуру датчика по порядковому номеру */
|
||||
HAL_StatusTypeDef Dallas_SensorInitByInd(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Инициализирует датчик для работы */
|
||||
HAL_StatusTypeDef Dallas_SensorInit(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor, uint8_t (*ROM)[DALLAS_ROM_SIZE]);
|
||||
/* Деинициализирует структуру датчика */
|
||||
HAL_StatusTypeDef Dallas_SensorDeInit(DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Запускает измерение температуры на всех датчиках */
|
||||
HAL_StatusTypeDef Dallas_StartConvertTAll(DALLAS_HandleTypeDef *hdallas, DALLAS_WaitConvertionTypeDef waitCondition, uint8_t dallas_delay_ms);
|
||||
/* Измеряет температуру на датчике */
|
||||
HAL_StatusTypeDef Dallas_ConvertT(DALLAS_SensorHandleTypeDef *sensor, DALLAS_WaitConvertionTypeDef waitCondition);
|
||||
/* Читает измеренную датчиком температуру */
|
||||
HAL_StatusTypeDef Dallas_ReadTemperature(DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Проверяет подключен ли датчик (чтение scratchpad) */
|
||||
HAL_StatusTypeDef Dallas_IsConnected(DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Записывает пользовательские байты */
|
||||
HAL_StatusTypeDef Dallas_WriteUserBytes(DALLAS_SensorHandleTypeDef *sensor, uint16_t UserBytes12, uint16_t UserBytes34, uint8_t UserBytesMask);
|
||||
/* Записывает пользовательские байты */
|
||||
HAL_StatusTypeDef Dallas_ReadScratchpad(DALLAS_SensorHandleTypeDef *sensor);
|
||||
|
||||
|
||||
#endif // #ifndef DALLAS_TOOLS_H
|
||||
607
py_project/Core/Dallas/ds18b20_driver.c
Normal file
607
py_project/Core/Dallas/ds18b20_driver.c
Normal file
@@ -0,0 +1,607 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file ds18b20_driver.c
|
||||
* @brief This file includes the HAL/LL driver for DS18B20 1-Wire Digital
|
||||
* Thermometer
|
||||
******************************************************************************
|
||||
*/
|
||||
#include "ds18b20_driver.h"
|
||||
|
||||
DS18B20_Drv_t *DS;
|
||||
OneWire_t OW;
|
||||
|
||||
/**
|
||||
* @brief The function is used to check valid DS18B20 ROM
|
||||
* @retval Return in OK = 1, Failed = 0
|
||||
* @param ROM Pointer to ROM number
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_IsValidAddress(uint8_t *ROM)
|
||||
{
|
||||
if(ROM == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
uint8_t check_family = (*ROM == DS18B20_FAMILY_CODE);
|
||||
/* Calculate CRC */
|
||||
uint8_t crc = OneWire_CRC8(ROM, 7);
|
||||
uint8_t check_crc = (crc == ROM[7]);
|
||||
/* Checks if first byte is equal to DS18B20's family code */
|
||||
if(check_family && check_crc)
|
||||
return HAL_OK;
|
||||
else
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/**
|
||||
* @brief The function is used to check valid DS18B20 ROM
|
||||
* @retval Return in OK = 1, Failed = 0
|
||||
* @param ROM Pointer to ROM number
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_IsValid(uint8_t *ROM)
|
||||
{
|
||||
if(ROM == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
if(*ROM == DS18B20_FAMILY_CODE)
|
||||
return HAL_OK;
|
||||
else
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used to get resolution
|
||||
* @retval Return value in 9 - 12
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param ROM Pointer to ROM number
|
||||
*/
|
||||
uint8_t DS18B20_GetResolution(OneWire_t* OW, uint8_t *ROM) {
|
||||
uint8_t conf;
|
||||
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
if(ROM == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Check valid ROM */
|
||||
if (DS18B20_IsValid(ROM) != HAL_OK)
|
||||
return 0;
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
|
||||
|
||||
/* Ignore first 4 bytes */
|
||||
OneWire_ReadByte(OW);
|
||||
OneWire_ReadByte(OW);
|
||||
OneWire_ReadByte(OW);
|
||||
OneWire_ReadByte(OW);
|
||||
|
||||
/* 5th byte of scratchpad is configuration register */
|
||||
conf = OneWire_ReadByte(OW);
|
||||
|
||||
/* Return 9 - 12 value according to number of bits */
|
||||
return ((conf & 0x60) >> 5) + 9;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used as set resolution
|
||||
* @retval status in OK = 1, Failed = 0
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param ROM Pointer to ROM number
|
||||
* @param Resolution Resolution in 9 - 12
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_SetResolution(OneWire_t* OW, uint8_t *ROM,
|
||||
DS18B20_Res_t Resolution)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
if(ROM == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
uint8_t th, tl, conf;
|
||||
|
||||
/* Check valid ROM */
|
||||
if (DS18B20_IsValid(ROM) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
|
||||
|
||||
/* Ignore first 2 bytes */
|
||||
OneWire_ReadByte(OW);
|
||||
OneWire_ReadByte(OW);
|
||||
|
||||
th = OneWire_ReadByte(OW);
|
||||
tl = OneWire_ReadByte(OW);
|
||||
conf = OneWire_ReadByte(OW);
|
||||
|
||||
/* Set choosed resolution */
|
||||
conf = Resolution;
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Write scratchpad command by onewire protocol, only th, tl and conf
|
||||
* register can be written */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_WRITESCRATCHPAD);
|
||||
|
||||
/* Write bytes */
|
||||
OneWire_WriteByte(OW, th);
|
||||
OneWire_WriteByte(OW, tl);
|
||||
OneWire_WriteByte(OW, conf);
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Copy scratchpad to EEPROM of DS18B20 */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_COPYSCRATCHPAD);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used as start selected ROM device
|
||||
* @retval status in OK = 1, Failed = 0
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param ROM Pointer to ROM number
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_StartConvT(OneWire_t* OW, uint8_t *ROM)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
if(ROM == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Check if device is DS18B20 */
|
||||
if(DS18B20_IsValid(ROM) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Start temperature conversion */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_CONVERT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @brief The function is used as start all ROM device
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_StartConvTAll(OneWire_t* OW)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Reset pulse */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Skip rom */
|
||||
OneWire_WriteByte(OW, ONEWIRE_CMD_SKIPROM);
|
||||
|
||||
/* Start conversion on all connected devices */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_CONVERT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used as read temreature from device and store in selected
|
||||
* destination
|
||||
* @retval status in OK = 1, Failed = 0
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param ROM Pointer to ROM number
|
||||
* @param Destination Pointer to return value
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_CalcTemperature(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad, float *Destination)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
if(ROM == NULL)
|
||||
return HAL_ERROR;
|
||||
if(Scratchpad == NULL)
|
||||
return HAL_ERROR;
|
||||
if(Destination == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
uint16_t temperature;
|
||||
uint8_t resolution;
|
||||
int8_t digit, minus = 0;
|
||||
float decimal;
|
||||
|
||||
/* Check if device is DS18B20 */
|
||||
if (DS18B20_IsValid(ROM) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* First two bytes of scratchpad are temperature values */
|
||||
temperature = Scratchpad[0] | (Scratchpad[1] << 8);
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Check if temperature is negative */
|
||||
if (temperature & 0x8000) {
|
||||
/* Two's complement, temperature is negative */
|
||||
temperature = ~temperature + 1;
|
||||
minus = 1;
|
||||
}
|
||||
|
||||
/* Get sensor resolution */
|
||||
resolution = Scratchpad[4];
|
||||
|
||||
/* Store temperature integer digits and decimal digits */
|
||||
digit = temperature >> 4;
|
||||
digit |= ((temperature >> 8) & 0x7) << 4;
|
||||
|
||||
/* Store decimal digits */
|
||||
switch (resolution) {
|
||||
case DS18B20_RESOLUTION_9BITS: {
|
||||
decimal = (temperature >> 3) & 0x01;
|
||||
decimal *= (float)DS18B20_DECIMAL_STEP_9BIT;
|
||||
} break;
|
||||
case DS18B20_RESOLUTION_10BITS: {
|
||||
decimal = (temperature >> 2) & 0x03;
|
||||
decimal *= (float)DS18B20_DECIMAL_STEP_10BIT;
|
||||
} break;
|
||||
case DS18B20_RESOLUTION_11BITS: {
|
||||
decimal = (temperature >> 1) & 0x07;
|
||||
decimal *= (float)DS18B20_DECIMAL_STEP_11BIT;
|
||||
} break;
|
||||
case DS18B20_RESOLUTION_12BITS: {
|
||||
decimal = temperature & 0x0F;
|
||||
decimal *= (float)DS18B20_DECIMAL_STEP_12BIT;
|
||||
} break;
|
||||
default: {
|
||||
*Destination = 0;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for negative part */
|
||||
decimal = digit + decimal;
|
||||
if (minus) {
|
||||
decimal = 0 - decimal;
|
||||
}
|
||||
|
||||
/* Set to pointer */
|
||||
*Destination = decimal;
|
||||
|
||||
/* Return HAL_OK, temperature valid */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used as read scratchpad from device
|
||||
* @retval status in OK = 1, Failed = 0
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param ROM Pointer to ROM number
|
||||
* @param Destination Pointer to Scratchpad array
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_ReadScratchpad(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
if(ROM == NULL)
|
||||
return HAL_ERROR;
|
||||
if(Scratchpad == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
|
||||
|
||||
/* Get data */
|
||||
for (int i = 0; i < 9; i++) {
|
||||
/* Read byte by byte */
|
||||
Scratchpad[i] = OneWire_ReadByte(OW);
|
||||
}
|
||||
|
||||
/* Calculate CRC */
|
||||
uint8_t crc = OneWire_CRC8(Scratchpad, 8);
|
||||
|
||||
/* Check if CRC is ok */
|
||||
if (crc != Scratchpad[8]) {
|
||||
/* CRC invalid */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to wait for end of convertion
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_WaitForEndConvertion(OneWire_t* OW)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait until line is released, then coversion is completed */
|
||||
while(OneWire_ReadBit(OW) == 0)
|
||||
{
|
||||
if(HAL_GetTick() - tickstart > DS18B20_DELAY_MS_MAX)
|
||||
return HAL_TIMEOUT; // end of convertion has not come
|
||||
}
|
||||
return HAL_OK; // convertion done
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to wait for end of convertion without blocking
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_WaitForEndConvertion_NonBlocking(OneWire_t* OW)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* If line is pull down - conversion is ongoing */
|
||||
if(OneWire_ReadBit(OW) == 0)
|
||||
return HAL_BUSY;
|
||||
else
|
||||
return HAL_OK; // convertion done
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used as set temperature alarm range on
|
||||
* selected device
|
||||
* @retval status in OK = 1, Failed = 0
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param ROM Pointer to ROM number
|
||||
* @param Low Low temperature alarm, value > -55, 0 = reset
|
||||
* @param High High temperature alarm,, value < 125, 0 = reset
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_SetTempAlarm(OneWire_t* OW, uint8_t *ROM, int8_t Low,
|
||||
int8_t High)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
if(ROM == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
uint8_t tl, th, conf;
|
||||
|
||||
/* Check if device is DS18B20 */
|
||||
if (DS18B20_IsValid(ROM) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
Low = ((Low < -55) || (Low == 0)) ? -55 : Low;
|
||||
High = ((High > 125) || (High == 0)) ? 125 : High;
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
|
||||
|
||||
/* Ignore first 2 bytes */
|
||||
OneWire_ReadByte(OW);
|
||||
OneWire_ReadByte(OW);
|
||||
|
||||
th = OneWire_ReadByte(OW);
|
||||
tl = OneWire_ReadByte(OW);
|
||||
conf = OneWire_ReadByte(OW);
|
||||
|
||||
th = (uint8_t)High;
|
||||
tl = (uint8_t)Low;
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Write scratchpad command by onewire protocol, only th, tl and conf
|
||||
* register can be written */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_WRITESCRATCHPAD);
|
||||
|
||||
/* Write bytes */
|
||||
OneWire_WriteByte(OW, th);
|
||||
OneWire_WriteByte(OW, tl);
|
||||
OneWire_WriteByte(OW, conf);
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Copy scratchpad to EEPROM of DS18B20 */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_COPYSCRATCHPAD);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used as set user bytes with mask
|
||||
* @retval status in OK = 1, Failed = 0
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param ROM Pointer to ROM number
|
||||
* @param UserBytes12 First 2 User Bytes (tHigh and tLow)
|
||||
* @param UserBytes34 Second 2 User Bytes
|
||||
* @param UserBytesMask Which User Bytes write, and which ignore
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_WriteUserBytes(OneWire_t* OW, uint8_t *ROM, int16_t UserBytes12,
|
||||
int16_t UserBytes34, uint8_t UserBytesMask)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
if(ROM == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
uint8_t ub1, ub2, conf, ub3, ub4;
|
||||
uint8_t UserByte1 = UserBytes12 & 0xFF;
|
||||
uint8_t UserByte2 = UserBytes12 >> 8;
|
||||
uint8_t UserByte3 = UserBytes34 & 0xFF;
|
||||
uint8_t UserByte4 = UserBytes34 >> 8;
|
||||
|
||||
/* Check if device is DS18B20 */
|
||||
if (DS18B20_IsValid(ROM) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Read scratchpad command by onewire protocol */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_READSCRATCHPAD);
|
||||
|
||||
/* Ignore first 2 bytes */
|
||||
OneWire_ReadByte(OW);
|
||||
OneWire_ReadByte(OW);
|
||||
|
||||
ub1 = OneWire_ReadByte(OW);
|
||||
ub2 = OneWire_ReadByte(OW);
|
||||
conf = OneWire_ReadByte(OW);
|
||||
OneWire_ReadByte(OW);
|
||||
ub3 = OneWire_ReadByte(OW);
|
||||
ub4 = OneWire_ReadByte(OW);
|
||||
|
||||
/* If user bytes in mask */
|
||||
if(UserBytesMask & (1<<0))
|
||||
{
|
||||
ub1 = UserByte1;
|
||||
}
|
||||
if(UserBytesMask & (1<<1))
|
||||
{
|
||||
ub2 = UserByte2;
|
||||
}
|
||||
if(UserBytesMask & (1<<2))
|
||||
{
|
||||
ub3 = UserByte3;
|
||||
}
|
||||
if(UserBytesMask & (1<<3))
|
||||
{
|
||||
ub4 = UserByte4;
|
||||
}
|
||||
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Write scratchpad command by onewire protocol, only th, tl and conf
|
||||
* register can be written */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_WRITESCRATCHPAD);
|
||||
|
||||
/* Write bytes */
|
||||
OneWire_WriteByte(OW, ub1);
|
||||
OneWire_WriteByte(OW, ub2);
|
||||
OneWire_WriteByte(OW, conf);
|
||||
OneWire_WriteByte(OW, ub3);
|
||||
OneWire_WriteByte(OW, ub4);
|
||||
|
||||
/* Reset line */
|
||||
OneWire_Reset(OW);
|
||||
|
||||
/* Select ROM number */
|
||||
OneWire_MatchROM(OW, ROM);
|
||||
|
||||
/* Copy scratchpad to EEPROM of DS18B20 */
|
||||
OneWire_WriteByte(OW, DS18B20_CMD_COPYSCRATCHPAD);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
///**
|
||||
// * @brief The function is used as search device that had temperature alarm
|
||||
// * triggered and store it in DS18B20 alarm data structure
|
||||
// * @retval status of search, OK = 1, Failed = 0
|
||||
// * @param DS DS18B20 HandleTypedef
|
||||
// * @param OW OneWire HandleTypedef
|
||||
// */
|
||||
//uint8_t DS18B20_AlarmSearch(DS18B20_Drv_t *DS, OneWire_t* OW)
|
||||
//{
|
||||
// uint8_t t = 0;
|
||||
|
||||
// /* Reset Alarm in DS */
|
||||
// for(uint8_t i = 0; i < OW->RomCnt; i++)
|
||||
// {
|
||||
// for(uint8_t j = 0; j < 8; j++)
|
||||
// {
|
||||
// DS->AlmAddr[i][j] = 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /* Start alarm search */
|
||||
// while (OneWire_Search(OW, DS18B20_CMD_ALARM_SEARCH))
|
||||
// {
|
||||
// /* Store ROM of device which has alarm flag set */
|
||||
// OneWire_GetDevRom(OW, DS->AlmAddr[t]);
|
||||
// t++;
|
||||
// }
|
||||
// return (t > 0) ? 1 : 0;
|
||||
//}
|
||||
|
||||
/**
|
||||
* @brief The function is used to initialize the DS18B20 sensor, and search
|
||||
* for all ROM along the line. Store in DS18B20 data structure
|
||||
* @retval Rom detect status, OK = 1, No Rom detected = 0
|
||||
* @param DS DS18B20 HandleTypedef
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
HAL_StatusTypeDef DS18B20_Search(DS18B20_Drv_t *DS, OneWire_t *OW)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
|
||||
OW->RomCnt = 0;
|
||||
/* Search all OneWire devices ROM */
|
||||
while(1)
|
||||
{
|
||||
/* Start searching for OneWire devices along the line */
|
||||
if(OneWire_Search(OW, ONEWIRE_CMD_SEARCHROM) != 1) break;
|
||||
|
||||
/* Get device ROM */
|
||||
OneWire_GetDevRom(OW, DS->DevAddr[OW->RomCnt]);
|
||||
|
||||
OW->RomCnt++;
|
||||
}
|
||||
for(int i = OW->RomCnt; i < DS18B20_DEVICE_AMOUNT; i++)
|
||||
{
|
||||
for(int j = 0; j < 8; j++)
|
||||
DS->DevAddr[i][j] = 0;
|
||||
}
|
||||
|
||||
|
||||
if(OW->RomCnt > 0)
|
||||
return HAL_OK;
|
||||
else
|
||||
return HAL_BUSY;
|
||||
}
|
||||
105
py_project/Core/Dallas/ds18b20_driver.h
Normal file
105
py_project/Core/Dallas/ds18b20_driver.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file ds18b20_driver.h
|
||||
* @brief This file contains all the constants parameters for the DS18B20
|
||||
* 1-Wire Digital Thermometer
|
||||
******************************************************************************
|
||||
* @attention
|
||||
* Usage:
|
||||
* Uncomment LL Driver for HAL driver
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef DS18B20_H
|
||||
#define DS18B20_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "onewire.h"
|
||||
|
||||
/* I/O Port ------------------------------------------------------------------*/
|
||||
#define DS_Pin GPIO_PIN_0
|
||||
#define DS_GPIO_Port GPIOB
|
||||
|
||||
/* Data Structure ------------------------------------------------------------*/
|
||||
#define DS18B20_DEVICE_AMOUNT 30
|
||||
|
||||
/* Register ------------------------------------------------------------------*/
|
||||
#define DS18B20_CMD_CONVERT 0x44
|
||||
#define DS18B20_CMD_ALARM_SEARCH 0xEC
|
||||
#define DS18B20_CMD_READSCRATCHPAD 0xBE
|
||||
#define DS18B20_CMD_WRITESCRATCHPAD 0x4E
|
||||
#define DS18B20_CMD_COPYSCRATCHPAD 0x48
|
||||
/* Data Structure ------------------------------------------------------------*/
|
||||
#define DS18B20_FAMILY_CODE 0x28
|
||||
|
||||
|
||||
#define DS18B20_SERIAL_NUMBER_LEN_BYTES 6
|
||||
#define DS18B20_SERIAL_NUMBER_OFFSET_BYTES 1
|
||||
|
||||
#define DS18B20_SCRATCHPAD_T_LSB_BYTE_IDX 0
|
||||
#define DS18B20_SCRATCHPAD_T_MSB_BYTE_IDX 1
|
||||
#define DS18B20_SCRATCHPAD_T_LIMIT_H_BYTE_IDX 2
|
||||
#define DS18B20_SCRATCHPAD_T_LIMIT_L_BYTE_IDX 3
|
||||
#define DS18B20_SCRATCHPAD_CONFIG_BYTE_IDX 4
|
||||
#define DS18B20_SCRATCHPAD_USER_BYTE_3_IDX 6
|
||||
#define DS18B20_SCRATCHPAD_USER_BYTE_4_IDX 7
|
||||
#define DS18B20_SCRATCHPAD_CRC_IDX 8
|
||||
|
||||
/* Bits locations for resolution */
|
||||
#define DS18B20_RESOLUTION_R1 6
|
||||
#define DS18B20_RESOLUTION_R0 5
|
||||
|
||||
#define DS18B20_DECIMAL_STEP_12BIT 0.0625
|
||||
#define DS18B20_DECIMAL_STEP_11BIT 0.125
|
||||
#define DS18B20_DECIMAL_STEP_10BIT 0.25
|
||||
#define DS18B20_DECIMAL_STEP_9BIT 0.5
|
||||
|
||||
#define DS18B20_DELAY_MS_9_BITS 94
|
||||
#define DS18B20_DELAY_MS_10_BITS 188
|
||||
#define DS18B20_DELAY_MS_11_BITS 375
|
||||
#define DS18B20_DELAY_MS_12_BITS 750
|
||||
#define DS18B20_DELAY_MS_MAX DS18B20_DELAY_MS_12_BITS
|
||||
|
||||
|
||||
/* DS18B20 Resolutions */
|
||||
typedef enum {
|
||||
DS18B20_RESOLUTION_9BITS = 0x1F,
|
||||
DS18B20_RESOLUTION_10BITS = 0x3F,
|
||||
DS18B20_RESOLUTION_11BITS = 0x5F,
|
||||
DS18B20_RESOLUTION_12BITS = 0x7F
|
||||
} DS18B20_Res_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t DevAddr[DS18B20_DEVICE_AMOUNT][8];
|
||||
} DS18B20_Drv_t;
|
||||
extern DS18B20_Drv_t *DS;;
|
||||
extern OneWire_t OW;
|
||||
|
||||
/* External Function ---------------------------------------------------------*/
|
||||
HAL_StatusTypeDef DS18B20_Search(DS18B20_Drv_t *DS, OneWire_t *OW);
|
||||
HAL_StatusTypeDef DS18B20_StartConvT(OneWire_t* OW, uint8_t *ROM);
|
||||
HAL_StatusTypeDef DS18B20_StartConvTAll(OneWire_t* OW);
|
||||
HAL_StatusTypeDef DS18B20_CalcTemperature(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad, float *destination);
|
||||
HAL_StatusTypeDef DS18B20_ReadScratchpad(OneWire_t* OW, uint8_t *ROM, uint8_t *Scratchpad);
|
||||
HAL_StatusTypeDef DS18B20_WaitForEndConvertion(OneWire_t* OW);
|
||||
HAL_StatusTypeDef DS18B20_WaitForEndConvertion_NonBlocking(OneWire_t* OW);
|
||||
HAL_StatusTypeDef DS18B20_SetTempAlarm(OneWire_t* OW, uint8_t *ROM, int8_t Low,
|
||||
int8_t High);
|
||||
HAL_StatusTypeDef DS18B20_WriteUserBytes(OneWire_t* OW, uint8_t *ROM, int16_t UserBytes12,
|
||||
int16_t UserBytes34, uint8_t UserBytesMask);
|
||||
uint8_t DS18B20_AlarmSearch(DS18B20_Drv_t *DS, OneWire_t* OW);
|
||||
|
||||
HAL_StatusTypeDef DS18B20_SetResolution(OneWire_t* OW, uint8_t *ROM,
|
||||
DS18B20_Res_t Resolution);
|
||||
HAL_StatusTypeDef DS18B20_IsValidAddress(uint8_t *ROM);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DS18B20_H */
|
||||
58
py_project/Core/Dallas/dwt.c
Normal file
58
py_project/Core/Dallas/dwt.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file dwt.c
|
||||
* @brief This file includes the utilities for DWT
|
||||
******************************************************************************
|
||||
*/
|
||||
#include "dwt.h"
|
||||
|
||||
static uint32_t SysCClk, start;
|
||||
|
||||
/**
|
||||
* @brief Initialize DWT
|
||||
*/
|
||||
void DwtInit(void)
|
||||
{
|
||||
SysCClk = (SystemCoreClock / 1000000); // Calculate in us
|
||||
DWT_LAR |= DWT_LAR_UNLOCK;
|
||||
DEM_CR |= (uint32_t)DEM_CR_TRCENA;
|
||||
DWT_CYCCNT = (uint32_t)0u; // Reset the clock counter
|
||||
DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start DWT Counter
|
||||
*/
|
||||
void DwtStart(void)
|
||||
{
|
||||
start = DWT_CYCCNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate Interval Base On Previous Start Time
|
||||
* @retval Interval in us
|
||||
*/
|
||||
float DwtInterval(void)
|
||||
{
|
||||
return (float)(DWT_CYCCNT - start) / SysCClk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to delay in microsecond
|
||||
* @param usec Period in microsecond
|
||||
*/
|
||||
inline void DwtDelay_us(uint32_t usec)
|
||||
{
|
||||
start = DWT_CYCCNT;
|
||||
while(((DWT_CYCCNT - start) / SysCClk) < usec) {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to delay in millisecond
|
||||
* @param msec Period in millisecond
|
||||
*/
|
||||
inline void DwtDelay_ms(uint32_t msec)
|
||||
{
|
||||
start = DWT_CYCCNT;
|
||||
while(((DWT_CYCCNT - start) / SysCClk) < (msec * 1000)) {};
|
||||
}
|
||||
39
py_project/Core/Dallas/dwt.h
Normal file
39
py_project/Core/Dallas/dwt.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file dwt.h
|
||||
* @brief This file contains all the constants parameters for the dwt delay
|
||||
******************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef DWT_H
|
||||
#define DWT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "py32f0xx_hal.h"
|
||||
|
||||
/* Custom Define -------------------------------------------------------------*/
|
||||
#define DWT_LAR_UNLOCK (uint32_t)0xC5ACCE55
|
||||
#define DEM_CR_TRCENA (1 << 24)
|
||||
#define DWT_CR_CYCCNTENA (1 << 0)
|
||||
#define DWT_CR *(volatile uint32_t *)0xE0001000
|
||||
#define DWT_LAR *(volatile uint32_t *)0xE0001FB0
|
||||
#define DWT_CYCCNT *(volatile uint32_t *)0xE0001004
|
||||
#define DEM_CR *(volatile uint32_t *)0xE000EDFC
|
||||
|
||||
|
||||
/* External Function ---------------------------------------------------------*/
|
||||
void DwtInit(void);
|
||||
void DwtStart(void);
|
||||
float DwtInterval(void);
|
||||
void DwtDelay_us(uint32_t usec);
|
||||
void DwtDelay_ms(uint32_t msec);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DWT_H */
|
||||
379
py_project/Core/Dallas/onewire.c
Normal file
379
py_project/Core/Dallas/onewire.c
Normal file
@@ -0,0 +1,379 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file onewire.c
|
||||
* @brief This file includes the HAL/LL driver for OneWire devices
|
||||
******************************************************************************
|
||||
*/
|
||||
#include "onewire.h"
|
||||
|
||||
/**
|
||||
* @brief The internal function is used to write bit
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param bit bit in 0 or 1
|
||||
*/
|
||||
void OneWire_WriteBit(OneWire_t* OW, uint8_t bit)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return;
|
||||
#ifndef ONEWIRE_UART_H
|
||||
__disable_irq();
|
||||
if(bit)
|
||||
{
|
||||
/* Set line low */
|
||||
OneWire_Pin_Level(OW, 0);
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
|
||||
/* Forming pulse */
|
||||
OneWire_Delay_uw(ONEWIRE_WRITE_1_US);
|
||||
|
||||
/* Release line (pull up line) */
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
|
||||
/* Wait for 55 us and release the line */
|
||||
OneWire_Delay_uw(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_1_US);
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
}else{
|
||||
/* Set line low */
|
||||
OneWire_Pin_Level(OW, 0);
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
|
||||
/* Forming pulse */
|
||||
OneWire_Delay_uw(ONEWIRE_WRITE_0_US);
|
||||
|
||||
/* Release line (pull up line) */
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
|
||||
/* Wait for 5 us and release the line */
|
||||
OneWire_Delay_uw(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_0_US);
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
}
|
||||
__enable_irq();
|
||||
#else
|
||||
OneWireUART_ProcessBit(onewire_uart, bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used to read bit
|
||||
* @retval bit
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
uint8_t OneWire_ReadBit(OneWire_t* OW)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return 0;
|
||||
|
||||
__disable_irq();
|
||||
uint8_t bit = 0;
|
||||
#ifndef ONEWIRE_UART_H
|
||||
/* Line low */
|
||||
OneWire_Pin_Level(OW, 0);
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
OneWire_Delay_uw(ONEWIRE_READ_CMD_US);
|
||||
|
||||
/* Release line */
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
OneWire_Delay_uw(ONEWIRE_READ_DELAY_US);
|
||||
|
||||
/* Read line value */
|
||||
bit = OneWire_Pin_Read(OW);
|
||||
|
||||
/* Wait 50us to complete 60us period */
|
||||
OneWire_Delay_uw(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_READ_CMD_US - ONEWIRE_READ_DELAY_US);
|
||||
__enable_irq();
|
||||
#else
|
||||
bit = OneWireUART_ProcessBit(onewire_uart, 1);
|
||||
#endif
|
||||
/* Return bit value */
|
||||
return bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used to write byte
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param byte byte to write
|
||||
*/
|
||||
void OneWire_WriteByte(OneWire_t* OW, uint8_t byte)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return;
|
||||
|
||||
#ifndef ONEWIRE_UART_H
|
||||
uint8_t bit = 8;
|
||||
/* Write 8 bits */
|
||||
while (bit--) {
|
||||
/* LSB bit is first */
|
||||
OneWire_WriteBit(OW, byte & 0x01);
|
||||
byte >>= 1;
|
||||
}
|
||||
#else
|
||||
OneWireUART_ProcessByte(onewire_uart, byte);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used to read byte
|
||||
* @retval byte from device
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
uint8_t OneWire_ReadByte(OneWire_t* OW)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return 0;
|
||||
|
||||
uint8_t byte = 0;
|
||||
#ifndef ONEWIRE_UART_H
|
||||
uint8_t bit = 8;
|
||||
while (bit--) {
|
||||
byte >>= 1;
|
||||
byte |= (OneWire_ReadBit(OW) << 7);
|
||||
}
|
||||
#else
|
||||
byte = OneWireUART_ProcessByte(onewire_uart, 0xFF);
|
||||
#endif
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used to reset device
|
||||
* @retval respond from device
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
uint8_t OneWire_Reset(OneWire_t* OW)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return 1;
|
||||
|
||||
#ifndef ONEWIRE_UART_H
|
||||
/* Line low, and wait 480us */
|
||||
OneWire_Pin_Level(OW, 0);
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
OneWire_Delay_uw(ONEWIRE_RESET_PULSE_US);
|
||||
|
||||
/* Release line and wait for 70us */
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
OneWire_Delay_uw(ONEWIRE_PRESENCE_WAIT_US);
|
||||
|
||||
/* Check bit value */
|
||||
uint8_t rslt = OneWire_Pin_Read(OW);
|
||||
|
||||
/* Delay for 410 us */
|
||||
OneWire_Delay_uw(ONEWIRE_PRESENCE_DURATION_US);
|
||||
#else
|
||||
|
||||
uint8_t rslt = 0;
|
||||
if(OneWireUART_Reset(onewire_uart) == HAL_OK)
|
||||
rslt = 0;
|
||||
else
|
||||
rslt = 1;
|
||||
#endif
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used to search device
|
||||
* @retval Search result
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
uint8_t OneWire_Search(OneWire_t* OW, uint8_t Cmd)
|
||||
{
|
||||
if(OW == NULL)
|
||||
return 0;
|
||||
|
||||
uint8_t id_bit_number = 1;
|
||||
uint8_t last_zero = 0;
|
||||
uint8_t rom_byte_number = 0;
|
||||
uint8_t search_result = 0;
|
||||
uint8_t rom_byte_mask = 1;
|
||||
uint8_t id_bit, cmp_id_bit, search_direction;
|
||||
|
||||
/* if the last call was not the last one */
|
||||
if (!OW->LastDeviceFlag)
|
||||
{
|
||||
if (OneWire_Reset(OW))
|
||||
{
|
||||
OW->LastDiscrepancy = 0;
|
||||
OW->LastDeviceFlag = 0;
|
||||
OW->LastFamilyDiscrepancy = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// issue the search command
|
||||
OneWire_WriteByte(OW, Cmd);
|
||||
|
||||
// loop to do the search
|
||||
do {
|
||||
// read a bit and its complement
|
||||
id_bit = OneWire_ReadBit(OW);
|
||||
cmp_id_bit = OneWire_ReadBit(OW);
|
||||
|
||||
// check for no devices on 1-wire
|
||||
if ((id_bit == 1) && (cmp_id_bit == 1))
|
||||
{
|
||||
break;
|
||||
} else {
|
||||
// all devices coupled have 0 or 1
|
||||
if (id_bit != cmp_id_bit)
|
||||
{
|
||||
search_direction = id_bit; // bit write value for search
|
||||
} else {
|
||||
/* if this discrepancy if before the Last Discrepancy
|
||||
* on a previous next then pick the same as last time */
|
||||
if (id_bit_number < OW->LastDiscrepancy)
|
||||
{
|
||||
search_direction = ((OW->RomByte[rom_byte_number] & rom_byte_mask) > 0);
|
||||
} else {
|
||||
// if equal to last pick 1, if not then pick 0
|
||||
search_direction = (id_bit_number == OW->LastDiscrepancy);
|
||||
}
|
||||
|
||||
// if 0 was picked then record its position in LastZero
|
||||
if (search_direction == 0)
|
||||
{
|
||||
last_zero = id_bit_number;
|
||||
|
||||
// check for Last discrepancy in family
|
||||
if (last_zero < 9)
|
||||
{
|
||||
OW->LastFamilyDiscrepancy = last_zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set or clear the bit in the ROM byte rom_byte_number
|
||||
* with mask rom_byte_mask */
|
||||
if (search_direction == 1)
|
||||
{
|
||||
OW->RomByte[rom_byte_number] |= rom_byte_mask;
|
||||
} else {
|
||||
OW->RomByte[rom_byte_number] &= ~rom_byte_mask;
|
||||
}
|
||||
|
||||
// serial number search direction write bit
|
||||
OneWire_WriteBit(OW, search_direction);
|
||||
|
||||
/* increment the byte counter id_bit_number and shift the
|
||||
* mask rom_byte_mask */
|
||||
id_bit_number++;
|
||||
rom_byte_mask <<= 1;
|
||||
|
||||
/* if the mask is 0 then go to new SerialNum byte
|
||||
* rom_byte_number and reset mask */
|
||||
if (rom_byte_mask == 0)
|
||||
{
|
||||
rom_byte_number++;
|
||||
rom_byte_mask = 1;
|
||||
}
|
||||
}
|
||||
} while (rom_byte_number < 8); /* loop until through all ROM bytes 0-7
|
||||
if the search was successful then */
|
||||
|
||||
if (!(id_bit_number < 65))
|
||||
{
|
||||
/* search successful so set LastDiscrepancy, LastDeviceFlag,
|
||||
* search_result */
|
||||
OW->LastDiscrepancy = last_zero;
|
||||
// check for last device
|
||||
if (OW->LastDiscrepancy == 0) {
|
||||
OW->LastDeviceFlag = 1;
|
||||
}
|
||||
search_result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* if no device found then reset counters so next 'search' will be like a
|
||||
* first */
|
||||
if (!search_result || !OW->RomByte[0])
|
||||
{
|
||||
OW->LastDiscrepancy = 0;
|
||||
OW->LastDeviceFlag = 0;
|
||||
OW->LastFamilyDiscrepancy = 0;
|
||||
search_result = 0;
|
||||
}
|
||||
|
||||
return search_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used get ROM full address
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param ROM Pointer to device ROM
|
||||
*/
|
||||
void OneWire_GetDevRom(OneWire_t* OW, uint8_t *ROM)
|
||||
{
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
*(ROM + i) = OW->RomByte[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used to initialize OneWire Communication
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
void OneWire_Init(OneWire_t* OW)
|
||||
{
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
OneWire_Pin_Level(OW, 1);
|
||||
OneWire_Delay_uw(1000);
|
||||
OneWire_Pin_Level(OW, 0);
|
||||
OneWire_Delay_uw(1000);
|
||||
OneWire_Pin_Level(OW, 1);
|
||||
OneWire_Delay_uw(2000);
|
||||
|
||||
/* Reset the search state */
|
||||
OW->LastDiscrepancy = 0;
|
||||
OW->LastDeviceFlag = 0;
|
||||
OW->LastFamilyDiscrepancy = 0;
|
||||
OW->RomCnt = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used selected specific device ROM
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param ROM Pointer to device ROM
|
||||
*/
|
||||
void OneWire_MatchROM(OneWire_t* OW, uint8_t *ROM)
|
||||
{
|
||||
OneWire_WriteByte(OW, ONEWIRE_CMD_MATCHROM);
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
OneWire_WriteByte(OW, *(ROM + i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used to access to all ROM
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
void OneWire_Skip(OneWire_t* OW)
|
||||
{
|
||||
OneWire_WriteByte(OW, ONEWIRE_CMD_SKIPROM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function is used check CRC
|
||||
* @param Addr Pointer to address
|
||||
* @param ROM Number of byte
|
||||
*/
|
||||
uint8_t OneWire_CRC8(uint8_t *Addr, uint8_t Len)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
uint8_t inbyte, i, mix;
|
||||
|
||||
while (Len--)
|
||||
{
|
||||
inbyte = *Addr++;
|
||||
|
||||
for (i = 8; i; i--)
|
||||
{
|
||||
mix = (crc ^ inbyte) & 0x01;
|
||||
crc >>= 1;
|
||||
crc ^= (mix) ? 0x8C : 0;
|
||||
inbyte >>= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
77
py_project/Core/Dallas/onewire.h
Normal file
77
py_project/Core/Dallas/onewire.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file onewire.h
|
||||
* @brief This file contains all the constants parameters for the OneWire
|
||||
******************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef ONEWIRE_H
|
||||
#define ONEWIRE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "ow_port.h"
|
||||
|
||||
/* Driver Selection ----------------------------------------------------------*/
|
||||
//#define LL_Driver
|
||||
#define CMSIS_Driver
|
||||
/* OneWire Timings -----------------------------------------------------------*/
|
||||
#define ONEWIRE_RESET_PULSE_US 480 // Длительность импульса сброса
|
||||
#define ONEWIRE_PRESENCE_WAIT_US 70 // Ожидание ответа от датчика
|
||||
#define ONEWIRE_PRESENCE_DURATION_US 410 // Длительность сигнала присутствия
|
||||
|
||||
#define ONEWIRE_WRITE_1_US 8 // Длительность записи "1"
|
||||
#define ONEWIRE_WRITE_0_US 57 // Длительность записи "0"
|
||||
#define ONEWIRE_READ_CMD_US 2 // Время комманды чтения бита
|
||||
#define ONEWIRE_READ_DELAY_US 6 // Задержка перед считыванием бита
|
||||
#define ONEWIRE_COMMAND_SLOT_US 58 // Общее время комманды OneWire
|
||||
#define ONEWIRE_RECOVERY_TIME_US 1 // Восстановление перед следующим слотом
|
||||
/* Common Register -----------------------------------------------------------*/
|
||||
#define ONEWIRE_CMD_SEARCHROM 0xF0
|
||||
#define ONEWIRE_CMD_READROM 0x33
|
||||
#define ONEWIRE_CMD_MATCHROM 0x55
|
||||
#define ONEWIRE_CMD_SKIPROM 0xCC
|
||||
|
||||
/* Data Structure ------------------------------------------------------------*/
|
||||
typedef enum
|
||||
{
|
||||
Input,
|
||||
Output
|
||||
} PinMode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t LastDiscrepancy;
|
||||
uint8_t LastFamilyDiscrepancy;
|
||||
uint8_t LastDeviceFlag;
|
||||
uint8_t RomByte[8];
|
||||
uint8_t RomCnt;
|
||||
uint16_t DataPin;
|
||||
GPIO_TypeDef *DataPort;
|
||||
} OneWire_t;
|
||||
|
||||
/* External Function ---------------------------------------------------------*/
|
||||
void OneWire_Init(OneWire_t* OW);
|
||||
uint8_t OneWire_Search(OneWire_t* OW, uint8_t Cmd);
|
||||
void OneWire_GetDevRom(OneWire_t* OW, uint8_t *dev);
|
||||
uint8_t OneWire_Reset(OneWire_t* OW);
|
||||
uint8_t OneWire_ReadBit(OneWire_t* OW);
|
||||
uint8_t OneWire_ReadByte(OneWire_t* OW);
|
||||
void OneWire_WriteByte(OneWire_t* OW, uint8_t byte);
|
||||
void OneWire_MatchROM(OneWire_t* OW, uint8_t *Rom);
|
||||
void OneWire_Skip(OneWire_t* OW);
|
||||
uint8_t OneWire_CRC8(uint8_t *addr, uint8_t len);
|
||||
|
||||
void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode);
|
||||
void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level);
|
||||
uint8_t OneWire_Pin_Read(OneWire_t* OW);
|
||||
void OneWire_WriteBit(OneWire_t* OW, uint8_t bit);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ONEWIRE_H */
|
||||
109
py_project/Core/Dallas/ow_port.c
Normal file
109
py_project/Core/Dallas/ow_port.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file ow_port.c
|
||||
* @brief This file includes the driver for port for OneWire purposes
|
||||
******************************************************************************
|
||||
*/
|
||||
#include "ow_port.h"
|
||||
#include "onewire.h"
|
||||
#include "tim.h"
|
||||
|
||||
/**
|
||||
* @brief The internal function is used as gpio pin mode
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param Mode Input or Output
|
||||
*/
|
||||
void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode)
|
||||
{
|
||||
#ifdef CMSIS_Driver
|
||||
if(Mode == Input)
|
||||
{
|
||||
OW->DataPort->MODER &= ~((GPIO_MODER_MODE0_Msk) << 0);
|
||||
OW->DataPort->MODER |= (GPIO_MODE_INPUT << (0+2));
|
||||
}else{
|
||||
OW->DataPort->MODER &= ~((GPIO_MODER_MODE0_Msk) << 0);
|
||||
OW->DataPort->MODER |= (GPIO_MODE_OUTPUT_PP << 0);
|
||||
}
|
||||
#else
|
||||
#ifdef LL_Driver
|
||||
if(Mode == Input)
|
||||
{
|
||||
LL_GPIO_SetPinMode(OW->DataPort, OW->DataPin, LL_GPIO_MODE_INPUT);
|
||||
}else{
|
||||
LL_GPIO_SetPinMode(OW->DataPort, OW->DataPin, LL_GPIO_MODE_OUTPUT);
|
||||
}
|
||||
#else
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
GPIO_InitStruct.Pin = OW->DataPin;
|
||||
if(Mode == Input)
|
||||
{
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
}else{
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
}
|
||||
HAL_GPIO_Init(OW->DataPort, &GPIO_InitStruct);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The internal function is used as gpio pin level
|
||||
* @param OW OneWire HandleTypedef
|
||||
* @param Mode Level: Set/High = 1, Reset/Low = 0
|
||||
*/
|
||||
void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
||||
{
|
||||
#ifdef CMSIS_Driver
|
||||
if (Level != GPIO_PIN_RESET)
|
||||
{
|
||||
OW->DataPort->BSRR = OW->DataPin;
|
||||
}
|
||||
else
|
||||
{
|
||||
OW->DataPort->BSRR = (uint32_t)OW->DataPin << 16u;
|
||||
}
|
||||
#else
|
||||
#ifdef LL_Driver
|
||||
if(Level == 1)
|
||||
{
|
||||
LL_GPIO_SetOutputPin(OW->DataPort, OW->DataPin);
|
||||
}else{
|
||||
LL_GPIO_ResetOutputPin(OW->DataPort, OW->DataPin);
|
||||
}
|
||||
#else
|
||||
HAL_GPIO_WritePin(OW->DataPort, OW->DataPin, Level);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The internal function is used to read data pin
|
||||
* @retval Pin level status
|
||||
* @param OW OneWire HandleTypedef
|
||||
*/
|
||||
uint8_t OneWire_Pin_Read(OneWire_t* OW)
|
||||
{
|
||||
#ifdef CMSIS_Driver
|
||||
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
||||
#else
|
||||
#ifdef LL_Driver
|
||||
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
||||
#else
|
||||
return HAL_GPIO_ReadPin(OW->DataPort, OW->DataPin);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
uint32_t tim_1us_period = 24;
|
||||
void OneWire_Delay_uw(uint32_t us)
|
||||
{
|
||||
// start = htim1.Instance->CNT;
|
||||
// end = start + us*tim_1us_period;
|
||||
TIM1->CNT = 0;
|
||||
end = us*tim_1us_period;
|
||||
|
||||
while(TIM1->CNT < end) {};
|
||||
}
|
||||
17
py_project/Core/Dallas/ow_port.h
Normal file
17
py_project/Core/Dallas/ow_port.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file ow_port.h
|
||||
* @brief This file includes the driver for port for OneWire purposes
|
||||
******************************************************************************
|
||||
*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef ONEWIRE_PORT_H
|
||||
#define ONEWIRE_PORT_H
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "py32f0xx_hal.h"
|
||||
/* OneWire Timings -----------------------------------------------------------*/
|
||||
void OneWire_Delay_uw(uint32_t us);
|
||||
/* Common Register -----------------------------------------------------------*/
|
||||
#endif /* ONEWIRE_PORT_H */
|
||||
47
py_project/Core/Inc/gpio.h
Normal file
47
py_project/Core/Inc/gpio.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file gpio.h
|
||||
* @brief This file contains all the function prototypes for
|
||||
* the gpio.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __GPIO_H__
|
||||
#define __GPIO_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* Exported variables prototypes ---------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void MX_GPIO_Init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GPIO_H__ */
|
||||
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
52
py_project/Core/Inc/iwdg.h
Normal file
52
py_project/Core/Inc/iwdg.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file iwdg.h
|
||||
* @brief This file contains all the function prototypes for
|
||||
* the iwdg.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __IWDG_H__
|
||||
#define __IWDG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
extern IWDG_HandleTypeDef hiwdg;
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
void MX_IWDG_Init(void);
|
||||
|
||||
/* USER CODE BEGIN Prototypes */
|
||||
|
||||
/* USER CODE END Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __IWDG_H__ */
|
||||
|
||||
51
py_project/Core/Inc/main.h
Normal file
51
py_project/Core/Inc/main.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file main.h
|
||||
* @author MCU Application Team
|
||||
* @brief Header for main.c file.
|
||||
* This file contains the common defines of the application.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __MAIN_H
|
||||
#define __MAIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "py32f0xx_hal.h"
|
||||
#include "interface_config.h"
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define GPIO_LED_2 GPIO_PIN_1
|
||||
#define GPIO_LED_3 GPIO_PIN_5
|
||||
#define GPIO_LED_4 GPIO_PIN_4
|
||||
|
||||
/* Exported variables prototypes ---------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void Error_Handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MAIN_H */
|
||||
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
214
py_project/Core/Inc/py32f002b_hal_conf.h
Normal file
214
py_project/Core/Inc/py32f002b_hal_conf.h
Normal file
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file py32f002b_hal_conf.h
|
||||
* @author MCU Application Team
|
||||
* @brief HAL configuration file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __PY32F002B_HAL_CONF_H
|
||||
#define __PY32F002B_HAL_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* ########################## Module Selection ############################## */
|
||||
/**
|
||||
* @brief This is the list of modules to be used in the HAL driver
|
||||
*/
|
||||
#define HAL_MODULE_ENABLED
|
||||
#define HAL_RCC_MODULE_ENABLED
|
||||
//#define HAL_ADC_MODULE_ENABLED
|
||||
//#define HAL_CRC_MODULE_ENABLED
|
||||
//#define HAL_COMP_MODULE_ENABLED
|
||||
#define HAL_FLASH_MODULE_ENABLED
|
||||
#define HAL_GPIO_MODULE_ENABLED
|
||||
#define HAL_IWDG_MODULE_ENABLED
|
||||
#define HAL_TIM_MODULE_ENABLED
|
||||
//#define HAL_LPTIM_MODULE_ENABLED
|
||||
#define HAL_PWR_MODULE_ENABLED
|
||||
//#define HAL_I2C_MODULE_ENABLED
|
||||
#define HAL_UART_MODULE_ENABLED
|
||||
#define HAL_USART_MODULE_ENABLED
|
||||
//#define HAL_SPI_MODULE_ENABLED
|
||||
//#define HAL_EXTI_MODULE_ENABLED
|
||||
#define HAL_CORTEX_MODULE_ENABLED
|
||||
|
||||
/* ########################## Oscillator Values adaptation ####################*/
|
||||
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE ((uint32_t)24000000) /*!< Value of the Internal oscillator in Hz */
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/**
|
||||
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
|
||||
* This value is used by the RCC HAL module to compute the system frequency
|
||||
*/
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE ((uint32_t)24000000) /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (HSE_STARTUP_TIMEOUT)
|
||||
#define HSE_STARTUP_TIMEOUT ((uint32_t)200) /*!< Time out for HSE start up, in ms */
|
||||
#endif /* HSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief Internal Low Speed Internal oscillator (LSI) value.
|
||||
*/
|
||||
#if !defined (LSI_VALUE)
|
||||
#define LSI_VALUE ((uint32_t)32768) /*!< LSI Typical Value in Hz */
|
||||
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
|
||||
The real value may vary depending on the variations
|
||||
in voltage and temperature. */
|
||||
|
||||
/**
|
||||
* @brief Adjust the value of External Low Speed oscillator (LSE) used in your application.
|
||||
* This value is used by the RCC HAL module to compute the system frequency
|
||||
*/
|
||||
#if !defined (LSE_VALUE)
|
||||
#define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/
|
||||
#endif /* LSE_VALUE */
|
||||
|
||||
#if !defined (LSE_STARTUP_TIMEOUT)
|
||||
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */
|
||||
#endif /* LSE_STARTUP_TIMEOUT */
|
||||
|
||||
/* Tip: To avoid modifying this file each time you need to use different HSE,
|
||||
=== you can define the HSE value in your toolchain compiler preprocessor. */
|
||||
|
||||
/* ########################### System Configuration ######################### */
|
||||
/**
|
||||
* @brief This is the HAL system configuration section
|
||||
*/
|
||||
#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */
|
||||
#define PRIORITY_HIGHEST 0
|
||||
#define PRIORITY_HIGH 1
|
||||
#define PRIORITY_LOW 2
|
||||
#define PRIORITY_LOWEST 3
|
||||
#define TICK_INT_PRIORITY ((uint32_t)PRIORITY_LOWEST) /*!< tick interrupt priority (lowest by default) */
|
||||
#define USE_RTOS 0
|
||||
#define PREFETCH_ENABLE 0
|
||||
|
||||
/* ########################## Assert Selection ############################## */
|
||||
/**
|
||||
* @brief Uncomment the line below to expanse the "assert_param" macro in the
|
||||
* HAL drivers code
|
||||
*/
|
||||
/* #define USE_FULL_ASSERT 1U */
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Include module's header file
|
||||
*/
|
||||
#ifdef HAL_MODULE_ENABLED
|
||||
#include "py32f0xx_hal.h"
|
||||
#endif /* HAL_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RCC_MODULE_ENABLED
|
||||
#include "py32f002b_hal_rcc.h"
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_EXTI_MODULE_ENABLED
|
||||
#include "py32f002b_hal_exti.h"
|
||||
#endif /* HAL_EXTI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "py32f002b_hal_gpio.h"
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||
#include "py32f002b_hal_cortex.h"
|
||||
#endif /* HAL_CORTEX_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ADC_MODULE_ENABLED
|
||||
#include "py32f002b_hal_adc.h"
|
||||
#endif /* HAL_ADC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRC_MODULE_ENABLED
|
||||
#include "py32f002b_hal_crc.h"
|
||||
#endif /* HAL_CRC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_COMP_MODULE_ENABLED
|
||||
#include "py32f002b_hal_comp.h"
|
||||
#endif /* HAL_COMP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
#include "py32f002b_hal_flash.h"
|
||||
#endif /* HAL_FLASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
#include "py32f002b_hal_i2c.h"
|
||||
#endif /* HAL_I2C_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IWDG_MODULE_ENABLED
|
||||
#include "py32f002b_hal_iwdg.h"
|
||||
#endif /* HAL_IWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PWR_MODULE_ENABLED
|
||||
#include "py32f002b_hal_pwr.h"
|
||||
#endif /* HAL_PWR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
#include "py32f002b_hal_spi.h"
|
||||
#endif /* HAL_SPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TIM_MODULE_ENABLED
|
||||
#include "py32f002b_hal_tim.h"
|
||||
#endif /* HAL_TIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LPTIM_MODULE_ENABLED
|
||||
#include "py32f002b_hal_lptim.h"
|
||||
#endif /* HAL_LPTIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
#include "py32f002b_hal_uart.h"
|
||||
#endif /* HAL_UART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_USART_MODULE_ENABLED
|
||||
#include "py32f002b_hal_usart.h"
|
||||
#endif /* HAL_USART_MODULE_ENABLED */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief The assert_param macro is used for function's parameters check.
|
||||
* @param expr: If expr is false, it calls assert_failed function
|
||||
* which reports the name of the source file and the source
|
||||
* line number of the call that failed.
|
||||
* If expr is true, it returns no value.
|
||||
* @retval None
|
||||
*/
|
||||
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void assert_failed(uint8_t* file, uint32_t line);
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PY32F002B_HAL_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
48
py_project/Core/Inc/py32f002b_it.h
Normal file
48
py_project/Core/Inc/py32f002b_it.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file py32f002b_it.h
|
||||
* @author MCU Application Team
|
||||
* @brief This file contains the headers of the interrupt handlers.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __PY32F002B_IT_H
|
||||
#define __PY32F002B_IT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void NMI_Handler(void);
|
||||
void HardFault_Handler(void);
|
||||
void SVC_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PY32F002B_IT_H */
|
||||
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
54
py_project/Core/Inc/tim.h
Normal file
54
py_project/Core/Inc/tim.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file tim.h
|
||||
* @brief This file contains all the function prototypes for
|
||||
* the tim.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __TIM_H__
|
||||
#define __TIM_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
extern TIM_HandleTypeDef htim1;
|
||||
extern TIM_HandleTypeDef htim14;
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
void MX_TIM1_Init(void);
|
||||
void MX_TIM14_Init(void);
|
||||
|
||||
/* USER CODE BEGIN Prototypes */
|
||||
|
||||
/* USER CODE END Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TIM_H__ */
|
||||
|
||||
52
py_project/Core/Inc/usart.h
Normal file
52
py_project/Core/Inc/usart.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usart.h
|
||||
* @brief This file contains all the function prototypes for
|
||||
* the usart.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USART_H__
|
||||
#define __USART_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
extern UART_HandleTypeDef huart1;
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
void MX_USART1_UART_Init(void);
|
||||
|
||||
/* USER CODE BEGIN Prototypes */
|
||||
|
||||
/* USER CODE END Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USART_H__ */
|
||||
|
||||
65
py_project/Core/Modbus/crc_algs.c
Normal file
65
py_project/Core/Modbus/crc_algs.c
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "crc_algs.h"
|
||||
|
||||
|
||||
uint32_t CRC_calc;
|
||||
uint32_t CRC_ref;
|
||||
|
||||
//uint16_t CRC_calc;
|
||||
//uint16_t CRC_ref;
|
||||
|
||||
|
||||
|
||||
/*Table of CRC values for high order byte*/
|
||||
const unsigned char auchCRCHi[]=
|
||||
{
|
||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
|
||||
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
|
||||
};
|
||||
/*Table of CRC values for low order byte*/
|
||||
const char auchCRCLo[] =
|
||||
{
|
||||
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04,
|
||||
0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8,
|
||||
0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,
|
||||
0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,
|
||||
0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,
|
||||
0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38,
|
||||
0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,
|
||||
0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,
|
||||
0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,
|
||||
0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,
|
||||
0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,
|
||||
0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,
|
||||
0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
|
||||
0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,
|
||||
0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
|
||||
0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40,
|
||||
};
|
||||
uint16_t crc16(uint8_t *data, uint32_t data_size)
|
||||
{
|
||||
uint8_t uchCRCHi = 0xFF;
|
||||
uint8_t uchCRCLo = 0xFF;
|
||||
unsigned uIndex;
|
||||
/* CRC Generation Function */
|
||||
while( data_size--) /* pass through message buffer */
|
||||
{
|
||||
uIndex = uchCRCHi ^ *data++; /* calculate the CRC */
|
||||
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
|
||||
uchCRCLo = auchCRCLo[uIndex];
|
||||
}
|
||||
return uchCRCHi | uchCRCLo<<8;
|
||||
}
|
||||
9
py_project/Core/Modbus/crc_algs.h
Normal file
9
py_project/Core/Modbus/crc_algs.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "mylibs_include.h"
|
||||
|
||||
// extern here to use in bootloader.c
|
||||
extern uint32_t CRC_calc;
|
||||
extern uint32_t CRC_ref;
|
||||
|
||||
|
||||
uint16_t crc16(uint8_t *data, uint32_t data_size);
|
||||
uint32_t crc32(uint8_t *data, uint32_t data_size);
|
||||
63
py_project/Core/Modbus/interface_config.h
Normal file
63
py_project/Core/Modbus/interface_config.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file interface_config.h
|
||||
* @brief Конфигурации для интерфейсов
|
||||
**************************************************************************
|
||||
* @defgroup INTERFACE_CONFIGS Configs for interfaces
|
||||
* @brief Конфигурации для интерфейсов
|
||||
* @details
|
||||
@{
|
||||
*************************************************************************/
|
||||
#ifndef _INTERFACE_CONFIG_H_
|
||||
#define _INTERFACE_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @addtogroup MODBUS_CONFIG Конфигурации для модбас
|
||||
* @ingroup INTERFACE_CONFIGS
|
||||
* @ingroup MODBUS
|
||||
@{
|
||||
*/
|
||||
|
||||
#define MODBUS_VENDOR_NAME "NIO-12"
|
||||
#define MODBUS_PRODUCT_CODE "12345"
|
||||
#define MODBUS_REVISION "Ver. 1.0"
|
||||
#define MODBUS_VENDOR_URL "https://git.arktika.cyou/set506/DS18B20_Library/"
|
||||
#define MODBUS_PRODUCT_NAME "Dallas Driver"
|
||||
#define MODBUS_MODEL_NAME "PY32F002B"
|
||||
#define MODBUS_USER_APPLICATION_NAME "PY32Dallas"
|
||||
|
||||
#define MODBUS_SPEED 115200 ///< Скорость UART для модбас
|
||||
// defines for modbus behaviour
|
||||
#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства
|
||||
|
||||
#define MODBUS_DATA_SIZE 27 ///< maximum number of data: DWORD (NOT MESSAGE SIZE)
|
||||
|
||||
|
||||
#define RS_UART_Init MX_USART1_UART_Init
|
||||
#define RS_UART_DeInit HAL_UART_MspDeInit
|
||||
#define RS_TIM_Init MX_TIM2_Init
|
||||
#define RS_TIM_DeInit HAL_TIM_Base_MspDeInit
|
||||
#define rs_huart huart1
|
||||
#define rs_htim htim14
|
||||
/**
|
||||
* @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей)
|
||||
* @details Терминалка от двигателей использует для чтения регистров комманду R_HOLD_REGS вместо R_IN_REGS
|
||||
* Поэтому чтобы считывать Input Regs - надо поменять их местами.
|
||||
*/
|
||||
//#define MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////---CALC DEFINES---//////////////////////////
|
||||
|
||||
/** MODBUS_CONFIG
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/** INTERFACE_CONFIGS
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif //_INTERFACE_CONFIG_H_
|
||||
1019
py_project/Core/Modbus/modbus.c
Normal file
1019
py_project/Core/Modbus/modbus.c
Normal file
@@ -0,0 +1,1019 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file modbus.c
|
||||
* @brief Модуль для реализации MODBUS.
|
||||
**************************************************************************
|
||||
* @par Функции и дефайны
|
||||
*
|
||||
* Defines: data access
|
||||
* - MB_Set_Coil_Local() - Выставление коила по локальному адресу относительно начала массива
|
||||
* - MB_Reset_Coil_Local() - Сброс коила по локальному адресу относительно начала массива
|
||||
* - MB_Toogle_Coil_Local() - Переключение коила по локальному адресу относительно начала массива
|
||||
* - MB_Read_Coil_Local() - Чтение коила по локальному адресу относительно начала массива
|
||||
*
|
||||
* Functions: data access
|
||||
* - MB_Write_Coil_Global() - Запись 0/1 в один коил по глобальному адресу
|
||||
* - MB_Read_Coil_Global() - Чтение одного коила по глобальному адресу
|
||||
*
|
||||
* Functions: process message
|
||||
* - MB_DefineRegistersAddress() - Определение "начального" адреса регистров
|
||||
* - MB_DefineCoilsAddress() - Определение "начального" адреса коилов
|
||||
* - MB_Check_Address_For_Arr() - Определение принадлежит ли адресс Addr конкретному массиву
|
||||
* - Обработка команд модбас
|
||||
* - MB_Read_Coils(),
|
||||
* - MB_Read_Hold_Regs(),
|
||||
* - MB_Write_Single_Coil()
|
||||
* - MB_Write_Miltuple_Coils()
|
||||
* - MB_Write_Miltuple_Regs()
|
||||
*
|
||||
* Functions: RS functions
|
||||
* - RS_Parse_Message() / RS_Collect_Message() - Заполнение структуры сообщения и буфера
|
||||
* - RS_Response() - Ответ на комманду
|
||||
* - RS_Define_Size_of_RX_Message() - Определение размера принимаемых данных
|
||||
* - RS_Init() - Инициализация периферии и modbus handler
|
||||
*
|
||||
* Functions: initialization
|
||||
* - MODBUS_FirstInit() - Инициализация modbus
|
||||
*
|
||||
**************************************************************************
|
||||
* @par Данные для модбас
|
||||
*
|
||||
* Holding/Input Registers
|
||||
* - Регистры представляют собой 16-битные числа (слова). В обработке комманд
|
||||
* находится адресс "начального" регистра и записывается в указатель. Доступ к
|
||||
* остальным регистрам осуществляется через указатель. Таким образом, сами
|
||||
* регистры могут представлять собой как массив так и структуру.
|
||||
*
|
||||
* Coils
|
||||
* - Коилы представляют собой биты, упакованные в 16-битные регистры. В обработке
|
||||
* комманд находится адресс "начального" регистра запрашиваемого коила. Доступ к
|
||||
* остальным коилам осуществляется через маску и указатель. Таким образом, сами
|
||||
* коилы могут представлять собой как массив так и структуру.
|
||||
*
|
||||
@verbatim
|
||||
EXAMPLE: INIT SLAVE RECEIVE
|
||||
//--------------Настройка модбас--------------//
|
||||
// set up UART for modbus
|
||||
modbus1_suart.huart.Instance = USED_MODBUS_UART;
|
||||
modbus1_suart.huart.Init.BaudRate = PROJSET.MB_SPEED;
|
||||
modbus1_suart.GPIOx = GPIOB;
|
||||
modbus1_suart.GPIO_PIN_RX = GPIO_PIN_11;
|
||||
modbus1_suart.GPIO_PIN_TX = GPIO_PIN_10;
|
||||
|
||||
// set up timeout TIM for modbus
|
||||
modbus1_stim.htim.Instance = TIM7;
|
||||
modbus1_stim.sTimAHBFreqMHz = 84;
|
||||
modbus1_stim.sTimMode = TIM_IT_CONF;
|
||||
|
||||
// set up modbus: MB_RX_Size_NotConst and Timeout enable
|
||||
hmodbus1.ID = 1;
|
||||
hmodbus1.sRS_Timeout = 5000;
|
||||
hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT;
|
||||
hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst;
|
||||
|
||||
// INIT
|
||||
hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &modbus1_suart, &modbus1_stim, 0);
|
||||
|
||||
//----------------Прием модбас----------------//
|
||||
RS_MsgTypeDef MODBUS_MSG;
|
||||
RS_Receive_IT(&hmodbus1, &MODBUS_MSG);
|
||||
@endverbatim
|
||||
*************************************************************************/
|
||||
|
||||
#include "rs_message.h"
|
||||
uint32_t dbg_temp, dbg_temp2, dbg_temp3; // for debug
|
||||
/* MODBUS HANDLES */
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
UART_SettingsTypeDef modbus1_suart;
|
||||
TIM_SettingsTypeDef modbus1_stim;
|
||||
#else
|
||||
extern UART_HandleTypeDef rs_huart;
|
||||
extern TIM_HandleTypeDef rs_htim;
|
||||
#endif
|
||||
RS_HandleTypeDef hmodbus1;
|
||||
|
||||
/* DEFINE REGISTERS/COILS */
|
||||
MB_DeviceIdentificationTypeDef MB_INFO;
|
||||
MB_DataStructureTypeDef MB_DATA;
|
||||
RS_MsgTypeDef MODBUS_MSG;
|
||||
|
||||
uint32_t delay_scide = 1;
|
||||
uint32_t numb_scide = 10;
|
||||
//-------------------------------------------------------------------
|
||||
//-----------------------------FOR USER------------------------------
|
||||
/**
|
||||
* @brief First set up of MODBUS.
|
||||
* @details Первый инит модбас. Заполняет структуры и инициализирует таймер и юарт для общения по модбас.
|
||||
* Скважность ШИМ меняется по закону синусоиды, каждый канал генерирует свой полупериод синуса (от -1 до 0 И от 0 до 1)
|
||||
* ШИМ генерируется на одном канале.
|
||||
* @note This called from main
|
||||
*/
|
||||
void MODBUS_FirstInit(void)
|
||||
{
|
||||
MB_DevoceInentificationInit();
|
||||
//-----------SETUP MODBUS-------------
|
||||
// set up UART for modbus
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
modbus1_suart.huart.Instance = USED_MODBUS_UART;
|
||||
modbus1_suart.huart.Init.BaudRate = MODBUS_SPEED;
|
||||
modbus1_suart.GPIOx = MODBUS_GPIOX;
|
||||
modbus1_suart.GPIO_PIN_RX = MODBUS_GPIO_PIN_RX;
|
||||
modbus1_suart.GPIO_PIN_TX = MODBUS_GPIO_PIN_TX;
|
||||
|
||||
// set up timeout TIM for modbus
|
||||
modbus1_stim.htim.Instance = USED_MODBUS_TIM;
|
||||
modbus1_stim.sTimAHBFreqMHz = MODBUS_TIM_AHB_FREQ;
|
||||
modbus1_stim.sTimMode = TIM_IT_CONF;
|
||||
|
||||
#endif
|
||||
// set up modbus: MB_RX_Size_NotConst and Timeout enable
|
||||
hmodbus1.ID = MODBUS_DEVICE_ID;
|
||||
hmodbus1.sRS_Mode = SLAVE_ALWAYS_WAIT;
|
||||
hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst;
|
||||
hmodbus1.sRS_Timeout = 1;
|
||||
|
||||
// INIT
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &modbus1_suart, &modbus1_stim, 0);
|
||||
#else
|
||||
hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, &rs_htim, 0);
|
||||
#endif
|
||||
|
||||
RS_EnableReceive();
|
||||
}
|
||||
/**
|
||||
* @brief Set or Reset Coil at its global address.
|
||||
* @param Addr - адрес коила.
|
||||
* @param WriteVal - Что записать в коил: 0 или 1.
|
||||
* @return ExceptionCode - Код исключения если коила по адресу не существует, и NO_ERRORS если все ок.
|
||||
*
|
||||
* @details Позволяет обратиться к любому коилу по его глобальному адрессу.
|
||||
Вне зависимости от того как коилы размещены в памяти.
|
||||
*/
|
||||
MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
MB_ExceptionTypeDef Exception = NO_ERRORS;
|
||||
uint16_t *coils;
|
||||
uint16_t start_shift = 0; // shift in coils register
|
||||
|
||||
//------------WRITE COIL-------------
|
||||
Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 1);
|
||||
if(Exception == NO_ERRORS)
|
||||
{
|
||||
switch(WriteVal)
|
||||
{
|
||||
case SET_COIL:
|
||||
*coils |= (1<<start_shift);
|
||||
break;
|
||||
|
||||
case RESET_COIL:
|
||||
*coils &= ~(1<<start_shift);
|
||||
break;
|
||||
|
||||
case TOOGLE_COIL:
|
||||
*coils ^= (1<<start_shift);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return Exception;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read Coil at its global address.
|
||||
* @param Addr - адрес коила.
|
||||
* @param Exception - Указатель на переменную для кода исключения, в случа неудачи при чтении.
|
||||
* @return uint16_t - Возвращает весь регистр с маской на запрошенном коиле.
|
||||
*
|
||||
* @details Позволяет обратиться к любому коилу по его глобальному адрессу.
|
||||
Вне зависимости от того как коилы размещены в памяти.
|
||||
*/
|
||||
uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
MB_ExceptionTypeDef Exception_tmp;
|
||||
if(Exception == NULL) // if exception is not given to func fill it
|
||||
Exception = &Exception_tmp;
|
||||
|
||||
uint16_t *coils;
|
||||
uint16_t start_shift = 0; // shift in coils register
|
||||
|
||||
//------------READ COIL--------------
|
||||
*Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 0);
|
||||
if(*Exception == NO_ERRORS)
|
||||
{
|
||||
return ((*coils)&(1<<start_shift));
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//----------------FUNCTIONS FOR PROCESSING MESSAGE-------------------
|
||||
/**
|
||||
* @brief Check is address valid for certain array.
|
||||
* @param Addr - начальный адресс.
|
||||
* @param Qnt - количество запрашиваемых элементов.
|
||||
* @param R_ARR_ADDR - начальный адресс массива R_ARR.
|
||||
* @param R_ARR_NUMB - количество элементов в массиве R_ARR.
|
||||
* @return ExceptionCode - ILLEGAL DATA ADRESS если адресс недействителен, и NO_ERRORS если все ок.
|
||||
*
|
||||
* @details Позволяет определить, принадлежит ли адресс Addr массиву R_ARR:
|
||||
* Если адресс Addr находится в диапазоне адрессов массива R_ARR, то возвращаем NO_ERROR.
|
||||
* Если адресс Addr находится за пределами адрессов массива R_ARR - ILLEGAL_DATA_ADDRESSю.
|
||||
*/
|
||||
MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB)
|
||||
{
|
||||
// if address from this array
|
||||
if(Addr >= R_ARR_ADDR)
|
||||
{
|
||||
// if quantity too big return error
|
||||
if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB)
|
||||
{
|
||||
return ILLEGAL_DATA_ADDRESS; // return exception code
|
||||
}
|
||||
// if all ok - return no errors
|
||||
return NO_ERRORS;
|
||||
}
|
||||
// if address isnt from this array return error
|
||||
else
|
||||
return ILLEGAL_DATA_ADDRESS; // return exception code
|
||||
}
|
||||
/**
|
||||
* @brief Define Address Origin for Input/Holding Registers
|
||||
* @param pRegs - указатель на указатель регистров.
|
||||
* @param Addr - адрес начального регистра.
|
||||
* @param Qnt - количество запрашиваемых регистров.
|
||||
* @param WriteFlag - флаг регистр нужны для чтения или записи.
|
||||
* @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет.
|
||||
*
|
||||
* @details Определение адреса начального регистра.
|
||||
* @note WriteFlag пока не используется.
|
||||
*/
|
||||
MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType)
|
||||
{
|
||||
/* check quantity error */
|
||||
if (Qnt > 125)
|
||||
{
|
||||
return ILLEGAL_DATA_VALUE; // return exception code
|
||||
}
|
||||
|
||||
if(RegisterType == RegisterType_Holding)
|
||||
{
|
||||
// Параметры для инициализации датчика
|
||||
if(MB_Check_Address_For_Arr(Addr, Qnt, R_SENS_INIT_ADDR, R_SENS_INIT_QNT) == NO_ERRORS)
|
||||
{
|
||||
*pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr); // начало регистров хранения/входных
|
||||
}
|
||||
// if address doesnt match any array - return illegal data address response
|
||||
else
|
||||
{
|
||||
return ILLEGAL_DATA_ADDRESS;
|
||||
}
|
||||
}
|
||||
else if(RegisterType == RegisterType_Input)
|
||||
{
|
||||
// Измеренные температуры
|
||||
if(MB_Check_Address_For_Arr(Addr, Qnt, R_TEMPERATURE_ADDR, R_TEMPERATURE_QNT) == NO_ERRORS)
|
||||
{
|
||||
*pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr); // начало регистров хранения/входных
|
||||
MB_DATA.Coils.ConvertionDone = 0; // сброс флага
|
||||
}
|
||||
// Параметры датчика
|
||||
else if(MB_Check_Address_For_Arr(Addr, Qnt, R_SENS_PARAMS_ADDR, R_SENS_PARAMS_QNT) == NO_ERRORS)
|
||||
{
|
||||
*pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr); // начало регистров хранения/входных
|
||||
// икрементирвоание счетчика скана, для вывода всех датчиков на линии в модбас структуру
|
||||
extern void PYModule_IncrementScanSensor(void);
|
||||
PYModule_IncrementScanSensor();
|
||||
}
|
||||
// Все найденные ROM на линии
|
||||
else if(MB_Check_Address_For_Arr(Addr, Qnt, R_ALL_ROMS_ADDR, R_ALL_ROMS_QNT) == NO_ERRORS)
|
||||
{
|
||||
*pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr); // начало регистров хранения/входных
|
||||
}
|
||||
// if address doesnt match any array - return illegal data address response
|
||||
else
|
||||
{
|
||||
return ILLEGAL_DATA_ADDRESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ILLEGAL_FUNCTION;
|
||||
}
|
||||
// if found requeried array return no err
|
||||
return NO_ERRORS; // return no errors
|
||||
}
|
||||
/**
|
||||
* @brief Define Address Origin for coils
|
||||
* @param pCoils - указатель на указатель коилов.
|
||||
* @param Addr - адресс начального коила.
|
||||
* @param Qnt - количество запрашиваемых коилов.
|
||||
* @param start_shift - указатель на переменную содержащую сдвиг внутри регистра для начального коила.
|
||||
* @param WriteFlag - флаг коилы нужны для чтения или записи.
|
||||
* @return ExceptionCode - Код исключения если есть, и NO_ERRORS если нет.
|
||||
*
|
||||
* @details Определение адреса начального регистра запрашиваемых коилов.
|
||||
* @note WriteFlag используется для определния регистров GPIO: ODR или IDR.
|
||||
*/
|
||||
MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag)
|
||||
{
|
||||
/* check quantity error */
|
||||
if (Qnt > 2000)
|
||||
{
|
||||
return ILLEGAL_DATA_VALUE; // return exception code
|
||||
}
|
||||
|
||||
// Флаги всей шины датчиков
|
||||
if(MB_Check_Address_For_Arr(Addr, Qnt, C_FLAGS_ADDR, C_FLAGS_QNT) == NO_ERRORS)
|
||||
{
|
||||
*pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr);
|
||||
}
|
||||
// Управление датчиками
|
||||
else if(MB_Check_Address_For_Arr(Addr, Qnt, C_CONTROL_ADDR, C_CONTROL_QNT) == NO_ERRORS)
|
||||
{
|
||||
*pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr);
|
||||
}
|
||||
// if address doesnt match any array - return illegal data address response
|
||||
else
|
||||
{
|
||||
return ILLEGAL_DATA_ADDRESS;
|
||||
}
|
||||
|
||||
*start_shift = Addr % 16; // set shift to requested coil
|
||||
// if found requeried array return no err
|
||||
return NO_ERRORS; // return no errors
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Proccess command Read Coils (01 - 0x01).
|
||||
* @param modbus_msg - указатель на структуру собщения modbus.
|
||||
* @return fMessageHandled - статус о результате обработки комманды.
|
||||
* @details Обработка команды Read Coils.
|
||||
*/
|
||||
uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
uint16_t *coils;
|
||||
uint16_t start_shift = 0; // shift in coils register
|
||||
|
||||
modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 0);
|
||||
if(modbus_msg->Except_Code != NO_ERRORS)
|
||||
return 0;
|
||||
|
||||
//-----------READING COIL------------
|
||||
// setup output message data size
|
||||
modbus_msg->ByteCnt = Divide_Up(modbus_msg->Qnt, 8);
|
||||
// create mask for coils
|
||||
uint16_t mask_for_coils = 0; // mask for coils that've been chosen
|
||||
uint16_t setted_coils = 0; // value of setted coils
|
||||
uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen
|
||||
uint16_t coil_cnt = 0; // counter for processed coils
|
||||
|
||||
// cycle until all registers with requered coils would be processed
|
||||
int shift = start_shift; // set shift to first coil in first register
|
||||
int ind = 0; // index for coils registers and data
|
||||
for(; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++)
|
||||
{
|
||||
//----SET MASK FOR COILS REGISTER----
|
||||
mask_for_coils = 0;
|
||||
for(; shift < 0x10; shift++)
|
||||
{
|
||||
mask_for_coils |= 1<<(shift); // choose certain coil
|
||||
if(++coil_cnt >= modbus_msg->Qnt)
|
||||
break;
|
||||
}
|
||||
shift = 0; // set shift to zero for the next step
|
||||
|
||||
//-----------READ COILS--------------
|
||||
modbus_msg->DATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift;
|
||||
if(ind > 0)
|
||||
modbus_msg->DATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift;
|
||||
|
||||
}
|
||||
// т.к. DATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты
|
||||
for(; ind >= 0; --ind)
|
||||
modbus_msg->DATA[ind] = ByteSwap16(modbus_msg->DATA[ind]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Proccess command Read Holding Registers (03 - 0x03).
|
||||
* @param modbus_msg - указатель на структуру собщения modbus.
|
||||
* @return fMessageHandled - статус о результате обработки комманды.
|
||||
* @details Обработка команды Read Holding Registers.
|
||||
*/
|
||||
uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
// get origin address for data
|
||||
uint16_t *pHoldRegs;
|
||||
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров
|
||||
if(modbus_msg->Except_Code != NO_ERRORS)
|
||||
return 0;
|
||||
|
||||
|
||||
//-----------READING REGS------------
|
||||
// setup output message data size
|
||||
modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits
|
||||
// read data
|
||||
int i;
|
||||
for (i = 0; i<modbus_msg->Qnt; i++)
|
||||
{
|
||||
modbus_msg->DATA[i] = *(pHoldRegs++);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Proccess command Read Input Registers (04 - 0x04).
|
||||
* @param modbus_msg - указатель на структуру собщения modbus.
|
||||
* @return fMessageHandled - статус о результате обработки комманды.
|
||||
* @details Обработка команды Read Input Registers.
|
||||
*/
|
||||
uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
// get origin address for data
|
||||
uint16_t *pInRegs;
|
||||
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pInRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Input); // определение адреса регистров
|
||||
if(modbus_msg->Except_Code != NO_ERRORS)
|
||||
return 0;
|
||||
|
||||
|
||||
//-----------READING REGS------------
|
||||
// setup output message data size
|
||||
modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits
|
||||
// read data
|
||||
int i;
|
||||
for (i = 0; i<modbus_msg->Qnt; i++)
|
||||
{
|
||||
if(*((int16_t *)pInRegs) > 0)
|
||||
modbus_msg->DATA[i] = (*pInRegs++);
|
||||
else
|
||||
modbus_msg->DATA[i] = (*pInRegs++);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* @brief Proccess command Write Single Coils (05 - 0x05).
|
||||
* @param modbus_msg - указатель на структуру собщения modbus.
|
||||
* @return fMessageHandled - статус о результате обработки комманды.
|
||||
* @details Обработка команды Write Single Coils.
|
||||
*/
|
||||
uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00))
|
||||
{
|
||||
modbus_msg->Except_Code = ILLEGAL_DATA_VALUE;
|
||||
return 0;
|
||||
}
|
||||
// define position of coil
|
||||
uint16_t *coils;
|
||||
uint16_t start_shift = 0; // shift in coils register
|
||||
modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, 0, &start_shift, 1);
|
||||
if(modbus_msg->Except_Code != NO_ERRORS)
|
||||
return 0;
|
||||
|
||||
|
||||
//----------WRITTING COIL------------
|
||||
if(modbus_msg->Qnt == 0xFF00)
|
||||
*(coils) |= 1<<start_shift; // write flags corresponding to received data
|
||||
else
|
||||
*(coils) &= ~(1<<start_shift); // write flags corresponding to received data
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Proccess command Write Single Register (06 - 0x06).
|
||||
* @param modbus_msg - указатель на структуру собщения modbus.
|
||||
* @return fMessageHandled - статус о результате обработки комманды.
|
||||
* @details Обработка команды Write Single Register.
|
||||
*/
|
||||
uint8_t MB_Write_Single_Reg(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
// get origin address for data
|
||||
uint16_t *pHoldRegs;
|
||||
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding); // определение адреса регистров
|
||||
if(modbus_msg->Except_Code != NO_ERRORS)
|
||||
return 0;
|
||||
|
||||
//-----------WRITTING REG------------
|
||||
*(pHoldRegs) = modbus_msg->Qnt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Proccess command Write Multiple Coils (15 - 0x0F).
|
||||
* @param modbus_msg - указатель на структуру собщения modbus.
|
||||
* @return fMessageHandled - статус о результате обработки комманды.
|
||||
* @details Обработка команды Write Multiple Coils.
|
||||
*/
|
||||
uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8))
|
||||
{ // if quantity too large OR if quantity and bytes count arent match
|
||||
modbus_msg->Except_Code = ILLEGAL_DATA_VALUE;
|
||||
return 0;
|
||||
}
|
||||
// define position of coil
|
||||
uint16_t *coils; // pointer to coils
|
||||
uint16_t start_shift = 0; // shift in coils register
|
||||
modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 1);
|
||||
if(modbus_msg->Except_Code != NO_ERRORS)
|
||||
return 0;
|
||||
|
||||
//----------WRITTING COILS-----------
|
||||
// create mask for coils
|
||||
uint16_t mask_for_coils = 0; // mask for coils that've been chosen
|
||||
uint32_t setted_coils = 0; // value of setted coils
|
||||
uint16_t temp_reg = 0; // temp register for saving coils that hasnt been chosen
|
||||
uint16_t coil_cnt = 0; // counter for processed coils
|
||||
|
||||
// cycle until all registers with requered coils would be processed
|
||||
int shift = start_shift; // set shift to first coil in first register
|
||||
for(int ind = 0; ind <= Divide_Up(start_shift + modbus_msg->Qnt, 16); ind++)
|
||||
{
|
||||
//----SET MASK FOR COILS REGISTER----
|
||||
mask_for_coils = 0;
|
||||
for(; shift < 0x10; shift++)
|
||||
{
|
||||
mask_for_coils |= 1<<(shift); // choose certain coil
|
||||
if(++coil_cnt >= modbus_msg->Qnt)
|
||||
break;
|
||||
}
|
||||
shift = 0; // set shift to zero for the next step
|
||||
|
||||
|
||||
|
||||
//-----------WRITE COILS-------------
|
||||
// get current coils
|
||||
temp_reg = *(coils+ind);
|
||||
// set coils
|
||||
setted_coils = ByteSwap16(modbus_msg->DATA[ind]) << start_shift;
|
||||
if(ind > 0)
|
||||
{
|
||||
setted_coils |= ((ByteSwap16(modbus_msg->DATA[ind-1]) << start_shift) >> 16);
|
||||
}
|
||||
// write coils
|
||||
|
||||
*(coils+ind) = setted_coils & mask_for_coils;
|
||||
// restore untouched coils
|
||||
*(coils+ind) |= temp_reg&(~mask_for_coils);
|
||||
|
||||
|
||||
if(coil_cnt >= modbus_msg->Qnt) // if all coils written - break cycle
|
||||
break; // *kind of unnecessary
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Proccess command Write Multiple Registers (16 - 0x10).
|
||||
* @param modbus_msg - указатель на структуру собщения modbus.
|
||||
* @return fMessageHandled - статус о результате обработки комманды.
|
||||
* @details Обработка команды Write Multiple Registers.
|
||||
*/
|
||||
uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
if (modbus_msg->Qnt*2 != modbus_msg->ByteCnt)
|
||||
{ // if quantity and bytes count arent match
|
||||
modbus_msg->Except_Code = 3;
|
||||
return 0;
|
||||
}
|
||||
// get origin address for data
|
||||
uint16_t *pHoldRegs;
|
||||
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров
|
||||
if(modbus_msg->Except_Code != NO_ERRORS)
|
||||
return 0;
|
||||
|
||||
//-----------WRITTING REGS-----------
|
||||
for (int i = 0; i<modbus_msg->Qnt; i++)
|
||||
{
|
||||
*(pHoldRegs++) = modbus_msg->DATA[i];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MB_WriteObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj)
|
||||
{
|
||||
mbdata[(*ind)++] = obj->length;
|
||||
for (int i = 0; i < obj->length; i++)
|
||||
{
|
||||
mbdata[(*ind)++] = obj->name[i];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Proccess command Read Device Identification (43/14 - 0x2B/0E).
|
||||
* @param modbus_msg - указатель на структуру собщения modbus.
|
||||
* @return fMessageHandled - статус о результате обработки комманды.
|
||||
* @details Обработка команды Write Single Register.
|
||||
*/
|
||||
uint8_t MB_Read_Device_Identification(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
char *mbdata = (char *)modbus_msg->DATA;
|
||||
unsigned ind = 0;
|
||||
switch(modbus_msg->DevId.ReadDevId)
|
||||
{
|
||||
case MB_BASIC_IDENTIFICATION:
|
||||
mbdata[ind++] = 0x00;
|
||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.VendorName);
|
||||
mbdata[ind++] = 0x01;
|
||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ProductCode);
|
||||
mbdata[ind++] = 0x02;
|
||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.Revision);
|
||||
modbus_msg->DevId.NumbOfObj = 3;
|
||||
break;
|
||||
case MB_REGULAR_IDENTIFICATION:
|
||||
mbdata[ind++] = 0x03;
|
||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.VendorUrl);
|
||||
mbdata[ind++] = 0x04;
|
||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ProductName);
|
||||
mbdata[ind++] = 0x05;
|
||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.ModelName);
|
||||
mbdata[ind++] = 0x06;
|
||||
MB_WriteObjectToMessage(mbdata, &ind, &MB_INFO.UserApplicationName);
|
||||
modbus_msg->DevId.NumbOfObj = 4;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
modbus_msg->ByteCnt = ind;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Respond accord to received message.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @return RS_RES - статус о результате ответа на комманду.
|
||||
* @details Обработка принятой комманды и ответ на неё.
|
||||
*/
|
||||
RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
RS_StatusTypeDef MB_RES = 0;
|
||||
hmodbus->f.MessageHandled = 0;
|
||||
hmodbus->f.EchoResponse = 0;
|
||||
RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit
|
||||
|
||||
if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing
|
||||
{
|
||||
switch (modbus_msg->Func_Code)
|
||||
{
|
||||
// Read Coils
|
||||
case MB_R_COILS:
|
||||
hmodbus->f.MessageHandled = MB_Read_Coils(hmodbus->pMessagePtr);
|
||||
break;
|
||||
|
||||
// Read Hodling Registers
|
||||
case MB_R_HOLD_REGS:
|
||||
hmodbus->f.MessageHandled = MB_Read_Hold_Regs(hmodbus->pMessagePtr);
|
||||
break;
|
||||
case MB_R_IN_REGS:
|
||||
hmodbus->f.MessageHandled = MB_Read_Input_Regs(hmodbus->pMessagePtr);
|
||||
break;
|
||||
|
||||
|
||||
// Write Single Coils
|
||||
case MB_W_COIL:
|
||||
hmodbus->f.MessageHandled = MB_Write_Single_Coil(hmodbus->pMessagePtr);
|
||||
if(hmodbus->f.MessageHandled)
|
||||
{
|
||||
hmodbus->f.EchoResponse = 1;
|
||||
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
|
||||
}
|
||||
break;
|
||||
|
||||
case MB_W_HOLD_REG:
|
||||
hmodbus->f.MessageHandled = MB_Write_Single_Reg(hmodbus->pMessagePtr);
|
||||
if(hmodbus->f.MessageHandled)
|
||||
{
|
||||
hmodbus->f.EchoResponse = 1;
|
||||
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
|
||||
}
|
||||
break;
|
||||
|
||||
// Write Multiple Coils
|
||||
case MB_W_COILS:
|
||||
hmodbus->f.MessageHandled = MB_Write_Miltuple_Coils(hmodbus->pMessagePtr);
|
||||
if(hmodbus->f.MessageHandled)
|
||||
{
|
||||
hmodbus->f.EchoResponse = 1;
|
||||
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
|
||||
}
|
||||
break;
|
||||
|
||||
// Write Multiple Registers
|
||||
case MB_W_HOLD_REGS:
|
||||
hmodbus->f.MessageHandled = MB_Write_Miltuple_Regs(hmodbus->pMessagePtr);
|
||||
if(hmodbus->f.MessageHandled)
|
||||
{
|
||||
hmodbus->f.EchoResponse = 1;
|
||||
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
|
||||
}
|
||||
break;
|
||||
|
||||
case MB_R_DEVICE_INFO:
|
||||
hmodbus->f.MessageHandled = MB_Read_Device_Identification(hmodbus->pMessagePtr);
|
||||
break;
|
||||
|
||||
|
||||
/* unknown func code */
|
||||
default: modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */
|
||||
}
|
||||
|
||||
if(hmodbus->f.MessageHandled == 0)
|
||||
{
|
||||
TrackerCnt_Err(hmodbus->rs_err);
|
||||
modbus_msg->Func_Code += ERR_VALUES_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackerCnt_Ok(hmodbus->rs_err);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// if we need response - check that transmit isnt busy
|
||||
if( RS_Is_TX_Busy(hmodbus) )
|
||||
RS_Abort(hmodbus, ABORT_TX); // if tx busy - set it free
|
||||
|
||||
// Transmit right there, or sets (fDeferredResponse) to transmit response in main code
|
||||
MB_RES = RS_Handle_Transmit_Start(hmodbus, modbus_msg);
|
||||
|
||||
hmodbus->RS_STATUS = MB_RES;
|
||||
return MB_RES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Collect message in buffer to transmit it.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @param msg_uart_buff - указатель на буффер UART.
|
||||
* @return RS_RES - статус о результате заполнения буфера.
|
||||
* @details Заполнение буффера UART из структуры сообщения.
|
||||
*/
|
||||
RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
|
||||
{
|
||||
int ind = 0; // ind for modbus-uart buffer
|
||||
|
||||
if(hmodbus->f.EchoResponse && hmodbus->f.MessageHandled) // if echo response need
|
||||
ind = hmodbus->RS_Message_Size;
|
||||
else
|
||||
{
|
||||
//------INFO ABOUT DATA/MESSAGE------
|
||||
//-----------[first bytes]-----------
|
||||
// set ID of message/user
|
||||
modbus_uart_buff[ind++] = modbus_msg->MbAddr;
|
||||
|
||||
// set dat or err response
|
||||
modbus_uart_buff[ind++] = modbus_msg->Func_Code;
|
||||
|
||||
if (modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur
|
||||
{
|
||||
// fill modbus header
|
||||
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // devide identification header
|
||||
{
|
||||
modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type;
|
||||
modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId;
|
||||
modbus_uart_buff[ind++] = modbus_msg->DevId.Conformity;
|
||||
modbus_uart_buff[ind++] = modbus_msg->DevId.MoreFollows;
|
||||
modbus_uart_buff[ind++] = modbus_msg->DevId.NextObjId;
|
||||
modbus_uart_buff[ind++] = modbus_msg->DevId.NumbOfObj;
|
||||
|
||||
if (modbus_msg->ByteCnt > DATA_SIZE*2) // if ByteCnt less than DATA_SIZE
|
||||
{
|
||||
TrackerCnt_Err(hmodbus->rs_err);
|
||||
return RS_COLLECT_MSG_ERR;
|
||||
}
|
||||
|
||||
|
||||
//---------------DATA----------------
|
||||
//-----------[data bytes]------------
|
||||
uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA;
|
||||
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
|
||||
{ // set data
|
||||
modbus_uart_buff[ind++] = *tmp_data_addr;
|
||||
tmp_data_addr++;
|
||||
}
|
||||
|
||||
}
|
||||
else // modbus data header
|
||||
{
|
||||
// set size of received data
|
||||
if (modbus_msg->ByteCnt <= DATA_SIZE*2) // if ByteCnt less than DATA_SIZE
|
||||
modbus_uart_buff[ind++] = modbus_msg->ByteCnt;
|
||||
else // otherwise return data_size err
|
||||
{
|
||||
TrackerCnt_Err(hmodbus->rs_err);
|
||||
return RS_COLLECT_MSG_ERR;
|
||||
}
|
||||
|
||||
//---------------DATA----------------
|
||||
//-----------[data bytes]------------
|
||||
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA;
|
||||
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
|
||||
{ // set data
|
||||
if (i%2 == 0) // HI byte
|
||||
modbus_uart_buff[ind++] = (*tmp_data_addr)>>8;
|
||||
else // LO byte
|
||||
{
|
||||
modbus_uart_buff[ind++] = *tmp_data_addr;
|
||||
tmp_data_addr++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else // if some error occur
|
||||
{ // send expection code
|
||||
modbus_uart_buff[ind++] = modbus_msg->Except_Code;
|
||||
}
|
||||
}
|
||||
//---------------CRC----------------
|
||||
//---------[last 16 bytes]----------
|
||||
// calc crc of received data
|
||||
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
|
||||
// write crc to message structure and modbus-uart buffer
|
||||
modbus_msg->MB_CRC = CRC_VALUE;
|
||||
modbus_uart_buff[ind++] = CRC_VALUE;
|
||||
modbus_uart_buff[ind++] = CRC_VALUE >> 8;
|
||||
|
||||
hmodbus->RS_Message_Size = ind;
|
||||
|
||||
return RS_OK; // returns ok
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse message from buffer to process it.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @param msg_uart_buff - указатель на буффер UART.
|
||||
* @return RS_RES - статус о результате заполнения структуры.
|
||||
* @details Заполнение структуры сообщения из буффера UART.
|
||||
*/
|
||||
RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
|
||||
{
|
||||
uint32_t check_empty_buff;
|
||||
int ind = 0; // ind for modbus-uart buffer
|
||||
//-----INFO ABOUT DATA/MESSAGE-------
|
||||
//-----------[first bits]------------
|
||||
// get ID of message/user
|
||||
modbus_msg->MbAddr = modbus_uart_buff[ind++];
|
||||
if(modbus_msg->MbAddr != hmodbus->ID)
|
||||
return RS_SKIP;
|
||||
|
||||
// get func code
|
||||
modbus_msg->Func_Code = modbus_uart_buff[ind++];
|
||||
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // if it device identification request
|
||||
{
|
||||
modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++];
|
||||
modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++];
|
||||
modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++];
|
||||
modbus_msg->ByteCnt = 0;
|
||||
}
|
||||
else // if its classic modbus request
|
||||
{
|
||||
// get address from CMD
|
||||
modbus_msg->Addr = modbus_uart_buff[ind++] << 8;
|
||||
modbus_msg->Addr |= modbus_uart_buff[ind++];
|
||||
|
||||
// get address from CMD
|
||||
modbus_msg->Qnt = modbus_uart_buff[ind++] << 8;
|
||||
modbus_msg->Qnt |= modbus_uart_buff[ind++];
|
||||
}
|
||||
if(hmodbus->f.RX_Half == 0) // if all message received
|
||||
{
|
||||
//---------------DATA----------------
|
||||
// (optional)
|
||||
if (modbus_msg->ByteCnt != 0)
|
||||
{
|
||||
ind++; // increment ind for data_size byte
|
||||
//check that data size is correct
|
||||
if (modbus_msg->ByteCnt > DATA_SIZE*2)
|
||||
{
|
||||
TrackerCnt_Err(hmodbus->rs_err);
|
||||
modbus_msg->Func_Code += ERR_VALUES_START;
|
||||
return RS_PARSE_MSG_ERR;
|
||||
}
|
||||
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA;
|
||||
for(int i = 0; i < modbus_msg->ByteCnt; i++) // /2 because we transmit 8 bits, not 16 bits
|
||||
{ // set data
|
||||
if (i%2 == 0)
|
||||
*tmp_data_addr = ((uint16_t)modbus_uart_buff[ind++] << 8);
|
||||
else
|
||||
{
|
||||
*tmp_data_addr |= modbus_uart_buff[ind++];
|
||||
tmp_data_addr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------CRC----------------
|
||||
//----------[last 16 bits]----------
|
||||
// calc crc of received data
|
||||
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
|
||||
// get crc of received data
|
||||
modbus_msg->MB_CRC = modbus_uart_buff[ind++];
|
||||
modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8;
|
||||
// compare crc
|
||||
if (modbus_msg->MB_CRC != CRC_VALUE)
|
||||
{
|
||||
TrackerCnt_Err(hmodbus->rs_err);
|
||||
modbus_msg->Func_Code += ERR_VALUES_START;
|
||||
}
|
||||
// hmodbus->MB_RESPONSE = MB_CRC_ERR; // set func code - error about wrong crc
|
||||
|
||||
// check is buffer empty
|
||||
check_empty_buff = 0;
|
||||
for(int i=0; i<ind;i++)
|
||||
check_empty_buff += modbus_uart_buff[i];
|
||||
// if(check_empty_buff == 0)
|
||||
// hmodbus->MB_RESPONSE = MB_EMPTY_MSG; //
|
||||
}
|
||||
|
||||
return RS_OK;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Define size of RX Message that need to be received.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия.
|
||||
* @return RS_RES - статус о корректности рассчета кол-ва байт для принятия.
|
||||
* @details Определение сколько байтов надо принять по протоколу.
|
||||
*/
|
||||
RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hmodbus, uint32_t *rx_data_size)
|
||||
{
|
||||
RS_StatusTypeDef MB_RES = 0;
|
||||
|
||||
MB_RES = RS_Parse_Message(hmodbus, hmodbus->pMessagePtr, hmodbus->pBufferPtr);
|
||||
if(MB_RES == RS_SKIP) // if message not for us
|
||||
return MB_RES; // return
|
||||
|
||||
|
||||
if ((hmodbus->pMessagePtr->Func_Code & ~ERR_VALUES_START) < 0x0F)
|
||||
{
|
||||
hmodbus->pMessagePtr->ByteCnt = 0;
|
||||
*rx_data_size = 1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
hmodbus->pMessagePtr->ByteCnt = hmodbus->pBufferPtr[RX_FIRST_PART_SIZE-1]; // get numb of data in command
|
||||
// +1 because that defines is size, not ind.
|
||||
*rx_data_size = hmodbus->pMessagePtr->ByteCnt + 2;
|
||||
}
|
||||
|
||||
|
||||
if(hmodbus->pMessagePtr->Func_Code == MB_R_DEVICE_INFO)
|
||||
{
|
||||
*rx_data_size = 0;
|
||||
}
|
||||
|
||||
hmodbus->RS_Message_Size = RX_FIRST_PART_SIZE + *rx_data_size; // size of whole message
|
||||
return RS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------FOR USER------------------------------
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
||||
void MB_DevoceInentificationInit(void)
|
||||
{
|
||||
MB_INFO.VendorName.name = MODBUS_VENDOR_NAME;
|
||||
MB_INFO.ProductCode.name = MODBUS_PRODUCT_CODE;
|
||||
MB_INFO.Revision.name = MODBUS_REVISION;
|
||||
MB_INFO.VendorUrl.name = MODBUS_VENDOR_URL;
|
||||
MB_INFO.ProductName.name = MODBUS_PRODUCT_NAME;
|
||||
MB_INFO.ModelName.name = MODBUS_MODEL_NAME;
|
||||
MB_INFO.UserApplicationName.name = MODBUS_USER_APPLICATION_NAME;
|
||||
|
||||
|
||||
MB_INFO.VendorName.length = sizeof(MODBUS_VENDOR_NAME);
|
||||
MB_INFO.ProductCode.length = sizeof(MODBUS_PRODUCT_CODE);
|
||||
MB_INFO.Revision.length = sizeof(MODBUS_REVISION);
|
||||
MB_INFO.VendorUrl.length = sizeof(MODBUS_VENDOR_URL);
|
||||
MB_INFO.ProductName.length = sizeof(MODBUS_PRODUCT_NAME);
|
||||
MB_INFO.ModelName.length = sizeof(MODBUS_MODEL_NAME);
|
||||
MB_INFO.UserApplicationName.length = sizeof(MODBUS_USER_APPLICATION_NAME);
|
||||
}
|
||||
|
||||
|
||||
|
||||
357
py_project/Core/Modbus/modbus.h
Normal file
357
py_project/Core/Modbus/modbus.h
Normal file
@@ -0,0 +1,357 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file modbus.h
|
||||
* @brief Заголовочный файл модуля MODBUS.
|
||||
* @details Данный файл необходимо подключить в rs_message.h. После подключать
|
||||
* rs_message.h к основному проекту.
|
||||
*
|
||||
* @defgroup MODBUS
|
||||
* @brief Modbus stuff
|
||||
*
|
||||
*************************************************************************/
|
||||
#ifndef __MODBUS_H_
|
||||
#define __MODBUS_H_
|
||||
|
||||
#include "mylibs_include.h"
|
||||
#include "modbus_data.h"
|
||||
//#include "settings.h" // for modbus settings
|
||||
|
||||
/**
|
||||
* @addtogroup MODBUS_SETTINGS
|
||||
* @ingroup MODBUS
|
||||
* @brief Some defines for modbus
|
||||
@{
|
||||
*/
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////---SETTINGS---/////////////////////////////
|
||||
// USER SETTINGS FOR MODBUS IN interface_config.h
|
||||
//////////////////////////---SETTINGS---/////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////---USER MESSAGE DEFINES---//////////////////////
|
||||
//-------------DEFINES FOR STRUCTURE----------------
|
||||
/* defines for structure of modbus message */
|
||||
#define MbAddr_SIZE 1 ///< size of (MbAddr)
|
||||
#define Func_Code_SIZE 1 ///< size of (Func_Code)
|
||||
#define Addr_SIZE 2 ///< size of (Addr)
|
||||
#define Qnt_SIZE 2 ///< size of (Qnt)
|
||||
#define ByteCnt_SIZE 1 ///< size of (ByteCnt)
|
||||
#define DATA_SIZE MODBUS_DATA_SIZE ///< maximum number of data: DWORD (NOT MESSAGE SIZE)
|
||||
#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes
|
||||
|
||||
/** @brief Size of whole message */
|
||||
#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE)
|
||||
|
||||
/** @brief Size of first part of message that will be received
|
||||
first receive info part of message, than defines size of rest message*/
|
||||
#define RX_FIRST_PART_SIZE INFO_SIZE_MAX
|
||||
|
||||
/** @brief Size of buffer: max size of whole message */
|
||||
#define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message
|
||||
|
||||
/** @brief Structure for modbus exception codes */
|
||||
typedef enum //MB_ExceptionTypeDef
|
||||
{
|
||||
// reading
|
||||
NO_ERRORS = 0x00, ///< no errors
|
||||
ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан
|
||||
ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен
|
||||
ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной
|
||||
SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие
|
||||
// ACKNOWLEDGE = 0x05, ///< idk
|
||||
// SLAVE_DEVICE_BUSY = 0x06, ///< idk
|
||||
// MEMORY_PARITY_ERROR = 0x08, ///< idk
|
||||
}MB_ExceptionTypeDef;
|
||||
|
||||
#define ERR_VALUES_START 0x80U ///< from this value starts error func codes
|
||||
/** @brief Structure for modbus func codes */
|
||||
typedef enum //MB_FunctonTypeDef
|
||||
{
|
||||
/* COMMANDS */
|
||||
// reading
|
||||
MB_R_COILS = 0x01, ///< Чтение битовых ячеек
|
||||
MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов
|
||||
#ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
|
||||
MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров
|
||||
MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения
|
||||
#else
|
||||
MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров
|
||||
MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения
|
||||
#endif
|
||||
|
||||
// writting
|
||||
MB_W_COIL = 0x05, ///< Запись битовой ячейки
|
||||
MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра
|
||||
MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек
|
||||
MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров
|
||||
|
||||
MB_R_DEVICE_INFO = 0x2B, ///< Чтения информации об устройстве
|
||||
|
||||
/* ERRORS */
|
||||
// error reading
|
||||
MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек
|
||||
MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов
|
||||
MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения
|
||||
MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров
|
||||
|
||||
// error writting
|
||||
MB_ERR_W_COIL = MB_W_COIL + ERR_VALUES_START, ///< Ошибка записи битовой ячейки
|
||||
MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра
|
||||
MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек
|
||||
MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров
|
||||
}MB_FunctonTypeDef;
|
||||
|
||||
/** @brief Structure for MEI func codes */
|
||||
typedef enum //MB_FunctonTypeDef
|
||||
{
|
||||
MEI_DEVICE_IDENTIFICATION = 0x0E,
|
||||
}MB_MEITypeDef;
|
||||
|
||||
/** @brief Structure for MEI func codes */
|
||||
typedef enum //MB_FunctonTypeDef
|
||||
{
|
||||
MB_BASIC_IDENTIFICATION = 0x01,
|
||||
MB_REGULAR_IDENTIFICATION = 0x02,
|
||||
|
||||
|
||||
/* ERRORS */
|
||||
MB_ERR_BASIC_IDENTIFICATION = MB_BASIC_IDENTIFICATION + ERR_VALUES_START,
|
||||
MB_ERR_REGULAR_IDENTIFICATION = MB_REGULAR_IDENTIFICATION + ERR_VALUES_START,
|
||||
}MB_ConformityTypeDef;
|
||||
|
||||
/** @brief Structure for decive identification message type */
|
||||
typedef struct
|
||||
{
|
||||
MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identification Interface
|
||||
MB_ConformityTypeDef ReadDevId;
|
||||
MB_ConformityTypeDef Conformity;
|
||||
uint8_t MoreFollows; ///< in this library always a zero
|
||||
uint8_t NextObjId;
|
||||
uint8_t NumbOfObj;
|
||||
}MB_DevIdMsgTypeDef;
|
||||
|
||||
/** @brief Structure for modbus messsage */
|
||||
typedef struct // RS_MsgTypeDef
|
||||
{
|
||||
uint8_t MbAddr; ///< Modbus Slave Address
|
||||
MB_FunctonTypeDef Func_Code; ///< Modbus Function Code
|
||||
MB_DevIdMsgTypeDef DevId; ///< Read Device Identification Header struct
|
||||
uint16_t Addr; ///< Modbus Address of data
|
||||
uint16_t Qnt; ///< Quantity of modbus data
|
||||
uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive
|
||||
|
||||
uint16_t DATA[DATA_SIZE]; ///< Modbus Data
|
||||
MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command
|
||||
|
||||
uint16_t MB_CRC; ///< Modbus CRC
|
||||
}RS_MsgTypeDef;
|
||||
//--------------------------------------------------
|
||||
extern RS_MsgTypeDef MODBUS_MSG;
|
||||
/////////////////////---MODBUS USER SETTINGS---//////////////////////
|
||||
|
||||
/** MODBUS_SETTINGS
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
|
||||
/**
|
||||
* @addtogroup MODBUS_MESSAGE_DEFINES
|
||||
* @ingroup MODBUS
|
||||
* @brief Some defines for modbus
|
||||
@{
|
||||
*/
|
||||
/** @brief Structure for coils operation */
|
||||
typedef enum
|
||||
{
|
||||
SET_COIL,
|
||||
RESET_COIL,
|
||||
TOOGLE_COIL,
|
||||
}MB_CoilsOpTypeDef;
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Macros to set pointer to 16-bit array
|
||||
* @param _arr_ - массив регистров (16-бит).
|
||||
*/
|
||||
#define MB_Set_Arr16_Ptr(_arr_) ((uint16_t*)(&(_arr_)))
|
||||
/**
|
||||
* @brief Macros to set pointer to register
|
||||
* @param _parr_ - массив регистров.
|
||||
* @param _addr_ - Номер регистра (его индекс) от начала массива _arr_.
|
||||
*/
|
||||
#define MB_Set_Register_Ptr(_parr_, _addr_) ((uint16_t *)(_parr_)+(_addr_))
|
||||
|
||||
/**
|
||||
* @brief Macros to set pointer to a certain register that contains certain coil
|
||||
* @param _parr_ - массив коилов.
|
||||
* @param _coil_ - Номер коила от начала массива _arr_.
|
||||
* @note Используется вместе с @ref MB_Set_Coil_Mask
|
||||
@verbatim Пояснение выражений
|
||||
(_coil_/16) - get index (address shift) of register that contain certain coil
|
||||
Visual explanation: 30th coil in coils registers array
|
||||
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|
||||
|register[0]----| |register[1]----|
|
||||
|skip this------| |get this-------|
|
||||
|shift to 14 bit|
|
||||
@endverbatim
|
||||
*/
|
||||
#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16))
|
||||
/**
|
||||
* @brief Macros to set mask to a certain bit in coils register
|
||||
* @param _coil_ - Номер коила от начала массива _arr_.
|
||||
* @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr
|
||||
@verbatim Пояснение выражений
|
||||
(16*(_coil_/16) - how many coils we need to skip. e.g. (16*30/16) - skip 16 coils from first register
|
||||
_coil_-(16*(_coil_/16)) - shift to certain coil in certain register
|
||||
e.g. Coil(30) gets in register[1] (30/16 = 1) coil №14 (30 - (16*30/16) = 30 - 16 = 14)
|
||||
|
||||
Visual explanation: 30th coil in coils registers array
|
||||
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|
||||
|register[0]----| |register[1]----|
|
||||
|skip this------| |get this-------|
|
||||
|shift to 14 bit|
|
||||
@endverbatim
|
||||
*/
|
||||
#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) ))
|
||||
|
||||
/**
|
||||
* @brief Read Coil at its local address.
|
||||
* @param _parr_ - массив коилов.
|
||||
* @param _coil_ - Номер коила от начала массива _arr_.
|
||||
* @return uint16_t - Возвращает запрошенный коил на 0м бите.
|
||||
*
|
||||
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
||||
*/
|
||||
#define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_))
|
||||
/**
|
||||
* @brief Set Coil at its local address.
|
||||
* @param _parr_ - указатель на массив коилов.
|
||||
* @param _coil_ - Номер коила от начала массива _arr_.
|
||||
*
|
||||
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
||||
*/
|
||||
#define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_)
|
||||
/**
|
||||
* @brief Reset Coil at its local address.
|
||||
* @param _parr_ - указатель на массив коилов.
|
||||
* @param _coil_ - Номер коила от начала массива _arr_.
|
||||
*
|
||||
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
||||
*/
|
||||
#define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_))
|
||||
/**
|
||||
* @brief Set Coil at its local address.
|
||||
* @param _parr_ - указатель на массив коилов.
|
||||
* @param _coil_ - Номер коила от начала массива _arr_.
|
||||
*
|
||||
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
||||
*/
|
||||
#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_)
|
||||
//--------------------------------------------------
|
||||
|
||||
|
||||
//------------------OTHER DEFINES-------------------
|
||||
#define RegisterType_Holding 0
|
||||
#define RegisterType_Input 1
|
||||
#define RegisterType_Discrete 2
|
||||
// create hadnles and settings for uart, tim, rs with _modbus_ name
|
||||
#define CONCAT(a,b) a##b
|
||||
#define Create_MODBUS_Handles(_modbus_) \
|
||||
UART_SettingsTypeDef CONCAT(_modbus_, _suart); \
|
||||
UART_HandleTypeDef CONCAT(_modbus_, _huart); \
|
||||
TIM_SettingsTypeDef CONCAT(_modbus_, _stim); \
|
||||
TIM_HandleTypeDef CONCAT(_modbus_, _htim); \
|
||||
RS_HandleTypeDef CONCAT(h, _modbus_)
|
||||
//--------------------------------------------------
|
||||
/** GENERAL_MODBUS_STUFF
|
||||
* @}
|
||||
*/
|
||||
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////---FUNCTIONS---/////////////////////////////
|
||||
/**
|
||||
* @addtogroup MODBUS_FUNCTIONS
|
||||
* @ingroup MODBUS
|
||||
* @brief Function for controling modbus communication
|
||||
*/
|
||||
|
||||
//----------------FUNCTIONS FOR USER----------------
|
||||
/**
|
||||
* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS
|
||||
* @ingroup MODBUS_FUNCTIONS
|
||||
* @brief Function for user use
|
||||
@{
|
||||
*/
|
||||
/* First set up of MODBUS */
|
||||
void MODBUS_FirstInit(void);
|
||||
/* Set or Reset Coil at its global address */
|
||||
MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal);
|
||||
/* Read Coil at its global address */
|
||||
uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception);
|
||||
|
||||
/** MODBUS_DATA_ACCESS_FUNCTIONS
|
||||
* @}
|
||||
*/
|
||||
|
||||
//---------PROCESS MODBUS COMMAND FUNCTIONS---------
|
||||
/**
|
||||
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
|
||||
* @ingroup MODBUS_FUNCTIONS
|
||||
* @brief Function process commands
|
||||
@{
|
||||
*/
|
||||
/* Check is address valid for certain array */
|
||||
MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB);
|
||||
/* Define Address Origin for Input/Holding Registers */
|
||||
MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType);
|
||||
/* Define Address Origin for coils */
|
||||
MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag);
|
||||
/* Proccess command Read Coils (01 - 0x01) */
|
||||
uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg);
|
||||
/* Proccess command Read Holding Registers (03 - 0x03) */
|
||||
uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg);
|
||||
/* Proccess command Read Input Registers (04 - 0x04) */
|
||||
uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg);
|
||||
/* Proccess command Write Single Coils (05 - 0x05) */
|
||||
uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg);
|
||||
/* Proccess command Write Multiple Coils (15 - 0x0F) */
|
||||
uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg);
|
||||
/* Proccess command Write Multiple Register (16 - 0x10) */
|
||||
uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg);
|
||||
|
||||
/** MODBUS_DATA_ACCESS_FUNCTIONS
|
||||
* @}
|
||||
*/
|
||||
/////////////////////////---FUNCTIONS---/////////////////////////////
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////---CALC DEFINES---//////////////////////////
|
||||
|
||||
|
||||
// TRACES DEFINES
|
||||
#ifndef Trace_MB_UART_Enter
|
||||
#define Trace_MB_UART_Enter()
|
||||
#endif //Trace_MB_UART_Enter
|
||||
|
||||
#ifndef Trace_MB_UART_Exit
|
||||
#define Trace_MB_UART_Exit()
|
||||
#endif //Trace_MB_UART_Exit
|
||||
|
||||
#ifndef Trace_MB_TIM_Enter
|
||||
#define Trace_MB_TIM_Enter()
|
||||
#endif //Trace_MB_TIM_Enter
|
||||
|
||||
#ifndef Trace_MB_TIM_Exit
|
||||
#define Trace_MB_TIM_Exit()
|
||||
#endif //Trace_MB_TIM_Exit
|
||||
|
||||
#endif //__MODBUS_H_
|
||||
179
py_project/Core/Modbus/modbus_data.h
Normal file
179
py_project/Core/Modbus/modbus_data.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file modbus_data.h
|
||||
* @brief Заголовочный файл с описанием даты MODBUS.
|
||||
* @details Данный файл необходимо подключается в rs_message.h. После rs_message.h
|
||||
* подключается к основному проекту.
|
||||
*
|
||||
* @defgroup MODBUS_DATA
|
||||
* @ingroup MODBUS
|
||||
* @brief Modbus data description
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _MODBUS_DATA_H_
|
||||
#define _MODBUS_DATA_H_
|
||||
|
||||
#include "stdint.h"
|
||||
#include "ds18b20_driver.h"
|
||||
//--------------DEFINES FOR REGISTERS---------------
|
||||
// DEFINES FOR ARRAYS
|
||||
/**
|
||||
* @addtogroup MODBUS_DATA_RERISTERS_DEFINES
|
||||
* @ingroup MODBUS_DATA
|
||||
* @brief Defines for registers
|
||||
Структура дефайна адресов
|
||||
@verbatim
|
||||
Для массивов регистров:
|
||||
R_<NAME_ARRAY>_ADDR - модбас адресс первого регистра в массиве
|
||||
R_<NAME_ARRAY>_QNT - количество регистров в массиве
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
//typedef struct
|
||||
//{
|
||||
// uint16_t ROM[4];
|
||||
// uint16_t Location;
|
||||
// uint16_t Resolution;
|
||||
// uint16_t Losted;
|
||||
//}MB_SensorResponseTypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t Location;
|
||||
uint16_t ROM[4];
|
||||
uint16_t Config;
|
||||
uint16_t Status;
|
||||
}MB_SensorParamsTypeDef;
|
||||
/**
|
||||
* @brief Регистры хранения
|
||||
*/
|
||||
typedef struct //MB_DataInRegsTypeDef
|
||||
{
|
||||
uint16_t SensTemperature[DS18B20_DEVICE_AMOUNT];
|
||||
MB_SensorParamsTypeDef Response;
|
||||
uint16_t reserved;
|
||||
uint16_t AllROMs[DS18B20_DEVICE_AMOUNT][4];
|
||||
}MB_DataInRegsTypeDef;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Входные регистры
|
||||
*/
|
||||
typedef struct //MB_DataInRegsTypeDef
|
||||
{
|
||||
MB_SensorParamsTypeDef InitStruct;
|
||||
}MB_DataHoldRegsTypeDef;
|
||||
|
||||
|
||||
// DEFINES FOR INPUT REGISTERS ARRAYS
|
||||
#define R_TEMPERATURE_ADDR (0)
|
||||
#define R_TEMPERATURE_QNT (DS18B20_DEVICE_AMOUNT)
|
||||
#define R_SENS_PARAMS_ADDR (DS18B20_DEVICE_AMOUNT) // 30
|
||||
#define R_SENS_PARAMS_QNT (sizeof(MB_SensorParamsTypeDef)/sizeof(uint16_t)) // 7
|
||||
#define R_ALL_ROMS_ADDR (R_SENS_PARAMS_ADDR+R_SENS_PARAMS_QNT + 1) // 38
|
||||
#define R_ALL_ROMS_QNT (DS18B20_DEVICE_AMOUNT*4)
|
||||
|
||||
// DEFINES FOR HOLDING REGISTERS ARRAYS
|
||||
#define R_SENS_INIT_ADDR (0)
|
||||
#define R_SENS_INIT_QNT (sizeof(MB_SensorParamsTypeDef)/sizeof(uint16_t))
|
||||
|
||||
|
||||
// DEFINES FOR REGISTERS LOCAL ADDRESSES
|
||||
//#define R_SET_ERROR(_te_num_) 0
|
||||
|
||||
|
||||
/** MODBUS_DATA_RERISTERS_DEFINES
|
||||
* @}
|
||||
*/
|
||||
|
||||
//----------------DEFINES FOR COILS-----------------
|
||||
/**
|
||||
* @addtogroup MODBUS_DATA_COILS_DEFINES
|
||||
* @ingroup MODBUS_DATA
|
||||
* @brief Defines for coils
|
||||
@verbatim
|
||||
Структура дефайна
|
||||
Для массивов коилов:
|
||||
C_<NAME_ARRAY>_ADDR - модбас адресс первого коила в массиве
|
||||
C_<NAME_ARRAY>_QNT - количество коилов в массиве (минимум 16)
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Коилы
|
||||
*/
|
||||
typedef struct //MB_DataCoilsTypeDef
|
||||
{
|
||||
/* reg 1 - control */
|
||||
unsigned RunConvertions:1;
|
||||
unsigned ReadSensor:1;
|
||||
unsigned InitSensor:1;
|
||||
unsigned DeInitSensor:1;
|
||||
unsigned ScanSensors:1;
|
||||
|
||||
unsigned reserved:11;
|
||||
|
||||
/* reg 2 - settings */
|
||||
unsigned ConvertionDone:1;
|
||||
unsigned LostedSensors:1;
|
||||
unsigned reserved2:11;
|
||||
}MB_DataCoilsTypeDef;
|
||||
|
||||
// DEFINES FOR COIL ARRAYS
|
||||
#define C_CONTROL_ADDR 0
|
||||
#define C_CONTROL_QNT 5
|
||||
|
||||
#define C_FLAGS_ADDR 16
|
||||
#define C_FLAGS_QNT 10
|
||||
|
||||
/** MODBUS_DATA_COILS_DEFINES
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
//-----------MODBUS DEVICE DATA SETTING-------------
|
||||
// MODBUS DATA STRUCTTURE
|
||||
/**
|
||||
* @brief Структура со всеми регистрами и коилами модбас
|
||||
* @ingroup MODBUS_DATA
|
||||
*/
|
||||
typedef struct // tester modbus data
|
||||
{
|
||||
MB_DataInRegsTypeDef InRegs; ///< Modbus input registers @ref MB_DataInRegsTypeDef
|
||||
|
||||
MB_DataCoilsTypeDef Coils; ///< Modbus coils @ref MB_DataCoilsTypeDef
|
||||
|
||||
MB_DataHoldRegsTypeDef HoldRegs; ///< Modbus holding registers @ref MB_DataHoldRegsTypeDef
|
||||
}MB_DataStructureTypeDef;
|
||||
extern MB_DataStructureTypeDef MB_DATA;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned length;
|
||||
char *name;
|
||||
}MB_DeviceObjectTypeDef;
|
||||
typedef struct
|
||||
{
|
||||
MB_DeviceObjectTypeDef VendorName;
|
||||
MB_DeviceObjectTypeDef ProductCode;
|
||||
MB_DeviceObjectTypeDef Revision;
|
||||
MB_DeviceObjectTypeDef VendorUrl;
|
||||
MB_DeviceObjectTypeDef ProductName;
|
||||
MB_DeviceObjectTypeDef ModelName;
|
||||
MB_DeviceObjectTypeDef UserApplicationName;
|
||||
}MB_DeviceIdentificationTypeDef;
|
||||
void MB_DevoceInentificationInit(void);
|
||||
|
||||
|
||||
#endif //_MODBUS_DATA_H_
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
///////////////////////TEMP/OUTDATE/OTHER////////////////////
|
||||
615
py_project/Core/Modbus/rs_message.c
Normal file
615
py_project/Core/Modbus/rs_message.c
Normal file
@@ -0,0 +1,615 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file rs_message.c
|
||||
* @brief Модуль для реализации протоколов по RS/UART.
|
||||
**************************************************************************
|
||||
@verbatim
|
||||
//-------------------Функции-------------------//
|
||||
Functions: users
|
||||
- RS_Parse_Message/RS_Collect_Message Заполнение структуры сообщения и буфера
|
||||
- RS_Response Ответ на сообщение
|
||||
- RS_Define_Size_of_RX_Message Определение размера принимаемых данных
|
||||
|
||||
Functions: general
|
||||
- RS_Receive_IT Ожидание комманды и ответ на неё
|
||||
- RS_Transmit_IT Отправление комманды и ожидание ответа
|
||||
- RS_Init Инициализация переферии и структуры для RS
|
||||
- RS_ReInit_UART Реинициализация UART для RS
|
||||
- RS_Abort Отмена приема/передачи по ЮАРТ
|
||||
- RS_Init Инициализация периферии и modbus handler
|
||||
|
||||
Functions: callback/handler
|
||||
- RS_Handle_Receive_Start Функция для запуска приема или остановки RS
|
||||
- RS_Handle_Transmit_Start Функция для запуска передачи или остановки RS
|
||||
|
||||
- RS_UART_RxCpltCallback Коллбек при окончании приема или передачи
|
||||
RS_UART_TxCpltCallback
|
||||
|
||||
- RS_UART_Handler Обработчик прерывания для UART
|
||||
- RS_TIM_Handler Обработчик прерывания для TIM
|
||||
|
||||
Functions: uart initialize (это было в отдельных файлах, мб надо обратно разнести)
|
||||
- UART_Base_Init Инициализация UART для RS
|
||||
- RS_UART_GPIO_Init Инициализация GPIO для RS
|
||||
- UART_DMA_Init Инициализация DMA для RS
|
||||
- UART_MspInit Аналог HAL_MspInit для RS
|
||||
- UART_MspDeInit Аналог HAL_MspDeInit для RS
|
||||
|
||||
@endverbatim
|
||||
*************************************************************************/
|
||||
#include "rs_message.h"
|
||||
|
||||
uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer
|
||||
|
||||
#ifndef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
extern void RS_UART_Init(void);
|
||||
extern void RS_UART_DeInit(UART_HandleTypeDef *huart);
|
||||
extern void RS_TIM_Init(void);
|
||||
extern void RS_TIM_DeInit(TIM_HandleTypeDef *htim);
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//-------------------------GENERAL FUNCTIONS-------------------------
|
||||
/**
|
||||
* @brief Start receive IT.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @return RS_RES - статус о состоянии RS после инициализации приема.
|
||||
*/
|
||||
RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
|
||||
{
|
||||
RS_StatusTypeDef RS_RES = 0;
|
||||
HAL_StatusTypeDef uart_res = 0;
|
||||
|
||||
//-------------CHECK RS LINE----------------
|
||||
// check that receive isnt busy
|
||||
if( RS_Is_RX_Busy(hRS) ) // if tx busy - return busy status
|
||||
return RS_BUSY;
|
||||
|
||||
//-----------INITIALIZE RECEIVE-------------
|
||||
// if all OK: start receiving
|
||||
RS_EnableReceive();
|
||||
RS_Set_Busy(hRS); // set RS busy
|
||||
RS_Set_RX_Flags(hRS); // initialize flags for receive
|
||||
hRS->pMessagePtr = RS_msg; // set pointer to message structire for filling it from UARTHandler fucntions
|
||||
|
||||
// start receiving
|
||||
uart_res = HAL_UART_Receive_IT(hRS->huart, hRS->pBufferPtr, RX_FIRST_PART_SIZE); // receive until ByteCnt+1 byte,
|
||||
// then in Callback restart receive for rest bytes
|
||||
|
||||
// if receive isnt started - abort RS
|
||||
if(uart_res != HAL_OK)
|
||||
{
|
||||
RS_RES = RS_Abort(hRS, ABORT_RS);
|
||||
printf_rs_err("\n%d: Error RS: Failed to start RS receiving...", uwTick);
|
||||
TrackerCnt_Err(hRS->rs_err);
|
||||
}
|
||||
else
|
||||
{
|
||||
RS_RES = RS_OK;
|
||||
printf_rs("\n%d: RS: Start Receiving...", uwTick);
|
||||
TrackerCnt_Ok(hRS->rs_err);
|
||||
}
|
||||
|
||||
hRS->RS_STATUS = RS_RES;
|
||||
return RS_RES; // returns result of receive init
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start transmit IT.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @return RS_RES - статус о состоянии RS после инициализации передачи.
|
||||
*/
|
||||
RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
|
||||
{
|
||||
RS_StatusTypeDef RS_RES = 0;
|
||||
HAL_StatusTypeDef uart_res = 0;
|
||||
|
||||
//-------------CHECK RS LINE----------------
|
||||
// check that transmit isnt busy
|
||||
if( RS_Is_TX_Busy(hRS) ) // if tx busy - return busy status
|
||||
return RS_BUSY;
|
||||
// check receive line
|
||||
|
||||
|
||||
//------------COLLECT MESSAGE---------------
|
||||
RS_RES = RS_Collect_Message(hRS, RS_msg, hRS->pBufferPtr);
|
||||
if (RS_RES != RS_OK) // if message isnt collect - stop RS and return error in RS_RES
|
||||
{// need collect message status, so doesnt write abort to RS_RES
|
||||
RS_Abort(hRS, ABORT_RS);
|
||||
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); // restart receive
|
||||
}
|
||||
else // if collect successful
|
||||
{
|
||||
|
||||
//----------INITIALIZE TRANSMIT-------------
|
||||
RS_EnableTransmit();
|
||||
// for(int i = 0; i < hRS->sRS_Timeout; i++);
|
||||
|
||||
RS_Set_Busy(hRS); // set RS busy
|
||||
RS_Set_TX_Flags(hRS); // initialize flags for transmit IT
|
||||
hRS->pMessagePtr = RS_msg; // set pointer for filling given structure from UARTHandler fucntion
|
||||
|
||||
// if all OK: start transmitting
|
||||
uart_res = HAL_UART_Transmit_IT(hRS->huart, hRS->pBufferPtr, hRS->RS_Message_Size);
|
||||
// if transmit isnt started - abort RS
|
||||
if(uart_res != HAL_OK)
|
||||
{
|
||||
RS_RES = RS_Abort(hRS, ABORT_RS);
|
||||
printf_rs_err("\n%d: Error RS: Failed to start RS transmitting...", uwTick);
|
||||
TrackerCnt_Err(hRS->rs_err);
|
||||
}
|
||||
else
|
||||
{
|
||||
RS_RES = RS_OK;
|
||||
printf_rs("\n%d: RS: Start Transmitting...", uwTick);
|
||||
TrackerCnt_Ok(hRS->rs_err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
hRS->RS_STATUS = RS_RES;
|
||||
return RS_RES; // returns result of transmit init
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize UART and handle RS stucture.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param suart - указатель на структуру с настройками UART.
|
||||
* @param stim - указатель на структуру с настройками таймера.
|
||||
* @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер.
|
||||
* @return RS_RES - статус о состоянии RS после инициализации.
|
||||
* @note Инициализация перефирии и структуры для приема-передачи по RS.
|
||||
*/
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart, TIM_SettingsTypeDef *stim, uint8_t *pRS_BufferPtr)
|
||||
#else
|
||||
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr)
|
||||
#endif
|
||||
{
|
||||
// check that hRS is defined
|
||||
if (hRS == NULL)
|
||||
return RS_ERR;
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
// check that huart is defined
|
||||
if ((suart->huart.Instance == NULL) || (suart->huart.Init.BaudRate == NULL))
|
||||
return RS_ERR;
|
||||
#else
|
||||
// check that huart is defined
|
||||
if (huart == NULL)
|
||||
return RS_ERR;
|
||||
#endif
|
||||
// init uart
|
||||
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
UART_Base_Init(suart);
|
||||
hRS->huart = &suart->huart;
|
||||
#else
|
||||
// RS_UART_Init();
|
||||
hRS->huart = huart;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
// check that timeout in interrupt needed
|
||||
if (hRS->sRS_Timeout)
|
||||
{
|
||||
if (stim->htim.Instance == NULL) // check is timer defined
|
||||
return RS_ERR;
|
||||
|
||||
// calc frequency corresponding to timeout and tims 1ms tickbase
|
||||
stim->sTickBaseUS = TIM_TickBase_1MS;
|
||||
stim->htim.Init.Period = hRS->sRS_Timeout;
|
||||
|
||||
TIM_Base_Init(stim);
|
||||
hRS->htim = &stim->htim;
|
||||
}
|
||||
#else
|
||||
// RS_TIM_Init();
|
||||
hRS->htim = htim;
|
||||
#endif
|
||||
|
||||
if (hRS->sRS_RX_Size_Mode == NULL)
|
||||
return RS_ERR;
|
||||
|
||||
// check that buffer is defined
|
||||
if (hRS->pBufferPtr == NULL)
|
||||
{
|
||||
hRS->pBufferPtr = RS_Buffer; // if no - set default
|
||||
}
|
||||
else
|
||||
hRS->pBufferPtr = pRS_BufferPtr; // if yes - set by user
|
||||
|
||||
return RS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ReInitialize UART and RS receive.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param suart - указатель на структуру с настройками UART.
|
||||
* @return RS_RES - статус о состоянии RS после инициализации.
|
||||
* @note Реинициализация UART и приема по RS.
|
||||
*/
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart)
|
||||
#else
|
||||
HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart)
|
||||
#endif
|
||||
{
|
||||
HAL_StatusTypeDef RS_RES;
|
||||
hRS->f.ReInit_UART = 0;
|
||||
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
// check is settings are valid
|
||||
if(Check_UART_Init_Struct(suart) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
RS_Abort(hRS, ABORT_RS);
|
||||
|
||||
UART_MspDeInit(&suart->huart);
|
||||
|
||||
RS_RES = UART_Base_Init(suart);
|
||||
|
||||
#else
|
||||
// // check is settings are valid
|
||||
// if(Check_UART_Init_Struct(suart) != HAL_OK)
|
||||
// return HAL_ERROR;
|
||||
|
||||
RS_Abort(hRS, ABORT_RS);
|
||||
|
||||
RS_UART_DeInit(huart);
|
||||
|
||||
RS_UART_Init();
|
||||
|
||||
#endif
|
||||
|
||||
RS_Receive_IT(hRS, hRS->pMessagePtr);
|
||||
return RS_RES;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Abort RS/UART.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param AbortMode - выбор, что надо отменить.
|
||||
- ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX,
|
||||
- ABORT_RX: Отмена приема по ЮАРТ, с очищением флагов RX,
|
||||
- ABORT_RX_TX: Отмена приема и передачи по ЮАРТ,
|
||||
- ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры.
|
||||
* @return RS_RES - статус о состоянии RS после аборта.
|
||||
* @note Отмена работы UART в целом или отмена приема/передачи RS.
|
||||
Также очищается хендл hRS.
|
||||
*/
|
||||
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode)
|
||||
{
|
||||
HAL_StatusTypeDef uart_res = 0;
|
||||
hRS->htim->Instance->CNT = 0;
|
||||
|
||||
if(hRS->sRS_Timeout) // if timeout setted
|
||||
{
|
||||
TIM14->DIER &= ~(TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM14->CR1 &= ~(TIM_CR1_CEN);
|
||||
}
|
||||
|
||||
if((AbortMode&ABORT_RS) == 0x00)
|
||||
{
|
||||
if((AbortMode&ABORT_RX) == ABORT_RX)
|
||||
{
|
||||
uart_res = HAL_UART_AbortReceive(hRS->huart); // abort receive
|
||||
RS_Reset_RX_Flags(hRS);
|
||||
}
|
||||
|
||||
if((AbortMode&ABORT_TX) == ABORT_TX)
|
||||
{
|
||||
uart_res = HAL_UART_AbortTransmit(hRS->huart); // abort transmit
|
||||
RS_Reset_TX_Flags(hRS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_res = HAL_UART_Abort(hRS->huart);
|
||||
RS_Clear_All(hRS);
|
||||
}
|
||||
hRS->RS_STATUS = RS_ABORTED;
|
||||
return RS_ABORTED;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------GENERAL FUNCTIONS-------------------------
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
|
||||
/**
|
||||
* @brief Handle for starting receive.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @return RS_RES - статус о состоянии RS после инициализации приема или окончания общения.
|
||||
* @note Определяет начинать прием команды/ответа или нет.
|
||||
*/
|
||||
RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
|
||||
{
|
||||
RS_StatusTypeDef RS_RES = 0;
|
||||
|
||||
switch(hRS->sRS_Mode)
|
||||
{
|
||||
case SLAVE_ALWAYS_WAIT: // in slave mode with permanent waiting
|
||||
RS_RES = RS_Receive_IT(hRS, RS_msg); break; // start receiving again
|
||||
case SLAVE_TIMEOUT_WAIT: // in slave mode with timeout waiting (start receiving cmd by request)
|
||||
RS_Set_Free(hRS); RS_RES = RS_OK; break; // end RS communication (set RS unbusy)
|
||||
}
|
||||
|
||||
if(RS_RES != RS_OK)
|
||||
{
|
||||
TrackerCnt_Err(hRS->rs_err);
|
||||
}
|
||||
|
||||
return RS_RES;
|
||||
}
|
||||
/**
|
||||
* @brief Handle for starting transmit.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @return RS_RES - статус о состоянии RS после инициализации передачи.
|
||||
* @note Определяет отвечать ли на команду или нет.
|
||||
*/
|
||||
RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
|
||||
{
|
||||
RS_StatusTypeDef RS_RES = 0;
|
||||
|
||||
switch(hRS->sRS_Mode)
|
||||
{
|
||||
case SLAVE_ALWAYS_WAIT: // in slave mode always response
|
||||
case SLAVE_TIMEOUT_WAIT: // transmit response
|
||||
RS_RES = RS_Transmit_IT(hRS, RS_msg); break;
|
||||
}
|
||||
if(RS_RES != RS_OK)
|
||||
{
|
||||
TrackerCnt_Err(hRS->rs_err);
|
||||
}
|
||||
|
||||
return RS_RES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART RX Callback: define behaviour after receiving parts of message.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @return RS_RES - статус о состоянии RS после обработки приема.
|
||||
* @note Контролирует прием сообщения: определяет размер принимаемой посылки и обрабатывает его.
|
||||
*/
|
||||
RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS)
|
||||
{
|
||||
RS_StatusTypeDef RS_RES = 0;
|
||||
HAL_StatusTypeDef uart_res = 0;
|
||||
|
||||
// if we had received bytes before ByteCnt
|
||||
if((hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) && (hRS->f.RX_Half == 0)) // if data size isnt constant and its first half, and
|
||||
{ // First receive part of message, then define size of rest of message, and start receive it
|
||||
hRS->f.RX_Half = 1;
|
||||
//---------------FIND DATA SIZE-----------------
|
||||
uint32_t NuRS_of_Rest_Bytes = 0xFFFF;
|
||||
RS_RES = RS_Define_Size_of_RX_Message(hRS, &NuRS_of_Rest_Bytes);
|
||||
|
||||
|
||||
// if we need to skip this message - restart receive
|
||||
if(RS_RES == RS_SKIP || NuRS_of_Rest_Bytes == 0xFFFF)
|
||||
{
|
||||
TrackerCnt_Err(hRS->rs_err);
|
||||
RS_Abort(hRS, ABORT_RX);
|
||||
RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||
return RS_RES;
|
||||
}
|
||||
|
||||
// if there is no bytes to receive
|
||||
if(NuRS_of_Rest_Bytes == 0)
|
||||
{
|
||||
hRS->f.RX_Half = 0;
|
||||
|
||||
//---------PROCESS DATA & ENDING RECEIVING--------
|
||||
RS_Set_RX_End(hRS);
|
||||
|
||||
if(hRS->sRS_Timeout) // if timeout setted
|
||||
{
|
||||
TIM14->DIER &= ~(TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM14->CR1 &= ~(TIM_CR1_CEN);
|
||||
}
|
||||
|
||||
// parse received data
|
||||
RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message
|
||||
|
||||
// RESPONSE
|
||||
RS_RES = RS_Response(hRS, hRS->pMessagePtr);
|
||||
return RS_RES;
|
||||
}
|
||||
|
||||
|
||||
//-------------START UART RECEIVE---------------
|
||||
uart_res = HAL_UART_Receive_IT(hRS->huart, (hRS->pBufferPtr + RX_FIRST_PART_SIZE), NuRS_of_Rest_Bytes);
|
||||
|
||||
if(uart_res != HAL_OK)
|
||||
{// need uart status, so doesnt write abort to RS_RES
|
||||
TrackerCnt_Err(hRS->rs_err);
|
||||
RS_RES = RS_Abort(hRS, ABORT_RS);
|
||||
}
|
||||
else
|
||||
RS_RES = RS_OK;
|
||||
}
|
||||
else // if we had received whole message
|
||||
{
|
||||
hRS->f.RX_Half = 0;
|
||||
|
||||
//---------PROCESS DATA & ENDING RECEIVING--------
|
||||
RS_Set_RX_End(hRS);
|
||||
|
||||
if(hRS->sRS_Timeout) // if timeout setted
|
||||
{
|
||||
TIM14->DIER &= ~(TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM14->CR1 &= ~(TIM_CR1_CEN);
|
||||
}
|
||||
|
||||
// parse received data
|
||||
RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message
|
||||
|
||||
// RESPONSE
|
||||
RS_RES = RS_Response(hRS, hRS->pMessagePtr);
|
||||
}
|
||||
|
||||
return RS_RES;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief UART TX Callback: define behaviour after transmiting message.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @return RS_RES - статус о состоянии RS после обработки приема.
|
||||
* @note Определяет поведение RS после передачи сообщения.
|
||||
*/
|
||||
RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS)
|
||||
{
|
||||
RS_StatusTypeDef RS_RES = RS_OK;
|
||||
HAL_StatusTypeDef uart_res = 0;
|
||||
|
||||
//--------------ENDING TRANSMITTING-------------
|
||||
RS_Set_TX_End(hRS);
|
||||
RS_EnableReceive();
|
||||
// for(int i = 0; i < hRS->sRS_Timeout; i++);
|
||||
|
||||
//-----------START RECEIVING or END RS----------
|
||||
RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||
|
||||
return RS_RES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handler for UART.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @note Обрабатывает ошибки если есть и вызывает RS Коллбеки.
|
||||
* Добавить вызов этой функции в UARTx_IRQHandler().
|
||||
*/
|
||||
void RS_UART_Handler(RS_HandleTypeDef *hRS)
|
||||
{
|
||||
HAL_UART_IRQHandler(hRS->huart);
|
||||
//-------------CALL RS CALLBACKS------------
|
||||
/* IF NO ERROR OCCURS */
|
||||
if(hRS->huart->ErrorCode == 0)
|
||||
{
|
||||
hRS->htim->Instance->CNT = 0; // reset cnt;
|
||||
/* Start timeout */
|
||||
if(hRS->sRS_Timeout) // if timeout setted
|
||||
if((hRS->huart->RxXferCount+1 == hRS->huart->RxXferSize) && RS_Is_RX_Busy(hRS)) // if first byte is received and receive is active
|
||||
{
|
||||
TIM14->DIER |= (TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM14->CR1 |= (TIM_CR1_CEN);
|
||||
RS_Set_RX_Active_Flags(hRS);
|
||||
}
|
||||
|
||||
/* RX Callback */
|
||||
if (( hRS->huart->RxXferCount == 0U) && RS_Is_RX_Busy(hRS) && // if all bytes are received and receive is active
|
||||
hRS->huart->RxState != HAL_UART_STATE_BUSY_RX) // also check that receive "REALLY" isnt busy
|
||||
RS_UART_RxCpltCallback(hRS);
|
||||
|
||||
/* TX Callback */
|
||||
if (( hRS->huart->TxXferCount == 0U) && RS_Is_TX_Busy(hRS) && // if all bytes are transmited and transmit is active
|
||||
hRS->huart->gState != HAL_UART_STATE_BUSY_TX) // also check that receive "REALLY" isnt busy
|
||||
RS_UART_TxCpltCallback(hRS);
|
||||
}
|
||||
//----------------ERRORS HANDLER----------------
|
||||
else
|
||||
{
|
||||
TrackerCnt_Err(hRS->rs_err);
|
||||
/* de-init uart transfer */
|
||||
RS_Abort(hRS, ABORT_RS);
|
||||
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||
|
||||
// later, maybe, will be added specific handlers for err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handler for TIM.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @note Попадание сюда = таймаут и перезапуск RS приема
|
||||
* Добавить вызов этой функции в TIMx_IRQHandler().
|
||||
*/
|
||||
void RS_TIM_Handler(RS_HandleTypeDef *hRS)
|
||||
{
|
||||
TIM14->SR = ~(TIM_IT_UPDATE);
|
||||
/* Disable the TIM Update interrupt */
|
||||
TIM14->DIER &= ~(TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM14->CR1 &= ~(TIM_CR1_CEN);
|
||||
|
||||
RS_Abort(hRS, ABORT_RS);
|
||||
|
||||
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
||||
}
|
||||
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE---------------
|
||||
/**
|
||||
* @brief Respond accord to received message.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @return RS_RES - статус о результате ответа на комманду.
|
||||
* @note Обработка принятой комманды и ответ на неё.
|
||||
*/
|
||||
__weak RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
|
||||
{
|
||||
/* Redefine function for user purposes */
|
||||
return RS_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Collect message in buffer to transmit it.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @param msg_uart_buff - указатель на буффер UART.
|
||||
* @return RS_RES - статус о результате заполнения буфера.
|
||||
* @note Заполнение буффера UART из структуры сообщения.
|
||||
*/
|
||||
__weak RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff)
|
||||
{
|
||||
/* Redefine function for user purposes */
|
||||
return RS_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse message from buffer to process it.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param RS_msg - указатель на структуру сообщения.
|
||||
* @param msg_uart_buff - указатель на буффер UART.
|
||||
* @return RS_RES - статус о результате заполнения структуры.
|
||||
* @note Заполнение структуры сообщения из буффера UART.
|
||||
*/
|
||||
__weak RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff)
|
||||
{
|
||||
/* Redefine function for user purposes */
|
||||
return RS_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Define size of RX Message that need to be received.
|
||||
* @param hRS - указатель на хендлер RS.
|
||||
* @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия.
|
||||
* @return RS_RES - статус о корректности рассчета кол-ва байт для принятия.
|
||||
* @note Определение сколько байтов надо принять по протоколу.
|
||||
*/
|
||||
__weak RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size)
|
||||
{
|
||||
/* Redefine function for user purposes */
|
||||
return RS_ERR;
|
||||
}
|
||||
//--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE---------------
|
||||
//-------------------------------------------------------------------
|
||||
265
py_project/Core/Modbus/rs_message.h
Normal file
265
py_project/Core/Modbus/rs_message.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file rs_message.h
|
||||
* @brief Заголовочный файл для модуля реализации протоколов по RS/UART.
|
||||
**************************************************************************
|
||||
* @defgroup RS_TOOLS
|
||||
* @brief Всякое для работы по UART/RS
|
||||
**************************************************************************
|
||||
@details
|
||||
**************************************************************************
|
||||
Для настройки RS/UART под нужный протокол, необходимо:
|
||||
- Определить структуру сообщения RS_MsgTypeDef и
|
||||
дефайны RX_FIRST_PART_SIZE и MSG_SIZE_MAX.
|
||||
- Подключить этот файл в раздел rs_message.h.
|
||||
- Определить функции для обработки сообщения: RS_Parse_Message(),
|
||||
RS_Collect_Message(), RS_Response(), RS_Define_Size_of_RX_Message()
|
||||
- Добавить UART/TIM Handler в Хендлер используемых UART/TIM.
|
||||
|
||||
Так же данный модуль использует счетчики
|
||||
**************************************************************************
|
||||
@verbatim
|
||||
Визуальное описание. Форматирование сохраняется как в коде.
|
||||
@endverbatim
|
||||
*************************************************************************/
|
||||
#ifndef __RS_LIB_H_
|
||||
#define __RS_LIB_H_
|
||||
|
||||
#include "modbus.h"
|
||||
|
||||
#include "mylibs_include.h"
|
||||
#include "crc_algs.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////---DEFINES---////////////////////////////
|
||||
/* Check that all defines required by RS are defined */
|
||||
#ifndef MSG_SIZE_MAX
|
||||
#error Define MSG_SIZE_MAX (Maximum size of message). This is necessary to create buffer for UART.
|
||||
#endif
|
||||
|
||||
#ifndef RX_FIRST_PART_SIZE
|
||||
#error Define RX_FIRST_PART_SIZE (Size of first part of message). This is necessary to receive the first part of the message, from which determine the size of the remaining part of the message.
|
||||
#endif
|
||||
|
||||
|
||||
/* Clear message-uart buffer */
|
||||
#define RS_Clear_Buff(_buff_) for(int i=0; i<MSG_SIZE_MAX;i++) _buff_[i] = NULL
|
||||
|
||||
/* Set/Reset flags */
|
||||
#define RS_Set_Free(_hRS_) _hRS_->f.RS_Busy = 0
|
||||
#define RS_Set_Busy(_hRS_) _hRS_->f.RS_Busy = 1
|
||||
|
||||
#define RS_Set_RX_Flags(_hRS_) _hRS_->f.RX_Busy = 1; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0
|
||||
#define RS_Set_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 1
|
||||
|
||||
|
||||
#define RS_Set_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 1; _hRS_->f.TX_Done = 0
|
||||
|
||||
#define RS_Reset_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 0
|
||||
#define RS_Reset_RX_Flags(_hRS_) RS_Reset_RX_Active_Flags(_hRS_); _hRS_->f.RX_Busy = 0; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0
|
||||
#define RS_Reset_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 0; _hRS_->f.TX_Done = 0
|
||||
|
||||
#define RS_Set_RX_End_Flag(_hRS_) _hRS_->f.RX_Done = 1;
|
||||
#define RS_Set_TX_End_Flag(_hRS_) _hRS_->f.TX_Done = 1
|
||||
|
||||
#define RS_Set_RX_End(_hRS_) RS_Reset_RX_Flags(_hRS_); RS_Set_RX_End_Flag(_hRS_)
|
||||
#define RS_Set_TX_End(_hRS_) RS_Reset_TX_Flags(_hRS_); RS_Set_TX_End_Flag(_hRS_)
|
||||
|
||||
/* Clear all RS stuff */
|
||||
#define RS_Clear_All(_hRS_) RS_Clear_Buff(_hRS_->pBufferPtr); RS_Reset_RX_Flags(_hRS_); RS_Reset_TX_Flags(_hRS_);
|
||||
|
||||
//#define MB_Is_RX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_RX)
|
||||
//#define MB_Is_TX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_TX)
|
||||
#define RS_Is_RX_Busy(_hRS_) (_hRS_->f.RX_Busy == 1)
|
||||
#define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1)
|
||||
|
||||
|
||||
#ifndef RS_EnableReceive
|
||||
#define RS_EnableReceive()
|
||||
#endif
|
||||
#ifndef RS_EnableTransmit
|
||||
#define RS_EnableTransmit()
|
||||
#endif
|
||||
////////////////////////////---DEFINES---////////////////////////////
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
///////////////////////---STRUCTURES & ENUMS---//////////////////////
|
||||
//------------------ENUMERATIONS--------------------
|
||||
/** @brief Enums for respond CMD about RS status */
|
||||
typedef enum // RS_StatusTypeDef
|
||||
{
|
||||
/* IN-CODE STATUS (start from 0x01, and goes up)*/
|
||||
/*0x01*/ RS_OK = 0x01,
|
||||
/*0x02*/ RS_ERR,
|
||||
/*0x03*/ RS_ABORTED,
|
||||
/*0x04*/ RS_BUSY,
|
||||
/*0x05*/ RS_SKIP,
|
||||
|
||||
/*0x06*/ RS_COLLECT_MSG_ERR,
|
||||
/*0x07*/ RS_PARSE_MSG_ERR,
|
||||
|
||||
// reserved values
|
||||
// /*0x00*/ RS_UNKNOWN_ERR = 0x00, ///< reserved for case, if no one error founded (nothing changed response from zero)
|
||||
}RS_StatusTypeDef;
|
||||
|
||||
|
||||
/** @brief Enums for RS Modes */
|
||||
typedef enum // RS_ModeTypeDef
|
||||
{
|
||||
SLAVE_ALWAYS_WAIT = 0x01, ///< Slave mode with infinity waiting
|
||||
SLAVE_TIMEOUT_WAIT = 0x02, ///< Slave mode with waiting with timeout
|
||||
// MASTER = 0x03, ///< Master mode
|
||||
}RS_ModeTypeDef;
|
||||
|
||||
/** @brief Enums for RS UART Modes */
|
||||
typedef enum // RS_ITModeTypeDef
|
||||
{
|
||||
BLCK_MODE = 0x00, ///< Blocking mode
|
||||
IT_MODE = 0x01, ///< Interrupt mode
|
||||
}RS_ITModeTypeDef;
|
||||
|
||||
/** @brief Enums for Abort modes */
|
||||
typedef enum // RS_AbortTypeDef
|
||||
{
|
||||
ABORT_TX = 0x01, ///< Abort transmit
|
||||
ABORT_RX = 0x02, ///< Abort receive
|
||||
ABORT_RX_TX = 0x03, ///< Abort receive and transmit
|
||||
ABORT_RS = 0x04, ///< Abort uart and reset RS structure
|
||||
}RS_AbortTypeDef;
|
||||
|
||||
/** @brief Enums for RX Size modes */
|
||||
typedef enum // RS_RXSizeTypeDef
|
||||
{
|
||||
RS_RX_Size_Const = 0x01, ///< size of receiving message is constant
|
||||
RS_RX_Size_NotConst = 0x02, ///< size of receiving message isnt constant
|
||||
}RS_RXSizeTypeDef;
|
||||
|
||||
|
||||
//-----------STRUCTURE FOR HANDLE RS------------
|
||||
/** @brief Struct for flags RS */
|
||||
typedef struct
|
||||
{
|
||||
unsigned RX_Half:1; ///< flag: 0 - receiving msg before ByteCnt, 0 - receiving msg after ByteCnt
|
||||
|
||||
unsigned RS_Busy:1; ///< flag: 1 - RS is busy, 0 - RS isnt busy
|
||||
unsigned RX_Ongoing:1; ///< flag: 1 - receiving data right now, 0 - waiting for receiving data
|
||||
|
||||
unsigned RX_Busy:1; ///< flag: 1 - receiving is active, 0 - receiving isnt active
|
||||
unsigned TX_Busy:1; ///< flag: 1 - transmiting is active, 0 - transmiting isnt active
|
||||
|
||||
unsigned RX_Done:1; ///< flag: 1 - receiving is done, 0 - receiving isnt done
|
||||
unsigned TX_Done:1; ///< flag: 1 - transmiting is done, 0 - transmiting isnt done
|
||||
|
||||
// setted by user
|
||||
unsigned MessageHandled:1; ///< flag: 1 - RS command is handled, 0 - RS command isnt handled yet
|
||||
unsigned EchoResponse:1; ///< flag: 1 - response with received msg, 0 - response with own msg
|
||||
unsigned DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt
|
||||
unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing
|
||||
}RS_FlagsTypeDef;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle for RS communication.
|
||||
* @note Prefixes: h - handle, s - settings, f - flag
|
||||
*/
|
||||
typedef struct // RS_HandleTypeDef
|
||||
{
|
||||
/* MESSAGE */
|
||||
uint8_t ID; ///< ID of RS "channel"
|
||||
RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct
|
||||
uint8_t *pBufferPtr; ///< pointer to message buffer
|
||||
uint32_t RS_Message_Size; ///< size of whole message, not only data
|
||||
|
||||
/* HANDLERS and SETTINGS */
|
||||
UART_HandleTypeDef *huart; ///< handler for used uart
|
||||
TIM_HandleTypeDef *htim; ///< handler for used tim
|
||||
RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef
|
||||
RS_ITModeTypeDef sRS_IT_Mode; ///< setting: 1 - IT mode, 0 - Blocking mode
|
||||
uint16_t sRS_Timeout; ///< setting: timeout in ms
|
||||
RS_RXSizeTypeDef sRS_RX_Size_Mode; ///< setting: 1 - not const, 0 - const
|
||||
|
||||
/* FLAGS */
|
||||
RS_FlagsTypeDef f; ///< These flags for controling receive/transmit
|
||||
|
||||
/* RS STATUS */
|
||||
RS_StatusTypeDef RS_STATUS; ///< RS status
|
||||
RS_TrackerTypeDef rs_err;
|
||||
}RS_HandleTypeDef;
|
||||
extern RS_HandleTypeDef hmodbus1;
|
||||
|
||||
|
||||
///////////////////////---STRUCTURES & ENUMS---//////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////---FUNCTIONS---///////////////////////////
|
||||
//----------------FUNCTIONS FOR PROCESSING MESSAGE-------------------
|
||||
/*--------------------Defined by users purposes--------------------*/
|
||||
/* Respond accord to received message */
|
||||
RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
|
||||
|
||||
/* Collect message in buffer to transmit it */
|
||||
RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff);
|
||||
|
||||
/* Parse message from buffer to process it */
|
||||
RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff);
|
||||
|
||||
/* Define size of RX Message that need to be received */
|
||||
RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size);
|
||||
|
||||
|
||||
//-------------------------GENERAL FUNCTIONS-------------------------
|
||||
/*-----------------Should be called from main code-----------------*/
|
||||
/* Start receive IT */
|
||||
RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
|
||||
|
||||
/* Start transmit IT */
|
||||
RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
|
||||
|
||||
/* Initialize UART and handle RS stucture */
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart, TIM_SettingsTypeDef *stim, uint8_t *pRS_BufferPtr);
|
||||
#else
|
||||
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr);
|
||||
#endif
|
||||
/* ReInitialize UART and RS receive */
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart);
|
||||
#else
|
||||
HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *suart);
|
||||
#endif
|
||||
/* Abort RS/UART */
|
||||
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode);
|
||||
//-------------------------GENERAL FUNCTIONS-------------------------
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
|
||||
/* Handle for starting receive */
|
||||
RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
|
||||
/* Handle for starting transmit */
|
||||
RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
|
||||
/* UART RX Callback: define behaviour after receiving parts of message */
|
||||
RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS);
|
||||
/* UART TX Callback: define behaviour after transmiting message */
|
||||
RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS);
|
||||
/* Handler for UART */
|
||||
void RS_UART_Handler(RS_HandleTypeDef *hRS);
|
||||
/* Handler for TIM */
|
||||
void RS_TIM_Handler(RS_HandleTypeDef *hRS);
|
||||
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
|
||||
///////////////////////////---FUNCTIONS---///////////////////////////
|
||||
|
||||
|
||||
#ifndef printf_rs_err
|
||||
#define printf_rs_err(...)
|
||||
#endif
|
||||
|
||||
#ifndef printf_rs
|
||||
#define printf_rs(...)
|
||||
#endif
|
||||
#endif // __RS_LIB_H_
|
||||
249
py_project/Core/MyLibs/bit_access.h
Normal file
249
py_project/Core/MyLibs/bit_access.h
Normal file
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file mylibs_defs.h
|
||||
* @brief Заголочный файл для дефайнов библиотеки MyLibsGeneral.
|
||||
**************************************************************************
|
||||
* @defgroup BIT_ACCESS_DEFINES Bit access defines
|
||||
* @ingroup MYLIBS_DEFINES
|
||||
* @brief Всякое для доступа к битам в unsigned
|
||||
*************************************************************************/
|
||||
#ifndef __BIT_ACCESS_H_
|
||||
#define __BIT_ACCESS_H_
|
||||
#include "mylibs_defs.h"
|
||||
|
||||
/**
|
||||
* @addtogroup BIT_ACCESS_TYPEDEF Byte access typedefs
|
||||
* @ingroup BIT_ACCESS_DEFINES
|
||||
* @brief Дефайны юнионов для обращения к битам.
|
||||
@{
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
uint8_t all;
|
||||
struct
|
||||
{
|
||||
unsigned bit0:1;
|
||||
unsigned bit1:1;
|
||||
unsigned bit2:1;
|
||||
unsigned bit3:1;
|
||||
unsigned reserved:4;
|
||||
}bit;
|
||||
}uint4_BitTypeDef;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t all;
|
||||
struct
|
||||
{
|
||||
unsigned bit0:1;
|
||||
unsigned bit1:1;
|
||||
unsigned bit2:1;
|
||||
unsigned bit3:1;
|
||||
unsigned bit4:1;
|
||||
unsigned reserved:3;
|
||||
}bit;
|
||||
}uint5_BitTypeDef;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t all;
|
||||
struct
|
||||
{
|
||||
unsigned bit0:1;
|
||||
unsigned bit1:1;
|
||||
unsigned bit2:1;
|
||||
unsigned bit3:1;
|
||||
unsigned bit4:1;
|
||||
unsigned bit5:1;
|
||||
unsigned reserved:2;
|
||||
}bit;
|
||||
}uint6_BitTypeDef;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t all;
|
||||
struct
|
||||
{
|
||||
unsigned bit0:1;
|
||||
unsigned bit1:1;
|
||||
unsigned bit2:1;
|
||||
unsigned bit3:1;
|
||||
unsigned bit4:1;
|
||||
unsigned bit5:1;
|
||||
unsigned bit6:1;
|
||||
unsigned reserved:1;
|
||||
}bit;
|
||||
}uint7_BitTypeDef;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t all;
|
||||
struct
|
||||
{
|
||||
unsigned bit0:1;
|
||||
unsigned bit1:1;
|
||||
unsigned bit2:1;
|
||||
unsigned bit3:1;
|
||||
unsigned bit4:1;
|
||||
unsigned bit5:1;
|
||||
unsigned bit6:1;
|
||||
unsigned bit7:1;
|
||||
}bit;
|
||||
}uint8_BitTypeDef;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint16_t all;
|
||||
struct
|
||||
{
|
||||
unsigned bit0:1;
|
||||
unsigned bit1:1;
|
||||
unsigned bit2:1;
|
||||
unsigned bit3:1;
|
||||
unsigned bit4:1;
|
||||
unsigned bit5:1;
|
||||
unsigned bit6:1;
|
||||
unsigned bit7:1;
|
||||
unsigned bit8:1;
|
||||
unsigned bit9:1;
|
||||
unsigned bit10:1;
|
||||
unsigned bit11:1;
|
||||
unsigned bit12:1;
|
||||
unsigned bit13:1;
|
||||
unsigned bit14:1;
|
||||
unsigned bit15:1;
|
||||
}bit;
|
||||
}uint16_BitTypeDef;
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint32_t all;
|
||||
struct
|
||||
{
|
||||
unsigned bit0:1;
|
||||
unsigned bit1:1;
|
||||
unsigned bit2:1;
|
||||
unsigned bit3:1;
|
||||
unsigned bit4:1;
|
||||
unsigned bit5:1;
|
||||
unsigned bit6:1;
|
||||
unsigned bit7:1;
|
||||
unsigned bit8:1;
|
||||
unsigned bit9:1;
|
||||
unsigned bit10:1;
|
||||
unsigned bit11:1;
|
||||
unsigned bit12:1;
|
||||
unsigned bit13:1;
|
||||
unsigned bit14:1;
|
||||
unsigned bit15:1;
|
||||
unsigned bit16:1;
|
||||
unsigned bit17:1;
|
||||
unsigned bit18:1;
|
||||
unsigned bit19:1;
|
||||
unsigned bit20:1;
|
||||
unsigned bit21:1;
|
||||
unsigned bit22:1;
|
||||
unsigned bit23:1;
|
||||
unsigned bit24:1;
|
||||
unsigned bit25:1;
|
||||
unsigned bit26:1;
|
||||
unsigned bit27:1;
|
||||
unsigned bit28:1;
|
||||
unsigned bit29:1;
|
||||
unsigned bit30:1;
|
||||
unsigned bit31:1;
|
||||
}bit;
|
||||
}uint32_BitTypeDef;
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint64_t all;
|
||||
struct
|
||||
{
|
||||
unsigned bit0:1;
|
||||
unsigned bit1:1;
|
||||
unsigned bit2:1;
|
||||
unsigned bit3:1;
|
||||
unsigned bit4:1;
|
||||
unsigned bit5:1;
|
||||
unsigned bit6:1;
|
||||
unsigned bit7:1;
|
||||
unsigned bit8:1;
|
||||
unsigned bit9:1;
|
||||
unsigned bit10:1;
|
||||
unsigned bit11:1;
|
||||
unsigned bit12:1;
|
||||
unsigned bit13:1;
|
||||
unsigned bit14:1;
|
||||
unsigned bit15:1;
|
||||
unsigned bit16:1;
|
||||
unsigned bit17:1;
|
||||
unsigned bit18:1;
|
||||
unsigned bit19:1;
|
||||
unsigned bit20:1;
|
||||
unsigned bit21:1;
|
||||
unsigned bit22:1;
|
||||
unsigned bit23:1;
|
||||
unsigned bit24:1;
|
||||
unsigned bit25:1;
|
||||
unsigned bit26:1;
|
||||
unsigned bit27:1;
|
||||
unsigned bit28:1;
|
||||
unsigned bit29:1;
|
||||
unsigned bit30:1;
|
||||
unsigned bit31:1;
|
||||
unsigned bit32:1;
|
||||
unsigned bit33:1;
|
||||
unsigned bit34:1;
|
||||
unsigned bit35:1;
|
||||
unsigned bit36:1;
|
||||
unsigned bit37:1;
|
||||
unsigned bit38:1;
|
||||
unsigned bit39:1;
|
||||
unsigned bit40:1;
|
||||
unsigned bit41:1;
|
||||
unsigned bit42:1;
|
||||
unsigned bit43:1;
|
||||
unsigned bit44:1;
|
||||
unsigned bit45:1;
|
||||
unsigned bit46:1;
|
||||
unsigned bit47:1;
|
||||
unsigned bit48:1;
|
||||
unsigned bit49:1;
|
||||
unsigned bit50:1;
|
||||
unsigned bit51:1;
|
||||
unsigned bit52:1;
|
||||
unsigned bit53:1;
|
||||
unsigned bit54:1;
|
||||
unsigned bit55:1;
|
||||
unsigned bit56:1;
|
||||
unsigned bit57:1;
|
||||
unsigned bit58:1;
|
||||
unsigned bit59:1;
|
||||
unsigned bit60:1;
|
||||
unsigned bit61:1;
|
||||
unsigned bit62:1;
|
||||
unsigned bit63:1;
|
||||
}bit;
|
||||
}uint64_BitTypeDef;
|
||||
/** BIT_ACCESS_TYPEDEF
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup BIT_ACCESS_FUNCTIONS Byte access functions
|
||||
* @ingroup BIT_ACCESS_DEFINES
|
||||
* @brief Дефайны для обращения к битам в unsigned.
|
||||
@{
|
||||
*/
|
||||
#define uint8_bit(_uint8_, _bit_) (*(uint8_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_
|
||||
#define uint16_bit(_uint8_, _bit_) (*(uint16_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_
|
||||
#define uint32_bit(_uint8_, _bit_) (*(uint32_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_
|
||||
#define uint64_bit(_uint8_, _bit_) (*(uint64_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_
|
||||
|
||||
/** BIT_ACCESS_FUNCTIONS
|
||||
* @}
|
||||
*/
|
||||
#endif //__BIT_ACCESS_H_
|
||||
128
py_project/Core/MyLibs/general_gpio.c
Normal file
128
py_project/Core/MyLibs/general_gpio.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file general_gpio.c
|
||||
* @brief Модуль для инициализации портов.
|
||||
**************************************************************************
|
||||
@verbatim
|
||||
//-------------------Функции-------------------//
|
||||
Functions: users
|
||||
- GPIO_Clock_Enable Инициализация тактирования порта
|
||||
@endverbatim
|
||||
***************************************************************************/
|
||||
#include "general_gpio.h"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//------------------------GPIO INIT FUNCTIONS------------------------
|
||||
|
||||
HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
// choose port for enable clock
|
||||
if (GPIOx==GPIOA)
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
else if (GPIOx==GPIOB)
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
else if (GPIOx==GPIOC)
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
#ifdef GPIOD
|
||||
else if (GPIOx==GPIOD)
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
#endif
|
||||
#ifdef GPIOE
|
||||
else if (GPIOx==GPIOE)
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
#endif
|
||||
else
|
||||
status = HAL_ERROR;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//------------------------GPIO INIT FUNCTIONS------------------------
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//------------------------GPIO LED FUNCTIONS-------------------------
|
||||
|
||||
/**
|
||||
* @brief Включить светодиод
|
||||
*/
|
||||
void GPIO_LED_On(GPIO_LEDTypeDef *led)
|
||||
{
|
||||
led->state = LED_IS_ON;
|
||||
HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, LED_ON);
|
||||
}
|
||||
/**
|
||||
* @brief Выключить светодиод
|
||||
*/
|
||||
void GPIO_LED_Off(GPIO_LEDTypeDef *led)
|
||||
{
|
||||
led->state = LED_IS_OFF;
|
||||
HAL_GPIO_WritePin(led->LED_Port, led->LED_Pin, LED_OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Активировать моргание светодиодом
|
||||
*/
|
||||
void GPIO_LED_Blink_Start(GPIO_LEDTypeDef *led, uint32_t period)
|
||||
{
|
||||
led->state = LED_IS_BLINKING;
|
||||
led->LED_Period = period;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Моргание светодиодом
|
||||
*/
|
||||
void GPIO_LED_Blink_Handle(GPIO_LEDTypeDef *led)
|
||||
{
|
||||
if(led->state == LED_IS_BLINKING)
|
||||
{
|
||||
uint32_t tickcurrent = HAL_GetTick();
|
||||
if((tickcurrent - led->tickprev) > led->LED_Period)
|
||||
{
|
||||
HAL_GPIO_TogglePin(led->LED_Port, led->LED_Pin);
|
||||
led->tickprev = tickcurrent;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------GPIO LED FUNCTIONS-------------------------
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
//------------------------GPIO SW FUNCTIONS-------------------------
|
||||
|
||||
/**
|
||||
* @brief Считать состоянии кнопки запуска
|
||||
*/
|
||||
uint8_t GPIO_Read_Swich(GPIO_SwitchTypeDef *sw)
|
||||
{
|
||||
|
||||
if(HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == SW_ON)
|
||||
{
|
||||
sw->Sw_PrevState = 1;
|
||||
|
||||
if(sw->tickprev == 0)
|
||||
sw->tickprev = HAL_GetTick();
|
||||
|
||||
if((HAL_GetTick() - sw->tickprev) > sw->Sw_FilterDelay)
|
||||
{
|
||||
if(HAL_GPIO_ReadPin(sw->Sw_Port, sw->Sw_Pin) == SW_ON)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sw->tickprev = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sw->Sw_PrevState = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//------------------------GPIO SW FUNCTIONS-------------------------
|
||||
//-------------------------------------------------------------------
|
||||
88
py_project/Core/MyLibs/general_gpio.h
Normal file
88
py_project/Core/MyLibs/general_gpio.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file general_gpio.h
|
||||
* @brief Заголовочный файл для модуля инициализации портов.
|
||||
*************************************************************************/
|
||||
#ifndef __GPIO_GENERAL_H_
|
||||
#define __GPIO_GENERAL_H_
|
||||
|
||||
#include "mylibs_defs.h"
|
||||
|
||||
|
||||
#define SPI_Alternate_Mapping(INSTANCE) ((((INSTANCE) == TIM1) || ((INSTANCE) == TIM2))? GPIO_AF1_TIM1: \
|
||||
(((INSTANCE) == TIM3) || ((INSTANCE) == TIM4) || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3: \
|
||||
(((INSTANCE) == TIM8) || ((INSTANCE) == TIM9) || ((INSTANCE) == TIM10) || ((INSTANCE) == TIM11))? GPIO_AF3_TIM8: \
|
||||
(((INSTANCE) == TIM12) || ((INSTANCE) == TIM13) || ((INSTANCE) == TIM14))? GPIO_AF9_TIM12: \
|
||||
(0))
|
||||
|
||||
|
||||
#define TIM_Alternate_Mapping(INSTANCE) ((((INSTANCE) == TIM1) || ((INSTANCE) == TIM2))? GPIO_AF1_TIM1: \
|
||||
(((INSTANCE) == TIM3) || ((INSTANCE) == TIM4) || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3: \
|
||||
(((INSTANCE) == TIM8) || ((INSTANCE) == TIM9) || ((INSTANCE) == TIM10) || ((INSTANCE) == TIM11))? GPIO_AF3_TIM8: \
|
||||
(((INSTANCE) == TIM12) || ((INSTANCE) == TIM13) || ((INSTANCE) == TIM14))? GPIO_AF9_TIM12: \
|
||||
(0))
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LED_IS_OFF = 0,
|
||||
LED_IS_ON = 1,
|
||||
LED_IS_BLINKING = 2,
|
||||
LED_IS_FADING = 3,
|
||||
}GPIO_LEDStateTypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GPIO_LEDStateTypeDef state;
|
||||
|
||||
GPIO_TypeDef *LED_Port;
|
||||
uint32_t LED_Pin;
|
||||
|
||||
uint32_t LED_Period;
|
||||
uint32_t tickprev;
|
||||
}GPIO_LEDTypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GPIO_TypeDef *Sw_Port;
|
||||
uint32_t Sw_Pin;
|
||||
|
||||
uint32_t Sw_PrevState;
|
||||
uint32_t Sw_FilterDelay;
|
||||
uint32_t tickprev;
|
||||
}GPIO_SwitchTypeDef;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////---FUNCTIONS---///////////////////////////
|
||||
HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx);
|
||||
|
||||
/* Считать состоянии кнопки запуска */
|
||||
uint8_t GPIO_Read_Swich(GPIO_SwitchTypeDef *swstart);
|
||||
/* Включить светодиод */
|
||||
void GPIO_LED_On(GPIO_LEDTypeDef *led);
|
||||
/* Выключить светодиод */
|
||||
void GPIO_LED_Off(GPIO_LEDTypeDef *led);
|
||||
/* Активировать моргание светодиодом */
|
||||
void GPIO_LED_Blink_Start(GPIO_LEDTypeDef *led, uint32_t period);
|
||||
/* Моргание светодиодом */
|
||||
void GPIO_LED_Blink_Handle(GPIO_LEDTypeDef *led);
|
||||
///////////////////////////---FUNCTIONS---///////////////////////////
|
||||
|
||||
|
||||
#ifndef LED_ON
|
||||
#define LED_ON 0
|
||||
#endif
|
||||
|
||||
#ifndef LED_0FF
|
||||
#define LED_OFF 1
|
||||
#endif
|
||||
|
||||
#ifndef SW_ON
|
||||
#define SW_ON 0
|
||||
#endif
|
||||
|
||||
#ifndef SW_0FF
|
||||
#define SW_OFF 1
|
||||
#endif
|
||||
|
||||
#endif // __GPIO_GENERAL_H_
|
||||
35
py_project/Core/MyLibs/mylibs_config.h
Normal file
35
py_project/Core/MyLibs/mylibs_config.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file mylibs_config.h
|
||||
* @brief Конфигурации для библиотек MyLibs
|
||||
**************************************************************************
|
||||
* @defgroup MYLIBS_CONFIG Configs My Libs
|
||||
* @ingroup MYLIBS_ALL
|
||||
* @brief Конфигурации для библиотек MyLibs
|
||||
@{
|
||||
*************************************************************************/
|
||||
#ifndef __MYLIBS_CONFIG_H_
|
||||
#define __MYLIBS_CONFIG_H_
|
||||
|
||||
#include "py32f0xx_hal.h"
|
||||
|
||||
// user includes
|
||||
#include "interface_config.h"
|
||||
|
||||
|
||||
#define RS_USER_VARS_NUMB 0
|
||||
#define ADC_USER_VARS_NUMB 0
|
||||
#define ADC_CH_USER_VARS_NUMB 0
|
||||
|
||||
|
||||
#define INCLUDE_BIT_ACCESS_LIB
|
||||
#define INCLUDE_TRACKERS_LIB
|
||||
#define INCLUDE_TRACE_LIB
|
||||
//#define INCLUDE_GENERAL_PERIPH_LIBS
|
||||
//#define FREERTOS_DELAY
|
||||
|
||||
|
||||
/** MYLIBS_CONFIG
|
||||
* @}
|
||||
*/
|
||||
#endif //__MYLIBS_CONFIG_H_
|
||||
105
py_project/Core/MyLibs/mylibs_defs.h
Normal file
105
py_project/Core/MyLibs/mylibs_defs.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file mylibs_defs.h
|
||||
* @brief Заголочный файл для дефайнов библиотеки MyLibsGeneral.
|
||||
**************************************************************************
|
||||
* @defgroup MYLIBS_DEFINES My Libs defines
|
||||
* @brief Базовые дефайны для всего проекта
|
||||
*
|
||||
*************************************************************************/
|
||||
#ifndef __MYLIBS_DEFINES_H_
|
||||
#define __MYLIBS_DEFINES_H_
|
||||
|
||||
#include "mylibs_config.h"
|
||||
|
||||
/***************************************************************************
|
||||
******************************ERROR_HANDLER********************************/
|
||||
/**
|
||||
* @addtogroup ERROR_HANDLER_DEFINES Error Handler defines
|
||||
* @ingroup MYLIBS_DEFINES
|
||||
* @brief Дефайны для определения функции обработки ошибок
|
||||
@{
|
||||
*/
|
||||
|
||||
/* extern Error_Handler from main.h */
|
||||
extern void Error_Handler(void);
|
||||
|
||||
/* Define error handler for MyLibs */
|
||||
#define MyLibs_Error_Handler(_params_) Error_Handler(_params_)
|
||||
/* If error handler not defined - set void */
|
||||
#ifndef MyLibs_Error_Handler
|
||||
#define ((void)0U)
|
||||
#endif // MyLibs_Error_Handler
|
||||
|
||||
/** ERROR_HANDLER_DEFINES
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
********************************ACCESS_DEFINES*****************************/
|
||||
|
||||
#define ClearStruct(_struct_) memset(&(_struct_), 0, sizeof(_struct_))
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
******************************DELAYS_DEFINES*******************************/
|
||||
/**
|
||||
* @addtogroup DELAYS_DEFINES Delays defines
|
||||
* @ingroup MYLIBS_DEFINES
|
||||
* @brief Дефайны для реализации задержек
|
||||
@{
|
||||
*/
|
||||
|
||||
#ifdef FREERTOS_DELAY
|
||||
#define msDelay(_ms_) osDelay(_ms_)
|
||||
#else
|
||||
#define msDelay(_ms_) if(_ms_ != 0) HAL_Delay(_ms_-1)
|
||||
#endif
|
||||
|
||||
/** DELAYS_DEFINES
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*******************************MATH_DEFINES********************************/
|
||||
/**
|
||||
* @addtogroup MATH_DEFINES Math defines
|
||||
* @ingroup MYLIBS_DEFINES
|
||||
* @brief Дефайны для различных математических функций
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Calc dividing including remainder
|
||||
* @param _val_ - делимое.
|
||||
* @param _div_ - делитель.
|
||||
* @details Если результат деления без остатка: он возвращается как есть
|
||||
Если с остатком - округляется вверх
|
||||
*/
|
||||
//#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */
|
||||
#define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */
|
||||
|
||||
/**
|
||||
* @brief Swap between Little Endian and Big Endian
|
||||
* @param v - Переменная для свапа.
|
||||
* @return v (new) - Свапнутая переменная.
|
||||
* @details Переключения между двумя типами хранения слова: HI-LO байты и LO-HI байты.
|
||||
*/
|
||||
#define ByteSwap16(v) (((v&0xFF00) >> (8)) | ((v&0x00FF) << (8)))
|
||||
|
||||
/**
|
||||
* @brief Absolute
|
||||
* @param x - Переменная для модудя.
|
||||
* @return x (new) - Число по модулю.
|
||||
* @details Берет число по модулю. Хз как работает библиотечный abs в stdlib.h, мб это быстрее, но вряд ли конечно.
|
||||
*/
|
||||
#define ABS(x) ( ((x) > 0)? (x) : -(x))?
|
||||
|
||||
/** MATH_DEFINES
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif //__MYLIBS_DEFINES_H_
|
||||
80
py_project/Core/MyLibs/mylibs_include.h
Normal file
80
py_project/Core/MyLibs/mylibs_include.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file mylibs_include.h
|
||||
* @brief Заголочный файл для всех библиотек
|
||||
**************************************************************************
|
||||
@details
|
||||
Здесь нужно собрать библиотеки и дефайны, которые должны быть видны во всем проекте,
|
||||
чтобы не подключать 100 инклюдов в каждом ".c" файле
|
||||
**************************************************************************
|
||||
* @defgroup MYLIBS_ALL My Libs
|
||||
* @brief Все используемые MyLibs библиотеки
|
||||
*
|
||||
*************************************************************************/
|
||||
#ifndef __MYLIBS_INCLUDE_H_
|
||||
#define __MYLIBS_INCLUDE_H_
|
||||
|
||||
#include "mylibs_defs.h"
|
||||
|
||||
|
||||
#ifdef ARM_MATH_CM4
|
||||
#include "arm_math.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef INCLUDE_BIT_ACCESS_LIB
|
||||
#include "bit_access.h"
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_TRACKERS_LIB
|
||||
#include "trackers.h"
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_TRACE_LIB
|
||||
#include "trace.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
|
||||
|
||||
#include "general_flash.h"
|
||||
#include "general_gpio.h"
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
#include "general_spi.h"
|
||||
#endif
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
#include "general_uart.h"
|
||||
#endif
|
||||
#ifdef HAL_TIM_MODULE_ENABLED
|
||||
#include "general_tim.h"
|
||||
#endif
|
||||
|
||||
#endif //INCLUDE_GENERAL_PERIPH_LIBS
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////---USER SETTINGS---/////////////////////////
|
||||
// user includes
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "math.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "modbus_data.h"
|
||||
#include "general_gpio.h"
|
||||
|
||||
/** @brief Struct for trackers for Measure */
|
||||
/** @brief Struct for trackers for RS */
|
||||
typedef TrackerTypeDef(RS_USER_VARS_NUMB) RS_TrackerTypeDef;
|
||||
/** @brief Struct for trackers for ADC */
|
||||
typedef TrackerTypeDef(ADC_USER_VARS_NUMB) ADC_TrackerTypeDef;
|
||||
/** @brief Struct for trackers for ADC Channel */
|
||||
typedef TrackerTypeDef(ADC_CH_USER_VARS_NUMB) ADCChannel_TrackerTypeDef;
|
||||
/////////////////////////---USER SETTINGS---/////////////////////////
|
||||
|
||||
|
||||
#endif // __MYLIBS_INCLUDE_H_
|
||||
|
||||
80
py_project/Core/MyLibs/trace.h
Normal file
80
py_project/Core/MyLibs/trace.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file trace.h
|
||||
* @brief Заголочный файл для работы с трассировкой.
|
||||
**************************************************************************
|
||||
* @addtogroup TRACE Trace defines
|
||||
* @ingroup MYLIBS_DEFINES
|
||||
* @brief Дефайны для работы с трассировкой
|
||||
*************************************************************************/
|
||||
#ifndef __TRACE_H_
|
||||
#define __TRACE_H_
|
||||
#include "mylibs_defs.h"
|
||||
|
||||
/**
|
||||
* @addtogroup TRACE_SERIAL Serial trace defines
|
||||
* @ingroup TRACE
|
||||
* @brief Дефайны для работы с serial трассировкой
|
||||
* @details Определяется дефайн my_printf() для работы с serial трассировкой:
|
||||
- для RTT это будет вызов функции SEGGER_RTT_printf(), с подключением библиотеки SEGGER_RTT.h
|
||||
- для SWO это будет просто printf(), но библиотеку STDOUT надо подключить самостоятельно:
|
||||
|
||||
@verbatim
|
||||
Manage Run-Time Environment -> Compiler -> I/O -> STDOUT
|
||||
@endverbatim
|
||||
|
||||
- Если трассировка отключена, то все дефайны определяются как 'ничего' и на производительность кода не влияют
|
||||
@{
|
||||
*/
|
||||
/* Выбор какой serial trace использовать */
|
||||
#ifdef SERIAL_TRACE_ENABLE
|
||||
|
||||
#if defined(RTT_TRACE_ENABLE)
|
||||
#undef SWO_TRACE_ENABLE
|
||||
#include "SEGGER_RTT.h"
|
||||
#define my_printf(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#elif defined(SWO_TRACE_ENABLE)
|
||||
#undef RTT_TRACE_ENABLE
|
||||
#define my_printf(...) printf(__VA_ARGS__)
|
||||
#else // NO_TRACE
|
||||
#define my_printf(...)
|
||||
#warning No trace is selected. Serial debug wont work.
|
||||
#endif // RTT_TRACE_ENABLE/SWO_TRACE_ENABLE/NO_TRACE
|
||||
#else //SERIAL_TRACE_ENABLE
|
||||
#define my_printf(...)
|
||||
#undef RTT_TRACE_ENABLE
|
||||
#undef SWO_TRACE_ENABLE
|
||||
|
||||
#endif //SERIAL_TRACE_ENABLE
|
||||
|
||||
/** TRACE_SERIAL
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup TRACE_GPIO GPIO trace defines
|
||||
* @ingroup TRACE
|
||||
* @brief Дефайны для работы с GPIO трассировкой
|
||||
* @details Определяется дефайны для работы с GPIO трассировкой:
|
||||
- TRACE_GPIO_RESET() - для сброса ножки GPIO (через BSRR)
|
||||
- TRACE_GPIO_SET() - для выставления ножки GPIO (через BSRR)
|
||||
|
||||
- Если трассировка отключена, то все дефайны определяются как 'ничего' и на производительность кода не влияют
|
||||
@{
|
||||
*/
|
||||
#ifndef GPIO_TRACE_ENABLE
|
||||
#define TRACE_GPIO_RESET(_gpio_,_pin_)
|
||||
#define TRACE_GPIO_SET(_gpio_,_pin_)
|
||||
#else
|
||||
#define TRACE_GPIO_RESET(_gpio_,_pin_) (_gpio_)->BSRR = ((_pin_)<<16)
|
||||
#define TRACE_GPIO_SET(_gpio_,_pin_) (_gpio_)->BSRR = (((_pin_)))
|
||||
#endif //GPIO_TRACE_ENABLE
|
||||
|
||||
|
||||
/** TRACE_GPIO
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif //__TRACE_H_
|
||||
141
py_project/Core/MyLibs/trackers.h
Normal file
141
py_project/Core/MyLibs/trackers.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file mylibs_defs.h
|
||||
* @brief Заголочный файл для дефайнов библиотеки MyLibsGeneral.
|
||||
**************************************************************************
|
||||
* @defgroup MYLIBS_DEFINES My Libs defines
|
||||
* @brief Базовые дефайны для всего проекта
|
||||
*
|
||||
*************************************************************************/
|
||||
#ifndef __TRACKERS_H_
|
||||
#define __TRACKERS_H_
|
||||
#include "mylibs_defs.h"
|
||||
|
||||
/**
|
||||
* @addtogroup TRACKERS Trackers defines
|
||||
* @ingroup MYLIBS_DEFINES
|
||||
* @brief Дефайны для работы с трекерами
|
||||
* @details Есть дефайн для объявления структуры трекера: TrackerTypeDef(num_user_vars).
|
||||
Структура состоит из следующих элементов:
|
||||
- cnt_ok
|
||||
- cnt_err
|
||||
- cnt_warn
|
||||
- user[num_user_vars]
|
||||
Также есть ряд функций (дефайнов) для обращения к элементам этой структуры.
|
||||
|
||||
|
||||
Если трассировка отключена, то все дефайны определяются как ничего и на производительность кода не влияют
|
||||
|
||||
@par Пример:
|
||||
Определяем typedef трекера измерений @ref Measure_TrackerTypeDef
|
||||
|
||||
@verbatim
|
||||
typedef TrackerTypeDef(MEASURE_USER_VARS_NUMB) Measure_TrackerTypeDef;
|
||||
@endverbatim
|
||||
|
||||
И через @ref Measure_TrackerTypeDef структура подключается в @ref TESTER_MeasureHandleTypeDef, а также
|
||||
если необхожимо в другие структуру, например в структуру всех ошибок через указатель @ref TESTER_TrackerTypeDef
|
||||
|
||||
@{
|
||||
*/
|
||||
|
||||
#ifdef TRACKERS_ENABLE
|
||||
/**
|
||||
* @brief Структура для счетчиков отладки
|
||||
* @param num_user_vars - количество пользовательских счетчиков
|
||||
* @details Содержит счетчик для успешных событый (cnt_ok),
|
||||
* счетчик для ошибок (cnt_err), счетчик для предупреждений (cnt_warn).
|
||||
*
|
||||
* Также есть возможность объявить пользовательские счетчики в
|
||||
* количестве <num_user_vars> штук.
|
||||
*
|
||||
* Для работы с структурой можно использовать функции:
|
||||
* - TrackerCnt_Ok()
|
||||
* - TrackerCnt_Err()
|
||||
* - TrackerCnt_Warn()
|
||||
* - TrackerCnt_User()
|
||||
* - TrackerWrite_User()
|
||||
* - TrackerClear_All()
|
||||
* - TrackerClear_Ok()
|
||||
* - TrackerClear_Err()
|
||||
* - TrackerClear_Warn()
|
||||
* - TrackerClear_User()
|
||||
* - TrackerClear_UserAll()
|
||||
*/
|
||||
#define TrackerTypeDef(num_user_vars) \
|
||||
struct \
|
||||
{ \
|
||||
uint32_t cnt_ok; \
|
||||
uint32_t cnt_err; \
|
||||
uint32_t cnt_warn; \
|
||||
uint32_t user[num_user_vars]; \
|
||||
}
|
||||
|
||||
/** @brief Получить количетство пользовательских переменных */
|
||||
#define num_of_usercnts(_user_) (sizeof(_user_) / sizeof(_user_[0]))
|
||||
/** @brief Проверка существует ли указанная пользовательская переменная */
|
||||
#define assert_usertracker(_cntstruct_, _uservarnumb_) ((_uservarnumb_) < num_of_usercnts((_cntstruct_).user))
|
||||
/** @brief Условие для проверки существует ли указанная пользовательская переменная */
|
||||
#define if_assert_usertracker(_cntstruct_, _uservarnumb_) if(assert_usertracker(_cntstruct_, _uservarnumb_))
|
||||
/** @brief Тернарный оператор для проверки существует ли указанная пользовательская переменная */
|
||||
#define tern_assert_usertracker(_cntstruct_, _uservarnumb_) (assert_usertracker(_cntstruct_, _uservarnumb_)) ? _uservarnumb_ : 0
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Запись числа в пользовательскую переменную
|
||||
* @note Здесь нет проверки - существует ли пользовательская переменная!
|
||||
* Есть возможность выйти за границы структуры!!!
|
||||
* Чтобы этого избежать используете дефайн #ref assert_usertracker()
|
||||
*/
|
||||
#define TrackerGet_User(_cntstruct_, _uservarnumb_) (_cntstruct_).user[tern_assert_usertracker(_cntstruct_, _uservarnumb_)]
|
||||
|
||||
|
||||
|
||||
/** @brief Инкрементирование счетчика успешных событий */
|
||||
#define TrackerCnt_Ok(_cntstruct_) (_cntstruct_).cnt_ok++
|
||||
/** @brief Инкрементирование счетчика ошибок */
|
||||
#define TrackerCnt_Err(_cntstruct_) (_cntstruct_).cnt_err++
|
||||
/** @brief Инкрементирование счетчика предупреждений */
|
||||
#define TrackerCnt_Warn(_cntstruct_) (_cntstruct_).cnt_warn++
|
||||
/** @brief Инкрементирование пользовательской переменной */
|
||||
#define TrackerCnt_User(_cntstruct_, _uservarnumb_) if_assert_usertracker(_cntstruct_, _uservarnumb_) (_cntstruct_).user[_uservarnumb_]++;
|
||||
/** @brief Запись числа в пользовательскую переменную */
|
||||
#define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_) if_assert_usertracker(_cntstruct_, _uservarnumb_) (_cntstruct_).user[_uservarnumb_] = (_val_)
|
||||
|
||||
/** @brief Очистка всей структуры */
|
||||
#define TrackerClear_All(_cntstruct_) memset(&(_cntstruct_), 0, sizeof(_cntstruct_))
|
||||
/** @brief Очистка счетчика успешных событий */
|
||||
#define TrackerClear_Ok(_cntstruct_) (_cntstruct_).cnt_ok = 0
|
||||
/** @brief Очистка счетчика ошибок */
|
||||
#define TrackerClear_Err(_cntstruct_) (_cntstruct_).cnt_err = 0
|
||||
/** @brief Очистка счетчика предупреждений */
|
||||
#define TrackerClear_Warn(_cntstruct_) (_cntstruct_).cnt_warn = 0
|
||||
/** @brief Очистка пользовательской переменной */
|
||||
#define TrackerClear_User(_cntstruct_, _uservarnumb_) if_assert_usertracker(_cntstruct_, _uservarnumb_) (_cntstruct_).user[_uservarnumb_] = 0;
|
||||
/** @brief Очистка всех пользовательских переменных */
|
||||
#define TrackerClear_UserAll(_cntstruct_) memset(&(_cntstruct_).user, 0, sizeof((_cntstruct_).user))
|
||||
|
||||
#else //TRACKERS_ENABLE
|
||||
#define TrackerTypeDef(num_user_vars) void *
|
||||
|
||||
#define num_of_usercnts(_user_)
|
||||
#define assert_tracecnt(_cntstruct_, _uservarnumb_)
|
||||
|
||||
#define TrackerCnt_Ok(_cntstruct_)
|
||||
#define TrackerCnt_Err(_cntstruct_)
|
||||
#define TrackerCnt_Warn(_cntstruct_)
|
||||
#define TrackerCnt_User(_cntstruct_, _uservarnumb_)
|
||||
#define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_)
|
||||
|
||||
/** @brief Очистка всей структуры */
|
||||
#define TrackerClear_All(_cntstruct_)
|
||||
#define TrackerClear_Ok(_cntstruct_)
|
||||
#define TrackerClear_Err(_cntstruct_)
|
||||
#define TrackerClear_Warn(_cntstruct_)
|
||||
#define TrackerClear_User(_cntstruct_)
|
||||
#define TrackerClear_UserAll(_cntstruct_)
|
||||
|
||||
#endif //TRACKERS_ENABLE
|
||||
|
||||
#endif //__TRACKERS_H_
|
||||
392
py_project/Core/PY32Module/PY32module_main.c
Normal file
392
py_project/Core/PY32Module/PY32module_main.c
Normal file
@@ -0,0 +1,392 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file pch_sensors.c
|
||||
* @brief Работа с датчиками температуры DS18B20 в ПЧ
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/* Includes ----------------------------------------------------------------*/
|
||||
|
||||
#include "PY32module_main.h"
|
||||
#include "rs_message.h"
|
||||
|
||||
/* Declarations and definitions --------------------------------------------*/
|
||||
PCHSens_TypeDef pchsens;
|
||||
PCHSens_DallasBusHandle DallasBus;
|
||||
static uint8_t scan_cnt;
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
void PYModule_FillResponse(PCHSens_SensorTypeDef* sensor, Sensor_ResponseStatusTypeDef status);
|
||||
void PYModule_CheckModuleLosted(PCHSens_ModuleTypeDef *module, uint8_t *losted_flag);
|
||||
void PYModule_StoreModuleToModbus(PCHSens_ModuleTypeDef *module);
|
||||
|
||||
void PYModule_main(void)
|
||||
{
|
||||
|
||||
if(MB_DATA.Coils.RunConvertions)
|
||||
{
|
||||
if(DS18B20_WaitForEndConvertion_NonBlocking(hdallas1.onewire) == HAL_OK)
|
||||
{
|
||||
PCHSens_StartCovert(&DallasBus);
|
||||
GPIOA->ODR ^= GPIO_LED_2;
|
||||
}
|
||||
}
|
||||
|
||||
if(MB_DATA.Coils.ReadSensor)
|
||||
{
|
||||
PYModule_ReadSensor(&hdallas1, &pchsens);
|
||||
MB_DATA.Coils.ReadSensor = 0;
|
||||
}
|
||||
|
||||
// if(MB_DATA.Coils.ScanSensors)
|
||||
// {
|
||||
// PYModule_ScanSensor(&DallasBus);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// scan_cnt = 0;
|
||||
// }
|
||||
|
||||
if(MB_DATA.Coils.InitSensor)
|
||||
{
|
||||
PYModule_InitSensor(&pchsens);
|
||||
MB_DATA.Coils.InitSensor = 0;
|
||||
}
|
||||
|
||||
if(MB_DATA.Coils.DeInitSensor != NULL)
|
||||
{
|
||||
PYModule_DeInitSensor(&pchsens);
|
||||
MB_DATA.Coils.DeInitSensor = 0;
|
||||
}
|
||||
|
||||
PYModule_CheckLosted(&pchsens);
|
||||
|
||||
if(MB_DATA.Coils.RunConvertions)
|
||||
{
|
||||
if(DS18B20_WaitForEndConvertion_NonBlocking(hdallas1.onewire) == HAL_OK)
|
||||
{
|
||||
PCHSens_ModuleReadTemperature(&pchsens.module1);
|
||||
// PCHSens_ModuleReadTemperature(&pchsens.module2);
|
||||
// PCHSens_ModuleReadTemperature(&pchsens.module3);
|
||||
// PCHSens_ModuleReadTemperature(&pchsens.module4);
|
||||
// PCHSens_ModuleReadTemperature(&pchsens.module5);
|
||||
// PCHSens_ModuleReadTemperature(&pchsens.module6);
|
||||
|
||||
PYModule_StoreModbus(&pchsens);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PYModule_FirstInit(void)
|
||||
{
|
||||
OW.DataPin = DS_Pin;
|
||||
OW.DataPort = DS_GPIO_Port;
|
||||
|
||||
/* Инициализация onewire и поиск датчиков*/
|
||||
DS = (DS18B20_Drv_t *)&MB_DATA.InRegs.AllROMs;
|
||||
OneWire_Init(&OW);
|
||||
DS18B20_Search(DS, &OW);
|
||||
|
||||
|
||||
/* Инициализация modbus */
|
||||
MODBUS_FirstInit();
|
||||
RS_Receive_IT(&hmodbus1, &MODBUS_MSG);
|
||||
|
||||
/* Инициализация структур датчиков ПЧ */
|
||||
DallasBus.hdallas = &hdallas1;
|
||||
DallasBus.hdallas->onewire = &OW;
|
||||
DallasBus.hdallas->ds_devices = DS;
|
||||
PCHSens_InitModule(&hdallas1, &pchsens.module1, REG_PCH_NUMB_11|REG_PCH_DIODE_NUMB_1);
|
||||
// PCHSens_InitModule(&hdallas1, &pchsens.module2, REG_PCH_NUMB_12|REG_PCH_DIODE_NUMB_1);
|
||||
// PCHSens_InitModule(&hdallas1, &pchsens.module3, REG_PCH_NUMB_21|REG_PCH_DIODE_NUMB_1);
|
||||
// PCHSens_InitModule(&hdallas1, &pchsens.module4, REG_PCH_NUMB_22|REG_PCH_DIODE_NUMB_1);
|
||||
// PCHSens_InitModule(&hdallas1, &pchsens.module5, REG_PCH_NUMB_31|REG_PCH_DIODE_NUMB_1);
|
||||
// PCHSens_InitModule(&hdallas1, &pchsens.module6, REG_PCH_NUMB_32|REG_PCH_DIODE_NUMB_1);
|
||||
|
||||
/* Поиск неизвестных сенсоров */
|
||||
PCHSens_FindUnknownSensors(&DallasBus);
|
||||
|
||||
MB_DATA.Coils.RunConvertions = 1;
|
||||
}
|
||||
|
||||
|
||||
void PYModule_ScanSensor(PCHSens_DallasBusHandle *hbus)
|
||||
{
|
||||
PCHSens_SensorTypeDef sensor;
|
||||
sensor.sens.hdallas = hbus->hdallas;
|
||||
sensor.sens.sensROM = *(uint64_t *)(hbus->hdallas->ds_devices->DevAddr[scan_cnt]);
|
||||
if (scan_cnt >= hbus->hdallas->onewire->RomCnt)
|
||||
{
|
||||
scan_cnt = hbus->hdallas->onewire->RomCnt;
|
||||
PYModule_FillResponse(&sensor, STATUS_SCAN_END);
|
||||
return;
|
||||
}
|
||||
if(Dallas_ReadScratchpad(&sensor.sens) == HAL_OK)
|
||||
{
|
||||
PYModule_FillResponse(&sensor, STATUS_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
PYModule_FillResponse(&sensor, STATUS_ERR_SCAN);
|
||||
}
|
||||
}
|
||||
void PYModule_IncrementScanSensor(void)
|
||||
{
|
||||
if(MB_DATA.Coils.ScanSensors)
|
||||
{
|
||||
scan_cnt++;
|
||||
}
|
||||
}
|
||||
void PYModule_ReadSensor(DALLAS_HandleTypeDef *hdallas, PCHSens_TypeDef *pchsens)
|
||||
{
|
||||
// чтение по локации
|
||||
if(MB_DATA.HoldRegs.InitStruct.Location != 0) // если локация не равна нулю
|
||||
{
|
||||
PCHSens_SensorTypeDef *sensor;
|
||||
|
||||
if(PCHSens_GetSensorByLocation(pchsens, (PCHSens_LocationTypeDef)MB_DATA.HoldRegs.InitStruct.Location, &sensor) != HAL_OK)
|
||||
return;
|
||||
|
||||
if(Dallas_ReadScratchpad(&sensor->sens) == HAL_OK)
|
||||
{
|
||||
PYModule_FillResponse(sensor, STATUS_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
PYModule_FillResponse(sensor, STATUS_ERR_READ_LOCATION);
|
||||
}
|
||||
}
|
||||
// чтение по ROM
|
||||
else if(MB_DATA.HoldRegs.InitStruct.ROM[0] | MB_DATA.HoldRegs.InitStruct.ROM[1] | // если РОМ не равен нулю
|
||||
MB_DATA.HoldRegs.InitStruct.ROM[2] | MB_DATA.HoldRegs.InitStruct.ROM[3] != 0)
|
||||
{
|
||||
PCHSens_SensorTypeDef sensor;
|
||||
sensor.sens.hdallas = hdallas;
|
||||
sensor.sens.sensROM = *(uint64_t *)MB_DATA.HoldRegs.InitStruct.ROM;
|
||||
|
||||
if(Dallas_ReadScratchpad(&sensor.sens) == HAL_OK)
|
||||
{
|
||||
PYModule_FillResponse(&sensor, STATUS_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
PYModule_FillResponse(&sensor, STATUS_ERR_READ_ROM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PYModule_InitSensor(PCHSens_TypeDef *pchsens)
|
||||
{
|
||||
if( (MB_DATA.HoldRegs.InitStruct.Location != 0) && // если локация не равна нулю
|
||||
(MB_DATA.HoldRegs.InitStruct.ROM[0] | MB_DATA.HoldRegs.InitStruct.ROM[1] | // И если РОМ не равен нулю
|
||||
MB_DATA.HoldRegs.InitStruct.ROM[2] | MB_DATA.HoldRegs.InitStruct.ROM[3] != 0) )
|
||||
{
|
||||
PCHSens_SensorTypeDef *sensor;
|
||||
|
||||
if(PCHSens_GetSensorByLocation(pchsens, (PCHSens_LocationTypeDef)MB_DATA.HoldRegs.InitStruct.Location, &sensor) != HAL_OK)
|
||||
return;
|
||||
uint64_t connectROM = 0;
|
||||
connectROM = ((uint64_t)(__REV16(MB_DATA.HoldRegs.InitStruct.ROM[0])))<<48;
|
||||
connectROM |= ((uint64_t)(__REV16(MB_DATA.HoldRegs.InitStruct.ROM[1])))<<32;
|
||||
connectROM |= ((uint64_t)(__REV16(MB_DATA.HoldRegs.InitStruct.ROM[2])))<<16;
|
||||
connectROM |= ((uint64_t)(__REV16(MB_DATA.HoldRegs.InitStruct.ROM[3])));
|
||||
|
||||
if(PCHSens_InitNewSensor(&hdallas1, sensor, connectROM) == HAL_OK)
|
||||
{
|
||||
PYModule_FillResponse(sensor, STATUS_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
PYModule_FillResponse(sensor, STATUS_ERR_INIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PYModule_DeInitSensor(PCHSens_TypeDef *pchsens)
|
||||
{
|
||||
if(MB_DATA.HoldRegs.InitStruct.Location != 0) // если локация не равна нулю
|
||||
{
|
||||
PCHSens_SensorTypeDef *sensor;
|
||||
|
||||
if(PCHSens_GetSensorByLocation(pchsens, (PCHSens_LocationTypeDef)MB_DATA.HoldRegs.InitStruct.Location, &sensor) != HAL_OK)
|
||||
return;
|
||||
|
||||
if(PCHSens_UndefineSensor(sensor) == HAL_OK)
|
||||
{
|
||||
PYModule_FillResponse(sensor, STATUS_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
PYModule_FillResponse(sensor, STATUS_ERR_DEINIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PYModule_CheckLosted(PCHSens_TypeDef *pchsens)
|
||||
{
|
||||
uint8_t losted = 0;
|
||||
|
||||
// module1
|
||||
PYModule_CheckModuleLosted(&pchsens->module1, &losted);
|
||||
PYModule_CheckModuleLosted(&pchsens->module2, &losted);
|
||||
PYModule_CheckModuleLosted(&pchsens->module3, &losted);
|
||||
PYModule_CheckModuleLosted(&pchsens->module4, &losted);
|
||||
PYModule_CheckModuleLosted(&pchsens->module5, &losted);
|
||||
PYModule_CheckModuleLosted(&pchsens->module6, &losted);
|
||||
|
||||
if(losted)
|
||||
MB_DATA.Coils.LostedSensors = 1;
|
||||
else
|
||||
MB_DATA.Coils.LostedSensors = 0;
|
||||
}
|
||||
|
||||
void PYModule_StoreModbus(PCHSens_TypeDef *pchsens)
|
||||
{
|
||||
uint8_t losted = 0;
|
||||
|
||||
// module1
|
||||
PYModule_StoreModuleToModbus(&pchsens->module1);
|
||||
PYModule_StoreModuleToModbus(&pchsens->module2);
|
||||
PYModule_StoreModuleToModbus(&pchsens->module3);
|
||||
PYModule_StoreModuleToModbus(&pchsens->module4);
|
||||
PYModule_StoreModuleToModbus(&pchsens->module5);
|
||||
PYModule_StoreModuleToModbus(&pchsens->module6);
|
||||
|
||||
MB_DATA.Coils.ConvertionDone |= 1;
|
||||
}
|
||||
|
||||
void PYModule_FillResponse(PCHSens_SensorTypeDef* sensor, Sensor_ResponseStatusTypeDef status)
|
||||
{
|
||||
switch(status)
|
||||
{
|
||||
// successfull response
|
||||
case STATUS_OK:
|
||||
// fil with sensor data
|
||||
MB_DATA.InRegs.Response.Location = *(uint16_t *)&sensor->sens.hdallas->scratchpad.tHighRegister;
|
||||
MB_DATA.InRegs.Response.Config = sensor->sens.hdallas->scratchpad.ConfigRegister;
|
||||
MB_DATA.InRegs.Response.ROM[0] = __REV16((sensor->sens.sensROM) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.ROM[1] = __REV16((sensor->sens.sensROM >> 16) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.ROM[2] = __REV16((sensor->sens.sensROM >> 32) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.ROM[3] = __REV16((sensor->sens.sensROM >> 48) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.Status = status;
|
||||
break;
|
||||
|
||||
case STATUS_SCAN_END:
|
||||
MB_DATA.InRegs.Response.Location = 0;
|
||||
MB_DATA.InRegs.Response.Config = 0;
|
||||
MB_DATA.InRegs.Response.ROM[0] = 0;
|
||||
MB_DATA.InRegs.Response.ROM[1] = 0;
|
||||
MB_DATA.InRegs.Response.ROM[2] = 0;
|
||||
MB_DATA.InRegs.Response.ROM[3] = 0;
|
||||
MB_DATA.InRegs.Response.Status = status;
|
||||
break;
|
||||
|
||||
// error read by location
|
||||
case STATUS_ERR_READ_LOCATION:
|
||||
// fill only location from holdreg
|
||||
MB_DATA.InRegs.Response.Location = MB_DATA.HoldRegs.InitStruct.Location;
|
||||
MB_DATA.InRegs.Response.Config = 0;
|
||||
MB_DATA.InRegs.Response.ROM[0] = 0;
|
||||
MB_DATA.InRegs.Response.ROM[1] = 0;
|
||||
MB_DATA.InRegs.Response.ROM[2] = 0;
|
||||
MB_DATA.InRegs.Response.ROM[3] = 0;
|
||||
MB_DATA.InRegs.Response.Status = status;
|
||||
break;
|
||||
|
||||
// error read by ROM
|
||||
case STATUS_ERR_READ_ROM:
|
||||
// fill only ROM from holdreg
|
||||
MB_DATA.InRegs.Response.Location = 0;
|
||||
MB_DATA.InRegs.Response.Config = 0;
|
||||
MB_DATA.InRegs.Response.ROM[0] = MB_DATA.HoldRegs.InitStruct.ROM[0];
|
||||
MB_DATA.InRegs.Response.ROM[1] = MB_DATA.HoldRegs.InitStruct.ROM[1];
|
||||
MB_DATA.InRegs.Response.ROM[2] = MB_DATA.HoldRegs.InitStruct.ROM[2];
|
||||
MB_DATA.InRegs.Response.ROM[3] = MB_DATA.HoldRegs.InitStruct.ROM[3];
|
||||
MB_DATA.InRegs.Response.Status = status;
|
||||
break;
|
||||
|
||||
// error init
|
||||
case STATUS_ERR_INIT:
|
||||
// fill ROM and location from holdreg
|
||||
MB_DATA.InRegs.Response.Location = MB_DATA.HoldRegs.InitStruct.Location;
|
||||
MB_DATA.InRegs.Response.Config = 0;
|
||||
MB_DATA.InRegs.Response.ROM[0] = MB_DATA.HoldRegs.InitStruct.ROM[0];
|
||||
MB_DATA.InRegs.Response.ROM[1] = MB_DATA.HoldRegs.InitStruct.ROM[1];
|
||||
MB_DATA.InRegs.Response.ROM[2] = MB_DATA.HoldRegs.InitStruct.ROM[2];
|
||||
MB_DATA.InRegs.Response.ROM[3] = MB_DATA.HoldRegs.InitStruct.ROM[3];
|
||||
MB_DATA.InRegs.Response.Status = status;
|
||||
break;
|
||||
|
||||
// error deinit
|
||||
case STATUS_ERR_DEINIT:
|
||||
// fill with sensor data
|
||||
MB_DATA.InRegs.Response.Location = *(uint16_t *)&sensor->sens.hdallas->scratchpad.tHighRegister;
|
||||
MB_DATA.InRegs.Response.Config = sensor->sens.hdallas->scratchpad.ConfigRegister;
|
||||
MB_DATA.InRegs.Response.ROM[0] = __REV16((sensor->sens.sensROM) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.ROM[1] = __REV16((sensor->sens.sensROM >> 16) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.ROM[2] = __REV16((sensor->sens.sensROM >> 32) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.ROM[3] = __REV16((sensor->sens.sensROM >> 48) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.Status = status;
|
||||
break;
|
||||
|
||||
// error deinit
|
||||
case STATUS_ERR_SCAN:
|
||||
// fill with sensor data
|
||||
MB_DATA.InRegs.Response.Location = 0;
|
||||
MB_DATA.InRegs.Response.Config = 0;
|
||||
MB_DATA.InRegs.Response.ROM[0] = __REV16((sensor->sens.sensROM) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.ROM[1] = __REV16((sensor->sens.sensROM >> 16) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.ROM[2] = __REV16((sensor->sens.sensROM >> 32) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.ROM[3] = __REV16((sensor->sens.sensROM >> 48) & 0xFFFF);
|
||||
MB_DATA.InRegs.Response.Status = status;
|
||||
break;
|
||||
|
||||
default:
|
||||
MB_DATA.InRegs.Response.Location = 0;
|
||||
MB_DATA.InRegs.Response.Config = 0;
|
||||
MB_DATA.InRegs.Response.ROM[0] = 0;
|
||||
MB_DATA.InRegs.Response.ROM[1] = 0;
|
||||
MB_DATA.InRegs.Response.ROM[2] = 0;
|
||||
MB_DATA.InRegs.Response.ROM[3] = 0;
|
||||
MB_DATA.InRegs.Response.Status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void PYModule_CheckModuleLosted(PCHSens_ModuleTypeDef *module, uint8_t *losted_flag)
|
||||
{
|
||||
if(module->sens1.not_found)
|
||||
*losted_flag |= 1;
|
||||
if(module->sens2.not_found)
|
||||
*losted_flag |= 1;
|
||||
if(module->sens3.not_found)
|
||||
*losted_flag |= 1;
|
||||
if(module->sens4.not_found)
|
||||
*losted_flag |= 1;
|
||||
}
|
||||
void PYModule_StoreModuleToModbus(PCHSens_ModuleTypeDef *module)
|
||||
{
|
||||
uint8_t mb_location;
|
||||
uint8_t pch_numb = (module->refLocation.param.PCHdig1 - 1)*3 + (module->refLocation.param.PCHdig2 - 1);
|
||||
pch_numb *= 4;
|
||||
|
||||
mb_location = pch_numb + module->sens1.Location.param.Location;
|
||||
if (mb_location < DS18B20_DEVICE_AMOUNT)
|
||||
MB_DATA.InRegs.SensTemperature[mb_location] = module->sens1.sens.temperature*100;
|
||||
|
||||
mb_location = pch_numb + module->sens2.Location.param.Location;
|
||||
if (mb_location < DS18B20_DEVICE_AMOUNT)
|
||||
MB_DATA.InRegs.SensTemperature[mb_location] = module->sens2.sens.temperature*100;
|
||||
|
||||
mb_location = pch_numb + module->sens3.Location.param.Location;
|
||||
if (mb_location < DS18B20_DEVICE_AMOUNT)
|
||||
MB_DATA.InRegs.SensTemperature[mb_location] = module->sens3.sens.temperature*100;
|
||||
|
||||
mb_location = pch_numb + module->sens4.Location.param.Location;
|
||||
if (mb_location < DS18B20_DEVICE_AMOUNT)
|
||||
MB_DATA.InRegs.SensTemperature[mb_location] = module->sens4.sens.temperature*100;
|
||||
}
|
||||
|
||||
37
py_project/Core/PY32Module/PY32module_main.h
Normal file
37
py_project/Core/PY32Module/PY32module_main.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file pch_sensors.h
|
||||
* @brief Работа с датчиками температуры DS18B20 в ПЧ
|
||||
******************************************************************************
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef MODULE_MAIN_H
|
||||
#define MODULE_MAIN_H
|
||||
|
||||
/* Includes -----------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
#include "pch_sensors.h"
|
||||
#include "modbus_data.h"
|
||||
|
||||
/* Declarations and definitions ---------------------------------------------*/
|
||||
typedef enum
|
||||
{
|
||||
STATUS_OK = 0x01,
|
||||
STATUS_SCAN_END = 0x11,
|
||||
STATUS_ERR_READ_LOCATION = 0xF0,
|
||||
STATUS_ERR_READ_ROM = 0x0F,
|
||||
STATUS_ERR_INIT = 0xAA,
|
||||
STATUS_ERR_DEINIT = 0x55,
|
||||
STATUS_ERR_SCAN = 0xBB,
|
||||
}Sensor_ResponseStatusTypeDef;
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
void PYModule_main(void);
|
||||
void PYModule_FirstInit(void);
|
||||
void PYModule_ScanSensor(PCHSens_DallasBusHandle *hbus);
|
||||
void PYModule_ReadSensor(DALLAS_HandleTypeDef *hdallas, PCHSens_TypeDef *pchsens);
|
||||
void PYModule_InitSensor(PCHSens_TypeDef *pchsens);
|
||||
void PYModule_DeInitSensor(PCHSens_TypeDef *pchsens);
|
||||
void PYModule_CheckLosted(PCHSens_TypeDef *pchsens);
|
||||
void PYModule_StoreModbus(PCHSens_TypeDef *pchsens);
|
||||
#endif // #ifndef MODULE_MAIN_H
|
||||
272
py_project/Core/PY32Module/pch_sensors.c
Normal file
272
py_project/Core/PY32Module/pch_sensors.c
Normal file
@@ -0,0 +1,272 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file pch_sensors.c
|
||||
* @brief Работа с датчиками температуры DS18B20 в ПЧ
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/* Includes ----------------------------------------------------------------*/
|
||||
|
||||
#include "pch_sensors.h"
|
||||
#include "modbus_data.h"
|
||||
|
||||
/* Declarations and definitions --------------------------------------------*/
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
HAL_StatusTypeDef PCHSens_InitNewSensor(DALLAS_HandleTypeDef *hdallas, PCHSens_SensorTypeDef* sensor, uint64_t ROM)
|
||||
{
|
||||
DALLAS_SensorHandleTypeDef tempsens;
|
||||
HAL_StatusTypeDef result;
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
// sensor->UserBytes = (PCHSens_LocationTypeDef *)&sensor->sens.scratchpad.tHighRegister;
|
||||
|
||||
sensor->sens.Init.InitParam = ROM;
|
||||
sensor->sens.Init.init_func = &Dallas_SensorInitByROM;
|
||||
|
||||
result = Dallas_AddNewSensors(hdallas, &sensor->sens);
|
||||
if(result != HAL_OK)
|
||||
{
|
||||
sensor->not_found = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Dallas_WriteUserBytes(&sensor->sens, sensor->Location.all, sensor->Location.all, USED_USER_BYTES);
|
||||
if(result != HAL_OK)
|
||||
return result;
|
||||
|
||||
sensor->sens.Init.InitParam = sensor->Location.all;
|
||||
sensor->sens.Init.init_func = &Dallas_SensorInitByUserBytes;
|
||||
|
||||
result = Dallas_AddNewSensors(hdallas, &sensor->sens);
|
||||
if(result == HAL_OK)
|
||||
{
|
||||
sensor->not_found = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->not_found = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
HAL_StatusTypeDef PCHSens_AddSensor(DALLAS_HandleTypeDef *hdallas, PCHSens_SensorTypeDef* sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
sensor->sens.Init.InitParam = sensor->Location.all;
|
||||
|
||||
sensor->sens.Init.init_func = &Dallas_SensorInitByUserBytes;
|
||||
|
||||
result = Dallas_AddNewSensors(hdallas, &sensor->sens);
|
||||
|
||||
if(result == HAL_OK)
|
||||
{
|
||||
sensor->not_found = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->not_found = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef PCHSens_InitModule(DALLAS_HandleTypeDef *hdallas, PCHSens_ModuleTypeDef* module, uint16_t param)
|
||||
{
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
if(module == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
PCHSens_LocationTypeDef initlocation;
|
||||
initlocation.all = param;
|
||||
|
||||
module->hdallas = hdallas;
|
||||
module->refLocation = initlocation;
|
||||
|
||||
module->sens1.Location.all = module->refLocation.all;
|
||||
module->sens1.Location.param.Location = 0;
|
||||
PCHSens_AddSensor(hdallas, &module->sens1);
|
||||
|
||||
module->sens2.Location.all = module->refLocation.all;
|
||||
module->sens2.Location.param.Location = 1;
|
||||
PCHSens_AddSensor(hdallas, &module->sens2);
|
||||
|
||||
module->sens3.Location.all = module->refLocation.all;
|
||||
module->sens3.Location.param.Location = 2;
|
||||
PCHSens_AddSensor(hdallas, &module->sens3);
|
||||
|
||||
module->sens4.Location.all = module->refLocation.all;
|
||||
module->sens4.Location.param.Location = 3;
|
||||
PCHSens_AddSensor(hdallas, &module->sens4);
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
HAL_StatusTypeDef PCHSens_ModuleReadTemperature(PCHSens_ModuleTypeDef* module)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
if(module == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
result = PCHSens_SensorReadTemperature(module->hdallas, &module->sens1);
|
||||
result = PCHSens_SensorReadTemperature(module->hdallas, &module->sens2);
|
||||
result = PCHSens_SensorReadTemperature(module->hdallas, &module->sens3);
|
||||
result = PCHSens_SensorReadTemperature(module->hdallas, &module->sens4);
|
||||
|
||||
return result;
|
||||
}
|
||||
HAL_StatusTypeDef PCHSens_SensorReadTemperature(DALLAS_HandleTypeDef *hdallas, PCHSens_SensorTypeDef *sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
result = PCHSens_ReadTemperature(sensor);
|
||||
if(result != HAL_OK)
|
||||
PCHSens_CheckSensor(hdallas, sensor);
|
||||
|
||||
return result;
|
||||
}
|
||||
HAL_StatusTypeDef PCHSens_StartCovert(PCHSens_DallasBusHandle *hbus)
|
||||
{
|
||||
return Dallas_StartConvertTAll(hbus->hdallas, DALLAS_WAIT_NONE, 0);
|
||||
}
|
||||
HAL_StatusTypeDef PCHSens_ReadTemperature(PCHSens_SensorTypeDef* sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
if(sensor->sens.isInitialized == 0)
|
||||
return HAL_ERROR;
|
||||
|
||||
result = Dallas_ReadTemperature(&sensor->sens);
|
||||
|
||||
return result;
|
||||
}
|
||||
HAL_StatusTypeDef PCHSens_CheckSensor(DALLAS_HandleTypeDef *hdallas, PCHSens_SensorTypeDef* sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
unsigned unknow_sensors_flag = 0;
|
||||
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
if((sensor->sens.isLost == 1) || (sensor->sens.isInitialized == 0))
|
||||
{
|
||||
if(Dallas_ReplaceLostedSensor(&sensor->sens) == HAL_ERROR)
|
||||
{
|
||||
sensor->not_found = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->not_found = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor->not_found = 0;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
HAL_StatusTypeDef PCHSens_FindUnknownSensors(PCHSens_DallasBusHandle *hbus)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
if(hbus == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
hbus->UnknownCnt = 0;
|
||||
|
||||
PCHSens_LocationTypeDef *param = (PCHSens_LocationTypeDef *)&hbus->hdallas->scratchpad.tHighRegister;
|
||||
for(int i = 0; i < hbus->hdallas->onewire->RomCnt; i++)
|
||||
{
|
||||
/* Проверка присутствует ли выбранный датчик на линии */
|
||||
result = DS18B20_ReadScratchpad(hbus->hdallas->onewire, (uint8_t *)&hbus->hdallas->ds_devices->DevAddr[i], (uint8_t *)&hbus->hdallas->scratchpad);
|
||||
if(result != HAL_OK)
|
||||
__NOP();
|
||||
|
||||
if((IS_REG_SENS_LOCATION(param) == 0) ||
|
||||
(IS_REG_PCH_LOCATION(param) == 0) ||
|
||||
(IS_REG_PCH_NUMB(param) == 0) )
|
||||
{
|
||||
// unknowns->unknown_sensors[unknowns->UnknownCnt].Init.InitParam = i;
|
||||
// unknowns->unknown_sensors[unknowns->UnknownCnt].Init.init_func = &Dallas_SensorInitByInd;
|
||||
// result = Dallas_AddNewSensors(hbus, &unknowns->unknown_sensors[unknowns->UnknownCnt]);
|
||||
hbus->UnknownCnt++;
|
||||
if(result != HAL_OK)
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
HAL_StatusTypeDef PCHSens_UndefineSensor(PCHSens_SensorTypeDef *sensor)
|
||||
{
|
||||
HAL_StatusTypeDef result;
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
result = Dallas_WriteUserBytes(&sensor->sens, 0, 0, USED_USER_BYTES);
|
||||
if(result != HAL_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Dallas_SensorDeInit(&sensor->sens);
|
||||
return result;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef PCHSens_GetSensorByLocation(PCHSens_TypeDef *pchsens, PCHSens_LocationTypeDef Location, PCHSens_SensorTypeDef **sensor)
|
||||
{
|
||||
PCHSens_ModuleTypeDef *module;
|
||||
uint8_t pch_numb = (Location.param.PCHdig1 - 1)*3 + (Location.param.PCHdig2 - 1);
|
||||
|
||||
switch(pch_numb)
|
||||
{
|
||||
case 0:
|
||||
module = &pchsens->module1; break;
|
||||
case 1:
|
||||
module = &pchsens->module2; break;
|
||||
case 2:
|
||||
module = &pchsens->module3; break;
|
||||
case 3:
|
||||
module = &pchsens->module4; break;
|
||||
case 4:
|
||||
module = &pchsens->module5; break;
|
||||
case 5:
|
||||
module = &pchsens->module6; break;
|
||||
default:
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
switch(Location.param.Location)
|
||||
{
|
||||
case 0:
|
||||
*sensor = &module->sens1; break;
|
||||
case 1:
|
||||
*sensor = &module->sens2; break;
|
||||
case 2:
|
||||
*sensor = &module->sens3; break;
|
||||
case 3:
|
||||
*sensor = &module->sens4; break;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
179
py_project/Core/PY32Module/pch_sensors.h
Normal file
179
py_project/Core/PY32Module/pch_sensors.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file pch_sensors.h
|
||||
* @brief Работа с датчиками температуры DS18B20 в ПЧ
|
||||
******************************************************************************
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef PCH_SENSORS_H
|
||||
#define PCH_SENSORS_H
|
||||
|
||||
|
||||
|
||||
/* Includes -----------------------------------------------------------------*/
|
||||
#include "dallas_tools.h"
|
||||
|
||||
/* Declarations and definitions ---------------------------------------------*/
|
||||
#define USED_USER_BYTES DALLAS_USER_BYTE_12
|
||||
|
||||
/* Позиции параметров в UserBytes */
|
||||
#define REG_SENS_LOCATION_Pos (0) /*!< @brief Позиция параметра "Локация внутри модуля" */
|
||||
|
||||
#define REG_PCH_LOCATION_Pos (8) /*!< @brief Позиция параметра "Расположение в ПЧ" */
|
||||
#define REG_PCH_DIOD_PHASE_Pos (10) /*!< @brief Позиция параметра "Диодный или фазный модуль" @ref REG_PCH_LOCATION_Pos */
|
||||
#define REG_PCH_MODULE_NUMB_Pos (8) /*!< @brief Позиция параметра "Порядковый номер диодного/фазного модуля" @ref REG_PCH_LOCATION_Pos */
|
||||
|
||||
#define REG_PCH_NUMB_Pos (11) /*!< @brief Позиция параметра "Преобразователь частоты" */
|
||||
#define REG_PCH_NUMB_DIGIT_1_Pos (13) /*!< @brief Позиция параметра "Первая цифра номера преобразователя частоты" @ref REG_PCH_NUMB_Pos */
|
||||
#define REG_PCH_NUMB_DIGIT_2_Pos (11) /*!< @brief Позиция параметра "Вторая цифра номера преобразователя частоты" @ref REG_PCH_NUMB_Pos */
|
||||
|
||||
#define REG_ZIP_Pos (15) /*!< @brief Позиция параметра "ЗИП/не ЗИП" */
|
||||
|
||||
/* Маски параметров в UserBytes */
|
||||
#define REG_SENS_LOCATION_Mask ((uint16_t)0x3 << REG_SENS_LOCATION_Pos) /*!< @brief Маска параметра "Локация внутри модуля" */
|
||||
|
||||
#define REG_PCH_LOCATION_Mask ((uint16_t)0x7 << REG_PCH_LOCATION_Pos) /*!< @brief Маска параметра "Расположение в ПЧ" */
|
||||
#define REG_PCH_DIOD_PHASE_Mask ((uint16_t)0x1 << REG_PCH_DIOD_PHASE_Pos) /*!< @brief Маска параметра "Диодный или фазный модуль" */
|
||||
#define REG_PCH_MODULE_NUMB_Mask ((uint16_t)0x3 << REG_PCH_MODULE_NUMB_Pos) /*!< @brief Маска параметра "Порядковый номер диодного/фазного модуля" */
|
||||
|
||||
#define REG_PCH_NUMB_Mask ((uint16_t)0xF << REG_PCH_NUMB_Pos) /*!< @brief Маска параметра "Преобразователь частоты" */
|
||||
#define REG_PCH_NUMB_DIGIT_1_Mask ((uint16_t)0x3 << REG_PCH_NUMB_DIGIT_1_Pos) /*!< @brief Маска параметра "Первая цифра номера преобразователя частоты" */
|
||||
#define REG_PCH_NUMB_DIGIT_2_Mask ((uint16_t)0x3 << REG_PCH_NUMB_DIGIT_2_Pos) /*!< @brief Маска параметра "Вторая цифра номера преобразователя частоты" */
|
||||
|
||||
#define REG_ZIP_Mask ((uint16_t)0x1 << REG_ZIP_Pos) /*!< @brief Маска параметра "ЗИП/не ЗИП" */
|
||||
|
||||
/* Варианты параметров в UserBytes */
|
||||
#define REG_PCH_NUMB_11 ((1 << REG_PCH_NUMB_DIGIT_1_Pos) | (1 << REG_PCH_NUMB_DIGIT_2_Pos))
|
||||
#define REG_PCH_NUMB_12 ((1 << REG_PCH_NUMB_DIGIT_1_Pos) | (2 << REG_PCH_NUMB_DIGIT_2_Pos))
|
||||
#define REG_PCH_NUMB_21 ((2 << REG_PCH_NUMB_DIGIT_1_Pos) | (1 << REG_PCH_NUMB_DIGIT_2_Pos))
|
||||
#define REG_PCH_NUMB_22 ((2 << REG_PCH_NUMB_DIGIT_1_Pos) | (2 << REG_PCH_NUMB_DIGIT_2_Pos))
|
||||
#define REG_PCH_NUMB_31 ((3 << REG_PCH_NUMB_DIGIT_1_Pos) | (1 << REG_PCH_NUMB_DIGIT_2_Pos))
|
||||
#define REG_PCH_NUMB_32 ((3 << REG_PCH_NUMB_DIGIT_1_Pos) | (2 << REG_PCH_NUMB_DIGIT_2_Pos))
|
||||
|
||||
#define REG_PCH_DIODE_NUMB_1 ((0 << REG_PCH_DIOD_PHASE_Pos) | (1 << REG_PCH_MODULE_NUMB_Pos))
|
||||
#define REG_PCH_DIODE_NUMB_2 ((0 << REG_PCH_DIOD_PHASE_Pos) | (2 << REG_PCH_MODULE_NUMB_Pos))
|
||||
#define REG_PCH_DIODE_NUMB_3 ((0 << REG_PCH_DIOD_PHASE_Pos) | (3 << REG_PCH_MODULE_NUMB_Pos))
|
||||
#define REG_PCH_PHASE_NUMB_1 ((1 << REG_PCH_DIOD_PHASE_Pos) | (1 << REG_PCH_MODULE_NUMB_Pos))
|
||||
#define REG_PCH_PHASE_NUMB_2 ((1 << REG_PCH_DIOD_PHASE_Pos) | (2 << REG_PCH_MODULE_NUMB_Pos))
|
||||
#define REG_PCH_PHASE_NUMB_3 ((1 << REG_PCH_DIOD_PHASE_Pos) | (3 << REG_PCH_MODULE_NUMB_Pos))
|
||||
|
||||
/* Получить параметр из UserBytes */
|
||||
#define GET_REG_SENS_LOCATION(_REG_) ((_REG_) & REG_SENS_LOCATION_Mask) /*!< @brief Получить параметр "Локация внутри модуля" */
|
||||
|
||||
#define GET_REG_PCH_LOCATION(_REG_) ((_REG_) & REG_PCH_LOCATION_Mask) /*!< @brief Получить параметр "Расположение в ПЧ" */
|
||||
#define GET_REG_PCH_DIOD_PHASE(_REG_) ((_REG_) & REG_PCH_DIOD_PHASE_Mask) /*!< @brief Получить параметр "Диодный или фазный модуль" */
|
||||
#define GET_REG_PCH_MODULE_NUMB(_REG_) ((_REG_) & REG_PCH_MODULE_NUMB_Mask) /*!< @brief Получить параметр "Порядковый номер диодного/фазного модуля" */
|
||||
|
||||
#define GET_REG_PCH_NUMB(_REG_) ((_REG_) & REG_PCH_NUMB_Mask) /*!< @brief Получить параметр "Преобразователь частоты" */
|
||||
#define GET_REG_PCH_NUMB_DIGIT_1(_REG_) ((_REG_) & REG_PCH_NUMB_DIGIT_1_Mask) /*!< @brief Получить параметр "Первая цифра номера преобразователя частоты" */
|
||||
#define GET_REG_PCH_NUMB_DIGIT_2(_REG_) ((_REG_) & REG_PCH_NUMB_DIGIT_2_Mask) /*!< @brief Получить параметр "Вторая цифра номера преобразователя частоты" */
|
||||
|
||||
#define GET_REG_ZIP(_REG_) ((_REG_) & REG_ZIP_Mask) /*!< @brief Получить параметр "ЗИП/не ЗИП" */
|
||||
|
||||
/* Диапазоны параметров из UserBytes */
|
||||
#define REG_SENS_LOCATION_MAX 3
|
||||
#define REG_SENS_LOCATION_MIN 0
|
||||
#define REG_PCH_DIOD_PHASE_MAX 1
|
||||
#define REG_PCH_DIOD_PHASE_MIN 0
|
||||
#define REG_PCH_MODULE_NUMB_MAX 3
|
||||
#define REG_PCH_MODULE_NUMB_MIN 0
|
||||
#define REG_PCH_NUMB_DIGIT_1_MAX 3
|
||||
#define REG_PCH_NUMB_DIGIT_1_MIN 1
|
||||
#define REG_PCH_NUMB_DIGIT_2_MAX 2
|
||||
#define REG_PCH_NUMB_DIGIT_2_MIN 1
|
||||
|
||||
|
||||
/** @brief Получить параметр "Локация внутри модуля" */
|
||||
#define IS_REG_SENS_LOCATION(_REG_) (((_REG_)->param.Location <= REG_SENS_LOCATION_MAX) && ((_REG_)->param.Location >= REG_SENS_LOCATION_MIN))
|
||||
|
||||
/*!< @brief Получить параметр "Расположение в ПЧ" */
|
||||
#define IS_REG_PCH_LOCATION(_REG_) (IS_REG_PCH_DIOD_PHASE(_REG_) && IS_REG_PCH_MODULE_NUMB(_REG_))
|
||||
/*!< @brief Получить параметр "Диодный или фазный модуль" */
|
||||
#define IS_REG_PCH_DIOD_PHASE(_REG_) (((_REG_)->param.DiodeOrPhase <= REG_PCH_DIOD_PHASE_MAX) && ((_REG_)->param.DiodeOrPhase >= REG_PCH_DIOD_PHASE_MIN))
|
||||
/*!< @brief Получить параметр "Порядковый номер диодного/фазного модуля" */
|
||||
#define IS_REG_PCH_MODULE_NUMB(_REG_) (((_REG_)->param.ModuleNumb <= REG_PCH_MODULE_NUMB_MAX) && ((_REG_)->param.ModuleNumb >= REG_PCH_MODULE_NUMB_MIN))
|
||||
|
||||
/*!< @brief Получить параметр "Преобразователь частоты" */
|
||||
#define IS_REG_PCH_NUMB(_REG_) (IS_REG_PCH_NUMB_DIGIT_1(_REG_) && IS_REG_PCH_NUMB_DIGIT_2(_REG_))
|
||||
/*!< @brief Получить параметр "Первая цифра номера преобразователя частоты" */
|
||||
#define IS_REG_PCH_NUMB_DIGIT_1(_REG_) (((_REG_)->param.PCHdig1 <= REG_PCH_NUMB_DIGIT_1_MAX) && ((_REG_)->param.PCHdig1 >= REG_PCH_NUMB_DIGIT_1_MIN))
|
||||
/*!< @brief Получить параметр "Вторая цифра номера преобразователя частоты" */
|
||||
#define IS_REG_PCH_NUMB_DIGIT_2(_REG_) (((_REG_)->param.PCHdig2 <= REG_PCH_NUMB_DIGIT_2_MAX) && ((_REG_)->param.PCHdig2 >= REG_PCH_NUMB_DIGIT_2_MIN))
|
||||
/*!< @brief Получить параметр "ЗИП/не ЗИП" */
|
||||
#define IS_REG_ZIP(_REG_) (GET_REG_ZIP(_REG_))
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint16_t all;
|
||||
struct
|
||||
{
|
||||
unsigned Location:2;
|
||||
unsigned reserved:6;
|
||||
unsigned ModuleNumb:2;
|
||||
unsigned DiodeOrPhase:1;
|
||||
unsigned PCHdig2:2;
|
||||
unsigned PCHdig1:2;
|
||||
unsigned ZIP:1;
|
||||
}param;
|
||||
}PCHSens_LocationTypeDef;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned convertion;
|
||||
uint64_t connectROM;
|
||||
unsigned read;
|
||||
unsigned deinit;
|
||||
}PCHSens_SensorActionsTypeDef;
|
||||
extern PCHSens_SensorActionsTypeDef action;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DALLAS_SensorHandleTypeDef sens;
|
||||
PCHSens_LocationTypeDef Location;
|
||||
unsigned not_found:1;
|
||||
}PCHSens_SensorTypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DALLAS_HandleTypeDef *hdallas;
|
||||
|
||||
PCHSens_SensorTypeDef sens1;
|
||||
PCHSens_SensorTypeDef sens2;
|
||||
PCHSens_SensorTypeDef sens3;
|
||||
PCHSens_SensorTypeDef sens4;
|
||||
|
||||
PCHSens_LocationTypeDef refLocation;
|
||||
|
||||
}PCHSens_ModuleTypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DALLAS_HandleTypeDef *hdallas;
|
||||
uint8_t UnknownCnt;
|
||||
}PCHSens_DallasBusHandle;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PCHSens_ModuleTypeDef module1;
|
||||
PCHSens_ModuleTypeDef module2;
|
||||
PCHSens_ModuleTypeDef module3;
|
||||
PCHSens_ModuleTypeDef module4;
|
||||
PCHSens_ModuleTypeDef module5;
|
||||
PCHSens_ModuleTypeDef module6;
|
||||
}PCHSens_TypeDef;
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
HAL_StatusTypeDef PCHSens_InitNewSensor(DALLAS_HandleTypeDef *hdallas, PCHSens_SensorTypeDef* sensor, uint64_t ROM);
|
||||
HAL_StatusTypeDef PCHSens_AddSensor(DALLAS_HandleTypeDef *hdallas, PCHSens_SensorTypeDef* sensor);
|
||||
HAL_StatusTypeDef PCHSens_InitModule(DALLAS_HandleTypeDef *hdallas, PCHSens_ModuleTypeDef* module, uint16_t param);
|
||||
HAL_StatusTypeDef PCHSens_ModuleReadTemperature(PCHSens_ModuleTypeDef* module);
|
||||
HAL_StatusTypeDef PCHSens_SensorReadTemperature(DALLAS_HandleTypeDef *hdallas, PCHSens_SensorTypeDef *sensor);
|
||||
HAL_StatusTypeDef PCHSens_ReadTemperature(PCHSens_SensorTypeDef* sensor);
|
||||
HAL_StatusTypeDef PCHSens_StartCovert(PCHSens_DallasBusHandle *hbus);
|
||||
HAL_StatusTypeDef PCHSens_CheckSensor(DALLAS_HandleTypeDef *hdallas, PCHSens_SensorTypeDef* sensor);
|
||||
HAL_StatusTypeDef PCHSens_FindUnknownSensors(PCHSens_DallasBusHandle *hbus);
|
||||
HAL_StatusTypeDef PCHSens_UndefineSensor(PCHSens_SensorTypeDef *sensor);
|
||||
HAL_StatusTypeDef PCHSens_GetSensorByLocation(PCHSens_TypeDef *pchsens, PCHSens_LocationTypeDef Location, PCHSens_SensorTypeDef **sensor);
|
||||
#endif // #ifndef PCH_SENSORS_H
|
||||
64
py_project/Core/Src/gpio.c
Normal file
64
py_project/Core/Src/gpio.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file gpio.c
|
||||
* @brief This file provides code for the configuration
|
||||
* of all used GPIO pins.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "gpio.h"
|
||||
#include "ds18b20_driver.h"
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** Configure pins as
|
||||
* Analog
|
||||
* Input
|
||||
* Output
|
||||
* EVENT_OUT
|
||||
* EXTI
|
||||
*/
|
||||
void MX_GPIO_Init(void)
|
||||
{
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
|
||||
|
||||
/*Configure LED GPIO pin : PB0 (OneWire) */
|
||||
GPIO_InitStruct.Pin = DS_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
HAL_GPIO_Init(DS_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/*Configure LED GPIO pin : PA1 PA4 PA5 */
|
||||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5, GPIO_PIN_SET);
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
}
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
55
py_project/Core/Src/iwdg.c
Normal file
55
py_project/Core/Src/iwdg.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file iwdg.c
|
||||
* @brief This file provides code for the configuration
|
||||
* of the IWDG instances.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "iwdg.h"
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
IWDG_HandleTypeDef hiwdg;
|
||||
|
||||
/* IWDG init function */
|
||||
void MX_IWDG_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN IWDG_Init 0 */
|
||||
|
||||
/* USER CODE END IWDG_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN IWDG_Init 1 */
|
||||
|
||||
/* USER CODE END IWDG_Init 1 */
|
||||
hiwdg.Instance = IWDG;
|
||||
hiwdg.Init.Prescaler = IWDG_PRESCALER_32;
|
||||
hiwdg.Init.Reload = 1000;
|
||||
if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN IWDG_Init 2 */
|
||||
|
||||
/* USER CODE END IWDG_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
141
py_project/Core/Src/main.c
Normal file
141
py_project/Core/Src/main.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file main.c
|
||||
* @author MCU Application Team
|
||||
* @brief Main program body
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
#include "gpio.h"
|
||||
#include "tim.h"
|
||||
#include "usart.h"
|
||||
#include "iwdg.h"
|
||||
#include "PY32module_main.h"
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void APP_SystemClockConfig(void);
|
||||
|
||||
/**
|
||||
* @brief Application Entry Function.
|
||||
* @retval int
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
__HAL_DBGMCU_FREEZE_IWDG();
|
||||
__HAL_DBGMCU_FREEZE_TIM1();
|
||||
__HAL_DBGMCU_FREEZE_TIM14();
|
||||
/* Reset of all peripherals, Initializes the Systick. */
|
||||
HAL_Init();
|
||||
|
||||
/* System clock configuration */
|
||||
APP_SystemClockConfig();
|
||||
|
||||
// MX_IWDG_Init();
|
||||
MX_GPIO_Init();
|
||||
MX_TIM1_Init();
|
||||
MX_TIM14_Init();
|
||||
MX_USART1_UART_Init();
|
||||
|
||||
|
||||
|
||||
PYModule_FirstInit();
|
||||
/* infinite loop */
|
||||
while (1)
|
||||
{
|
||||
PYModule_main();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief System clock configuration function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void APP_SystemClockConfig(void)
|
||||
{
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||
|
||||
/* Oscillator configuration */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; /* Select oscillator HSE, HSI, LSI, LSE */
|
||||
RCC_OscInitStruct.HSIState = RCC_HSI_ON; /* Enable HSI */
|
||||
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; /* HSI 1 frequency division */
|
||||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_24MHz; /* Configure HSI clock 24MHz */
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS_DISABLE; /* Close HSE bypass */
|
||||
RCC_OscInitStruct.LSIState = RCC_LSI_OFF; /* Close LSI */
|
||||
/*RCC_OscInitStruct.LSICalibrationValue = RCC_LSICALIBRATION_32768Hz;*/
|
||||
RCC_OscInitStruct.LSEState = RCC_LSE_OFF; /* Close LSE */
|
||||
/*RCC_OscInitStruct.LSEDriver = RCC_LSEDRIVE_MEDIUM;*/
|
||||
/* Configure oscillator */
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/* Clock source configuration */
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1; /* Choose to configure clock HCLK, SYSCLK, PCLK1 */
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSISYS; /* Select HSISYS as the system clock */
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; /* AHB clock 1 division */
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; /* APB clock 1 division */
|
||||
/* Configure clock source */
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is executed in case of error occurrence.
|
||||
* @retval None
|
||||
*/
|
||||
void Error_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN Error_Handler_Debug */
|
||||
/* User can add his own implementation to report the HAL error return state */
|
||||
__disable_irq();
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
/* USER CODE END Error_Handler_Debug */
|
||||
}
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief Reports the name of the source file and the source line number
|
||||
* where the assert_param error has occurred.
|
||||
* @param file: pointer to the source file name
|
||||
* @param line: assert_param error line source number
|
||||
* @retval None
|
||||
*/
|
||||
void assert_failed(uint8_t *file, uint32_t line)
|
||||
{
|
||||
/* Users can add their own printing information as needed,
|
||||
for example: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||||
/* Infinite loop */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
43
py_project/Core/Src/py32f002b_hal_msp.c
Normal file
43
py_project/Core/Src/py32f002b_hal_msp.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file py32f002b_hal_msp.c
|
||||
* @author MCU Application Team
|
||||
* @brief This file provides code for the MSP Initialization
|
||||
* and de-Initialization codes.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* External functions --------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initialize global MSP.
|
||||
*/
|
||||
void HAL_MspInit(void)
|
||||
{
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
103
py_project/Core/Src/py32f002b_it.c
Normal file
103
py_project/Core/Src/py32f002b_it.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file py32f002b_it.c
|
||||
* @author MCU Application Team
|
||||
* @brief Interrupt Service Routines.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
#include "py32f002b_it.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cortex-M0+ Processor Interruption and Exception Handlers */
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @brief This function handles Non maskable interrupt.
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Hard fault interrupt.
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles System service call via SWI instruction.
|
||||
*/
|
||||
void SVC_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Pendable request for system service.
|
||||
*/
|
||||
void PendSV_Handler(void)
|
||||
{
|
||||
}
|
||||
#include "iwdg.h"
|
||||
/**
|
||||
* @brief This function handles System tick timer.
|
||||
*/
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
HAL_IWDG_Refresh(&hiwdg);
|
||||
HAL_IncTick();
|
||||
}
|
||||
|
||||
#include "rs_message.h"
|
||||
/**
|
||||
* @brief This function handles USART1.
|
||||
*/
|
||||
void USART1_IRQHandler(void)
|
||||
{
|
||||
RS_UART_Handler(&hmodbus1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles TIM2 global interrupt.
|
||||
*/
|
||||
void TIM14_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN TIM2_IRQn 0 */
|
||||
RS_TIM_Handler(&hmodbus1);
|
||||
}
|
||||
/******************************************************************************/
|
||||
/* PY32F002B Peripheral Interrupt Handlers */
|
||||
/* Add here the Interrupt Handlers for the used peripherals. */
|
||||
/* For the available peripheral interrupt handler names, */
|
||||
/* please refer to the startup file. */
|
||||
/******************************************************************************/
|
||||
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
162
py_project/Core/Src/system_py32f002b.c
Normal file
162
py_project/Core/Src/system_py32f002b.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file system_py32f002b.c
|
||||
* @author MCU Application Team
|
||||
* @Version V1.0.0
|
||||
* @Date 2020-10-19
|
||||
* @brief CMSIS Cortex-M0+ Device Peripheral Access Layer System Source File.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "py32f0xx.h"
|
||||
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE 24000000U /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE 24000000U /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
#if !defined (LSI_VALUE)
|
||||
#define LSI_VALUE 32768U /*!< Value of LSI in Hz*/
|
||||
#endif /* LSI_VALUE */
|
||||
|
||||
#if !defined (LSE_VALUE)
|
||||
#define LSE_VALUE 32768U /*!< Value of LSE in Hz*/
|
||||
#endif /* LSE_VALUE */
|
||||
|
||||
|
||||
/************************* Miscellaneous Configuration ************************/
|
||||
/*!< Uncomment the following line if you need to relocate your vector Table in
|
||||
Internal SRAM. */
|
||||
/* #define FORBID_VECT_TAB_MIGRATION */
|
||||
/* #define VECT_TAB_SRAM */
|
||||
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
|
||||
This value must be a multiple of 0x100. */
|
||||
/******************************************************************************/
|
||||
/*----------------------------------------------------------------------------
|
||||
Clock Variable definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
/* This variable is updated in three ways:
|
||||
1) by calling CMSIS function SystemCoreClockUpdate()
|
||||
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
|
||||
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
|
||||
Note: If you use this function to configure the system clock; then there
|
||||
is no need to call the 2 first functions listed above, since SystemCoreClock
|
||||
variable is updated automatically.
|
||||
*/
|
||||
uint32_t SystemCoreClock = HSI_VALUE;
|
||||
|
||||
const uint32_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
const uint32_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
|
||||
#if defined(RCC_HSI48M_SUPPORT)
|
||||
const uint32_t HSIFreqTable[8] = {0U, 0U, 0U, 0U, 24000000U, 48000000U, 0U, 0U};
|
||||
#else
|
||||
const uint32_t HSIFreqTable[8] = {0U, 0U, 0U, 0U, 24000000U, 0U, 0U, 0U};
|
||||
#endif
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
#ifndef SWD_DELAY
|
||||
static void DelayTime(uint32_t mdelay);
|
||||
#endif /* SWD_DELAY */
|
||||
|
||||
/**
|
||||
* @brief Clock functions.
|
||||
* @param none
|
||||
* @return none
|
||||
*/
|
||||
void SystemCoreClockUpdate(void) /* Get Core Clock Frequency */
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t hsidiv;
|
||||
uint32_t hsifs;
|
||||
|
||||
/* Get SYSCLK source -------------------------------------------------------*/
|
||||
switch (RCC->CFGR & RCC_CFGR_SWS)
|
||||
{
|
||||
case RCC_CFGR_SWS_0: /* HSE used as system clock */
|
||||
SystemCoreClock = HSE_VALUE;
|
||||
break;
|
||||
|
||||
case (RCC_CFGR_SWS_1 | RCC_CFGR_SWS_0): /* LSI used as system clock */
|
||||
SystemCoreClock = LSI_VALUE;
|
||||
break;
|
||||
#if defined(RCC_LSE_SUPPORT)
|
||||
case RCC_CFGR_SWS_2: /* LSE used as system clock */
|
||||
SystemCoreClock = LSE_VALUE;
|
||||
break;
|
||||
#endif /* RCC_LSE_SUPPORT */
|
||||
case 0x00000000U: /* HSI used as system clock */
|
||||
default: /* HSI used as system clock */
|
||||
hsifs = ((READ_BIT(RCC->ICSCR, RCC_ICSCR_HSI_FS)) >> RCC_ICSCR_HSI_FS_Pos);
|
||||
hsidiv = (1UL << ((READ_BIT(RCC->CR, RCC_CR_HSIDIV)) >> RCC_CR_HSIDIV_Pos));
|
||||
SystemCoreClock = (HSIFreqTable[hsifs] / hsidiv);
|
||||
break;
|
||||
}
|
||||
/* Compute HCLK clock frequency --------------------------------------------*/
|
||||
/* Get HCLK prescaler */
|
||||
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
|
||||
/* HCLK clock frequency */
|
||||
SystemCoreClock >>= tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup the microcontroller system.
|
||||
* Initialize the System.
|
||||
* @param none
|
||||
* @return none
|
||||
*/
|
||||
void SystemInit(void)
|
||||
{
|
||||
/*Set the HSI clock to 24MHz by default*/
|
||||
RCC->ICSCR = (RCC->ICSCR & 0xFFFF0000) | (*(uint32_t *)(0x1FFF0100));
|
||||
|
||||
/*Set the LSI clock to 32.768KHz by default*/
|
||||
RCC->ICSCR = (RCC->ICSCR & 0xFE00FFFF) | ((*(uint32_t *)(0x1FFF0144)) << RCC_ICSCR_LSI_TRIM_Pos);
|
||||
|
||||
/* Configure the Vector Table location add offset address ------------------*/
|
||||
#ifdef VECT_TAB_SRAM
|
||||
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
|
||||
#else
|
||||
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
|
||||
#endif /* VECT_TAB_SRAM */
|
||||
|
||||
#ifndef SWD_DELAY
|
||||
/* When the SWD pin is reused for other functions, this function is used to solve the
|
||||
problem of not being able to update the code. */
|
||||
DelayTime(100);
|
||||
#endif /* SWD_DELAY */
|
||||
}
|
||||
|
||||
#ifndef SWD_DELAY
|
||||
/**
|
||||
* @brief This function provides delay (in milliseconds) based on CPU cycles method.
|
||||
* @param mdelay: specifies the delay time length, in milliseconds.
|
||||
* @retval None
|
||||
*/
|
||||
static void DelayTime(uint32_t mdelay)
|
||||
{
|
||||
__IO uint32_t Delay = mdelay * (24000000U / 8U / 1000U);
|
||||
do
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
while (Delay --);
|
||||
}
|
||||
#endif /* SWD_DELAY */
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
206
py_project/Core/Src/tim.c
Normal file
206
py_project/Core/Src/tim.c
Normal file
@@ -0,0 +1,206 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file tim.c
|
||||
* @brief This file provides code for the configuration
|
||||
* of the TIM instances.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "tim.h"
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
//TIM_HandleTypeDef htim1;
|
||||
TIM_HandleTypeDef htim14;
|
||||
|
||||
/* TIM3 init function */
|
||||
void MX_TIM1_Init(void)
|
||||
{
|
||||
// Включение тактирования TIM1
|
||||
__HAL_RCC_TIM1_CLK_ENABLE();
|
||||
|
||||
// Установка предделителя (Prescaler)
|
||||
TIM1->PSC = 0;
|
||||
|
||||
// Установка режима счета вверх
|
||||
TIM1->CR1 &= ~TIM_CR1_DIR;
|
||||
|
||||
// Установка периода (ARR - Auto-reload register)
|
||||
TIM1->ARR = 0xFFFFFFFF;
|
||||
|
||||
// Установка делителя частоты (Clock Division)
|
||||
TIM1->CR1 &= ~TIM_CR1_CKD;
|
||||
|
||||
// Отключение режима предзагрузки
|
||||
TIM1->CR1 &= ~TIM_CR1_ARPE;
|
||||
|
||||
// Выбор внутреннего источника тактирования
|
||||
TIM1->SMCR &= ~TIM_SMCR_SMS;
|
||||
|
||||
// Настройка триггерного выхода (TRGO)
|
||||
TIM1->CR2 &= ~TIM_CR2_MMS;
|
||||
|
||||
// Отключение режима Master/Slave
|
||||
TIM1->SMCR &= ~TIM_SMCR_MSM;
|
||||
|
||||
// Включение таймера
|
||||
TIM1->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
// /* USER CODE BEGIN TIM3_Init 0 */
|
||||
|
||||
// /* USER CODE END TIM3_Init 0 */
|
||||
|
||||
// TIM_ClockConfigTypeDef sClockSourceConfig = {0};
|
||||
// TIM_MasterConfigTypeDef sMasterConfig = {0};
|
||||
|
||||
// /* USER CODE BEGIN TIM3_Init 1 */
|
||||
// HAL_RCC_GetPCLK1Freq();
|
||||
// /* USER CODE END TIM3_Init 1 */
|
||||
// htim1.Instance = TIM1;
|
||||
// htim1.Init.Prescaler = 0;
|
||||
// htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
// htim1.Init.Period = 0xFFFFFFFF;
|
||||
// htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
// htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
// if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
|
||||
// {
|
||||
// Error_Handler();
|
||||
// }
|
||||
// sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
|
||||
// if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
|
||||
// {
|
||||
// Error_Handler();
|
||||
// }
|
||||
// sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||
// sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||
// if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
|
||||
// {
|
||||
// Error_Handler();
|
||||
// }
|
||||
// /* USER CODE BEGIN TIM3_Init 2 */
|
||||
|
||||
// /* USER CODE END TIM3_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/* TIM2 init function */
|
||||
void MX_TIM14_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN TIM2_Init 0 */
|
||||
|
||||
/* USER CODE END TIM2_Init 0 */
|
||||
|
||||
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
|
||||
TIM_MasterConfigTypeDef sMasterConfig = {0};
|
||||
|
||||
/* USER CODE BEGIN TIM2_Init 1 */
|
||||
|
||||
/* USER CODE END TIM2_Init 1 */
|
||||
htim14.Instance = TIM14;
|
||||
htim14.Init.Prescaler = (HAL_RCC_GetPCLK1Freq()/1000000) - 1;
|
||||
htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim14.Init.Period = 50000;
|
||||
htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
|
||||
if (HAL_TIM_ConfigClockSource(&htim14, &sClockSourceConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim14, &sMasterConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN TIM2_Init 2 */
|
||||
|
||||
/* USER CODE END TIM2_Init 2 */
|
||||
|
||||
}
|
||||
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
|
||||
{
|
||||
|
||||
if(tim_baseHandle->Instance==TIM1)
|
||||
{
|
||||
/* USER CODE BEGIN TIM1_MspInit 0 */
|
||||
|
||||
/* USER CODE END TIM1_MspInit 0 */
|
||||
/* TIM1 clock enable */
|
||||
__HAL_RCC_TIM1_CLK_ENABLE();
|
||||
/* USER CODE BEGIN TIM1_MspInit 1 */
|
||||
|
||||
/* USER CODE END TIM1_MspInit 1 */
|
||||
}
|
||||
else if(tim_baseHandle->Instance==TIM14)
|
||||
{
|
||||
/* USER CODE BEGIN TIM14_MspInit 0 */
|
||||
|
||||
/* USER CODE END TIM14_MspInit 0 */
|
||||
/* TIM14 clock enable */
|
||||
__HAL_RCC_TIM14_CLK_ENABLE();
|
||||
|
||||
/* TIM14 interrupt Init */
|
||||
HAL_NVIC_SetPriority(TIM14_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(TIM14_IRQn);
|
||||
/* USER CODE BEGIN TIM14_MspInit 1 */
|
||||
|
||||
/* USER CODE END TIM14_MspInit 1 */
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
|
||||
{
|
||||
|
||||
if(tim_baseHandle->Instance==TIM1)
|
||||
{
|
||||
/* USER CODE BEGIN TIM1_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END TIM1_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_TIM1_CLK_DISABLE();
|
||||
|
||||
/* TIM1 interrupt Deinit */
|
||||
HAL_NVIC_DisableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
|
||||
/* USER CODE BEGIN TIM1_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END TIM1_MspDeInit 1 */
|
||||
}
|
||||
else if(tim_baseHandle->Instance==TIM14)
|
||||
{
|
||||
/* USER CODE BEGIN TIM14_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END TIM14_MspDeInit 0 */
|
||||
/* TIM14 clock disable */
|
||||
__HAL_RCC_TIM14_CLK_DISABLE();
|
||||
|
||||
/* TIM14 interrupt Deinit */
|
||||
HAL_NVIC_DisableIRQ(TIM14_IRQn);
|
||||
/* USER CODE BEGIN TIM14_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END TIM14_MspDeInit 1 */
|
||||
}
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
98
py_project/Core/Src/usart.c
Normal file
98
py_project/Core/Src/usart.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usart.c
|
||||
* @brief This file provides code for the configuration
|
||||
* of the USART instances.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usart.h"
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
UART_HandleTypeDef huart1;
|
||||
|
||||
/* USART1 init function */
|
||||
|
||||
void MX_USART1_UART_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN USART1_Init 0 */
|
||||
|
||||
/* USER CODE END USART1_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN USART1_Init 1 */
|
||||
|
||||
/* USER CODE END USART1_Init 1 */
|
||||
huart1.Instance = USART1;
|
||||
huart1.Init.BaudRate = MODBUS_SPEED;
|
||||
huart1.Init.WordLength = UART_WORDLENGTH_8B;
|
||||
huart1.Init.StopBits = UART_STOPBITS_1;
|
||||
huart1.Init.Parity = UART_PARITY_NONE;
|
||||
huart1.Init.Mode = UART_MODE_TX_RX;
|
||||
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
||||
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
|
||||
if (HAL_UART_Init(&huart1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN USART1_Init 2 */
|
||||
|
||||
/* USER CODE END USART1_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
|
||||
{
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
if(uartHandle->Instance==USART1)
|
||||
{
|
||||
/* USER CODE BEGIN USART1_MspInit 0 */
|
||||
|
||||
/* USER CODE END USART1_MspInit 0 */
|
||||
/* USART1 clock enable */
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_USART1_CLK_ENABLE();
|
||||
|
||||
/* GPIO initialization
|
||||
PB04:TX,
|
||||
PB05:RX
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_4;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_5;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* USART1 interrupt Init */
|
||||
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(USART1_IRQn);
|
||||
/* USER CODE BEGIN USART1_MspInit 1 */
|
||||
|
||||
/* USER CODE END USART1_MspInit 1 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
@@ -0,0 +1,165 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 19. March 2015
|
||||
* $Revision: V.1.4.5
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_abs_f32.c
|
||||
*
|
||||
* Description: Vector absolute value.
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of ARM LIMITED nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* ---------------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* @ingroup groupMath
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup BasicAbs Vector Absolute Value
|
||||
*
|
||||
* Computes the absolute value of a vector on an element-by-element basis.
|
||||
*
|
||||
* <pre>
|
||||
* pDst[n] = abs(pSrc[n]), 0 <= n < blockSize.
|
||||
* </pre>
|
||||
*
|
||||
* The functions support in-place computation allowing the source and
|
||||
* destination pointers to reference the same memory buffer.
|
||||
* There are separate functions for floating-point, Q7, Q15, and Q31 data types.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup BasicAbs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Floating-point vector absolute value.
|
||||
* @param[in] *pSrc points to the input buffer
|
||||
* @param[out] *pDst points to the output buffer
|
||||
* @param[in] blockSize number of samples in each vector
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_abs_f32(
|
||||
float32_t * pSrc,
|
||||
float32_t * pDst,
|
||||
uint32_t blockSize)
|
||||
{
|
||||
uint32_t blkCnt; /* loop counter */
|
||||
|
||||
#ifndef ARM_MATH_CM0_FAMILY
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
float32_t in1, in2, in3, in4; /* temporary variables */
|
||||
|
||||
/*loop Unrolling */
|
||||
blkCnt = blockSize >> 2u;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = |A| */
|
||||
/* Calculate absolute and then store the results in the destination buffer. */
|
||||
/* read sample from source */
|
||||
in1 = *pSrc;
|
||||
in2 = *(pSrc + 1);
|
||||
in3 = *(pSrc + 2);
|
||||
|
||||
/* find absolute value */
|
||||
in1 = fabsf(in1);
|
||||
|
||||
/* read sample from source */
|
||||
in4 = *(pSrc + 3);
|
||||
|
||||
/* find absolute value */
|
||||
in2 = fabsf(in2);
|
||||
|
||||
/* read sample from source */
|
||||
*pDst = in1;
|
||||
|
||||
/* find absolute value */
|
||||
in3 = fabsf(in3);
|
||||
|
||||
/* find absolute value */
|
||||
in4 = fabsf(in4);
|
||||
|
||||
/* store result to destination */
|
||||
*(pDst + 1) = in2;
|
||||
|
||||
/* store result to destination */
|
||||
*(pDst + 2) = in3;
|
||||
|
||||
/* store result to destination */
|
||||
*(pDst + 3) = in4;
|
||||
|
||||
|
||||
/* Update source pointer to process next sampels */
|
||||
pSrc += 4u;
|
||||
|
||||
/* Update destination pointer to process next sampels */
|
||||
pDst += 4u;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
|
||||
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
|
||||
** No loop unrolling is used. */
|
||||
blkCnt = blockSize % 0x4u;
|
||||
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
|
||||
/* Initialize blkCnt with number of samples */
|
||||
blkCnt = blockSize;
|
||||
|
||||
#endif /* #ifndef ARM_MATH_CM0_FAMILY */
|
||||
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = |A| */
|
||||
/* Calculate absolute and then store the results in the destination buffer. */
|
||||
*pDst++ = fabsf(*pSrc++);
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of BasicAbs group
|
||||
*/
|
||||
@@ -0,0 +1,179 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 19. March 2015
|
||||
* $Revision: V.1.4.5
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_abs_q15.c
|
||||
*
|
||||
* Description: Q15 vector absolute value.
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of ARM LIMITED nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupMath
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup BasicAbs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Q15 vector absolute value.
|
||||
* @param[in] *pSrc points to the input buffer
|
||||
* @param[out] *pDst points to the output buffer
|
||||
* @param[in] blockSize number of samples in each vector
|
||||
* @return none.
|
||||
*
|
||||
* <b>Scaling and Overflow Behavior:</b>
|
||||
* \par
|
||||
* The function uses saturating arithmetic.
|
||||
* The Q15 value -1 (0x8000) will be saturated to the maximum allowable positive value 0x7FFF.
|
||||
*/
|
||||
|
||||
void arm_abs_q15(
|
||||
q15_t * pSrc,
|
||||
q15_t * pDst,
|
||||
uint32_t blockSize)
|
||||
{
|
||||
uint32_t blkCnt; /* loop counter */
|
||||
|
||||
#ifndef ARM_MATH_CM0_FAMILY
|
||||
__SIMD32_TYPE *simd;
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
|
||||
q15_t in1; /* Input value1 */
|
||||
q15_t in2; /* Input value2 */
|
||||
|
||||
|
||||
/*loop Unrolling */
|
||||
blkCnt = blockSize >> 2u;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
simd = __SIMD32_CONST(pDst);
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = |A| */
|
||||
/* Read two inputs */
|
||||
in1 = *pSrc++;
|
||||
in2 = *pSrc++;
|
||||
|
||||
|
||||
/* Store the Absolute result in the destination buffer by packing the two values, in a single cycle */
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
*simd++ =
|
||||
__PKHBT(((in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1)),
|
||||
((in2 > 0) ? in2 : (q15_t)__QSUB16(0, in2)), 16);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
*simd++ =
|
||||
__PKHBT(((in2 > 0) ? in2 : (q15_t)__QSUB16(0, in2)),
|
||||
((in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1)), 16);
|
||||
|
||||
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
||||
|
||||
in1 = *pSrc++;
|
||||
in2 = *pSrc++;
|
||||
|
||||
|
||||
#ifndef ARM_MATH_BIG_ENDIAN
|
||||
|
||||
*simd++ =
|
||||
__PKHBT(((in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1)),
|
||||
((in2 > 0) ? in2 : (q15_t)__QSUB16(0, in2)), 16);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
*simd++ =
|
||||
__PKHBT(((in2 > 0) ? in2 : (q15_t)__QSUB16(0, in2)),
|
||||
((in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1)), 16);
|
||||
|
||||
#endif /* #ifndef ARM_MATH_BIG_ENDIAN */
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
pDst = (q15_t *)simd;
|
||||
|
||||
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
|
||||
** No loop unrolling is used. */
|
||||
blkCnt = blockSize % 0x4u;
|
||||
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = |A| */
|
||||
/* Read the input */
|
||||
in1 = *pSrc++;
|
||||
|
||||
/* Calculate absolute value of input and then store the result in the destination buffer. */
|
||||
*pDst++ = (in1 > 0) ? in1 : (q15_t)__QSUB16(0, in1);
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
|
||||
q15_t in; /* Temporary input variable */
|
||||
|
||||
/* Initialize blkCnt with number of samples */
|
||||
blkCnt = blockSize;
|
||||
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = |A| */
|
||||
/* Read the input */
|
||||
in = *pSrc++;
|
||||
|
||||
/* Calculate absolute value of input and then store the result in the destination buffer. */
|
||||
*pDst++ = (in > 0) ? in : ((in == (q15_t) 0x8000) ? 0x7fff : -in);
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
|
||||
#endif /* #ifndef ARM_MATH_CM0_FAMILY */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of BasicAbs group
|
||||
*/
|
||||
@@ -0,0 +1,130 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 19. March 2015
|
||||
* $Revision: V.1.4.5
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_abs_q31.c
|
||||
*
|
||||
* Description: Q31 vector absolute value.
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of ARM LIMITED nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupMath
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup BasicAbs
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Q31 vector absolute value.
|
||||
* @param[in] *pSrc points to the input buffer
|
||||
* @param[out] *pDst points to the output buffer
|
||||
* @param[in] blockSize number of samples in each vector
|
||||
* @return none.
|
||||
*
|
||||
* <b>Scaling and Overflow Behavior:</b>
|
||||
* \par
|
||||
* The function uses saturating arithmetic.
|
||||
* The Q31 value -1 (0x80000000) will be saturated to the maximum allowable positive value 0x7FFFFFFF.
|
||||
*/
|
||||
|
||||
void arm_abs_q31(
|
||||
q31_t * pSrc,
|
||||
q31_t * pDst,
|
||||
uint32_t blockSize)
|
||||
{
|
||||
uint32_t blkCnt; /* loop counter */
|
||||
q31_t in; /* Input value */
|
||||
|
||||
#ifndef ARM_MATH_CM0_FAMILY
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
q31_t in1, in2, in3, in4;
|
||||
|
||||
/*loop Unrolling */
|
||||
blkCnt = blockSize >> 2u;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = |A| */
|
||||
/* Calculate absolute of input (if -1 then saturated to 0x7fffffff) and then store the results in the destination buffer. */
|
||||
in1 = *pSrc++;
|
||||
in2 = *pSrc++;
|
||||
in3 = *pSrc++;
|
||||
in4 = *pSrc++;
|
||||
|
||||
*pDst++ = (in1 > 0) ? in1 : (q31_t)__QSUB(0, in1);
|
||||
*pDst++ = (in2 > 0) ? in2 : (q31_t)__QSUB(0, in2);
|
||||
*pDst++ = (in3 > 0) ? in3 : (q31_t)__QSUB(0, in3);
|
||||
*pDst++ = (in4 > 0) ? in4 : (q31_t)__QSUB(0, in4);
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
|
||||
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
|
||||
** No loop unrolling is used. */
|
||||
blkCnt = blockSize % 0x4u;
|
||||
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
|
||||
/* Initialize blkCnt with number of samples */
|
||||
blkCnt = blockSize;
|
||||
|
||||
#endif /* #ifndef ARM_MATH_CM0_FAMILY */
|
||||
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = |A| */
|
||||
/* Calculate absolute value of the input (if -1 then saturated to 0x7fffffff) and then store the results in the destination buffer. */
|
||||
in = *pSrc++;
|
||||
*pDst++ = (in > 0) ? in : ((in == INT32_MIN) ? INT32_MAX : -in);
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of BasicAbs group
|
||||
*/
|
||||
@@ -0,0 +1,157 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 19. March 2015
|
||||
* $Revision: V.1.4.5
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_abs_q7.c
|
||||
*
|
||||
* Description: Q7 vector absolute value.
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of ARM LIMITED nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupMath
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup BasicAbs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Q7 vector absolute value.
|
||||
* @param[in] *pSrc points to the input buffer
|
||||
* @param[out] *pDst points to the output buffer
|
||||
* @param[in] blockSize number of samples in each vector
|
||||
* @return none.
|
||||
*
|
||||
* \par Conditions for optimum performance
|
||||
* Input and output buffers should be aligned by 32-bit
|
||||
*
|
||||
*
|
||||
* <b>Scaling and Overflow Behavior:</b>
|
||||
* \par
|
||||
* The function uses saturating arithmetic.
|
||||
* The Q7 value -1 (0x80) will be saturated to the maximum allowable positive value 0x7F.
|
||||
*/
|
||||
|
||||
void arm_abs_q7(
|
||||
q7_t * pSrc,
|
||||
q7_t * pDst,
|
||||
uint32_t blockSize)
|
||||
{
|
||||
uint32_t blkCnt; /* loop counter */
|
||||
q7_t in; /* Input value1 */
|
||||
|
||||
#ifndef ARM_MATH_CM0_FAMILY
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
q31_t in1, in2, in3, in4; /* temporary input variables */
|
||||
q31_t out1, out2, out3, out4; /* temporary output variables */
|
||||
|
||||
/*loop Unrolling */
|
||||
blkCnt = blockSize >> 2u;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = |A| */
|
||||
/* Read inputs */
|
||||
in1 = (q31_t) * pSrc;
|
||||
in2 = (q31_t) * (pSrc + 1);
|
||||
in3 = (q31_t) * (pSrc + 2);
|
||||
|
||||
/* find absolute value */
|
||||
out1 = (in1 > 0) ? in1 : (q31_t)__QSUB8(0, in1);
|
||||
|
||||
/* read input */
|
||||
in4 = (q31_t) * (pSrc + 3);
|
||||
|
||||
/* find absolute value */
|
||||
out2 = (in2 > 0) ? in2 : (q31_t)__QSUB8(0, in2);
|
||||
|
||||
/* store result to destination */
|
||||
*pDst = (q7_t) out1;
|
||||
|
||||
/* find absolute value */
|
||||
out3 = (in3 > 0) ? in3 : (q31_t)__QSUB8(0, in3);
|
||||
|
||||
/* find absolute value */
|
||||
out4 = (in4 > 0) ? in4 : (q31_t)__QSUB8(0, in4);
|
||||
|
||||
/* store result to destination */
|
||||
*(pDst + 1) = (q7_t) out2;
|
||||
|
||||
/* store result to destination */
|
||||
*(pDst + 2) = (q7_t) out3;
|
||||
|
||||
/* store result to destination */
|
||||
*(pDst + 3) = (q7_t) out4;
|
||||
|
||||
/* update pointers to process next samples */
|
||||
pSrc += 4u;
|
||||
pDst += 4u;
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
|
||||
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
|
||||
** No loop unrolling is used. */
|
||||
blkCnt = blockSize % 0x4u;
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
blkCnt = blockSize;
|
||||
|
||||
#endif /* #define ARM_MATH_CM0_FAMILY */
|
||||
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = |A| */
|
||||
/* Read the input */
|
||||
in = *pSrc++;
|
||||
|
||||
/* Store the Absolute result in the destination buffer */
|
||||
*pDst++ = (in > 0) ? in : ((in == (q7_t) 0x80) ? 0x7f : -in);
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of BasicAbs group
|
||||
*/
|
||||
@@ -0,0 +1,150 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
|
||||
*
|
||||
* $Date: 19. March 2015
|
||||
* $Revision: V.1.4.5
|
||||
*
|
||||
* Project: CMSIS DSP Library
|
||||
* Title: arm_add_f32.c
|
||||
*
|
||||
* Description: Floating-point vector addition.
|
||||
*
|
||||
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of ARM LIMITED nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* ---------------------------------------------------------------------------- */
|
||||
|
||||
#include "arm_math.h"
|
||||
|
||||
/**
|
||||
* @ingroup groupMath
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup BasicAdd Vector Addition
|
||||
*
|
||||
* Element-by-element addition of two vectors.
|
||||
*
|
||||
* <pre>
|
||||
* pDst[n] = pSrcA[n] + pSrcB[n], 0 <= n < blockSize.
|
||||
* </pre>
|
||||
*
|
||||
* There are separate functions for floating-point, Q7, Q15, and Q31 data types.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup BasicAdd
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Floating-point vector addition.
|
||||
* @param[in] *pSrcA points to the first input vector
|
||||
* @param[in] *pSrcB points to the second input vector
|
||||
* @param[out] *pDst points to the output vector
|
||||
* @param[in] blockSize number of samples in each vector
|
||||
* @return none.
|
||||
*/
|
||||
|
||||
void arm_add_f32(
|
||||
float32_t * pSrcA,
|
||||
float32_t * pSrcB,
|
||||
float32_t * pDst,
|
||||
uint32_t blockSize)
|
||||
{
|
||||
uint32_t blkCnt; /* loop counter */
|
||||
|
||||
#ifndef ARM_MATH_CM0_FAMILY
|
||||
|
||||
/* Run the below code for Cortex-M4 and Cortex-M3 */
|
||||
float32_t inA1, inA2, inA3, inA4; /* temporary input variabels */
|
||||
float32_t inB1, inB2, inB3, inB4; /* temporary input variables */
|
||||
|
||||
/*loop Unrolling */
|
||||
blkCnt = blockSize >> 2u;
|
||||
|
||||
/* First part of the processing with loop unrolling. Compute 4 outputs at a time.
|
||||
** a second loop below computes the remaining 1 to 3 samples. */
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = A + B */
|
||||
/* Add and then store the results in the destination buffer. */
|
||||
|
||||
/* read four inputs from sourceA and four inputs from sourceB */
|
||||
inA1 = *pSrcA;
|
||||
inB1 = *pSrcB;
|
||||
inA2 = *(pSrcA + 1);
|
||||
inB2 = *(pSrcB + 1);
|
||||
inA3 = *(pSrcA + 2);
|
||||
inB3 = *(pSrcB + 2);
|
||||
inA4 = *(pSrcA + 3);
|
||||
inB4 = *(pSrcB + 3);
|
||||
|
||||
/* C = A + B */
|
||||
/* add and store result to destination */
|
||||
*pDst = inA1 + inB1;
|
||||
*(pDst + 1) = inA2 + inB2;
|
||||
*(pDst + 2) = inA3 + inB3;
|
||||
*(pDst + 3) = inA4 + inB4;
|
||||
|
||||
/* update pointers to process next samples */
|
||||
pSrcA += 4u;
|
||||
pSrcB += 4u;
|
||||
pDst += 4u;
|
||||
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
|
||||
/* If the blockSize is not a multiple of 4, compute any remaining output samples here.
|
||||
** No loop unrolling is used. */
|
||||
blkCnt = blockSize % 0x4u;
|
||||
|
||||
#else
|
||||
|
||||
/* Run the below code for Cortex-M0 */
|
||||
|
||||
/* Initialize blkCnt with number of samples */
|
||||
blkCnt = blockSize;
|
||||
|
||||
#endif /* #ifndef ARM_MATH_CM0_FAMILY */
|
||||
|
||||
while(blkCnt > 0u)
|
||||
{
|
||||
/* C = A + B */
|
||||
/* Add and then store the results in the destination buffer. */
|
||||
*pDst++ = (*pSrcA++) + (*pSrcB++);
|
||||
|
||||
/* Decrement the loop counter */
|
||||
blkCnt--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @} end of BasicAdd group
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user