STM32 SysTick小结

本文深入解析STM32的SysTick系统定时器,涵盖其工作原理、寄存器配置、定时时间计算及固件库编程。介绍了SysTick的24位递减计数特性,如何通过STK_CTRL、STK_LOAD和STK_VAL寄存器控制计数过程,以及利用SysTick_Config函数设置中断优先级的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STM32 SysTick小结

SysTick简介

系统定时器,24位,只能递减,存在于内核,嵌套在 NVIC 中。其大部分内容可以查看 STM32F10xxx Cortex-M3编程手册-英文版

SysTick工作过程

1.计数器在时钟驱动下从初值开始计数直到0。
2.为0时可以产生中断或置位 COUNTFLAG 标志位。
3.如果没有关闭,则初值再次开始计数,如此循环。
计数过程中,计数器的实时值可由 STK_VAL 位得到

SysTick寄存器

STK_CTRL

控制及状态寄存器,只有四个有效位:
COUNTFLAG :如果计数器计到0,此位置1;如果软件读取这个位,这个位会置0;
CLKSOURCE :时钟选择位;0=AHB/8;1=AHB。
TICKINT:中断使能;0=无动作;1=产生中断。
ENABLE : 使能寄存器。

STK_LOAD

重装载寄存器。
RELOAD: 数到0时,被重新装载的值。

STK_VAL

当前数据寄存器;
CURRENT :读取时返回当前倒计时的值。

定时时间的计算

t = reload * (1/clk)
所以Clk = 72M,reload=72 时,t = 1us;

SysTick固件库编程

SysTick寄存器的结构体

结构体在 core_cm3.h 文件中。

SysTick固件库函数

配置函数在 core_cm3.h 文件中

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
   //如果传入的重载值大于2^24,则跳出。
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);
   //把重载值装入重装载寄存 器                                                            
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
	//配置中断优先级,默认为最低的优先级
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  
  //初始化计数器的值为0
  SysTick->VAL   = 0;     
  //配置时钟为72M,使能中断,使能SysTick                                     
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    
  return (0);                                                  
}

SysTick中断优先级

在上面固件库编程中,使用了 NVIC_SetPriority 来编程
在这里插入图片描述函数的意思是,如果为内核,修改SCB寄存器;如果为外设,修改NVIC寄存器;

上面的语句

NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);

__NVIC_PRIO_BITS 为4,也就是说,SysTick中断优先级被配置为15,即1111。这个优先级比较呢?

首先,优先级的值越大,优先级越低。在内核中,SysTick的优先级最低。和外设比较,通过中断优先级分组的规则进行比较。中断优先级对内核和外设同样适用。可见,SysTick的优先级非常低。

编写程序

单独创建一个h和c文件,加入USER的group中,并且在Configure中添加路径。

首先,因为要用到内核库中的函数,头文件中必须包含 core_cm3.h , 又因为这个头文件用到了 stm32f10x.h 中的定义,所以还要包含stm32f10x.h
代码如下:

#ifndef _BSP_SYSTICK_H_
#define _BSP_SYSTICK_H_
#include "stm32f10x.h"
#include "core_cm3.h"
#endif

bsp_systick.c 中编写一个函数可以延时1us。

void SysTick_Delay_us(uint32_t us)
{
	int i = 0;
	SysTick_Config(72);
	for(i=0;i<us;i++)
	{
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

}

  由上面的介绍可以知道,SysTick_Config 是用来配置定时器的函数,传入的参数是重装载的值。
  当一次计数到0时COUNTFLAG 位会被置1,而COUNTFLAGSTK_CTRL 寄存器的第16位,使用寄存器访问这个变量就是 (SysTick->CTRL)&(1<<16)),当其置1时,跳出while循环,读取后会自动置0。
  完成指定的for循环后,实际上计时工作就已经完成了,但我们最好还是把计时器给关上。对 STK_CTRLENABLE位置0即可,即 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk。这样就完成了us延时的函数。
如法炮制完成ms延时。

