Очень часто в программе есть необходимость выполнять задержку выполнения программы на некоторый промежуток времени. Не буду приводить все варианты реализации функции Delay. Из всевозможных способов всегда лучше других это аппаратный. Кортексы с ядрами M3, M4, M7 содержат в своем составе модуль DWT (Data Watchpoint and Trace Unit). В нем есть 32 битный счетчик тиков (циклов тактовой частоты ядра) его мы и будем использовать для реализации функций задержки (не подходит для использования в многопоточных приложениях). Работа функций выполняеться в блокирующем режиме.
Модули библиотеки обращаються к main.h где я указываю основные параметры программы и именно тут я подключаю все хедеры относящиеся к конкретному МК в проекте, так они могут использоваться в разных проетах без внесения изменений.
main.h
/* * main.h * * Created on: 31 янв. 2018 г. * Author: */ #ifndef MAIN_H_ #define MAIN_H_ #include "stm32f4xx.h" // системная частота в герцах #define SYS_CLK 16000000 #endif /* MAIN_H_ */
Отдельный модуль для работы с WDT:
F4xx_DWT.h
/* * F4xx_DWT.h * * Created on: 31 янв. 2018 г. * Author: Home */ #ifndef F4XX_DWT_H_ #define F4XX_DWT_H_ #include <main.h> void DWT_CYC_Counter_Enable(void); #endif /* F4XX_DWT_H_ */
F4xx_DWT.c
/* * F4xx_DWT.c * * Created on: 31 янв. 2018 г. * Author: Home */ #include <F4xx_DWT.h> void DWT_CYC_Counter_Enable(void) { /* запускаем таймер DWT_CYC */ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; }
Модуль содержит всего одну функцию void DWT_CYC_Counter_Enable(void), которая разрешает работу счетчика.
F4xx_Delay.h
/* * F4xx_Delay.h * * Created on: 31 янв. 2018 г. * Author: Home */ #ifndef F4XX_DELAY_H_ #define F4XX_DELAY_H_ #include <F4xx_DWT.h> // задержка в микросекундах void Delay_us(__IO uint32_t tDelay); // задержка в милисекундах void Delay_ms(__IO uint32_t tDelay); #endif /* F4XX_DELAY_H_ */
F4xx_Delay.c
/* * F4xx_Delay.c * * Created on: 31 янв. 2018 г. * Author: Home */ #include <F4xx_Delay.h> // задержка в микросекундах void Delay_us(__IO uint32_t tDelay) { DWT->CYCCNT = 0; tDelay = tDelay * (SYS_CLK /1000000); while (DWT->CYCCNT < tDelay); } // задержка в милисекундах void Delay_ms(__IO uint32_t tDelay) { DWT->CYCCNT = 0; tDelay = tDelay * (SYS_CLK /1000); while (DWT->CYCCNT < tDelay); }
в данном модуле раелизованы функции задержки для микросекундных интервалов и миллисекундных.
Пример использования:
/* Includes */ #include "main.h" #include <F4xx_DWT.h> #include <F4xx_Delay.h> /* Private macro */ // гасим все светодиоды #define LED_CLR_ALL GPIOD->BSRR = GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15 // включаем соотв.светодиод #define LED1_SET GPIOD->BSRR = GPIO_BSRR_BS_12 #define LED2_SET GPIOD->BSRR = GPIO_BSRR_BS_13 #define LED3_SET GPIOD->BSRR = GPIO_BSRR_BS_14 #define LED4_SET GPIOD->BSRR = GPIO_BSRR_BS_15 #define DELAY_INIT_CNT 500000 // тестовая нога для анализатора #define TST_CLR GPIOD->BSRR = GPIO_BSRR_BR_0 #define TST_SET GPIOD->BSRR = GPIO_BSRR_BS_0 /* Private variables */ /* Private function prototypes */ /* Private functions */ void RCC_Init(void); void GPIO_Init(void); void RCC_Init(void) { RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN; // включаем тактирование GPIOD } void GPIO_Init(void) { GPIOD->MODER = GPIO_MODER_MODER0_0 | GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 | GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0; // настраиваем PD12, PD13, PD14, PD15 как "двухтактный выход общего назначения" } int main(void) { uint32_t a; RCC_Init(); GPIO_Init(); DWT_CYC_Counter_Enable(); while(1) { LED_CLR_ALL; LED1_SET; Delay_ms(500); LED_CLR_ALL; LED2_SET; Delay_us(500000); LED_CLR_ALL; LED3_SET; Delay_ms(500); LED_CLR_ALL; LED4_SET; Delay_us(500000); } }
Программа под F4Discovery.
Отредактировано MasterElectric (2018-02-28 23:00:07)