STM32&Systick(HAL库)

可以说,32系列的Systick就是一个加强功能了的51定时器。抛开HAL库不谈,Systick本身主要是寄托于三个寄存器运作的。本文章主要讲述运作框架;寄存器用法;Systick手动配置。

目录

1.Systick运作框架

2.SysTick的三个寄存器

CTRL

VAL&LOAD

3.SysTick配置

先说情况一:

再说情况二:

4.SysTick中断配置:


1.Systick运作框架

先看图:

然后讲原理:
Systic本质上就是一个按照LOAD的值不断递减的一个时钟。其来源于HCLK(所以在配置的时候一定要初始化时钟树,否则频率未知),也就是说HCLK频率是多少,那么Systick的频率也是多少。然后VAL是一个记录器,就是说当前Systick的值是多少那么VAL就是多少。最后是countflag,当它为1时标志这此时VAL为了,将要reload。

2.SysTick的三个寄存器

CTRL

也是直接看图:

这里科普一个常识,寄存器是从0位开始算的,就象数组一样。
该寄存器主要配置SysTick中断,使能,分频。

VAL&LOAD


功能就和上述的一样,非常简单直接。

3.SysTick配置

在使用中,其实分两种情况:
一:单纯使用单片机的定时功能,用Systick重写delay函数。
二:在运行着操作系统的情况下(比如FreeRTOS)执行上述情况

先说情况一:

这种情况很简单,就是按照上述的情况来配置你的delay就行:

1.获取要演示的us--->2.按照频率对应到SysTick要记录的次--->3.清空当前SysTick的值--->4.使能定时器--->5.记录countflag值,当时间足够跳出定时--->6.关闭定时器.

直接上代码:

void delay_us(uint32_t nus){
    uint32_t temp;
    SysTick->LOAD = 72 * nus;                           
    SysTick->VAL = 0x00;                               
    SysTick->CTRL |= 1 << 2;                           
    SysTick->CTRL |= 1 << 0;                            
    do
    {
        temp = SysTick->CTRL;
    } while ((temp & 0x01) && !(temp & (1 << 16)));     
    SysTick->CTRL &= ~(1<<0);     
}                   

这里如果你对C中的按位操作不熟悉的话,很可能看不懂这里的部分配置,我稍微讲解一下:
对于 
SysTick->CTRL |= 1 << 2;                 给寄存器第三位(2)置1           
SysTick->CTRL |= 1 << 0;                 给寄存器第一位(0)置1
SysTick->CTRL &= ~(1<<0);           给寄存器第一位(0)置0

1<<0是在位的概念上把1左移0位。所谓在位的概念上,这个事情需要从定义来讲起:
        定义一个变量比如char是1字节,就是8位。这里的八位就是二进制概念的八位
也就是说,当你char一个变量a,在内存看来变量a就是0000 0000,当然了,肯定不都是0。
由于STM32中uint是指的无符号int类型,所以:
uint8 a = 1,在内存上就是 0000 0001,那么此时对 a << 1: 0000 0010;
仍然不理解,我回头再从新出一篇文章专门细讲这个。

再说情况二:

假设此时单片机上运行着一个FreeRTOS,那么此时是不可以随意的关闭再打开SysTick的。因为操作系统以SysTcik为时基。

所以我们在重写delay时有一个新的思路:我们不关心LOAD的值,不关心此时VAL的值,我们只关心在单位时间内,SysTcik记录了多少次就行。
直接上代码:

void delay_us(uint32_t nus)
{
	uint16_t tnow,told,tcnt = nus*72;	//这里*72是因为Systick的时钟来源是HLCK,
                                        //而HLCK是72M也就是72*10^6,按照s和us的换算就是72
	uint32_t load = SysTick->LOAD;
	told = SysTick->VAL;
	while(1){
		tnow = SysTick->VAL;
		
		if(tnow > told){
			tcnt -= load + (tnow - told);
		}else if(tnow < told){
			tcnt -= told - tnow;
		}
		told = tnow;
		if(tcnt <= 0) break;
	}
}

看一遍代码就能看出思路,这里只说一个点:
当tnow<told时,说明此时在同意周期内。当tnow>told时,说明此时已经reload了一次。tnow在told之上,此时不能单纯计算差值,需要加上一个load值。 

4.SysTick中断配置:

