STM32 - счётчик DWT - микросекундные паузы
Здравствуйте.
Маленькая заметка, с примером, об очень прикольной и полезной вещице входящей в состав модуля DWT (Data Watchpoint and Trace unit) имеющегося у stm32.
Сам по себе модуль DWT достаточно сложная штуковина (почитать можно тут стр. 75), а отвечает он за отладку. Однако рассматривать этот модуль полностью у меня нет желания, во всяком случае в данный момент, а коснуться хотелось одной из его составляющих — счётчика тактов
По сути, счётчик DWT это просто 32-х битный регистр, значение в котором увеличивается на единичку с каждым последующим тактом. Мы можем писать в этот регистр и читать из него, а значит можем с его помощью измерять время выполнения каких-то кусков программы в тактах, и организовывать микросекундные задержки. Этот счётчик полностью независимый, то есть щёлкает и щелкает не смотря ни на прерывания, ни на другие задержки…
Чтоб измерить время выполнения какого-либо участка программы или функции, нужно сделать так…
#define DWT_CYCCNT *(volatile uint32_t*)0xE0001004
#define DWT_CONTROL *(volatile uint32_t*)0xE0001000
#define SCB_DEMCR *(volatile uint32_t*)0xE000EDFC
char str[16] = {0,};
uint32_t count_tic = 0;
SCB_DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;// разрешаем использовать DWT
DWT_CONTROL|= DWT_CTRL_CYCCNTENA_Msk; // включаем счётчик
DWT_CYCCNT = 0;// обнуляем счётчик
// здесь кусок измеряемого участка программы
count_tic = DWT_CYCCNT; // кол-во тактов
snprintf(str, 16, "Takt %lu\n", count_tic);
HAL_UART_Transmit(&huart1, (uint8_t*)str, strlen(str), 1000);
Измерил HAL_Delay(1000) на частоте 72МГц. Функция HAL_Delay() всегда немного подвирает в большую сторону, в данном случае на 33326 тактов, то есть приблизительно на 470 мкс.
Для организации микросекундных пауз создаём пару функций…
#define DWT_CONTROL *(volatile unsigned long *)0xE0001000
#define SCB_DEMCR *(volatile unsigned long *)0xE000EDFC
void DWT_Init(void)
{
SCB_DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // разрешаем использовать счётчик
DWT_CONTROL |= DWT_CTRL_CYCCNTENA_Msk; // запускаем счётчик
}
void delay_micros(uint32_t us)
{
uint32_t us_count_tic = us * (SystemCoreClock / 1000000); // получаем кол-во тактов за 1 мкс и умножаем на наше значение
DWT->CYCCNT = 0U; // обнуляем счётчик
while(DWT->CYCCNT < us_count_tic);
}
Перед бесконечным циклом инициализируем DWT…
/* USER CODE BEGIN 2 */
DWT_Init();
/* USER CODE END 2 */
И там где нужно, вставляем задержку, например 100 микросекунд…
delay_micros(100);
Пример в виде «библиотеки», а точнее в виде одного файла
Это всё, всем спасибо
Телеграм-чат istarik
Телеграм-чат STM32
- 0
- stD
26771
Поддержать автора
Комментарии (0)