Очень часто в программе есть необходимость выполнять задержку выполнения программы на некоторый промежуток времени. Не буду приводить все варианты реализации функции 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)