默认情况下,SysTick的中断被配置为1ms触发一次,配置的地方在这里:

按F12进入函数定义:
 
在STM32中,__weak就是用来给开发者重写函数的,所以如果你想要配置SysTick的中断服务部分,就在这里面配就行。
注意:这里的文件和函数位置都是HAL库版本的,至于标准库请再查询其他文章

<think>好的,用户想了解如何使用HAL配置SysTick,需要教程和示例代码。首先,我得回忆一下SysTickSTM32中的作用,它是系统定时器,用于提供时基,比如HAL的延时函数依赖它。用户可能需要进行精准的延时或者定时中断处理。 接下来,我需要整理配置SysTick的步骤。HAL中通常使用HAL_SYSTICK_Config函数来设置,参数是重装载值。需要根据系统时钟频率来计算,比如如果系统时钟是72MHz,那么1ms的中断需要72000-1的计数值。 然后要考虑中断优先级的设置,SysTick的中断优先级一般设置为最低,避免影响其他关键中断。HAL默认可能已经配置好了,但最好明确说明。 还要提到如何编写中断服务函数,HALSysTick_Handler会自动调用HAL_IncTick(),用户如果需要自己的处理,可以重写回调函数HAL_SYSTICK_Callback。 示例代码部分需要展示初始化配置和自定义回调的实现。注意代码的格式要正确,使用三个反引号包裹,并标明是C语言。 还要检查是否有相关的引用内容,用户提供的引用1提到HAL的中断处理,引用2提到不同STM32系列,可能需要关联这些信息,比如说明不同系列的时钟配置可能不同,需要根据具体情况调整参数。 用户可能遇到的问题包括时钟配置错误、中断未启用、优先级冲突等,需要提醒注意事项,比如确认系统时钟频率,检查中断服务函数是否正确绑定。 最后生成相关问题,考虑用户可能进一步想知道如何调整SysTick频率、使用其他定时器替代、或者处理溢出问题等。确保问题覆盖常见的使用场景和潜在疑问。</think>### 使用STM32 HAL配置SysTick的步骤 SysTick是Cortex-M内核的系统定时器,常用于提供操作系统的时基或实现精准延时。以下是基于HAL的配置方法: --- #### 1. **SysTick初始化** HAL默认在初始化时会自动配置SysTick,但需手动调用`HAL_Init()`以启用基础时钟[^1]: ```c int main(void) { HAL_Init(); // 初始化HAL,自动配置SysTick SystemClock_Config(); // 配置系统时钟(用户需实现) // ...其他初始化代码 } ``` --- #### 2. **自定义SysTick中断周期** 若需修改SysTick中断间隔(默认1ms),可通过以下函数调整: ```c // 示例:配置SysTick为500us中断一次(假设系统时钟为72MHz) uint32_t sysclk = 72000000; // 系统时钟频率 uint32_t tick = (sysclk / 1000000) * 500; // 500us计数值 HAL_SYSTICK_Config(tick); ``` --- #### 3. **编写中断回调函数** 重写`HAL_SYSTICK_Callback()`以添加自定义逻辑: ```c void HAL_SYSTICK_Callback(void) { static uint32_t count = 0; count++; if (count % 2000 == 0) { // 每1秒执行一次(假设中断间隔500us) HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); } } ``` --- #### 4. **注意事项** - **时钟验证**:通过`SystemCoreClock`变量确认实际系统时钟频率[^2] - **中断优先级**:SysTick默认使用最低优先级(15),可通过`NVIC_SetPriority(SysTick_IRQn, priority)`修改 - **超长延时**:避免直接操作`HAL_Delay()`,建议使用`osDelay()`(若使用RTOS) --- ### 完整示例代码 ```c #include "stm32f1xx_hal.h" void SystemClock_Config(void) { // 实现系统时钟配置(根据具体MCU型号调整) } int main(void) { HAL_Init(); SystemClock_Config(); // 配置GPIO(以LED为例) __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // 自定义SysTick周期(500us) HAL_SYSTICK_Config(SystemCoreClock / 2000); while (1) { // 主循环代码 } } // SysTick中断回调 void HAL_SYSTICK_Callback(void) { static uint32_t counter = 0; if (++counter >= 2000) { // 1秒间隔 HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); counter = 0; } } ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值