Compare commits
39
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ba89a0f52 | ||
|
|
bef05f2773 | ||
|
|
016efe4a05 | ||
|
|
570a11a37f | ||
|
|
4c987be8e7 | ||
|
|
15134a549a | ||
|
|
dbc9388f67 | ||
|
|
fad121a9fd | ||
|
|
424ca121f8 | ||
|
|
1d6ccdbef3 | ||
|
|
8d44a1a153 | ||
|
|
b4305e8296 | ||
|
|
b59da11afc | ||
|
|
1633a224f3 | ||
|
|
54c8a663e4 | ||
|
|
458d2d77c9 | ||
|
|
3687f2db60 | ||
|
|
26852bbec0 | ||
|
|
68794b6981 | ||
|
|
0b26757a73 | ||
|
|
28749c63e8 | ||
|
|
932a6cc8e0 | ||
|
|
617dcdd228 | ||
|
|
102831d24c | ||
|
|
9f438ccd2f | ||
|
|
495c358ada | ||
|
|
369e4a4b82 | ||
|
|
b5a26200f3 | ||
|
|
a5a14679f3 | ||
|
|
3402381c55 | ||
|
|
324c26e559 | ||
|
|
b96e00b166 | ||
|
|
aa5b4b3fcb | ||
|
|
e4b2830fcc | ||
|
|
884f1fc3f1 | ||
|
|
b6978c385a | ||
|
|
0f2736b8a5 | ||
|
|
0743e6699a | ||
|
|
c2e5f70f36 |
+5
-2
@@ -45,5 +45,8 @@ JLinkLog.txt
|
||||
|
||||
# Other Files
|
||||
|
||||
/test_project/MDK-ARM/DebugConfig/
|
||||
/test_project/MDK-ARM/ds18b20/
|
||||
/MDK-ARM/DebugConfig/
|
||||
/MDK-ARM/Output/
|
||||
/~$ds18b20_locations.xlsx
|
||||
/~$PY32F002A_Pins.xlsx
|
||||
/~$PY32F002B_Pins.xlsx
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : onewire_uart.c
|
||||
* @brief : Драйвер для работы с шиной 1-Wire через UART
|
||||
* @author : MicroTechnics (microtechnics.ru)
|
||||
******************************************************************************
|
||||
@details
|
||||
Этот файл реализует базовые функции для работы с 1-Wire через UART.
|
||||
Он включает в себя методы для передачи и приёма битов и байтов, а также
|
||||
выполнение reset-команды для устройств 1-Wire.
|
||||
|
||||
UART передает специально сформированные импульсы, эмулируя 1-Wire.
|
||||
*****************************************************************************/
|
||||
|
||||
/* Includes ----------------------------------------------------------------*/
|
||||
|
||||
#include "onewire_uart.h"
|
||||
|
||||
/* Declarations and definitions --------------------------------------------*/
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Устанавливает скорость передачи данных для UART.
|
||||
* @param huart Указатель на структуру UART
|
||||
* @param baudrate Требуемая скорость передачи (бит/с)
|
||||
* @details Функция изменяет скорость передачи UART в зависимости от используемой шины
|
||||
* (PCLK1 или PCLK2). Это важно для эмуляции временных параметров 1-Wire.
|
||||
*/
|
||||
static void UARTSetBaudrate(UART_HandleTypeDef *huart, uint32_t baudrate)
|
||||
{
|
||||
uint32_t pclk = 0;
|
||||
huart->Init.BaudRate = baudrate;
|
||||
|
||||
#if defined(USART6) && defined(UART9) && defined(UART10)
|
||||
if ((huart->Instance == USART1) || (huart->Instance == USART6) ||
|
||||
(huart->Instance == UART9) || (huart->Instance == UART10))
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
}
|
||||
#elif defined(USART6)
|
||||
if ((huart->Instance == USART1) || (huart->Instance == USART6))
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
}
|
||||
#else
|
||||
if (huart->Instance == USART1)
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
}
|
||||
#endif /* USART6 */
|
||||
else
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
|
||||
#if defined(USART_CR1_OVER8)
|
||||
if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
|
||||
{
|
||||
huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
|
||||
}
|
||||
#else
|
||||
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
|
||||
#endif /* USART_CR1_OVER8 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Передает и принимает один бит через 1-Wire.
|
||||
* @param huart Указатель на структуру UART
|
||||
* @param bit Бит для передачи (0 или 1)
|
||||
* @return Полученный бит (0 или 1)
|
||||
* @details Передача осуществляется отправкой специального импульса, длина которого определяет передаваемый бит.
|
||||
* Ответное значение читается сразу после передачи.
|
||||
*/
|
||||
uint8_t OneWireUART_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit)
|
||||
{
|
||||
uint8_t txData;
|
||||
uint8_t rxData = 0x00;
|
||||
|
||||
if (bit == 1)
|
||||
{
|
||||
txData = ONEWIRE_PULSE_SHORT; // Короткий импульс для передачи '1'
|
||||
}
|
||||
else
|
||||
{
|
||||
txData = ONEWIRE_PULSE_LONG; // Длинный импульс для передачи '0'
|
||||
}
|
||||
|
||||
HAL_UART_Transmit(huart, &txData, 1, ONEWIRE_UART_TIMEOUT);
|
||||
HAL_UART_Receive(huart, &rxData, 1, ONEWIRE_UART_TIMEOUT);
|
||||
|
||||
if (rxData == 0xFF)
|
||||
{
|
||||
bit = 1; // Короткий импульс для передачи '1'
|
||||
}
|
||||
else
|
||||
{
|
||||
bit = 0; // Длинный импульс для передачи '0'
|
||||
}
|
||||
return bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Передает и принимает байт через 1-Wire.
|
||||
* @param huart Указатель на структуру UART
|
||||
* @param byte Отправляемый байт
|
||||
* @return Принятый байт
|
||||
* @details Отправляет 8 бит последовательно, используя @ref OneWire_ProcessBit.
|
||||
* Каждый полученный бит собирается в байт и возвращается.
|
||||
*/
|
||||
uint8_t OneWireUART_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte)
|
||||
{
|
||||
uint8_t rxByte = 0x00;
|
||||
uint8_t txBit = 0;
|
||||
uint8_t rxBit = 0;
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
txBit = (byte >> i) & 0x01; // Извлекаем очередной бит для отправки
|
||||
rxBit = OneWireUART_ProcessBit(huart, txBit);
|
||||
|
||||
rxByte |= (rxBit << i); // Собираем принятые биты в байт
|
||||
}
|
||||
|
||||
return rxByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Выполняет 1-Wire Reset и проверяет наличие устройств на шине.
|
||||
* @param huart Указатель на структуру UART
|
||||
* @return HAL Status
|
||||
* @details Процедура Reset требует изменения скорости UART, чтобы сформировать
|
||||
* большой по длительности импульс сброса. Если устройство ответило, шина в рабочем состоянии.
|
||||
*/
|
||||
HAL_StatusTypeDef OneWireUART_Reset(UART_HandleTypeDef *huart)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint8_t txByte = ONEWIRE_RESET;
|
||||
uint8_t rxByte = 0x00;
|
||||
|
||||
UARTSetBaudrate(huart, ONEWIRE_RESET_BAUDRATE); // Устанавливаем низкую скорость для Reset-импульса
|
||||
|
||||
HAL_UART_Transmit(huart, &txByte, 1, ONEWIRE_UART_TIMEOUT);
|
||||
HAL_UART_Receive(huart, &rxByte, 1, ONEWIRE_UART_TIMEOUT);
|
||||
|
||||
UARTSetBaudrate(huart, ONEWIRE_BAUDRATE); // Возвращаем стандартную скорость
|
||||
|
||||
if (rxByte == txByte)
|
||||
{
|
||||
status = HAL_ERROR; // Если ответ совпадает с отправленным байтом, значит, устройств нет
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : onewire_uart.h
|
||||
* @brief : 1-Wire driver
|
||||
* @author : MicroTechnics (microtechnics.ru)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ONEWIRE_UART_H
|
||||
#define ONEWIRE_UART_H
|
||||
|
||||
|
||||
|
||||
/* Includes ----------------------------------------------------------------*/
|
||||
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
|
||||
/* Declarations and definitions --------------------------------------------*/
|
||||
#define ONEWIRE_BAUDRATE 115200
|
||||
#define ONEWIRE_RESET_BAUDRATE 9600
|
||||
#define ONEWIRE_UART_TIMEOUT 10
|
||||
|
||||
/**
|
||||
* @brief Комманды OneWire
|
||||
* @details Определяет байты для uart, которые будут
|
||||
* формировать необходимую длину импульса для разных комманд
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ONEWIRE_RESET = 0xF0, /*!< @brief Импульс длиной 520мкс для команды Reset (9600bod)
|
||||
@details 1-Wire требует импульс длительностью >480мкс */
|
||||
|
||||
ONEWIRE_PULSE_SHORT = 0xFF, /*!< @brief Импульс длиной 8.7 мкс для записи "1"/чтения бита (115200bod)
|
||||
@details 1-Wire требует импульс длительностью 1-15мкс */
|
||||
|
||||
|
||||
ONEWIRE_PULSE_LONG = 0x00, /*!< @brief импульс длиной 78.3 мкс для записи "0" (115200bod)
|
||||
@details 1-Wire требует импульс длительностью 60-120мкс */
|
||||
|
||||
// ONEWIRE_PULSE_1_15US = 0xFF,
|
||||
// ONEWIRE_PULSE_60_120US = 0x00,
|
||||
}ONEWIRE_Commands;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
/* Выполняет 1-Wire Reset и проверяет наличие устройств на шине */
|
||||
HAL_StatusTypeDef OneWireUART_Reset(UART_HandleTypeDef *huart);
|
||||
/* Передает и принимает байт через 1-Wire */
|
||||
uint8_t OneWireUART_ProcessByte(UART_HandleTypeDef *huart, uint8_t byte);
|
||||
/* Передает и принимает один бит через 1-Wire */
|
||||
uint8_t OneWireUART_ProcessBit(UART_HandleTypeDef *huart, uint8_t bit);
|
||||
|
||||
|
||||
|
||||
#endif // #ifndef ONEWIRE_UART_H
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @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 "stm32f1xx_hal.h"
|
||||
|
||||
/* I/O Port ------------------------------------------------------------------*/
|
||||
#define UART_Driver ///< использовтаь UART (onewire_uart.c/.h)
|
||||
//#define LL_Driver ///< использовать CMSIS для управления ножкой
|
||||
#define CMSIS_Driver ///< использовать CMSIS для управления ножкой
|
||||
// если ничего не выбрано - используется HAL
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup DEFAULT_SETTINGS Дефолтные параметры для OW
|
||||
* @details Определены дефолтные параметры для OW, применятся если передать NULL в Dallas_BusFirstInit.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Порт вывода для шины 1-Wire.
|
||||
* @details Указывает порт GPIO, к которому подключена линия данных 1-Wire (например, для DS18B20).
|
||||
*/
|
||||
#define OW_UART_Handle huart1
|
||||
|
||||
/**
|
||||
* @brief Порт вывода для шины 1-Wire.
|
||||
* @details Указывает порт GPIO, к которому подключена линия данных 1-Wire (например, для DS18B20).
|
||||
*/
|
||||
#define OW_GPIO_Port GPIOA
|
||||
|
||||
/**
|
||||
* @brief Маска пина, соответствующая номеру OW_Pin_Numb.
|
||||
* @details Используется при доступе к регистрам порта для управления состоянием линии 1-Wire.
|
||||
*/
|
||||
#define OW_Pin (GPIO_PIN_9)
|
||||
|
||||
/**
|
||||
* @brief Аппаратный таймер для формирования временных интервалов протокола 1-Wire.
|
||||
* @details Применяется для создания точных задержек при обмене данными по шине 1-Wire.
|
||||
*/
|
||||
#define OW_TIM TIM3
|
||||
|
||||
/**
|
||||
* @brief Количество тактов таймера OW_TIM, соответствующее 1 микросекунде.
|
||||
* @details Вычисляется на основе частоты таймера. Например, для таймера с частотой 24 МГц значение будет равно 24.
|
||||
*/
|
||||
#define OW_TIM_1US_PERIOD 72
|
||||
|
||||
|
||||
/** DEFAULT_SETTINGS
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* OneWire Timings -----------------------------------------------------------*/
|
||||
void OneWire_Delay_us(uint32_t us);
|
||||
/* Common Register -----------------------------------------------------------*/
|
||||
|
||||
|
||||
#if defined(UART_Driver)
|
||||
#include "onewire_uart.h"
|
||||
#include "usart.h"
|
||||
#endif
|
||||
#endif /* ONEWIRE_PORT_H */
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,101 +1,109 @@
|
||||
# Библиотека для работы с датчиками температуры DS18B20 по 1-Wire
|
||||
|
||||
---
|
||||
|
||||
## Описание
|
||||
|
||||
Данная библиотека предоставляет драйвер для работы с цифровыми температурными датчиками DS18B20, подключёнными по однопроводному интерфейсу 1-Wire. Библиотека поддерживает:
|
||||
- Инициализация шины 1-Wire и обнаружение всех датчиков на шине
|
||||
- Инициализация датчика по:
|
||||
- ROM-адресу
|
||||
- Пользовательским байтам (TH, TL, UserByte3, UserByte4)
|
||||
- Индексу (порядковому номеру) найденного устройства
|
||||
- Запуск преобразования температуры у всех или отдельных датчиков с выбором метода ожидания окончания преобразования (по шине или задержкой)
|
||||
- Чтение температуры и проверка статуса подключения датчика
|
||||
- Возможность замены потерянного датчика в структуре
|
||||
|
||||
---
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
### 1. Настройка порта и таймера для 1-Wire (файл `ow_port.h`):
|
||||
```c
|
||||
#define OW_GPIO_Port GPIOB
|
||||
#define OW_Pin_Numb 0
|
||||
#define OW_Pin (1 << OW_Pin_Numb)
|
||||
#define OW_TIM TIM3
|
||||
#define OW_TIM_1US_PERIOD 24
|
||||
```
|
||||
|
||||
### 2. Подключение библиотеки и инициализация таймера:
|
||||
```c
|
||||
#include "dallas_tools.h"
|
||||
|
||||
MX_TIM_Init(); // Инициализация таймера (например, TIM3)
|
||||
```
|
||||
|
||||
### 3. Инициализация шины и поиск датчиков:
|
||||
```c
|
||||
Dallas_BusFirstInit(&htim);
|
||||
```
|
||||
|
||||
### 4. Инициализация структуры датчика по одному из методов:
|
||||
```c
|
||||
// Объявление хендлов датчиков
|
||||
DALLAS_SensorHandleTypeDef sens;
|
||||
|
||||
// Инициализация по индексу (порядковому номеру найденного датчика)
|
||||
sens1.Init.init_func = &Dallas_SensorInitByInd;
|
||||
sens1.Init.InitParam.Ind = 0;
|
||||
|
||||
// Инициализация по ROM-адресу
|
||||
sens.Init.init_func = &Dallas_SensorInitByROM;
|
||||
sens.Init.InitParam.ROM = rom_address;
|
||||
|
||||
// Инициализация по пользовательским байтам
|
||||
sens.Init.init_func = &Dallas_SensorInitByUserBytes;
|
||||
sens.Init.InitParam.UserBytes.UserByte1 = 1;
|
||||
sens.Init.InitParam.UserBytes.UserByte2 = 2;
|
||||
sens.Init.InitParam.UserBytes.UserByte3 = 3;
|
||||
sens.Init.InitParam.UserBytes.UserByte4 = 4;
|
||||
|
||||
// добавление датчика в структуру sens
|
||||
Dallas_AddNewSensors(&hdallas, &sens);
|
||||
```
|
||||
|
||||
### 5. Запуск измерения и чтение температуры:
|
||||
```c
|
||||
Dallas_StartConvertTAll(&hdallas, DALLAS_WAIT_BUS, 0);
|
||||
Dallas_ReadTemperature(&sens);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Функции
|
||||
|
||||
| Функция | Описание |
|
||||
| -------------------------------------------------------- | ---------------------------------------------------------- |
|
||||
| `Dallas_BusFirstInit(&htim)` | Инициализация шины 1-Wire, запуск таймера и поиск датчиков |
|
||||
| `Dallas_AddNewSensors(&hdallas, &sensor)` | Инициализация структуры датчика и добавление в работу |
|
||||
| `Dallas_ReplaceLostedSensor(&sensor)` | Замена потерянного датчика на новый, если доступен |
|
||||
| `Dallas_StartConvertTAll(&hdallas, waitCondition, delay)` | Запуск преобразования температуры на всех датчиках |
|
||||
| `Dallas_ConvertT(&sensor, waitCondition)` | Запуск преобразования температуры на одном датчике |
|
||||
| `Dallas_ReadTemperature(&sensor)` | Чтение температуры с датчика |
|
||||
| `Dallas_IsConnected(&sensor)` | Проверка подключения датчика (чтение scratchpad) |
|
||||
| `Dallas_WriteUserBytes(&sensor, bytes12, bytes34, mask)` | Запись пользовательских байт в датчик |
|
||||
# PY32F002B PCHTemperature+Modbus Module
|
||||
Прога для PY32F002B которая будет считывать датчики температуры в ПЧ и сохранять их в модбас регистры.
|
||||
Конверсия идет непрерывно и после каждой конверсии считываются все датчики и записываются в модбас регистры.
|
||||
|
||||
|
||||
## Требуемые зависимости
|
||||
## **Чтение температуры**
|
||||
Для считывания температуры необходимо:
|
||||
- выставить коил `RunConvertion` (`№0`)
|
||||
- считывать инпут регистры `№0-29` для получения температуры [***Цельсий x 100***]
|
||||
|
||||
- Драйвер 1-Wire (`onewire.c/h`, `ow_port.c/h`)
|
||||
- Драйвер DS18B20 (`ds18b20_driver.c/h`)
|
||||
После выставления коила модуль будет непрерывно запускать конверсию и по её завершении обновлять инпут регистры.
|
||||
|
||||
---
|
||||
После каждого завершения конверсии выставляется коил `ConvertionDone` (`№16`), который сбрасывается при чтении инпут регистров температуры. Поэтому имеет смысл дополнительно проверить этот коил, обновились ли значения температуры с прошлого считывания.
|
||||
|
||||
## Примечания
|
||||
- Функции работы с датчиками возвращают статус в формате `HAL_StatusTypeDef`.
|
||||
- Ожидание окончания преобразования температуры настраивается через `DALLAS_WaitConvertionTypeDef`:
|
||||
- `DALLAS_WAIT_BUS` — ожидание по состоянию линии 1-Wire.
|
||||
- `DALLAS_WAIT_DELAY` — фиксированная задержка, зависящая от выбранного разрешения.
|
||||
- `DALLAS_WAIT_NONE` — без ожидания (асинхронный режим).
|
||||
- При потере связи с датчиком функция `Dallas_IsConnected` помечает датчик как потерянный. Для восстановления работы можно вызвать `Dallas_ReplaceLostedSensor`, она будет искать датчик и пытаться его инициализировать по заданной функции инициализации.
|
||||
Если какой-то датчик был потерян, в инпут регистры на его место записывается `0x0` и выставляется коил `LostedSensors` (`№17`)
|
||||
|
||||
## Управление датчиками
|
||||
Взаимодействие с датчиком строится по следующему принципу:
|
||||
- заполнение холдинг регистров (`№0-5`) для параметров датчика для обращения к нему
|
||||
- выставление коила для взаимодействия с датчиком (поиск, чтение, инит, деинит)
|
||||
- чтение инпут регистров (`№30-36`) содержащих ответ от датчика и [статус взаимодействия](#статус-общения-с-датчиком)
|
||||
|
||||
После выставления коила, происходит выбранное действие с датчиком и заполнение инпут регистров с ответом, поэтому имеет смысл сделать выдержку в пару миллисекунд между выставлением коила с считыванием ответа
|
||||
|
||||
### Адреса всех датчиков
|
||||
Для получения ROM всех датчиков необходимо:
|
||||
- считать инпут регистры `№38-158`
|
||||
|
||||
В них записаны ROM всех найденных датчиков (максимум 30 датчиков на линии), каждый ROM занимает 4 регистра Modbus. Т.е. ROM первого датчика находится в регистрах `№38-41`, ROM второго - в регистрах `№42-45` и так далее.
|
||||
|
||||
### Считывание параметров датчика
|
||||
Для считывания параметров конкретного датчика необходимо:
|
||||
- выставить холдинг регистры:
|
||||
- `Location` (`№0`), где находится датчик
|
||||
- `ROM` (`№1-4`), адрес датчика
|
||||
- Выставляется что-то одно из `Location`/`ROM`, а второе должно быть в нуле
|
||||
- выставить коил `ReadSensor` (`№1`)
|
||||
- считать ответ в инпут регистры:
|
||||
- `Location` (`№30`), где находится датчик
|
||||
- `ROM` (`№31-34`), адрес датчика
|
||||
- `Config` (`№35`), конфиг регистр датчика
|
||||
- `Status` (`№36`), [статус общения с датчиком](#статус-общения-с-датчиком)
|
||||
|
||||
После выставления коила, происходит чтение скратчпада датчика и заполнение им инпут регистров. Если чтение по локации не прошло успешно статус выставляется в `0xF0`. Если чтение по ROM не прошло успешно статус выставляется в `0xF0`
|
||||
|
||||
### Инициализация датчика
|
||||
Для инициализации датчика необходимо:
|
||||
- выставить холдинг регистры:
|
||||
- `Location` (`№0`), где находится датчик
|
||||
- `ROM` (`№1-4`), адрес датчика
|
||||
- `Config` (`№5`), конфиг регистр датчика
|
||||
- выставить коил `InitSensor` (`№2`)
|
||||
- считать ответ в инпут регистры:
|
||||
- `Location` (`№30`), где находится датчик
|
||||
- `ROM` (`№31-34`), адрес датчика
|
||||
- `Config` (`№35`), конфиг регистр датчика
|
||||
- `Status` (`№36`), [статус общения с датчиком](#статус-общения-с-датчиком)
|
||||
|
||||
После выставления коила в `UserByte` выбранного по ROM датчика записывается его локация и он включается в структуру датчиков микроконтроллера. Если инициализация не прошла успешно статус выставляется в `0xAA`
|
||||
|
||||
### Деинициализация датчика
|
||||
Для деинициализации датчика необходимо:
|
||||
- выставить холдинг регистр `Location` (`№0`), где находится датчик
|
||||
- выставить коил `DeInitSensor` (`№3`)
|
||||
- считать ответ в инпут регистры:
|
||||
- `Location` (`№30`), где находится датчик
|
||||
- `ROM` (`№31-34`), адрес датчика
|
||||
- `Config` (`№35`), конфиг регистр датчика
|
||||
- `Status` (`№36`), [статус общения с датчиком](#статус-общения-с-датчиком)
|
||||
|
||||
После выставления коила в `UserByte` выбранного по `ROM` датчика записываются нули и он выключается из структуры датчиков микроконтроллера. Если деинициализация не прошла успешно статус выставляется в `0x55`
|
||||
|
||||
### Статус общения с датчиком
|
||||
Статус сигнализирует о следующих событиях:
|
||||
- `0x01`- без ошибок, все ок
|
||||
- `0x11` - конец скана
|
||||
- `0xF0` - ошибка при чтении по выбранной локации
|
||||
- `0x0F` - ошибка при чтении по выбранному ROM
|
||||
- `0xAA` - ошибка инициализации выбранного датчика
|
||||
- `0x55` - ошибка деинициализации выбранного датчика
|
||||
- `0xBB` - ошибка при сканировании (в МК хранится адрес несуществующего датчика например)
|
||||
|
||||
|
||||
## Структура данных
|
||||
**Coils**: адреса для управления работой модуля
|
||||
- 0: `RunConvertion` - [запуск преобразований всех датчиков](#чтение-температуры)
|
||||
- 1: `ReadSensor` - [считать параметры датчика](#считывание-параметров-датчика)
|
||||
- 2: `InitSensor` - [инициализация датчика](#инициализация-датчика)
|
||||
- 3: `DeInitSensor` - [деинициализировать датчик](#деинициализация-датчика)
|
||||
- 4: `ScanSensors` - включить режим [поиска датчиков](#сканирование-датчиков)
|
||||
|
||||
**Coils**: адреса для флагов модуля
|
||||
- 16: `ConvertionDone` - флаг окончания конверсии. Сбрасывается после считывания температуры из регистров
|
||||
- 17: `LostedSensors` - флаг есть ли потерянные сенсоры. Сбрасывается по модбас
|
||||
|
||||
**Hodling Registers**: адреса для передачи параметров датчика и для инициализации/деинициализации.
|
||||
- 0: `Location` - локация датчика
|
||||
- 1-4: `ROM` - ROM датчика
|
||||
- 5: `Config` - разрешение датчика
|
||||
- 6: `Enable` - считывать напряжение с этого датчика или нет
|
||||
|
||||
**Input Registers**: адреса для хранения температуры и параметров датчика
|
||||
Температура храниться в первых 30 инпут регистрах
|
||||
- 0-29: `SensTemperature` - температура n-го датчика в [***Цельсий x 100***]
|
||||
Параметры храняться в рестрах N+1. Хранятся параметры последнего датчика к которому было совершнео обращение (коилы №1-3)
|
||||
- 30: `Location` - локация датчика, к которому было совершено обращение
|
||||
- 31-34: `ROM` - ROM датчика, к которому было совершено обращение
|
||||
- 35: `Config` - конфигурационный регистр датчика, к которому было совершено обращение
|
||||
- 36: `Status` - статус работы датчика, к которому было совершено обращение
|
||||
Binary file not shown.
@@ -2,75 +2,12 @@
|
||||
******************************************************************************
|
||||
* @file dallas_tools.c
|
||||
* @brief Драйвер для работы с датчиками температуры DS18B20
|
||||
* @author MicroTechnics (microtechnics.ru)
|
||||
******************************************************************************
|
||||
@details
|
||||
Библиотека предназначена для работы с цифровыми датчиками температуры DS18B20
|
||||
по однопроводному интерфейсу 1-Wire. Реализована поддержка инициализации, поиска,
|
||||
добавления и работы с несколькими датчиками.
|
||||
|
||||
@verbatim
|
||||
==============================================================================
|
||||
## Основные задачи библиотеки ##
|
||||
==============================================================================
|
||||
Эта библиотека предоставляет следующие основные функции:
|
||||
(+) Инициализация шины 1-Wire и обнаружение подключённых датчиков
|
||||
(+) Инициализация структуры датчика по:
|
||||
- ROM-адресу
|
||||
- пользовательским байтам (TH, TL, UserByte3, UserByte4)
|
||||
- порядковому номеру в списке найденных устройств
|
||||
(+) Конфигурация разрешения измерения
|
||||
(+) Чтение температуры
|
||||
(+) Замена «потерянного» датчика
|
||||
(+) Деинициализация структуры датчика
|
||||
|
||||
==============================================================================
|
||||
## Быстрый старт ##
|
||||
==============================================================================
|
||||
Пример последовательности инициализации и использования:
|
||||
|
||||
1. Определение пина и таймера для OneWire в ow_port.h:
|
||||
#define OW_GPIO_Port GPIOB
|
||||
#define OW_Pin_Numb 0
|
||||
#define OW_Pin (1<<OW_Pin_Numb)
|
||||
#define OW_TIM TIM3
|
||||
#define OW_TIM_1US_PERIOD 24
|
||||
|
||||
2. Подключение библиотеки и настройка таймеров:
|
||||
#include "dallas_tools.h"
|
||||
MX_TIM_Init();
|
||||
|
||||
3. Инициализация шины и поиск датчиков:
|
||||
Dallas_BusFirstInit(&htim);
|
||||
|
||||
4. Инициализация датчика Dallas_SensorHandleTypeDef по одному из методов:
|
||||
sens1.Init.init_func = &Dallas_SensorInitByInd; // по индексу
|
||||
sens1.Init.InitParam.Ind = 0; // порядковый номер найденного датика для инициализации
|
||||
|
||||
sens2.Init.init_func = &Dallas_SensorInitByROM; // по ROM-адресу
|
||||
sens2.Init.InitParam.ROM = 0; // ROM датика для инициализации
|
||||
|
||||
sens3.Init.init_func = &Dallas_SensorInitByUserBytes; // по пользовательским байтам
|
||||
sens3.Init.InitParam.UserBytes.UserByte1 = 1; // UseBytes датика для инициализации
|
||||
sens3.Init.InitParam.UserBytes.UserByte2 = 2; // UseBytes датика для инициализации
|
||||
sens3.Init.InitParam.UserBytes.UserByte3 = 3; // UseBytes датика для инициализации
|
||||
sens3.Init.InitParam.UserBytes.UserByte4 = 4; // UseBytes датика для инициализации
|
||||
|
||||
5. Инициализация структуруы датчика:
|
||||
Dallas_AddNewSensors(&hdallas, &sens);
|
||||
|
||||
6. Работа с датчиком:
|
||||
Dallas_StartConvertTAll(hdallas, DALLAS_WAIT_BUS, 0);
|
||||
Dallas_ReadTemperature(&sens);
|
||||
|
||||
==============================================================================
|
||||
## Требуемые зависимости ##
|
||||
==============================================================================
|
||||
Для работы библиотеки требуется:
|
||||
- Драйвер OneWire (файлы onewire.c/h и ow_port.c/.h)
|
||||
- Драйвер DS18B20 (файлы ds18b20.c/h)
|
||||
|
||||
@endverbatim
|
||||
==============================================================================
|
||||
@details
|
||||
Этот файл содержит реализацию функций для работы с датчиком DS18B20
|
||||
через интерфейс 1-Wire. Он предоставляет функции для чтения и записи
|
||||
конфигурации, выполнения измерений и обработки полученных данных.
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
@@ -81,73 +18,40 @@
|
||||
|
||||
|
||||
/* Declarations and definitions --------------------------------------------*/
|
||||
DALLAS_HandleTypeDef hdallas;
|
||||
DALLAS_HandleTypeDef hdallas1;
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Функция для иниицализации структуры dallas и шины OW для датчиков
|
||||
* @param hdallas Указатель на хендл для общения с датчиками
|
||||
* @param OW Указатель на структуру OneWire (если NULL — используется по умолчанию)
|
||||
* @param DS Указатель на структуру драйвера DS18B20 (если NULL — используется по умолчанию)
|
||||
* @retval HAL Status
|
||||
* @brief Функция для нахождения нового датчика на место потерянного
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
*/
|
||||
#ifndef UART_Driver
|
||||
HAL_StatusTypeDef Dallas_BusFirstInit(DALLAS_HandleTypeDef *hdallas, GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
|
||||
#else
|
||||
HAL_StatusTypeDef Dallas_BusFirstInit(DALLAS_HandleTypeDef *hdallas, UART_HandleTypeDef *huart)
|
||||
#endif
|
||||
HAL_StatusTypeDef Dallas_ReplaceLostedSensor(DALLAS_SensorHandleTypeDef *sensor)
|
||||
{
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
HAL_StatusTypeDef result;
|
||||
|
||||
#ifndef UART_Driver
|
||||
OW_TIM->CR1 |= TIM_CR1_CEN;
|
||||
if(GPIOx == NULL)
|
||||
{
|
||||
hdallas->onewire.DataPin = OW_Pin;
|
||||
hdallas->onewire.DataPort = OW_GPIO_Port;
|
||||
}
|
||||
else
|
||||
{
|
||||
hdallas->onewire.DataPin = GPIO_Pin;
|
||||
hdallas->onewire.DataPort = GPIOx;
|
||||
}
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
|
||||
if(sensor == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
result = Dallas_IsConnected(sensor);
|
||||
|
||||
if(sensor->isLost)
|
||||
{
|
||||
if (hdallas->onewire.DataPin & (1 << i))
|
||||
{
|
||||
hdallas->onewire.DataPinNumb = i;
|
||||
break;
|
||||
}
|
||||
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
|
||||
if(huart == NULL)
|
||||
hdallas->onewire.huart = &OW_UART_Handle;
|
||||
else
|
||||
hdallas->onewire.huart = huart;
|
||||
#endif
|
||||
/* Инициализация onewire и поиск датчиков*/
|
||||
OneWire_Init(&hdallas->onewire);
|
||||
|
||||
|
||||
return Dallas_Search(hdallas);
|
||||
{
|
||||
return HAL_BUSY; // датчик не потерян
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Поиск датчиков на шине onewire
|
||||
* @param hdallas Указатель на хендл для общения с датчиками
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_Search(DALLAS_HandleTypeDef *hdallas)
|
||||
{
|
||||
if(hdallas == NULL)
|
||||
return HAL_ERROR;
|
||||
|
||||
return DS18B20_Search(&hdallas->ds_devices, &hdallas->onewire) != HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Функция для иниицализации нового датчика в структуре
|
||||
@@ -173,38 +77,225 @@ HAL_StatusTypeDef Dallas_AddNewSensors(DALLAS_HandleTypeDef *hdallas, DALLAS_Sen
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Функция для нахождения нового датчика на место потерянного
|
||||
* @brief Инициализирует структуру датчика по ROM
|
||||
* @param hdallas Указатель на хендл для общения с датчиками
|
||||
* @param sensor Указатель на структуру датчика
|
||||
* @retval HAL Status
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef Dallas_ReplaceLostedSensor(DALLAS_SensorHandleTypeDef *sensor)
|
||||
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;
|
||||
|
||||
result = Dallas_IsConnected(sensor);
|
||||
if(DS18B20_IsValidAddress(ROM) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
if(sensor->isLost)
|
||||
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)
|
||||
{
|
||||
if(Dallas_Search(sensor->hdallas) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
if(sensor->Init.init_func(sensor->hdallas, sensor) != HAL_OK)
|
||||
return HAL_ERROR;
|
||||
|
||||
return HAL_OK;
|
||||
result = Dallas_SensorInit(hdallas, sensor, &hdallas->ds_devices->DevAddr[ROM_ind]);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY; // датчик не потерян
|
||||
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 Запускает измерение температуры на всех датчиках
|
||||
@@ -222,7 +313,7 @@ HAL_StatusTypeDef Dallas_StartConvertTAll(DALLAS_HandleTypeDef *hdallas, DALLAS_
|
||||
return HAL_ERROR;
|
||||
|
||||
// Отправка команды начала преобразования температуры
|
||||
result = DS18B20_StartConvTAll(&hdallas->onewire);
|
||||
result = DS18B20_StartConvTAll(hdallas->onewire);
|
||||
if(result != HAL_OK)
|
||||
{
|
||||
return result;
|
||||
@@ -234,7 +325,7 @@ HAL_StatusTypeDef Dallas_StartConvertTAll(DALLAS_HandleTypeDef *hdallas, DALLAS_
|
||||
// Ожидание завершения преобразования, путем проверки шины
|
||||
if (waitCondition == DALLAS_WAIT_BUS)
|
||||
{
|
||||
result = DS18B20_WaitForEndConvertion(&hdallas->onewire);
|
||||
result = DS18B20_WaitForEndConvertion(hdallas->onewire);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -293,7 +384,7 @@ HAL_StatusTypeDef Dallas_ConvertT(DALLAS_SensorHandleTypeDef *sensor, DALLAS_Wai
|
||||
return result;
|
||||
|
||||
// Отправка команды начала преобразования температуры
|
||||
result = DS18B20_StartConvT(&sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM);
|
||||
result = DS18B20_StartConvT(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM);
|
||||
if(result != HAL_OK)
|
||||
{
|
||||
return result;
|
||||
@@ -302,7 +393,7 @@ HAL_StatusTypeDef Dallas_ConvertT(DALLAS_SensorHandleTypeDef *sensor, DALLAS_Wai
|
||||
// Ожидание завершения преобразования, путем проверки шины
|
||||
if (waitCondition == DALLAS_WAIT_BUS)
|
||||
{
|
||||
result = DS18B20_WaitForEndConvertion(&sensor->hdallas->onewire);
|
||||
result = DS18B20_WaitForEndConvertion(sensor->hdallas->onewire);
|
||||
if(result == HAL_TIMEOUT)
|
||||
{
|
||||
sensor->f.timeout_convertion_cnt++;
|
||||
@@ -372,7 +463,7 @@ HAL_StatusTypeDef Dallas_ReadTemperature(DALLAS_SensorHandleTypeDef *sensor)
|
||||
}
|
||||
|
||||
|
||||
result = DS18B20_CalcTemperature(&sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, (uint8_t *)&sensor->hdallas->scratchpad, &sensor->temperature);
|
||||
result = DS18B20_CalcTemperature(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, (uint8_t *)&sensor->hdallas->scratchpad, &sensor->temperature);
|
||||
|
||||
if (result != HAL_OK)
|
||||
{
|
||||
@@ -440,7 +531,7 @@ HAL_StatusTypeDef Dallas_WriteUserBytes(DALLAS_SensorHandleTypeDef *sensor, uint
|
||||
if (result != HAL_OK)
|
||||
return result;
|
||||
|
||||
result = DS18B20_WriteUserBytes(&sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, UserBytes12, UserBytes34, UserBytesMask);
|
||||
result = DS18B20_WriteUserBytes(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, UserBytes12, UserBytes34, UserBytesMask);
|
||||
if (result != HAL_OK)
|
||||
{
|
||||
sensor->f.write_err_cnt++;
|
||||
@@ -460,225 +551,5 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.ROM >> (7*8)) & 0xFF;
|
||||
ROM[1] = (sensor->Init.InitParam.ROM >> (6*8)) & 0xFF;
|
||||
ROM[2] = (sensor->Init.InitParam.ROM >> (5*8)) & 0xFF;
|
||||
ROM[3] = (sensor->Init.InitParam.ROM >> (4*8)) & 0xFF;
|
||||
ROM[4] = (sensor->Init.InitParam.ROM >> (3*8)) & 0xFF;
|
||||
ROM[5] = (sensor->Init.InitParam.ROM >> (2*8)) & 0xFF;
|
||||
ROM[6] = (sensor->Init.InitParam.ROM >> (1*8)) & 0xFF;
|
||||
ROM[7] = (sensor->Init.InitParam.ROM >> (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.UserBytes.UserByte1;
|
||||
uint8_t UserByte2 = sensor->Init.InitParam.UserBytes.UserByte2;
|
||||
uint8_t UserByte3 = sensor->Init.InitParam.UserBytes.UserByte3;
|
||||
uint8_t UserByte4 = sensor->Init.InitParam.UserBytes.UserByte4;
|
||||
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(UserByte1 | UserByte2)
|
||||
{
|
||||
if( (hdallas->scratchpad.tHighRegister == UserByte1) &&
|
||||
(hdallas->scratchpad.tLowRegister == UserByte2))
|
||||
{
|
||||
UserByte12Cmp = 1;
|
||||
}
|
||||
}/* Если сравнение UserByte1 и UserByte2 не выбрано, то считаем что они совпадают */
|
||||
else
|
||||
{
|
||||
UserByte12Cmp = 1;
|
||||
}
|
||||
/* Сравнение UserByte3 и UserByte4, если они не равны нулю */
|
||||
if(UserByte3 | UserByte4)
|
||||
{
|
||||
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.Ind]);
|
||||
|
||||
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;
|
||||
return DS18B20_ReadScratchpad(sensor->hdallas->onewire, (uint8_t *)&sensor->sensROM, (uint8_t *)&sensor->hdallas->scratchpad);
|
||||
}
|
||||
@@ -14,11 +14,12 @@
|
||||
#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) ///< Второй пользовательский байт
|
||||
@@ -43,9 +44,6 @@
|
||||
#define DALLAS_DELAY_MS_12_BITS 750
|
||||
#define DALLAS_DELAY_MS_MAX DALLAS_DELAY_MS_12_BITS
|
||||
|
||||
typedef struct _SensorHandleStruct DALLAS_SensorHandleTypeDef;
|
||||
typedef struct _DallasHandleStruct DALLAS_HandleTypeDef;
|
||||
|
||||
/** @brief Структура Scratchpad датчика DALLAS */
|
||||
typedef struct
|
||||
{
|
||||
@@ -73,36 +71,24 @@ typedef struct
|
||||
/** @brief Структура инициализации датчика DALLAS */
|
||||
typedef struct __packed
|
||||
{
|
||||
union
|
||||
{
|
||||
uint64_t Ind; ///< порядковый номер датчика
|
||||
uint64_t ROM; ///< ROM датчика
|
||||
struct
|
||||
{
|
||||
uint8_t UserByte1; ///< Младший байт (бит 0–7)
|
||||
uint8_t UserByte2; ///< Следующий байт (бит 8–15)
|
||||
uint8_t UserByte3; ///< Байт (бит 16–23)
|
||||
uint8_t UserByte4; ///< Байт (бит 24–31)
|
||||
uint8_t Reserved[4]; ///< Остальные байты (бит 32–63, если нужно)
|
||||
} UserBytes; ///< UserBytes датчика
|
||||
}InitParam; ///< Параметр для инициализации: ROM/UserBytes/Индекс
|
||||
uint64_t InitParam; ///< Параметр для инициализации: ROM/UserBytes/Индекс
|
||||
uint8_t Resolution; ///< Разрешение датчика
|
||||
HAL_StatusTypeDef (*init_func)(DALLAS_HandleTypeDef *, DALLAS_SensorHandleTypeDef *); ///< Функция инициализации
|
||||
HAL_StatusTypeDef (*init_func)(); ///< Функция инициализации
|
||||
} DALLAS_InitStructTypeDef;
|
||||
|
||||
|
||||
|
||||
/** @brief Cтруктура обработчика DALLAS для общения с датчиком*/
|
||||
struct _DallasHandleStruct
|
||||
typedef struct
|
||||
{
|
||||
OneWire_t onewire;
|
||||
DS18B20_Drv_t ds_devices;
|
||||
OneWire_t *onewire;
|
||||
DS18B20_Drv_t *ds_devices;
|
||||
DALLAS_ScratchpadTypeDef scratchpad;
|
||||
};
|
||||
extern DALLAS_HandleTypeDef hdallas;
|
||||
}DALLAS_HandleTypeDef;
|
||||
extern DALLAS_HandleTypeDef hdallas1;
|
||||
|
||||
/** @brief Основная структура обработчика датчика DALLAS */
|
||||
struct _SensorHandleStruct
|
||||
typedef struct
|
||||
{
|
||||
unsigned isConnected:1; ///< Флаг соединения
|
||||
unsigned isInitialized:1; ///< Флаг инициализации
|
||||
@@ -115,7 +101,7 @@ struct _SensorHandleStruct
|
||||
|
||||
DALLAS_InitStructTypeDef Init; ///< Структура инициализации
|
||||
DALLAS_FlagsTypeDef f; ///< Флаги
|
||||
};
|
||||
} DALLAS_SensorHandleTypeDef;
|
||||
|
||||
|
||||
|
||||
@@ -130,14 +116,9 @@ typedef enum
|
||||
|
||||
|
||||
/* Functions ---------------------------------------------------------------*/
|
||||
/* Функция для иниицализации структуры dallas и шины OW для датчиков */
|
||||
#ifndef UART_Driver
|
||||
HAL_StatusTypeDef Dallas_BusFirstInit(DALLAS_HandleTypeDef *hdallas, GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);
|
||||
#else
|
||||
HAL_StatusTypeDef Dallas_BusFirstInit(DALLAS_HandleTypeDef *hdallas, UART_HandleTypeDef *huart);
|
||||
#endif
|
||||
/* Поиск датчиков на шине onewire */
|
||||
HAL_StatusTypeDef Dallas_Search(DALLAS_HandleTypeDef *hdallas);
|
||||
|
||||
/* Функция для нахождения нового датчика на место потерянного */
|
||||
HAL_StatusTypeDef Dallas_ReplaceLostedSensor(DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Функция для иниицализации нового датчика в структуре */
|
||||
HAL_StatusTypeDef Dallas_AddNewSensors(DALLAS_HandleTypeDef *hdallas, DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Инициализирует структуру датчика по ROM */
|
||||
@@ -150,8 +131,6 @@ HAL_StatusTypeDef Dallas_SensorInitByInd(DALLAS_HandleTypeDef *hdallas, DALLAS_S
|
||||
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_ReplaceLostedSensor(DALLAS_SensorHandleTypeDef *sensor);
|
||||
/* Запускает измерение температуры на всех датчиках */
|
||||
HAL_StatusTypeDef Dallas_StartConvertTAll(DALLAS_HandleTypeDef *hdallas, DALLAS_WaitConvertionTypeDef waitCondition, uint8_t dallas_delay_ms);
|
||||
/* Измеряет температуру на датчике */
|
||||
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
#include "ds18b20_driver.h"
|
||||
|
||||
DS18B20_Drv_t *DS;
|
||||
OneWire_t OW;
|
||||
|
||||
/**
|
||||
* @brief The function is used to check valid DS18B20 ROM
|
||||
@@ -21,6 +21,15 @@
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "onewire.h"
|
||||
|
||||
/* I/O Port ------------------------------------------------------------------*/
|
||||
#ifdef PY32F002Bx5
|
||||
#define DS_Pin GPIO_PIN_0
|
||||
#define DS_GPIO_Port GPIOB
|
||||
#endif
|
||||
#ifdef PY32F002Ax5
|
||||
#define DS_Pin GPIO_PIN_3
|
||||
#define DS_GPIO_Port GPIOA
|
||||
#endif
|
||||
|
||||
/* Data Structure ------------------------------------------------------------*/
|
||||
#define DS18B20_DEVICE_AMOUNT 30
|
||||
@@ -75,7 +84,7 @@ typedef struct
|
||||
{
|
||||
uint8_t DevAddr[DS18B20_DEVICE_AMOUNT][8];
|
||||
} DS18B20_Drv_t;
|
||||
extern DS18B20_Drv_t DS;;
|
||||
extern DS18B20_Drv_t *DS;;
|
||||
extern OneWire_t OW;
|
||||
|
||||
/* External Function ---------------------------------------------------------*/
|
||||
@@ -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)) {};
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -24,13 +24,13 @@ void OneWire_WriteBit(OneWire_t* OW, uint8_t bit)
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
|
||||
/* Forming pulse */
|
||||
OneWire_Delay_us(ONEWIRE_WRITE_1_US);
|
||||
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_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_1_US);
|
||||
OneWire_Delay_uw(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_1_US);
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
}else{
|
||||
/* Set line low */
|
||||
@@ -38,18 +38,18 @@ void OneWire_WriteBit(OneWire_t* OW, uint8_t bit)
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
|
||||
/* Forming pulse */
|
||||
OneWire_Delay_us(ONEWIRE_WRITE_0_US);
|
||||
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_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_0_US);
|
||||
OneWire_Delay_uw(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_WRITE_0_US);
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
}
|
||||
__enable_irq();
|
||||
#else
|
||||
OneWireUART_ProcessBit(OW->huart, bit);
|
||||
OneWireUART_ProcessBit(onewire_uart, bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -69,20 +69,20 @@ uint8_t OneWire_ReadBit(OneWire_t* OW)
|
||||
/* Line low */
|
||||
OneWire_Pin_Level(OW, 0);
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
OneWire_Delay_us(ONEWIRE_READ_CMD_US);
|
||||
OneWire_Delay_uw(ONEWIRE_READ_CMD_US);
|
||||
|
||||
/* Release line */
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
OneWire_Delay_us(ONEWIRE_READ_DELAY_US);
|
||||
OneWire_Delay_uw(ONEWIRE_READ_DELAY_US);
|
||||
|
||||
/* Read line value */
|
||||
bit = OneWire_Pin_Read(OW);
|
||||
|
||||
/* Wait 50us to complete 60us period */
|
||||
OneWire_Delay_us(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_READ_CMD_US - ONEWIRE_READ_DELAY_US);
|
||||
OneWire_Delay_uw(ONEWIRE_COMMAND_SLOT_US - ONEWIRE_READ_CMD_US - ONEWIRE_READ_DELAY_US);
|
||||
__enable_irq();
|
||||
#else
|
||||
bit = OneWireUART_ProcessBit(OW->huart, 1);
|
||||
bit = OneWireUART_ProcessBit(onewire_uart, 1);
|
||||
#endif
|
||||
/* Return bit value */
|
||||
return bit;
|
||||
@@ -107,7 +107,7 @@ void OneWire_WriteByte(OneWire_t* OW, uint8_t byte)
|
||||
byte >>= 1;
|
||||
}
|
||||
#else
|
||||
OneWireUART_ProcessByte(OW->huart, byte);
|
||||
OneWireUART_ProcessByte(onewire_uart, byte);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ uint8_t OneWire_ReadByte(OneWire_t* OW)
|
||||
byte |= (OneWire_ReadBit(OW) << 7);
|
||||
}
|
||||
#else
|
||||
byte = OneWireUART_ProcessByte(OW->huart, 0xFF);
|
||||
byte = OneWireUART_ProcessByte(onewire_uart, 0xFF);
|
||||
#endif
|
||||
|
||||
return byte;
|
||||
@@ -149,21 +149,21 @@ uint8_t OneWire_Reset(OneWire_t* OW)
|
||||
/* Line low, and wait 480us */
|
||||
OneWire_Pin_Level(OW, 0);
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
OneWire_Delay_us(ONEWIRE_RESET_PULSE_US);
|
||||
OneWire_Delay_uw(ONEWIRE_RESET_PULSE_US);
|
||||
|
||||
/* Release line and wait for 70us */
|
||||
OneWire_Pin_Mode(OW, Input);
|
||||
OneWire_Delay_us(ONEWIRE_PRESENCE_WAIT_US);
|
||||
OneWire_Delay_uw(ONEWIRE_PRESENCE_WAIT_US);
|
||||
|
||||
/* Check bit value */
|
||||
uint8_t rslt = OneWire_Pin_Read(OW);
|
||||
|
||||
/* Delay for 410 us */
|
||||
OneWire_Delay_us(ONEWIRE_PRESENCE_DURATION_US);
|
||||
OneWire_Delay_uw(ONEWIRE_PRESENCE_DURATION_US);
|
||||
#else
|
||||
|
||||
uint8_t rslt = 0;
|
||||
if(OneWireUART_Reset(OW->huart) == HAL_OK)
|
||||
if(OneWireUART_Reset(onewire_uart) == HAL_OK)
|
||||
rslt = 0;
|
||||
else
|
||||
rslt = 1;
|
||||
@@ -314,15 +314,14 @@ void OneWire_GetDevRom(OneWire_t* OW, uint8_t *ROM)
|
||||
*/
|
||||
void OneWire_Init(OneWire_t* OW)
|
||||
{
|
||||
#ifndef UART_Driver
|
||||
OneWire_Pin_Mode(OW, Output);
|
||||
OneWire_Pin_Level(OW, 1);
|
||||
OneWire_Delay_us(1000);
|
||||
OneWire_Delay_uw(1000);
|
||||
OneWire_Pin_Level(OW, 0);
|
||||
OneWire_Delay_us(1000);
|
||||
OneWire_Delay_uw(1000);
|
||||
OneWire_Pin_Level(OW, 1);
|
||||
OneWire_Delay_us(2000);
|
||||
#endif
|
||||
OneWire_Delay_uw(2000);
|
||||
|
||||
/* Reset the search state */
|
||||
OW->LastDiscrepancy = 0;
|
||||
OW->LastDeviceFlag = 0;
|
||||
@@ -14,8 +14,10 @@
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "ow_port.h"
|
||||
/* Driver Selection ----------------------------------------------------------*/
|
||||
|
||||
/* Driver Selection ----------------------------------------------------------*/
|
||||
//#define LL_Driver
|
||||
#define CMSIS_Driver
|
||||
/* OneWire Timings -----------------------------------------------------------*/
|
||||
#define ONEWIRE_RESET_PULSE_US 480 // Длительность импульса сброса
|
||||
#define ONEWIRE_PRESENCE_WAIT_US 70 // Ожидание ответа от датчика
|
||||
@@ -47,13 +49,8 @@ typedef struct
|
||||
uint8_t LastDeviceFlag;
|
||||
uint8_t RomByte[8];
|
||||
uint8_t RomCnt;
|
||||
#if defined(UART_Driver)
|
||||
UART_HandleTypeDef *huart;
|
||||
#else
|
||||
uint16_t DataPinNumb;
|
||||
uint16_t DataPin;
|
||||
GPIO_TypeDef *DataPort;
|
||||
#endif
|
||||
} OneWire_t;
|
||||
|
||||
/* External Function ---------------------------------------------------------*/
|
||||
@@ -8,6 +8,13 @@
|
||||
#include "onewire.h"
|
||||
#include "tim.h"
|
||||
|
||||
#ifdef PY32F002Bx5
|
||||
#define PIN_NUMB 0
|
||||
#endif
|
||||
#ifdef PY32F002Ax5
|
||||
#define PIN_NUMB 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The internal function is used as gpio pin mode
|
||||
* @param OW OneWire HandleTypedef
|
||||
@@ -15,26 +22,17 @@
|
||||
*/
|
||||
void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode)
|
||||
{
|
||||
#if defined(UART_Driver)
|
||||
#elif defined(CMSIS_Driver)
|
||||
volatile uint32_t *config_reg = (OW->DataPinNumb < 8) ? &(OW->DataPort->CRL) : &(OW->DataPort->CRH);
|
||||
uint32_t pin_pos = (OW->DataPinNumb < 8) ? (OW->DataPinNumb * 4) : ((OW->DataPinNumb - 8) * 4);
|
||||
// —брос текущих 4 бит (CNF + MODE)
|
||||
*config_reg &= ~(0xF << pin_pos);
|
||||
|
||||
if (Mode == Input)
|
||||
{
|
||||
// ¬ход с подт¤жкой или без Ц например, CNF = 0b01, MODE = 0b00
|
||||
// «десь устанавливаем вход с подт¤жкой:
|
||||
*config_reg |= (0x8 << pin_pos); // CNF=10, MODE=00 (вход с подт¤жкой)
|
||||
OW->DataPort->ODR |= (1 << OW->DataPinNumb); // ¬ключить подт¤жку вверх
|
||||
}
|
||||
else
|
||||
{
|
||||
// ¬ыход push-pull, 2 ћ√ц Ц MODE = 0b10, CNF = 0b00
|
||||
*config_reg |= (0x2 << pin_pos);
|
||||
}
|
||||
#elif defined(LL_Driver)
|
||||
#ifdef CMSIS_Driver
|
||||
if(Mode == Input)
|
||||
{
|
||||
OW->DataPort->MODER &= ~((GPIO_MODER_MODE0_Msk) << PIN_NUMB);
|
||||
OW->DataPort->MODER |= (GPIO_MODE_INPUT << (PIN_NUMB));
|
||||
}else{
|
||||
OW->DataPort->MODER &= ~((GPIO_MODER_MODE0_Msk) << PIN_NUMB);
|
||||
OW->DataPort->MODER |= (GPIO_MODE_OUTPUT_PP << PIN_NUMB);
|
||||
}
|
||||
#else
|
||||
#ifdef LL_Driver
|
||||
if(Mode == Input)
|
||||
{
|
||||
LL_GPIO_SetPinMode(OW->DataPort, OW->DataPin, LL_GPIO_MODE_INPUT);
|
||||
@@ -53,6 +51,7 @@ void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode)
|
||||
}
|
||||
HAL_GPIO_Init(OW->DataPort, &GPIO_InitStruct);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,8 +61,7 @@ void OneWire_Pin_Mode(OneWire_t* OW, PinMode Mode)
|
||||
*/
|
||||
void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
||||
{
|
||||
#if defined(UART_Driver)
|
||||
#elif defined(CMSIS_Driver)
|
||||
#ifdef CMSIS_Driver
|
||||
if (Level != GPIO_PIN_RESET)
|
||||
{
|
||||
OW->DataPort->BSRR = OW->DataPin;
|
||||
@@ -72,7 +70,8 @@ void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
||||
{
|
||||
OW->DataPort->BSRR = (uint32_t)OW->DataPin << 16u;
|
||||
}
|
||||
#elif defined(LL_Driver)
|
||||
#else
|
||||
#ifdef LL_Driver
|
||||
if(Level == 1)
|
||||
{
|
||||
LL_GPIO_SetOutputPin(OW->DataPort, OW->DataPin);
|
||||
@@ -82,6 +81,7 @@ void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
||||
#else
|
||||
HAL_GPIO_WritePin(OW->DataPort, OW->DataPin, Level);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,31 +91,26 @@ void OneWire_Pin_Level(OneWire_t* OW, uint8_t Level)
|
||||
*/
|
||||
uint8_t OneWire_Pin_Read(OneWire_t* OW)
|
||||
{
|
||||
#if defined(UART_Driver)
|
||||
return 0;
|
||||
#elif defined(CMSIS_Driver)
|
||||
#ifdef CMSIS_Driver
|
||||
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
||||
#elif defined(LL_Driver)
|
||||
#else
|
||||
#ifdef LL_Driver
|
||||
return ((OW->DataPort->IDR & OW->DataPin) != 0x00U) ? 1 : 0;
|
||||
#else
|
||||
return HAL_GPIO_ReadPin(OW->DataPort, OW->DataPin);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t tim_1us_period = OW_TIM_1US_PERIOD;
|
||||
void OneWire_Delay_us(uint32_t us)
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
uint32_t tim_1us_period = 24;
|
||||
void OneWire_Delay_uw(uint32_t us)
|
||||
{
|
||||
uint32_t ticks = us * tim_1us_period;
|
||||
uint16_t start = OW_TIM->CNT;
|
||||
uint32_t elapsed = 0;
|
||||
uint16_t prev = start;
|
||||
|
||||
while (elapsed < ticks)
|
||||
{
|
||||
uint16_t curr = OW_TIM->CNT;
|
||||
uint16_t delta = (uint16_t)(curr - prev); // учЄт переполнени¤
|
||||
elapsed += delta;
|
||||
prev = curr;
|
||||
}
|
||||
}
|
||||
|
||||
// start = htim1.Instance->CNT;
|
||||
// end = start + us*tim_1us_period;
|
||||
TIM1->CNT = 0;
|
||||
end = us*tim_1us_period;
|
||||
|
||||
while(TIM1->CNT < end) {};
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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******************/
|
||||
@@ -1,13 +1,13 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file gpio.h
|
||||
* @file iwdg.h
|
||||
* @brief This file contains all the function prototypes for
|
||||
* the gpio.c file
|
||||
* the iwdg.c file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
@@ -18,8 +18,8 @@
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __GPIO_H__
|
||||
#define __GPIO_H__
|
||||
#ifndef __IWDG_H__
|
||||
#define __IWDG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -32,11 +32,13 @@ extern "C" {
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
extern IWDG_HandleTypeDef hiwdg;
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
void MX_GPIO_Init(void);
|
||||
void MX_IWDG_Init(void);
|
||||
|
||||
/* USER CODE BEGIN Prototypes */
|
||||
|
||||
@@ -45,5 +47,6 @@ void MX_GPIO_Init(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*__ GPIO_H__ */
|
||||
|
||||
#endif /* __IWDG_H__ */
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @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
|
||||
|
||||
|
||||
#ifdef PY32F002Bx5
|
||||
#define TIM_MB TIM14
|
||||
#define __HAL_DBGMCU_FREEZE_TIM_MB __HAL_DBGMCU_FREEZE_TIM14
|
||||
#define __HAL_RCC_TIM_MB_CLK_ENABLE __HAL_RCC_TIM14_CLK_ENABLE
|
||||
#define TIM_MB_IRQn TIM14_IRQn
|
||||
#define TIM_MB_IRQHandler TIM14_IRQHandler
|
||||
#endif
|
||||
#ifdef PY32F002Ax5
|
||||
#define TIM_MB TIM16
|
||||
#define __HAL_DBGMCU_FREEZE_TIM_MB __HAL_DBGMCU_FREEZE_TIM16
|
||||
#define __HAL_RCC_TIM_MB_CLK_ENABLE __HAL_RCC_TIM16_CLK_ENABLE
|
||||
#define TIM_MB_IRQn TIM16_IRQn
|
||||
#define TIM_MB_IRQHandler TIM16_IRQHandler
|
||||
#endif
|
||||
|
||||
/* Exported variables prototypes ---------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void Error_Handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MAIN_H */
|
||||
|
||||
/************************ (C) COPYRIGHT Puya *****END OF 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******************/
|
||||
@@ -1,66 +1,48 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_it.h
|
||||
* @file py32f002b_it.h
|
||||
* @author MCU Application Team
|
||||
* @brief This file contains the headers of the interrupt handlers.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
* <h2><center>© Copyright (c) Puya Semiconductor Co.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* 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.
|
||||
* <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
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32F1xx_IT_H
|
||||
#define __STM32F1xx_IT_H
|
||||
#ifndef __PY32F002B_IT_H
|
||||
#define __PY32F002B_IT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void NMI_Handler(void);
|
||||
void HardFault_Handler(void);
|
||||
void MemManage_Handler(void);
|
||||
void BusFault_Handler(void);
|
||||
void UsageFault_Handler(void);
|
||||
void SVC_Handler(void);
|
||||
void DebugMon_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32F1xx_IT_H */
|
||||
#endif /* __PY32F002B_IT_H */
|
||||
|
||||
/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
|
||||
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file py32f0xx_hal_conf.h
|
||||
* @author MCU Application Team
|
||||
* @Version V1.0.0
|
||||
* @Date
|
||||
* @brief HAL configuration file.
|
||||
******************************************************************************
|
||||
**/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __PY32F0xx_HAL_CONF_H
|
||||
#define __PY32F0xx_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)8000000) /*!< Value of the Internal oscillator in Hz */
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/**
|
||||
* @brief Adjust the value of External High Speed oscillator (HXT) 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 HXT start up, in ms */
|
||||
#endif /* HSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief Internal Low Speed Internal oscillator (LIRC) value.
|
||||
*/
|
||||
#if !defined (LSI_VALUE)
|
||||
#define LSI_VALUE 32768U /*!< LIRC 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 (LXT) 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 LXT 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 1
|
||||
|
||||
/* ########################## 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 "py32f0xx_hal_rcc.h"
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_EXTI_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_exti.h"
|
||||
#endif /* HAL_EXTI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_gpio.h"
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_cortex.h"
|
||||
#endif /* HAL_CORTEX_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_DMA_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_dma.h"
|
||||
#endif /* HAL_DMA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ADC_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_adc.h"
|
||||
#endif /* HAL_ADC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRC_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_crc.h"
|
||||
#endif /* HAL_CRC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_COMP_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_comp.h"
|
||||
#endif /* HAL_COMP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_flash.h"
|
||||
#endif /* HAL_FLASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_i2c.h"
|
||||
#endif /* HAL_I2C_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IWDG_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_iwdg.h"
|
||||
#endif /* HAL_IWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PWR_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_pwr.h"
|
||||
#endif /* HAL_PWR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_rtc.h"
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_spi.h"
|
||||
#endif /* HAL_SPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TIM_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_tim.h"
|
||||
#endif /* HAL_TIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LPTIM_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_lptim.h"
|
||||
#endif /* HAL_LPTIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_uart.h"
|
||||
#endif /* HAL_UART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_WWDG_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_wwdg.h"
|
||||
#endif /* HAL_WWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LED_MODULE_ENABLED
|
||||
#include "py32f0xx_hal_led.h"
|
||||
#endif /* HAL_LED_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_USART_MODULE_ENABLED
|
||||
#include "py32f0xx_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 /* __PY32F0xx_HAL_CONF_H */
|
||||
|
||||
|
||||
@@ -32,13 +32,15 @@ extern "C" {
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
extern TIM_HandleTypeDef htim3;
|
||||
extern TIM_HandleTypeDef htim1;
|
||||
extern TIM_HandleTypeDef htim14;
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
void MX_TIM3_Init(void);
|
||||
void MX_TIM1_Init(void);
|
||||
void MX_TIMMB_Init(void);
|
||||
|
||||
/* USER CODE BEGIN Prototypes */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* Copyright (c) 2024 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "crc_algs.h"
|
||||
|
||||
|
||||
|
||||
/*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;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "main.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);
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @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
|
||||
|
||||
#define RS_EnableReceive() GPIOB->ODR |= GPIO_PIN_3
|
||||
#define RS_EnableTransmit() GPIOB->ODR &= ~GPIO_PIN_3
|
||||
/**
|
||||
* @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_
|
||||
@@ -0,0 +1,1018 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @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"
|
||||
/* 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, NULL, 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)
|
||||
{
|
||||
|
||||
modbus_msg->Func_Code += ERR_VALUES_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,394 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @file modbus.h
|
||||
* @brief Заголовочный файл модуля MODBUS.
|
||||
* @details Данный файл необходимо подключить в rs_message.h. После подключать
|
||||
* rs_message.h к основному проекту.
|
||||
*
|
||||
* @defgroup MODBUS
|
||||
* @brief Modbus stuff
|
||||
*
|
||||
*************************************************************************/
|
||||
#ifndef __MODBUS_H_
|
||||
#define __MODBUS_H_
|
||||
|
||||
#include "main.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---/////////////////////////////
|
||||
/***************************************************************************
|
||||
*******************************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
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////---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_
|
||||
@@ -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////////////////////
|
||||
@@ -0,0 +1,614 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @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);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
RS_RES = RS_OK;
|
||||
printf_rs("\n%d: RS: Start Receiving...", uwTick);
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
RS_RES = RS_OK;
|
||||
printf_rs("\n%d: RS: Start Transmitting...", uwTick);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
TIM_MB->DIER &= ~(TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM_MB->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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
TIM_MB->DIER &= ~(TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM_MB->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
|
||||
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
|
||||
{
|
||||
TIM_MB->DIER &= ~(TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM_MB->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
|
||||
{
|
||||
TIM_MB->DIER |= (TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM_MB->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
|
||||
{
|
||||
|
||||
/* 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)
|
||||
{
|
||||
TIM_MB->SR = ~(TIM_IT_UPDATE);
|
||||
/* Disable the TIM Update interrupt */
|
||||
TIM_MB->DIER &= ~(TIM_IT_UPDATE);
|
||||
/* Disable the Peripheral */
|
||||
TIM_MB->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---------------
|
||||
//-------------------------------------------------------------------
|
||||
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
**************************************************************************
|
||||
* @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 "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_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_
|
||||
@@ -0,0 +1,384 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @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_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);
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @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();
|
||||
|
||||
|
||||
/* Íàñòðîéêà ïèíà PB0 (OneWire) */
|
||||
DS_GPIO_Port->MODER &= ~(GPIO_MODER_MODE0);
|
||||
DS_GPIO_Port->MODER |= (GPIO_MODE_OUTPUT_PP << GPIO_MODER_MODE0_Pos);
|
||||
DS_GPIO_Port->PUPDR &= ~(GPIO_PUPDR_PUPD0);
|
||||
DS_GPIO_Port->PUPDR |= (GPIO_NOPULL << GPIO_PUPDR_PUPD0_Pos);
|
||||
DS_GPIO_Port->OSPEEDR |= (GPIO_SPEED_FREQ_VERY_HIGH << GPIO_OSPEEDR_OSPEED0_Pos);
|
||||
|
||||
/* Óñòàíîâêà PA1, PA4, PA5 â âûñîêèé óðîâåíü */
|
||||
GPIOA->BSRR = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
|
||||
|
||||
/*Configure LED GPIO pin : PA1 PA4 PA5 */
|
||||
/* Íàñòðîéêà ïèíîâ PA1, PA4, PA5 */
|
||||
GPIOA->MODER &= ~(GPIO_MODER_MODE1 | GPIO_MODER_MODE4 | GPIO_MODER_MODE5);
|
||||
GPIOA->MODER |= (GPIO_MODE_OUTPUT_PP << GPIO_MODER_MODE1_Pos) |
|
||||
(GPIO_MODE_OUTPUT_PP << GPIO_MODER_MODE4_Pos) |
|
||||
(GPIO_MODE_OUTPUT_PP << GPIO_MODER_MODE5_Pos);
|
||||
GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD1 | GPIO_PUPDR_PUPD4 | GPIO_PUPDR_PUPD5);
|
||||
GPIOA->PUPDR |= (GPIO_NOPULL << GPIO_PUPDR_PUPD1_Pos) |
|
||||
(GPIO_NOPULL << GPIO_PUPDR_PUPD4_Pos) |
|
||||
(GPIO_NOPULL << GPIO_PUPDR_PUPD5_Pos);
|
||||
GPIOA->OSPEEDR |= (GPIO_SPEED_FREQ_LOW << GPIO_OSPEEDR_OSPEED1_Pos) |
|
||||
(GPIO_SPEED_FREQ_LOW << GPIO_OSPEEDR_OSPEED4_Pos) |
|
||||
(GPIO_SPEED_FREQ_LOW << GPIO_OSPEEDR_OSPEED5_Pos);
|
||||
|
||||
/*Configure LED GPIO pin : PB3 (Receive Enable) */
|
||||
GPIOB->MODER &= ~(GPIO_MODER_MODE3);
|
||||
GPIOB->MODER |= (GPIO_MODE_OUTPUT_PP << GPIO_MODER_MODE3_Pos);
|
||||
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPD3);
|
||||
GPIOB->PUPDR |= (GPIO_NOPULL << GPIO_PUPDR_PUPD3_Pos);
|
||||
GPIOB->OSPEEDR |= (GPIO_SPEED_FREQ_HIGH << GPIO_OSPEEDR_OSPEED3_Pos);
|
||||
}
|
||||
/************************ (C) COPYRIGHT Puya *****END OF 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 */
|
||||
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @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_TIM_MB();
|
||||
/* Reset of all peripherals, Initializes the Systick. */
|
||||
HAL_Init();
|
||||
|
||||
/* System clock configuration */
|
||||
APP_SystemClockConfig();
|
||||
|
||||
// MX_IWDG_Init();
|
||||
MX_GPIO_Init();
|
||||
MX_TIM1_Init();
|
||||
MX_TIMMB_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();
|
||||
// }
|
||||
/* Âêëþ÷åíèå HSI */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
while (!(RCC->CR & RCC_CR_HSIRDY));
|
||||
|
||||
/* Íàñòðîéêà äåëèòåëÿ HSI */
|
||||
RCC->CR &= ~RCC_CR_HSIDIV;
|
||||
RCC->CR |= RCC_HSI_DIV1;
|
||||
|
||||
/* Êàëèáðîâêà HSI */
|
||||
RCC->ICSCR &= ~RCC_ICSCR_HSI_TRIM;
|
||||
RCC->ICSCR |= (RCC_HSICALIBRATION_24MHz << RCC_ICSCR_HSI_TRIM_Pos);
|
||||
|
||||
/* Îòêëþ÷åíèå LSI è LSE */
|
||||
#ifdef RCC_LSE_SUPPORT
|
||||
RCC->CSR &= ~RCC_CSR_LSION;
|
||||
RCC->BDCR &= ~RCC_BDCR_LSEON;
|
||||
#endif
|
||||
/* Îòêëþ÷åíèå áàéïàñà HSE */
|
||||
RCC->CR &= ~0x00000000U;
|
||||
|
||||
/* Óñòàíîâêà èñòî÷íèêà ñèñòåìíîé òàêòîâîé ÷àñòîòû */
|
||||
RCC->CFGR &= ~RCC_CFGR_SW;
|
||||
#ifdef PY32F002Bx5
|
||||
RCC->CFGR |= RCC_SYSCLKSOURCE_HSISYS;
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_SYSCLKSOURCE_HSISYS);
|
||||
#endif
|
||||
#ifdef PY32F002Ax5
|
||||
RCC->CFGR |= RCC_SYSCLKSOURCE_HSI;
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_SYSCLKSOURCE_HSI);
|
||||
#endif
|
||||
|
||||
/* Óñòàíîâêà äåëèòåëåé */
|
||||
RCC->CFGR &= ~(RCC_CFGR_HPRE | RCC_CFGR_PPRE_1);
|
||||
RCC->CFGR |= RCC_SYSCLK_DIV1 | RCC_HCLK_DIV1;
|
||||
|
||||
/* Íàñòðîéêà çàäåðæêè ôëåø-ïàìÿòè */
|
||||
FLASH->ACR &= ~FLASH_ACR_LATENCY;
|
||||
FLASH->ACR |= FLASH_LATENCY_0;
|
||||
}
|
||||
|
||||
uint32_t HAL_RCC_GetPCLK1Freq(void)
|
||||
{
|
||||
/* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
|
||||
return (uint32_t)((SystemCoreClock) >> (APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE) >> RCC_CFGR_PPRE_Pos] & 0x1FU));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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******************/
|
||||
@@ -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******************/
|
||||
@@ -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 TIM_MB_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******************/
|
||||
@@ -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******************/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user