Основни таймери
Този път ще разгледаме прилагането на закъснения и използването на основни таймери. Също така леко закачаме тактовата система STM32F4.
В резултат на това в една от библиотеките успях да изкопая функция, която ви позволява да използвате закъснения в милисекунди:
За да проверим работата на функцията, използваме кода leg-jump, постоянно обръщаме крака със закъснение от 10ms, т.е. осцилоскопът трябва да показва меандър с честота 1000/10*2=50Hz
Резултат, когато работи от вътрешния осцилатор на 16MHz,

Както можете да видите, забавянето е 10,1 ms вместо 10, така че трябваше да изкопая част от кода, който ви позволява да прехвърлите работата на камъка от външен кварц. Тук трябва да внимавате, тъй като тактовата честота в кокосовия орех е конфигурирана във файла stm32f4xx.h, който ще бъде разгледан по-долу.
RCC->CR=((uint32_t)RCC_CR_HSEON); докато (!(RCC->CR & RCC_CR_HSERDY)) <>; //изчакайте RCC да бъде готов->CFGR &=
RCC_CFGR_SW; // нулиране на битове RCC->CFGR = RCC_CFGR_SW_HSE; // Изберете HSE за тактова честота SW0=1.
При работа от външен генератор резултатът е доволен:

Можем да заключим, че функцията работи, забавянето се издава правилно, необходими са точни закъснения - използвайте кварц, ако не е необходима точност, тогава е достатъчен вътрешен RC генератор.
Между другото, iEugene0x7CA проведе подобен експеримент, демонстрирайки работата на AVR от вътрешен RC осцилатор и от външен кварц, и любезно сподели резултатите от своите наблюдения. Като експеримент беше използван кодът за скок на краката от 50 Hz:
PORTB.0=1; delay_ms(10); PORTB.0=0; delay_ms(10);
Осцилограма на работата на подобен код, при работа от вътрешен RC генератор и температура +20C:

Същото, само след охлаждане на микроконтролера с втечнен газ🙂

Както можете да видите, честотата "изплува" с почти 1 Hz. Е, за лека закуска работете с кварц:

Нека да преминем към използването на таймери, задачата е същата - да отскочите крака с определена честота. STM32F4 има няколко вида таймери, засега нека разгледаме така наречения Basic. В документацията виждаме, че това са TIM 6 и 7.

Това са най-простите таймери, те могат да тиктакат и прекъсват по съвпадение. Тъй като те са 16 бита, те могат да тиктакат от 0 до 2^16 = 65 536. когато таймерът преброи определена стойност, която ние сами определяме, възниква прекъсване, в което можете да определите необходимите по-нататъшни действия.
Също така, както в ситуацията с краката, преди да използвате таймера, трябва да включите часовника на автобуса, на който седи, и той седи на APB1. Можете да разрешите тактоване с помощта на регистъра за активиране на периферен часовник RCC APB1 (RCC_APB1ENR). Можете да активирате часовника на TIM6 по следния начин:
Но забавлението започва в момента, в който трябва да определите на каква честота работи APB1, тук лесно можете да вземете мозъчен тумор. След това ще дам малък преглед на това, което успях да разбера в момента, разбира се, системата за часовник е достойна за отделно разглеждане, вероятно в близко бъдеще ще бъде. Но сега е невъзможно напълно да пропуснете този момент, защото тук всичко е твърде взаимосвързано, така че смятаме това за предварително запознаване.
Хайде да го разберем. Листът с данни по този въпрос дава следната обща схема:

