Ардуино миллисе() в STM32 для

Я пытаюсь перенести некоторую библиотеку Arduino в stm32. В Arduino, millis() возвращает количество миллисекунд с момента загрузки. Есть ли эквивалентная функция в stm32? Я использую микроконтроллер stm32f0.

5 ответов


SysTick периферия сердечника рукоятки обеспеченная для этой цели. Адаптировать это к вашим потребностям:

во-первых, инициализировать его

// Initialise SysTick to tick at 1ms by initialising it with SystemCoreClock (Hz)/1000

volatile uint32_t counter = 0;
SysTick_Config(SystemCoreClock / 1000);

предоставьте обработчик прерываний. Компилятору может потребоваться, чтобы обработчики прерываний были украшены дополнительными атрибутами.

SysTick_Handler(void) {
  counter++;
}

вот вам


можно использовать HAL_GetTick(): this function gets current SysTick counter value (incremented in SysTick interrupt) used by peripherals drivers to handle timeouts.


в некоторых ситуациях вы не можете использовать SysTick для этой цели. Например, при использовании FreeRTOS, который уже реализует SysTick. В этом случае запустите код в задаче, и вы можете использовать vTaskDelay. В зависимости от того, что вы хотели бы сделать, таймер программного обеспечения также может сделать трюк:http://www.freertos.org/FreeRTOS-Software-Timer-API-Functions.html

Если вы не можете использовать SysTick, и у вас нет FreeRTOS или подобного, вы можете настроить таймер с прерыванием и поместите свой код в соответствующий обратный вызов.


Ну, я думаю, что мне нужно больше информации для правильного ответа, но я дам вам свой лучший шанс.

рассмотрение вам нужно иметь для вашего применения, если вы делаете измерения высокого разрешения (нужно точное время), то вам будет нужно обеспечить внешний кристалл для точности в виду того что внутренние часы MCU не довольно точны.

имея это в виду, вы должны сделать следующее:

  1. настройте TIM, чтобы он мог выполняйте прерывание каждые 1 мс
  2. включить прерывание TIM,
  3. в прерывании TIM увеличьте счетчик (это будет ваше время), который определен как глобальная переменная для этого модуля.

void interrupt TIMX_interrupt(void){ counter++; // this will have the time count in MS. }

  1. создайте функцию с именем millis() что возвращает счетчик что-то вроде:

uint32_t millis(void){ return counter; }

таким образом, вы можете использовать ту же функцию в этом MCU.


Я бы предложил сделать это с таймером. Таким образом, вы также можете получить шаг 1us, просто контролируйте размер шага времени. В любом случае, большинство STM32 MCU имеет 8 или более таймеров, поэтому в большинстве случаев вы можете взять один. Я покажу очень простую основную идею, как это сделать.

просто создайте таймер:

uint32_t time = 0;

void enable_timer(void){
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, ENABLE);
    TIM_TimeBaseInitTypeDef timerInitStructure;

    /* if MCU frequency 48 MHz, prescaler of value 48 will make 1us counter steps
    timerInitStructure.TIM_Prescaler = 48;

    timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    /*how often you'll get irq*/
    timerInitStructure.TIM_Period = 0xFFFF; // will get irq each 65535us on TIMx->CNT overflow
    timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM16, &timerInitStructure);
    TIM_Cmd(TIM16, ENABLE);
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = TIM16_IRQn;
    /*for more accuracy irq priority should be higher, but now its default*/
    NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    TIM_ClearITPendingBit(TIM16,TIM_IT_Update);
    NVIC_Init(&NVIC_InitStruct);
    TIM_ITConfig(TIM16,TIM_IT_Update,ENABLE);
}

В IRQ вы должны контролировать переполнения счетчика таймера и обновлять свое глобальное время

void TIM16_IRQHandler(void){
if (TIM_GetITStatus(TIM16, TIM_IT_Update) != RESET){
    TIM_ClearITPendingBit(TIM16, TIM_IT_Update);
    time +=65535;
}

}

и реальное время будет :

uint32_t real_time_us = time + (uint32_t)TIM16->CNT;

но если вы можете использовать 32-битный таймер, вы даже можете сделать это без IRQ, просто time= TIMx - >CNT. Да, это зависит от конфигурации таймера и ваших потребностей, также вы должны знать, что переменная времени uint32_t также может переполняться, но это детали, ею можно легко управлять.