Для реализации своего небольшого проекта решил использовать микроконтроллеры stm32 серии F0, о вкусах не спорят и публикация не об этом. В официальной документации присутствуют такие вот примеры кода с использованием библиотеки CMSIS:
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
GPIOA->AFR[0] |= 0x04 << GPIO_AFRL_AFRL4_Pos;
GPIOA->AFR[1] |= (0x02 << GPIO_AFRL_AFRH8_Pos) | (0x02 << GPIO_AFRL_AFRH9_Pos);
С одной стороны понять что это можно, с другой стороны разгадывать код как ребус не хочется. Использование библиотеки HAL и подобных абстракций приводит к неэффективному использованию ресурсов микроконтроллера, по моему скромному мнению конечно же.
Например мигание светодиодом с использованием библиотеки HAL у меня превратилось в прошивку весом 4Кб.
Поэтому я решил для дальнейшего изучения написать библиотеку битовых структур, которая позволяет писать достаточно компактный, понятный и удобный для изучения код как мне кажется.
Приведу два примера с использованием этой библиотеки.
Первый пример - мигалка без использования прерываний. Сначала инициализируем порт выводов для подключенного диода, затем настраиваем системный таймер и в основном цикле контролируем флаг перехода счётчика через 0 чтобы переключить состояние вывода и тем самым зажечь или погасить диод.
int main(void)
{
_RCC->AHBENR.IOPAEN = ON;//тактирование соответствующего порта
_GPIOA->MODER.Pin5 = OutputMOD;//режим вывода на соответствующем пине
_SYSTICK->RVR.RELOAD = 1000000;//значение счетчика
_SYSTICK->CSR.ENABLE = ON;//включаем счетчик
_SYSTICK->CVR.CURRENT = 0;//обнуляем текущее значение
for(;;)//бесконечный цикл
{
if( _SYSTICK->CSR.COUNTFLAG)//проверяем переход счётчика через ноль
{
if( _GPIOA->OUTPUTR.Pin5)//если на выводе высокий уровень
_GPIOA->RESETR.Pin5 = DROP;//включаем низкий уровень на выводе
else
_GPIOA->SETR.Pin5 = HIGH;//включаем высокий уровень
_SYSTICK->CVR.CURRENT = 0;//обнуляем текущее значение счетчика и COUNTFLAG
}
}
}
Во втором примере используем прерывание которое вызывает системный таймер при событии перехода через 0 и в обработчике этого прерывания переключаем состояние вывода.
void SysTick_Handler( void)//Функция обрабатывает прерывание при переполнении системного таймера
{
if( _GPIOA->OUTPUTR.Pin5)//если на выводе высокий уровень
_GPIOA->RESETR.Pin5 = DROP;//сбрасываем бит, включаем низкий уровень на выводе
else
_GPIOA->SETR.Pin5 = HIGH;//включаем высокий уровень
}
int main(void)
{
_RCC->AHBENR.IOPAEN = ON;//тактирование соответствующего порта
_GPIOA->MODER.Pin5 = OutputMOD;//режим вывода
_SYSTICK->RVR.RELOAD = 800000;//значение счетчика, интервал между прерываниями
_SYSTICK->CSR.ENABLE = ON;//включаем счетчик
_SYSTICK->CSR.TICKINT = ON;//включаем прерывание при переполнении
_SYSTICK->CVR.CURRENT = 0;//обнуляем текущее значение
for(;;);
}
Примеры написаны в официальной STM32CubeIDE для Nucleo-64 STM32F072RB, но работать должны на любом микроконтроллере серии F0, скачать можно по ссылке.
Библиотека основана на "RM0091 Reference manual" и "PM0215 Programming manual".