След няколко дни пушещи форуми и таблици с данни има следната картина: HSE (e-external) външен генератор може да действа като основен източник(кварц 4-26MHz) и HSI (I-вътрешен) - вътрешен (RC при 16MHz). Прилича на AVR. Но има функция, наречена PLLCLK, без да навлизаме в подробности, тази система ви позволява да умножите базовата честота, която се приема като HSE или HSI, като по този начин получавате заветните 168 MHz.
Работата със системата за време на таймерите не е толкова проста. Както можете да видите, сигналът от основния източник се подава към шината AHB, където го чака локалният предскалер (делител) 1.2 .. 512. След това се използва разделителят APB и ако делителят не е равен на 1, тогава честотата се умножава по 2. Този момент трябва да се вземе предвид, защото това е локална характеристика.
Обясненията към тази таблица най-накрая изваждат мозъка: Когато битът TIMPRE в регистъра RCC_DCKCFGR е нулиран и APBx prescaler е 1, тогава TIMxCLK = PCLKx, в противен случай TIMxCLK = 2x PCLKx. Когато TIMPRE регистър бит RCC_DCKCFGR е зададен и APBx prescaler е 1,2 или 4, тогава TIMxCLK = HCLK, в противен случай TIMxCLK = 4x PCLKx.
В резултат на това основното нещо, което трябва да разберете, е, че максималната честота на AHB е 180MHz, APB2 е 90MHz, а APB1 е 45MHz. По някакъв начин собственият софтуер от STM, който идва под формата на excel файл, ще помогне да се сортира тази тема. Това, наред с други неща, ще помогне да се генерира файлът system_stm32f4xx.c, в който са зададени всички честотни настройки и прескалери. Горещо препоръчвам да го изтеглите и да се запознаете с него, за да получите просто общо впечатление за това как работи часовниковият механизъм.

Завършвайки разговора за тактовата честота, трябва да запомните, че камъкът винаги започва от вътрешния осцилатор, дори ако се използва външен кварц. Можете да превключите към външен кварц с частта от кода, дадена по-горе. За простота ние не докосваме предварителните скалери, задаваме тактовата честота във файла stm32f4xx.h в редовете HSI_VALUE и HSE_VALUE. С тези настройки таймерътще тиктака на основната честота, т.е. 16MHz вътрешен или 8MHz външен.
Нека се опитаме да ритнем PD12 с помощта на таймер с честота 50Hz.
#include #include #include int main(void) < //Работим от външен 8MHz кварцов RCC->CR=((uint32_t)RCC_CR_HSEON); докато (!(RCC->CR & RCC_CR_HSERDY)) <>; RCC->CFGR &=
RCC_CFGR_SW; // Изчистване на битове SW0, SW1. RCC->CFGR = RCC_CFGR_SW_HSE; // Изберете HSE за тактова честота SW0=1. //Настройване на таймер 6 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE); //разрешаване на часовник на таймер 6 TIM6->PSC = 8000 - 1; //Настройване на делителя на 1000 "тикчета" в секунда, тъй като основната честота е 8MHz TIM6->ARR = 10-1; // Регистър за сравнение, преброен до 10 - нарича се прекъсване и т.н. на всеки 10ms TIM6->DIER = TIM_DIER_UIE; //Разрешаване на прекъсванията на таймера TIM6->CR1 = TIM_CR1_CEN; //Активиране на таймера NVIC_EnableIRQ(TIM6_DAC_IRQn); //Активиране на прекъсване TIM6_DAC_IRQn //задаване на пин GPIO_InitTypeDef GPIO_InitStructure; //Структура, съдържаща настройки на порт RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); //Активиране на тактоване на порт D GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //Изберете желаните пинове GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //Активиране на режим на изход GPIO_Init(GPIOD, &GPIO_InitStructure); //извикване на функцията за инициализация while(1) <> > void TIM6_DAC_IRQHandler(void) < TIM6->SR &=
TIM_SR_UIF; //Нулирайте флага за прекъсване GPIO_ToggleBits(GPIOD, GPIO_Pin_12); //инвертиране на състоянието на крака >
Може да изглежда, че изходният код е голям и неразбираем, но ако внимателно разберете, тогава няма нищо сложно. Предварителният мащабер на таймера е конфигуриран така, че таймерът да тиктака необходимия брой пъти в секунда, ние вкарваме желаната стойност в регистъра за сравнениеброй отброявания, активирайте обработката на прекъсване на таймера, стартирайте таймера. Всичко това не беше нищо ново в AVR. Вътре в прекъсването обърнете крака.
Резултатите са същите като при обикновените глупаци при работа от вътрешния генератор

Когато се захранва от кварц

Статията се оказа доста хаотична, радикално я пренаписах 7 пъти, в крайна сметка е като капка в морето, защото за разлика от AVR, работата със STM32 без лист с данни е немислима. Ако нарисувате всички тънкости на настройките на регистъра, тогава тук няма да има достатъчно статии. Затова ще се учим постепенно, докато това са само първите стъпки. Ще се върнем на таймерите.