Обновлены шапки и по мелочи

This commit is contained in:
2025-12-28 14:06:19 +03:00
parent f3e76e105a
commit 8b930ebe12
12 changed files with 523 additions and 251 deletions

View File

@@ -12,7 +12,7 @@
* - Установку callback-функций для событий:
* - завершение секвенсора
* - половина буфера
* - полный буфер
* - полный буфера
* - ошибка
* + Управление цифровыми компараторами (DC0-DC3):
* - Инициализацию и конфигурацию компараторов
@@ -39,56 +39,102 @@
##### Как использовать этот драйвер #####
==============================================================================
1. Общие функции ADC:
-------------------------- Общие функции АЦП --------------------------------
a) Инициализация:
(+) adc_init_first() обязательный вызов перед использованием ADC
1. Инициализация АЦП:
(+) adc_init_first() - обязательный вызов перед использованием АЦП
(+) Настраивает тактирование, GPIO и ожидает готовности аналогового модуля
2. Калибровка каналов:
(+) ADC_Channel_Calibr(&hadc, channel, OFFSET, GAIN) - калибровка смещения и усиления
(+) Формула калибровки: Dc = Dr * (4096+GAIN)/4096 + OFFSET
3. Чтение значений каналов:
(+) ADC_Channel_GetValue(&hadc, channel) - получение текущего значения канала
(+) Данные обновляются автоматически при работе секвенсоров
4. Инициализация GPIO:
(+) adc_gpio_init(hadc.ChannelEnable) - настраивает пины выбранных каналов
(+) Вызывается автоматически в adc_init_first()
------------------------ Секвенсоры (SEQ0, SEQ1) ----------------------------
b) Работа с каналами:
(+) ADC_Get_ChannelValue(&hadc, channel) — получение текущего значения канала
1. Настройка в periph_config.h:
(+) Определите adc_seq0_config, adc_seq1_config
(+) Настройте ADC_ClockSource и ADC_ClockMHz для тактирования АЦП
(+) Определите adc_ch_config для включения нужных каналов
2. Инициализация секвенсоров:
(+) adc_seq_init(&hadc, ADC_SEQ_Num_0, &adc_seq0_config) - инициализация SEQ0
(+) Аналогично для SEQ1 при необходимости
3. Работа с секвенсорами:
(+) ADC_SEQ_Start(&hadc, ADC_SEQ_Num_0, buffer, buffer_size) - запуск с буфером
(+) ADC_SEQ_Stop(&hadc, ADC_SEQ_Num_0) - остановка секвенсора
(+) ADC_SEQ_Set_Callback(&hadc, ADC_SEQ_Num_0, тип, func) - установка обработчика
(+) ADC_SEQ_SoftwareStart() - программный запуск преобразования
4. Обработка прерываний секвенсоров:
(+) ADC_SEQ0_IRQHandler - вызвать adc_seq_irq_handler(&hadc, ADC_SEQ_Num_0)
(+) ADC_SEQ1_IRQHandler - вызвать adc_seq_irq_handler(&hadc, ADC_SEQ_Num_1)
------------------------ Цифровые компараторы (DC) --------------------------
==============================================================================
##### Особенности работы #####
==============================================================================
-------------------------- Общие особенности --------------------------------
2. Секвенсоры (SEQ):
a) Настройка периферии (periph_config.h):
(+) Определить структуры ADC_SEQ_ExtInit_TypeDef для нужных секвенсоров:
adc_seq0_config, adc_seq1_config
(+) Настроить последовательность каналов, режимы работы
(+) Настроить прерывания (IT) и ITCount
(+) Определить callback-функции (можно NULL)
b) Инициализация:
(+) adc_init_first() — первичная настройка тактирования, сброс ADC, инициализация хендла hadc
(+) adc_seq_init(&hadc, ADC_SEQ_Num_0, &adc_seq0_config) — инициализация конкретного секвенсора
c) Callback-функции (опционально):
(+) ADC_SEQ_Set_Callback(&hadc, ADC_SEQ_Num_0, ADC_Callback_SeqCplt, Callback) — завершение секвенсора
(+) ADC_SEQ_Set_Callback(&hadc, ADC_SEQ_Num_0, ADC_Callback_BuffHalf, Callback) — половина буфера
(+) ADC_SEQ_Set_Callback(&hadc, ADC_SEQ_Num_0, ADC_Callback_BuffFull, Callback) — полный буфер
(+) ADC_SEQ_Set_Callback(&hadc, ADC_SEQ_Num_0, ADC_Callback_Error, Callback) — ошибки
d) Запуск и остановка:
(+) ADC_SEQ_Start(&hadc, ADC_SEQ_Num_0, data_buffer, buffer_size) — запуск с буфером
(+) ADC_SEQ_Stop(&hadc, ADC_SEQ_Num_0) — остановка секвенсора
e) Работа с данными:
(+) ADC_Get_ChannelValue(&hadc, channel) — чтение текущего значения канала из хендла
(+) ADC_SEQ_SoftwareStart() — программный запуск преобразования
f) Обработка прерываний:
(+) adc_seq_irq_handler(&hadc, ADC_SEQ_Num_0) — обработчик прерываний секвенсора
- В обработчике автоматически читаются данные из FIFO, обновляются каналы и буфер
- В обработчиках автоматически вызываются соответствующие callback-функции
и сбрасываются флаги
g) Особенности работы:
(+) Данные автоматически читаются из FIFO в прерывании
(+) Поддерживается кольцевой буфер (BufferCircular)
(+) Автоматический вызов callback при заполнении половины/всего буфера
3. Цифровые компараторы (DC):
- Частота ADC:
- Задается через ADC_ClockMHz в periph_config.h
- Автоматически настраивается делитель от источника тактирования
- Аналоговый модуль (AM):
- Требует времени для старта после включения (до 1 мс)
- adc_init_first() ожидает готовности AM с таймаутом 1 секунда
- При неудаче вызывает Error_Handler()
- Калибровка:
- OFFSET: смещение в диапазоне [-255, 255] квантов АЦП
- GAIN: коэффициент усиления в диапазоне [-255, 255] квантов АЦП (4096+GAIN)
- Калибровка применяется аппаратно для каждого канала отдельно
------------------------ Секвенсоры (SEQ0, SEQ1) ----------------------------
- Буферизация данных:
- Данные в буфере хранятся в формате [канал][время]
- При buffer_size=100 для 2 каналов буфер будет 200 элементов
- Буфер может быть кольцевым (BufferCircular=ENABLE)
- Прерывания секвенсоров:
- Генерируются после заданного количества рестартов (ITCount)
- ITCount=0 означает прерывание после каждого прохода секвенсора
- Данные автоматически читаются из FIFO в прерывании
- Работа с усреднением:
- Аппаратное усреднение измерения:
- 2, 4, 8, 16, 32 или 64 выборок (SEQ_Init.ReqAverage)
- Включается через SEQ_Init.ReqAverageEn
- Усредненные значения помещаются в FIFO как единый результат
- Аппаратное усреднение рестартов
- 2, 4, 8, 16, 32, 64, 128, 256 выборок (SER_Init.RestartCount + 1)
- Включается через SEQ_Init.RestartAverageEn
- Усредненные значения помещаются в FIFO как единый результат
- Таймер рестартов:
- Период в тиках ADC_ClockMHz/2 (драйвер автоматически делит на 2)
- Используется для периодического запуска секвенсора
- При RestartTimer=0 рестарт происходит немедленно
- Чтение FIFO:
- FIFO буфер на 32 элемента автоматически читается в прерывании
- Данные распределяются по каналам согласно последовательности в Req[0..3]
- При переполнении FIFO (>32 элементов до прерывания) возможна потеря данных
------------------------ Цифровые компараторы (DC) --------------------------
@endverbatim
******************************************************************************
*/
@@ -122,6 +168,10 @@ void adc_init_first(void)
// Включаем аналоговый модуль
ADC_AM_Cmd(ENABLE);
// Настройка пинов для ADC
hadc.ChannelEnable = &adc_ch_config;
adc_gpio_init(hadc.ChannelEnable);
hadc.Instance = ADC;
#endif
@@ -140,15 +190,6 @@ void adc_init_first(void)
}
#endif
#if (USE_ADC_DC0==1)
#endif
#if (USE_ADC_DC1==1)
#endif
#if (USE_ADC_DC2==1)
#endif
#if (USE_ADC_DC3==1)
#endif
#if (USE_ADC_SEQ0==1) || (USE_ADC_SEQ1==1) || (USE_ADC_DC0==1) || (USE_ADC_DC1==1) || (USE_ADC_DC2==1) || (USE_ADC_DC3==1)
uint32_t starttick = millis();
while (!ADC_AM_ReadyStatus()) {
@@ -158,6 +199,41 @@ void adc_init_first(void)
#endif
}
/**
* @brief Записать калибровочные значения канала
* @param hadc указатель на хендл АЦП
* @param channel номер канала
* @param OFFSET Коэффициент корректировки смещения нуля АЦП в квантах [-255:255]
* @param GAIN Коэффициент корректировки усиления зн АЦП в квантах [-255:255]
* @retval значение ADC (0 если данные невалидны)
* @details Результат преобразования передается на схему коррекции, которая нивелирует
* ошибку усиления и смещения нуля и работа которой описывается формулой
* Dc = Dr * (4096+GAIN)/4096 + OFFSET
*/
OperationStatus ADC_Channel_Calibr(ADC_HandleTypeDef *hadc, ADC_CH_Num_TypeDef channel, int OFFSET, int GAIN)
{
if (!hadc || (int)channel >= ADC_CH_Total)
return ERROR;
ADC_CH_SetOffsetTrim(channel, OFFSET);
ADC_CH_SetGainTrim(channel, GAIN);
return OK;
}
/**
* @brief Получение текущего значения канала
* @param hadc указатель на хендл АЦП
* @param channel номер канала
* @retval значение ADC (0 если данные невалидны)
*/
uint16_t ADC_Channel_GetValue(ADC_HandleTypeDef *hadc, ADC_CH_Num_TypeDef channel)
{
if (!hadc || (int)channel >= ADC_CH_Total)
return 0;
return hadc->ChannelData[channel];
}
//-- ADC Sequencers API functions ----------------------------------------------
/**
@@ -302,20 +378,6 @@ OperationStatus ADC_SEQ_Stop(ADC_HandleTypeDef *hadc, ADC_SEQ_Num_TypeDef SEQ_Nu
return OK;
}
/**
* @brief Получение текущего значения канала
* @param hadc указатель на хендл АЦП
* @param channel номер канала
* @retval значение ADC (0 если данные невалидны)
*/
uint16_t ADC_Get_ChannelValue(ADC_HandleTypeDef *hadc, ADC_CH_Num_TypeDef channel)
{
if (!hadc || (int)channel >= ADC_CH_Total)
return 0;
return hadc->ChannelData[channel];
}
/**
* @brief Программный запуск преобразования
*/
@@ -323,7 +385,7 @@ void ADC_SEQ_SoftwareStart(void)
{
ADC_SEQ_SwStartCmd();
}
int itcnt;
/**
* @brief Обработчик прерываний секвенсора
* @param hadc указатель на хендл АЦП
@@ -335,7 +397,7 @@ void adc_seq_irq_handler(ADC_HandleTypeDef *hadc, ADC_SEQ_Num_TypeDef SEQ_Num)
if (!hadc || !hadc->Instance || !hadc->SEQ[SEQ_Num].Config)
return;
// GPIO_SetBits(GPIOA, GPIO_Pin_7);
itcnt++;
ADC_SEQ_HandleTypeDef *hseq = &hadc->SEQ[SEQ_Num];
ADC_SEQ_ExtInit_TypeDef *conf = hseq->Config;
@@ -482,3 +544,45 @@ static void __adc_seq_fifo_read(ADC_HandleTypeDef *hadc, ADC_SEQ_Num_TypeDef SEQ
//-- ADC Digital Comparators API functions -------------------------------------
//-- ADC GPIO functions --------------------------------------------------------
/**
* @brief Инициализация GPIO для ADC
*/
void adc_gpio_init(ADC_ChannelEnableTypeDef *ChEn)
{
#if (USE_ADC_SEQ0==1) || (USE_ADC_SEQ1==1) || (USE_ADC_DC0==1) || (USE_ADC_DC1==1) || (USE_ADC_DC2==1) || (USE_ADC_DC3==1)
// Получаем структуру
GPIO_Init_TypeDef *ch0_config = gpio_get_init(ADC_Ch0_GPIO_Port, ADC_Ch0_Pin);
GPIO_Init_TypeDef *ch1_config = gpio_get_init(ADC_Ch1_GPIO_Port, ADC_Ch1_Pin);
GPIO_Init_TypeDef *ch2_config = gpio_get_init(ADC_Ch2_GPIO_Port, ADC_Ch2_Pin);
GPIO_Init_TypeDef *ch3_config = gpio_get_init(ADC_Ch3_GPIO_Port, ADC_Ch3_Pin);
if(ChEn->Ch0)
{
GPIO_StructInit(ch0_config);
ch0_config->Pin = ADC_Ch0_Pin;
GPIO_Init(ADC_Ch0_GPIO_Port, ch0_config);
}
if(ChEn->Ch1)
{
GPIO_StructInit(ch1_config);
ch1_config->Pin = ADC_Ch1_Pin;
GPIO_Init(ADC_Ch1_GPIO_Port, ch1_config);
}
if(ChEn->Ch2)
{
GPIO_StructInit(ch2_config);
ch2_config->Pin = ADC_Ch2_Pin;
GPIO_Init(ADC_Ch2_GPIO_Port, ch2_config);
}
if(ChEn->Ch3)
{
GPIO_StructInit(ch3_config);
ch3_config->Pin = ADC_Ch3_Pin;
GPIO_Init(ADC_Ch3_GPIO_Port, ch3_config);
}
#endif
}