STM32F4 (Discovery board) универсальная функция задержки (милисекунды)

В сети я нашел следующую функцию для задержки в миллисекундах для STM32F4 (Discovery board MCU:

void delay_us(const uint32_t us)
{
    us*=STM32_DELAY_US_MULT;

    /* fudge for function call overhead */
    //us--;
    asm volatile(" mov r0, %[us] \n\t"
                 "1: subs r0, #1 \n\t"
                 " bhi 1b \n\t"
                 :
                 : [us] "r" (us)
                 : "r0");
}

Внутри этой функции STM32_DELAY_US_MULTиспользуется константа, но она не объявлена ​​и не компилируется, но это не текущая проблема. Как получить текущие STM32F4часы и установить эту константу в соответствии с ними? Если я спрошу по-другому, как мне написать функцию задержки (миллисекунд) для STM32F4proc, которая не зависит от часов?

Ответы (2)

Вместо этого вы можете использовать таймер или RTC с точностью до миллисекунды. Они намного более универсальны и предотвращают ожидание . Их также можно легко настроить как занятые ожидания, добавив дополнительный цикл while, когда это необходимо.

Существует существующий пример кода для того, чего вы хотите достичь. В этом примере показано, как получить текущие системные часы и т. д.

Если вы загружаете: STM32F4 DSP и стандартную библиотеку периферийных устройств

и перейдите к:

STM32F4xx_DSP_StdPeriph_Lib_V1.2.0\Project\STM32F4xx_StdPeriph_Examples\SysTick\SysTick_Example\system_stm32f4xx.c

Существует функция с именем: SystemCoreClockUpdate()

Эта функция и комментарии в стиле Doxygen выше ответят на ваш вопрос.

По моему опыту работы с STM32, примеры стандартных библиотек периферийных устройств обычно дают больше всего ответов, когда дело доходит до конфигурации. Вы также можете посмотреть примеры стандартных библиотек периферийных устройств для STM32F1, STM32F2, STM32F3 и т. д. Есть много примеров. Также попробуйте примеры Keil.

Я только немного использовал серию STM32, но не могу представить, как можно было бы сделать ее полностью независимой от тактовой частоты. Вы можете прочитать настройки PLL, но не сможете узнать частоту кварца без другой привязки ко времени. Может быть несколько уловок, о которых я не знаю, таких вещей, как внутренний RC-генератор в сторожевом устройстве и другие периферийные устройства для обеспечения этого внешнего опорного сигнала, но я не уверен, что это будет стоить того, и точность не будет такой хорошо, если использовать значение, рассчитанное по частоте кристалла.

Лично я бы либо прочитал руководство по семейству и вычислил, сколько циклов должен выполнять цикл, и вычислил константу из этого, если требуется довольно высокая точность, либо в противном случае просто предположил бы начальное значение и позвонил с довольно высоким значением, например 1000 мс и измерьте с помощью области, сколько времени это действительно занимает, и отрегулируйте оттуда.

В вашем случае вы упомянули миллисекунды (хотя в приведенном выше коде упоминаются микросекунды), поэтому ваша константа будет довольно большой, поэтому, возможно, вы могли бы использовать что-то вроде следующего, не вводя неприемлемое количество ошибок:

#define STM32_CLOCK_HZ 72000000UL
#define STM32_CYCLES_PER_LOOP 6 // This will need tweaking or calculating

void delay_ms(const uint32_t ms)
{
    ms *= STM32_CLOCK_HZ / 1000 / STM32_CYCLES_PER_LOOP;

    asm volatile(" mov r0, %[ms] \n\t"
             "1: subs r0, #1 \n\t"
             " bhi 1b \n\t"
             :
             : [ms] "r" (ms)
             : "r0");
}

По крайней мере, тогда у вас будет легко читаемая/обновляемая константа для реальной тактовой частоты системы.