Ардуино миллисе() в 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 не довольно точны.
имея это в виду, вы должны сделать следующее:
- настройте TIM, чтобы он мог выполняйте прерывание каждые 1 мс
- включить прерывание TIM,
- в прерывании TIM увеличьте счетчик (это будет ваше время), который определен как глобальная переменная для этого модуля.
void interrupt TIMX_interrupt(void){
counter++; // this will have the time count in MS.
}
- создайте функцию с именем
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 также может переполняться, но это детали, ею можно легко управлять.