void SysTick_Handler(void)系统滴答时钟中断函数

可以作为整个系统的时基!在小调度程序和实时操作系统中可以用作系统的时基。

微控制器的定时器资源一般比较丰富,比如STM32存在8个定时器,为啥还要再提供一个SYSTICK? 原因就是所有基于ARM
Cortex_M3内核的控制器都带有SysTick定时器,这样就方便了程序在不同的器件之间的移植。而使用RTOS的第一项工作往往就是将其移植到开发人员的硬件平台上,由于SYSTICK的存在无疑降低了移植的难度。

SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。
要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。

由一下三个寄存器控制:

CTRL 寄存器:CTRL 是 SysTick 定时器的控制及状态寄存器
LOAD 寄存器:LOAD 是 SysTick 定时器的重装载数值寄存器
VAL 寄存器:VAL 是 SysTick 定时器的当前数值寄存器
CALIB 寄存器:CALIB 是 SysTick 定时器的校准数值寄存器

3.5版本的库函数与以往的有所区别
不存在stm32f10x_systick.c文件,故原来的一些函数也不存在,比如SysTick_SetReload(u32 reload);SysTick_ITConfig(FunctionalState NewState);等

在3.5版本的库函数中与systick相关的函数只有两个
第一个,SysTick_Config(uint32_t ticks),在core_cm3.h头文件中进行定义的。
第二个,void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),在misc.c文件中定义的。

SysTick_Config(uint32_t ticks),在core_cm3.h
主要的作用:
1、初始化systick
2、打开systick
3、打开systick的中断并设置优先级
4、返回一个0代表成功或1代表失败
注意:
Uint32_t ticks 即为重装值,
这个函数默认使用的时钟源是AHB,即不分频。
要想分频,调用void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),
但是要注意函数调用的次序,先SysTick_Config(uint32_t ticks),
后SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)