void SysTick_Delay_ms(uint32_t ms)
{
	int i = 0;
	SysTick_Config(72000);
	for(i=0;i<ms;i++)
	{
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

}
<think>好的,用户现在想了解分频因子的概念、作用及实现方式。首先,我需要回忆之前关于ADC时钟分频因子的讨论,用户之前遇到STM32配置的问题,特别是分频因子的选择导致编译错误。用户现在想更深入理解分频因子本身,而不仅仅是解决那个具体问题。 分频因子在数字电路和微控制器中很常见,主要是用来调整时钟频率的。首先,我需要明确分频因子的定义,也就是它如何将输入时钟频率分频,得到更低频率的输出。比如,分频因子为2时,输出频率是输入的一半。 接下来是作用,用户可能需要知道为什么需要分频,比如适应外设的工作频率,或者降低功耗。这里要结合STM32的ADC模块来说,因为ADC的采样率受时钟频率影响,分频因子可以调整ADC的时钟,确保其在允许范围内工作。 然后是实现方式,这里需要分硬件和软件。硬件分频可能通过寄存器设置分频因子,而软件分频可能用计数器实现。同时,用户之前提到了同步和异步分频因子,需要解释两者的区别。同步分频可能与系统时钟同步,而异步可能使用不同的时钟源,比如HAL库中的ADC异步时钟来自专门的PLL。 用户可能还关心具体的STM32配置,比如在代码中如何设置分频因子,比如使用HAL库的函数,或者直接操作寄存器。需要举例说明,比如在STM32CubeMX中的配置步骤,或者代码片段。 另外,用户之前遇到的问题是关于分频因子选项有限,可能现在需要解释为什么某些型号只有特定的分频选项,可能与芯片设计有关,比如时钟树的结构不同。同时,异步分频因子的存在可能允许更灵活的时钟配置,比如使用不同的时钟源来适应不同的需求。 还要注意用户可能的应用场景,比如在ADC采样时需要精确的时钟频率,分频因子的正确设置对采样精度和速度的影响。可能还需要提到分频因子设置不当会导致的问题,比如采样率过高导致数据不准确,或者过低影响性能。 最后,总结分频因子的重要性,并确保回答结构清晰,分点明确,结合用户之前的引用内容,但不要被其局限,要扩展到更一般的概念和应用。同时,生成的相关问题需要引导用户进一步了解时钟配置、同步异步分频的区别,以及具体芯片型号的影响。</think>#### 一、分频因子的定义 **分频因子(Divider Factor)**是数字电路中用于降低时钟频率的关键参数,通过将输入时钟频率按整数倍分频得到更低频率的输出时钟。例如,若输入时钟为$f_{\text{in}}$,分频因子为$N$,则输出频率为: $$f_{\text{out}} = \frac{f_{\text{in}}}{N}$$ 分频因子通常为2的整数次幂(如2、4、8等),但某些场景也支持自定义分频比[^1]。 --- #### 二、分频因子的作用 1. **适配外设工作频率** - 不同外设(如ADC、定时器)对时钟频率有上限要求。例如,STM32的ADC模块通常要求时钟频率≤36 MHz,需通过分频因子将系统时钟降低至安全范围[^1]。 2. **降低功耗** 通过分频降低时钟频率,可减少动态功耗(如低速传感器采样时)。 3. **实现多时钟域同步** 在复杂系统中,分频用于协调不同模块的时序(如通信协议中的波特率生成)[^1][^2]。 --- #### 三、分频因子的实现方式 1. **硬件分频器** - **固定分频**:通过电路设计实现固定分频比(如STM32的ADC同步分频仅支持1/2/4)。 - **可编程分频**:通过寄存器配置动态调整分频因子(如定时器的预分频器)。 ```c // STM32 ADC同步分频设置示例(HAL库) hadc.Instance->CCR |= ADC_CCR_PRESC_2; // 选择分频因子4 ``` 2. **软件分频** 通过计数器手动实现分频逻辑(灵活性高但占用CPU资源): ```c uint32_t counter = 0; void SysTick_Handler() { if (++counter >= N) { // N为分频因子 target_task(); // 执行目标任务 counter = 0; } } ``` 3. **同步与异步分频的区别** - **同步分频**:分频后的时钟与源时钟同相位且严格同步(如STM32 ADC的`PRESC`分频器),抗干扰强但分频选项有限[^1]。 - **异步分频**:分频时钟可能来自独立时钟源(如PLL),分频比灵活但需考虑跨时钟域同步问题(如STM32的ADC异步模式)[^1]。 --- #### 四、分频因子在STM32 ADC中的实际应用 1. **时钟源选择** - **同步时钟**:来源于APB总线时钟(需分频至≤36 MHz)。 - **异步时钟**:来源于专用PLL或独立时钟源(如某些型号支持最高60 MHz)[^1]。 2. **配置步骤(以STM32G431为例)** - **CubeMX配置**: - 在`Clock Configuration`中设置系统时钟(如170 MHz)。 - 在ADC参数页选择同步分频因子(1/2/4)或异步时钟源。 - **代码实现**: ```c hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 同步分频因子4 // 或 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; // 异步分频因子2 ``` 3. **分频因子受限的原因** - 芯片时钟树设计限制(如STM32G431的同步分频仅支持1/2/4)。 - 异步分频需额外硬件支持(如独立PLL),具体选项因型号而异。 --- #### 五、总结 - **分频因子本质**:通过整数除法降低时钟频率,平衡性能与稳定性。 - **核心价值**:适配外设需求、降低功耗、解决时序冲突。 - **注意事项**:需结合芯片手册选择合法分频值,避免超频或功能异常[^2]。 --- #### 相关问题 1. STM32中同步时钟与异步时钟的电路设计差异是什么? 2. 如何通过分频因子优化ADC采样精度? 3. 分频因子设置错误可能导致哪些硬件问题? 4. 不同STM32型号的ADC分频选项差异如何查询? [^1]: STM32配置ADC时钟分频因子问题小结 [^2]: 微控制器时钟系统设计与分频原理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值