【ST NUCLEO-U575ZI-Q 测评 】HAL/LL库使用之systick时基使用与测试
[复制链接]
前言
Systick是CORTEX-M系列单片机的标准内核外设。
一般用于时间基准,时间戳,或者rtos的滴答定时中断。
我们基于上一篇的GPIO可以测试systick的时间是否正确,在systick中断中翻转IO,用示波器/逻辑分析仪测量IO的波形周期即可测试时间是否准确。
过程
systick可以参考CORTEX-M3的内核架构文档这里不再赘述。直接看代码。
HAL库也使用了systick作为定时器,延时等操作都依赖于systick。
初始化
代码位于stm32u5xx_hal.c中的HAL_Init。
HAL_StatusTypeDef HAL_Init(void)
{
/* Configure Flash prefetch */
#if (PREFETCH_ENABLE != 0U)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* Update the SystemCoreClock global variable */
SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR2 & RCC_CFGR2_HPRE) >> RCC_CFGR2_HPRE_Pos];
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
{
return HAL_ERROR;
}
/* Init the low level hardware */
HAL_MspInit();
/* Return function status */
return HAL_OK;
}
调用HAL_InitTick进行初始化
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/
if ((uint32_t)uwTickFreq == 0UL)
{
return HAL_ERROR;
}
/* Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Return function status */
return HAL_OK;
}
其中定时周期由HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 1KHz */定义
默认是
typedef enum
{
HAL_TICK_FREQ_10HZ = 100U,
HAL_TICK_FREQ_100HZ = 10U,
HAL_TICK_FREQ_1KHZ = 1U,
HAL_TICK_FREQ_DEFAULT = HAL_TICK_FREQ_1KHZ
} HAL_TickFreqTypeDef;
中断处理
SysTick_Handler调用HAL_IncTick更新计数器。
void SysTick_Handler(void)
{
static volatile uint32_t num = 0;
if(num++ >= 1000)
{
LL_GPIO_TogglePin(GPIOB, 1u<<7);
num=0;
}
HAL_IncTick();
}
测量时间
总的代码
include "stm32u575xx.h"
include "stm32u5xx_ll_gpio.h"
include "stm32u5xx_ll_bus.h"
void SysTick_Handler(void)
{
static volatile uint32_t num = 0;
if(num++ >= 1000)
{
LL_GPIO_TogglePin(GPIOB, 1u<<7);
num=0;
}
HAL_IncTick();
}
void delay(uint32_t t)
{
volatile uint32_t timeout = t;
while(t--);
}
int main(void)
{
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_GPIO_InitTypeDef GPIO_InitStruct;
//LL_GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_Init();
while(1)
{
///delay(1000000ul);
///LL_GPIO_TogglePin(GPIOB, 1u<<7);
}
}
使用逻辑分析仪测量,IO翻转时间为1.982917488/2=0.991458744S.
由于中断响应,执行处理代码要一定时间所以有一些误差。
总结
本篇介绍了systick的使用,测试了其准确度,后面会经常用到时间基准,延时等等。得益于官方的库,几行代码就可以搞定很高效。
|