<think>嗯,我现在遇到了STM32的SysTick_Handler计数异常的问题,需要找出原因和解决方法。首先,我得回忆一下SysTick定时器的工作原理。SysTick系统定时器,通常用来产生周期性的中断,比如作为操作系统的时基或者进行延时函数。根据引用中的资料,SysTick的重装寄存器决定了定时器的频率,如果时钟源是72MHz,那么设置重装载值的时候需要根据所需的时基来计算。比如,如果要1ms的时基,重装载值应该是72000000/1000=72000。 那计数异常可能是什么原因呢?可能有很多因素。首先,可能是重装载值设置不正确。比如,如果计算错误,或者时钟源配置错误,比如SysTick的时钟源应该是HCLK的8分频还是不分频?记得不同的STM32系列可能配置不同。比如在引用3中提到,如果时钟源是72MHz,那么设置重载值时需要正确分频。如果分频错了,比如原本应该用不分频的HCLK,结果用了8分频,那实际频率就会低很多,导致定时器中断的时间间隔变长,从而计数看起来异常。 其次,中断处理函数是否有问题。比如,SysTick_Handler函数是否被正确实现,是否有清除中断标志的操作?根据引用1中的中断函数列表,SysTick_Handler是处理系统滴答定时器中断函数。如果中断函数中没有正确清除状态,或者有重复进入中断的情况,可能导致计数错误。 还有可能是优先级配置的问题。如果SysTick中断优先级被其他高优先级的中断抢占,可能导致中断处理延迟,进而影响计数的准确性。需要检查NVIC中的优先级设置,确保SysTick中断优先级合理。 另外,代码中的其他部分是否修改了SysTick的配置?比如在操作系统任务切换时,可能重新配置了SysTick,导致参数被覆盖。或者在某个地方意外修改了重装载寄存器或当前值寄存器,导致计数异常。 硬件问题也不能排除,比如时钟源不稳定,或者外部晶振有问题,导致SysTick的时钟频率不准确,进而影响计数。这时需要用示波器或者调试工具检查时钟信号是否正常。 再想一下,是否在SysTick_Handler中执行了耗时过长的操作,导致中断处理时间过长,甚至错过了后续的中断触发?比如在中断服务函数中进行复杂的计算或者调用阻塞函数,这会影响整个系统中断响应。 可能的解决方法包括: 1. 检查SysTick的时钟源配置是否正确,确认分频系数是否合适。 2. 核对重装载值的计算公式,确保时基计算无误。 3. 确保中断处理函数SysTick_Handler中没有遗漏清除中断标志的步骤,或者是否有重复进入中断的情况。 4. 检查中断优先级设置,避免被其他高优先级中断打断。 5. 使用调试工具查看SysTick相关寄存器的值,比如CTRL、LOAD、VAL等,确认是否按预期设置。 6. 检查是否有其他代码部分意外修改了SysTick的配置,比如在初始化后其他地方又调用了配置函数。 7. 在中断服务函数中尽量减少处理时间,避免复杂操作。 8. 硬件检查,确认时钟源稳定,晶振工作正常。 举个例子,假设原本应该使用HCLK作为时钟源,但实际配置成了HCLK/8,那么计算重载值时如果没考虑到分频,就会导致实际中断间隔是预期的8倍。比如原本要1ms中断一次,但实际是8ms一次,导致计数明显变慢。这时候需要检查RCC的配置,确认SysTick时钟源是否正确设置。 或者,如果在中断处理函数中没有正确清除某个状态,导致中断被重复触发,那么计数值就会异常增加。例如,SysTick中断标志在进入处理函数后会自动清除,但如果有其他操作影响了状态寄存器,可能导致标志未被清除,从而重复进入中断。 此外,使用调试工具如ST-Link,在IDE中查看SysTick寄存器的当前值,观察是否在每次中断后正确重载。同时,可以单步执行代码,确认配置流程是否正确,是否存在配置顺序错误,比如先启动定时器再设置重载值,导致初始值错误。 总结下来,可能的原因涉及配置错误、中断处理问题、优先级问题、代码冲突、硬件问题等,需要逐一排查。</think>### SysTick_Handler计数异常的原因及解决方法 #### **一、原因分析** 1. **重装载值配置错误** - 计算公式错误:例如,系统时钟为72MHz时,1ms时基的正确重装载值为$72000000/1000=72000$。若分频系数未正确计算,会导致定时周期异常[^3]。 - 时钟源选择错误:若SysTick时钟源误配置为HCLK/8而非HCLK,实际频率会降低8倍,导致中断间隔变长[^3]。 2. **中断处理函数问题** - 未及时清除中断标志:SysTick中断标志在进入中断后自动清除,但若处理函数中有其他操作(如重复读取寄存器),可能导致标志位异常[^1]。 - 中断函数执行时间过长:若在`SysTick_Handler`中执行耗时操作(如复杂计算),可能导致中断嵌套或丢失后续中断。 3. **优先级配置冲突** - SysTick中断优先级过低,被高优先级中断抢占,导致计数延迟或丢失[^1]。 4. **代码冲突或覆盖** - 其他代码(如RTOS任务)意外修改SysTick配置(如重装载值或使能状态)。 5. **硬件问题** - 系统时钟不稳定(如晶振故障),导致SysTick时钟源异常[^2]。 --- #### **二、解决方法** 1. **检查时钟源与重装载值** - 确认SysTick时钟源配置(HCLK或HCLK/8): ```c // 使用HCLK作为时钟源(无分频) SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); ``` - 验证重装载值计算公式: $$ \text{Reload Value} = \frac{\text{SystemCoreClock}}{\text{Desired Frequency}} - 1 $$ 2. **优化中断处理函数** - 确保中断函数简洁,仅执行必要操作(如递增计数器): ```c void SysTick_Handler(void) { tick_counter++; // 避免复杂逻辑 } ``` 3. **调整中断优先级** - 通过NVIC设置合理的优先级,避免抢占: ```c NVIC_SetPriority(SysTick_IRQn, 0); // 设为最高优先级 ``` 4. **排查代码冲突** - 检查是否有多处代码修改SysTick配置,确保初始化流程唯一且顺序正确(先配置时钟源,再设重装载值,最后使能中断)。 5. **调试寄存器状态** - 使用调试工具(如STM32CubeIDE)检查以下寄存器: - `SysTick->CTRL`:确认使能位(BIT0)和时钟源位(BIT2)正确。 - `SysTick->LOAD`:验证重装载值是否符合预期。 - `SysTick->VAL`:检查是否在每次中断后自动重置。 6. **硬件检测** - 用示波器测量系统时钟输出(如HCLK),确认频率稳定性。 --- #### **三、示例代码验证** ```c #include "stm32f1xx.h" volatile uint32_t tick = 0; void SysTick_Init(void) { SysTick->LOAD = SystemCoreClock / 1000 - 1; // 1ms时基 SysTick->VAL = 0; // 清空当前值 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | // 使用HCLK SysTick_CTRL_TICKINT_Msk | // 使能中断 SysTick_CTRL_ENABLE_Msk; // 启动定时器 } void SysTick_Handler(void) { tick++; // 仅更新计数器 } ``` --- #### **四、常见问题排查表** | 现象 | 可能原因 | 解决方法 | |-----------------------|-------------------------|------------------------------| | 计数速度过快/过慢 | 重装载值错误 | 核对公式与时钟源分频 | | 计数间歇性停止 | 中断优先级被抢占 | 提高SysTick中断优先级 | | 计数跳变异常 | 其他代码修改LOAD/VAL | 检查代码中是否有二次配置操作 | | 无中断触发 | SysTick未使能或时钟源错 | 验证CTRL寄存器配置 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值