Добавлено:
- рефакторинг названий: - маленькие буквы - инит периферии - ТакойСтильФункций - API для использования - сделаны шапки с инструкциями к функциями - доработан ацп секвенсора - доработан систем тики. можно настроить его на разные частоты и подключить коллбеки на разный период - в gpio добавлены функции для кнопок и диодов - генерация бинарника
This commit is contained in:
@@ -1,19 +1,96 @@
|
||||
/*==============================================================================
|
||||
* Инициализация тактирования с использованием бибилотеки PLIB035
|
||||
*------------------------------------------------------------------------------
|
||||
* ЦНИИ СЭТ, Разваляев Алексей <wot890089@mail.ru>
|
||||
*==============================================================================
|
||||
* ЦНИИ СЭТ
|
||||
*==============================================================================
|
||||
*/
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file sysclk.c
|
||||
* @author Разваляев Алексей
|
||||
* @brief Драйвер тактирования системы на основе PLIB035.
|
||||
* Этот файл содержит:
|
||||
* + Инициализацию системного тактирования (PLL, осцилляторы)
|
||||
* + Настройку частоты ядра и периферии
|
||||
* + Управление системным таймером (SysTick)
|
||||
* + Функции для работы со временем (millis, micros)
|
||||
* + Систему периодических коллбеков
|
||||
* + Настройку тактирования периферии
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Использование этого драйвера предполагает наличие корректных настроек:
|
||||
* - Определены константы SYSCLK_CORE_CLOCK_MHZ и SYSCLK_Oscil_Type в periph_config.h
|
||||
* - Определен тип системного тика SYSCLK_TickType в periph_config.h
|
||||
*
|
||||
******************************************************************************
|
||||
* @verbatim
|
||||
==============================================================================
|
||||
##### Как использовать этот драйвер #####
|
||||
==============================================================================
|
||||
|
||||
1. Настройка периферии (periph_config.h):
|
||||
(+) Определить SYSCLK_CORE_CLOCK_MHZ - частота ядра в МГц (например, 100)
|
||||
(+) Определить SYSCLK_Oscil_Type - тип осциллятора (RCU_Oscil_OSE или RCU_Oscil_OSI)
|
||||
(+) Определить SYSCLK_TickType - тип системного тика (SYSCLK_Tick_1us, SYSCLK_Tick_1ms и т.д.)
|
||||
|
||||
//-- Includes ------------------------------------------------------------------
|
||||
2. Инициализация тактирования:
|
||||
(+) sysclk_init() — обязательный вызов в начале программы
|
||||
- Автоматически настраивает PLL для заданной частоты
|
||||
- Настраивает SysTick для генерации системных тиков
|
||||
- Обновляет SystemCoreClock
|
||||
|
||||
3. Работа со временем:
|
||||
(+) millis() — получение текущего времени в миллисекундах
|
||||
(+) micros() — получение текущего времени в микросекундах
|
||||
(+) sysclk_irq_handler() — обработчик прерываний SysTick (должен вызываться из SysTick_Handler)
|
||||
|
||||
4. Система коллбеков:
|
||||
(+) SYSCLK_Set_Callback() — добавление периодического коллбека
|
||||
- Коллбеки автоматически вызываются в sysclk_irq_handler() с заданным периодом
|
||||
- Максимальное количество коллбеков: SYSCLK_NUMB_OF_CUSTOM_CALLBACKS
|
||||
|
||||
5. Настройка тактирования Периферии:
|
||||
(+) АЦП: rcu_set_clock_adc(ClkSrc, ClkMHz, state)
|
||||
- ClkSrc: источник тактирования (RCU_PeriphClk_OSEClk, RCU_PeriphClk_PLLClk и т.д.)
|
||||
- ClkMHz: желаемая частота ADC в МГц
|
||||
- state: включение/выключение тактирования
|
||||
|
||||
6. Особенности работы:
|
||||
(+) Системные тики работают на основе SysTick
|
||||
(+) Поддерживаются различные периоды тиков от 1 мкс до 100 мс
|
||||
(+) Переполнение счетчиков происходит через ~49 дней
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "periph_config.h"
|
||||
|
||||
__IO uint32_t uwTick; // Milliseconds ticks
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @brief Счетчик миллисекунд */
|
||||
__IO uint32_t msTick = 0;
|
||||
|
||||
/** @brief Счетчик микросекунд */
|
||||
__IO uint32_t usTick = 0;
|
||||
|
||||
/** @brief Инкремент для миллисекунд */
|
||||
static __IO uint32_t msTickInc = 0;
|
||||
|
||||
/** @brief Инкремент для микросекунд */
|
||||
static __IO uint32_t usTickInc = 0;
|
||||
|
||||
/** @brief Обработчик системных коллбеков */
|
||||
static SYSCLK_CallbackHandleTypeDef hsyscb = {0};
|
||||
//-- Defines -------------------------------------------------------------------
|
||||
|
||||
|
||||
//-- Private function prototypes -----------------------------------------------
|
||||
static inline void millis_inc(void);
|
||||
static inline void micros_inc(void);
|
||||
|
||||
//-- Peripheral init functions -------------------------------------------------
|
||||
/**
|
||||
* @brief Инициализация системного тактирования.
|
||||
* @details Настраивает PLL, SysTick и счетчики времени.
|
||||
* Должна быть вызвана первой в функции main().
|
||||
*/
|
||||
void sysclk_init(void)
|
||||
{
|
||||
OperationStatus status;
|
||||
@@ -23,41 +100,158 @@ void sysclk_init(void)
|
||||
Error_Handler();
|
||||
}
|
||||
SystemCoreClockUpdate();
|
||||
RCU_ClkOutConfig(RCU_SysPeriphClk_PLLClk, 1, ENABLE);
|
||||
RCU_ClkOutCmd(ENABLE);
|
||||
// RCU_ClkOutConfig(RCU_SysPeriphClk_PLLClk, 1, ENABLE);
|
||||
// RCU_ClkOutCmd(ENABLE);
|
||||
|
||||
/* Прерывание должно быть каждую миллисекунду:
|
||||
Для тактирования N Гц это каждый N / 1000 тик */
|
||||
SysTick_Config(SYSCLK_CORE_CLOCK_MHZ*__MHZ/1000);
|
||||
SysTick_Config(SYSCLK_CORE_CLOCK_MHZ*__MHZ/SYSCLK_TickType);
|
||||
switch(SYSCLK_TickType)
|
||||
{
|
||||
case SYSCLK_Tick_1us:
|
||||
usTickInc = 1;
|
||||
msTickInc = 1;
|
||||
break;
|
||||
case SYSCLK_Tick_10us:
|
||||
usTickInc = 10;
|
||||
msTickInc = 1;
|
||||
break;
|
||||
case SYSCLK_Tick_100us:
|
||||
usTickInc = 100;
|
||||
msTickInc = 1;
|
||||
break;
|
||||
case SYSCLK_Tick_1ms:
|
||||
usTickInc = 1000;
|
||||
msTickInc = 1;
|
||||
break;
|
||||
case SYSCLK_Tick_10ms:
|
||||
usTickInc = 10000;
|
||||
msTickInc = 10;
|
||||
break;
|
||||
case SYSCLK_Tick_100ms:
|
||||
usTickInc = 100000;
|
||||
msTickInc = 100;
|
||||
break;
|
||||
default:
|
||||
/* Должен быть определен в periph_config.h */
|
||||
Error_Handler();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Общий обработчик прерываний SysClock
|
||||
* @details Обрабатывает мс и мкс и вызывает коллбеки
|
||||
*/
|
||||
void sysclk_irq_handler(void)
|
||||
{
|
||||
static uint32_t usAccumulator = 0; // Накопитель мкс
|
||||
/* Инкремент микросекунд */
|
||||
micros_inc();
|
||||
|
||||
if(msTickInc == 1)
|
||||
{
|
||||
/* Аккумулятивный метод для миллисекунд (без деления) */
|
||||
usAccumulator += usTickInc;
|
||||
if (usAccumulator >= 1000) {
|
||||
millis_inc();
|
||||
usAccumulator -= 1000; // Вычитание быстрее деления
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
millis_inc();
|
||||
}
|
||||
|
||||
/* Вызов зарегистрированных коллбеков */
|
||||
for(int i = 0; i < hsyscb.CallbackInUse; i++)
|
||||
{
|
||||
if(hsyscb.Callback[i] != NULL)
|
||||
{
|
||||
/* Проверка истекшего времени */
|
||||
uint32_t elapsed = msTick - hsyscb.CallbackPrevMs[i];
|
||||
if(elapsed >= hsyscb.CallbackPeriod[i])
|
||||
{
|
||||
/* Обновление времени последнего вызова и вызов коллбека */
|
||||
hsyscb.CallbackPrevMs[i] = msTick;
|
||||
hsyscb.Callback[i]();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Добавление периодического коллбека.
|
||||
* @param Callback Указатель на функцию-коллбек
|
||||
* @param PeriodInMs Период вызова коллбека в миллисекундах
|
||||
* @retval OperationStatus OK при успехе, ERROR при ошибке
|
||||
* @note Максимальное количество коллбеков: SYSCLK_NUMB_OF_CUSTOM_CALLBACKS
|
||||
* @note Минимальный период: текущий период тика SysTick
|
||||
*/
|
||||
OperationStatus SYSCLK_Set_Callback(void (*Callback)(void), uint32_t PeriodInMs)
|
||||
{
|
||||
/* Проверка валидности указателя на функцию */
|
||||
if(Callback == NULL)
|
||||
return ERROR;
|
||||
|
||||
/* Проверка минимального периода */
|
||||
if(PeriodInMs < msTickInc)
|
||||
return ERROR;
|
||||
|
||||
/* Проверка доступности свободных слотов */
|
||||
if(hsyscb.CallbackInUse >= SYSCLK_NUMB_OF_CUSTOM_CALLBACKS)
|
||||
return ERROR;
|
||||
|
||||
/* Регистрация коллбека */
|
||||
hsyscb.Callback[hsyscb.CallbackInUse] = Callback;
|
||||
hsyscb.CallbackPeriod[hsyscb.CallbackInUse] = PeriodInMs;
|
||||
hsyscb.CallbackPrevMs[hsyscb.CallbackInUse] = msTick;
|
||||
|
||||
hsyscb.CallbackInUse++;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Получение текущего времени в миллисекундах.
|
||||
* @retval uint32_t Текущее время в миллисекундах
|
||||
* @note Переполнение происходит через ~49 дней
|
||||
*/
|
||||
uint32_t millis(void)
|
||||
{
|
||||
return uwTick;
|
||||
}
|
||||
void millis_inc(void)
|
||||
{
|
||||
uwTick++;
|
||||
return msTick;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Получение текущего времени в микросекундах.
|
||||
* @retval uint32_t Текущее время в микросекундах
|
||||
* @note Переполнение происходит через ~71 минуту
|
||||
*/
|
||||
uint32_t micros(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void micros_inc(void)
|
||||
{
|
||||
uwTick++;
|
||||
return usTick;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Настройка тактирования АЦП.
|
||||
* @param ClkSrc Источник тактирования (RCU_PeriphClk_TypeDef)
|
||||
* @param ClkMHz Желаемая частота АЦП в МГц
|
||||
* @param state Состояние (ENABLE/DISABLE)
|
||||
* @retval OperationStatus OK при успехе, ERROR при ошибке
|
||||
* @note Временное отключает тактирование АЦП во время настройки
|
||||
*/
|
||||
OperationStatus rcu_set_clock_adc(RCU_PeriphClk_TypeDef ClkSrc, float ClkMHz, FunctionalState state)
|
||||
{
|
||||
RCU_ADCClkCmd(DISABLE);
|
||||
uint32_t adc_raw_clock = 0;
|
||||
float adc_clock_div = 0;
|
||||
|
||||
/* Отключение тактирования АЦП для настройки */
|
||||
RCU_ADCClkCmd(DISABLE);
|
||||
|
||||
/* Определение частоты источника тактирования */
|
||||
switch(ClkSrc)
|
||||
{
|
||||
case RCU_PeriphClk_OSEClk:
|
||||
@@ -72,12 +266,41 @@ OperationStatus rcu_set_clock_adc(RCU_PeriphClk_TypeDef ClkSrc, float ClkMHz, Fu
|
||||
case RCU_PeriphClk_PLLDivClk:
|
||||
adc_raw_clock = RCU_GetPLLDivClkFreq();
|
||||
break;
|
||||
default:
|
||||
return ERROR;
|
||||
}
|
||||
adc_clock_div = adc_raw_clock/(ClkMHz*__MHZ);
|
||||
|
||||
/* Расчет делителя частоты */
|
||||
adc_clock_div = adc_raw_clock / (ClkMHz * __MHZ);
|
||||
if(adc_clock_div < 1)
|
||||
return ERROR;
|
||||
|
||||
RCU_ADCClkConfig(ClkSrc, 7, ENABLE); //12.5MHz
|
||||
RCU_ADCClkCmd(ENABLE);
|
||||
/* Настройка источника тактирования и делителя */
|
||||
RCU_ADCClkConfig(ClkSrc, (uint32_t)(adc_clock_div - 1), ENABLE);
|
||||
|
||||
/* Включение тактирования, если запрошено */
|
||||
if(state == ENABLE)
|
||||
{
|
||||
RCU_ADCClkCmd(ENABLE);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Инкремент счетчика миллисекунд.
|
||||
*/
|
||||
static inline void millis_inc(void)
|
||||
{
|
||||
msTick+=msTickInc;
|
||||
}
|
||||
/**
|
||||
* @brief Инкремент счетчика микросекунд.
|
||||
*/
|
||||
static inline void micros_inc(void)
|
||||
{
|
||||
usTick+=usTickInc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user