我正在尝试将一些Arduino库移植到stm32。在Arduino中,millis()
函数返回从启动开始以毫秒为单位计算的时间。在stm32中是否有相应的函数?我正在使用stm32f0微控制器。
我正在尝试将一些Arduino库移植到stm32。在Arduino中,millis()
函数返回从启动开始以毫秒为单位计算的时间。在stm32中是否有相应的函数?我正在使用stm32f0微控制器。
HAL_GetTick()
函数:此函数获取当前SysTick计数器值(在SysTick中断中递增),用于处理超时的外设驱动程序。SysTick
是ARM核心提供的外设,旨在实现定时器功能。根据您的需求进行适应:
首先,对其进行初始化。
// 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++;
}
这是你的 millis()
函数,非常简单:
uint32_t millis() {
return counter;
}
需要注意的一些限制条件。
SysTick是一个24位计数器,当溢出时会重新计数。在比较值或实现延迟方法时请注意这一点。
SysTick来源于处理器核心时钟。如果您更改了核心时钟(例如将其放慢以节省电源),则必须手动调整SysTick频率。
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时间变量也可能会溢出,但这只是一个细节,可以轻松管理。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
if (htim->Instance == TIM10) {
counter++;
}
/* USER CODE END Callback 0 */
if (htim->Instance == TIM1) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
HAL库使用定时器(您可以在STM32CubeMX中选择)生成Tick计数器。每个Tick需要1ms。您可以按照以下方式使用它来测量经过的时间:
uint32_t startTime = HAL_GetTick();
.
.
.
uint32_t endTime = HAL_GetTick();
uint32_t elapsedTime = endTime-startTime; // in ms
嗯,我认为我需要更多的信息才能给出一个合适的答案,但我会尽力。
如果您正在进行高分辨率测量(需要精确时间),那么您需要为准确性提供外部晶体,因为MCU的内部时钟不太准确。考虑到这一点,您应该这样做:
void interrupt TIMX_interrupt(void){
counter++; // 这将记录时间计数(毫秒)。
}
millis()
的函数,返回计数器的值,如下所示:uint32_t millis(void){
return counter;
}
通过这种方式,您可以在此MCU中使用相同的函数。
millis()
的实现(https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring.c),并尝试做类似的事情呢? - Ouss4