如何解决SysTick定时器错误问题
这篇文章主要介绍“如何解决SysTick定时器错误问题”,在日常操作中,相信很多人在如何解决SysTick定时器错误问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何解决SysTick定时器错误问题”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
01坑的由来
使用的就是systick定时器,具体代码如下
void delay_us(uint32_t nus) { uint32_t temp; SysTick->LOAD = RCC_Clocks.HCLK_Frequency/1000000/8*nus; SysTick->VAL=0X00;//清空计数器 SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源 do { temp=SysTick->CTRL;//读取当前倒计数值 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达 SysTick->CTRL=0x00; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } void delay_ms(uint16_t nms) { uint32_t temp; SysTick->LOAD = RCC_Clocks.HCLK_Frequency/1000/8*nms; SysTick->VAL=0X00;//清空计数器 SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源 do { temp=SysTick->CTRL;//读取当前倒计数值 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达 SysTick->CTRL=0x00; //关闭计数器 SysTick->VAL =0X00; //清空计数器 }
对于《STM32延时的四种方法》文中所说的内容如下
也就是下面代码中/8的原因。
SysTick->LOAD = RCC_Clocks.HCLK_Frequency/1000/8*nms;
我对此深信不疑,并在STM32F207参考手册(RM0033)上找到“证据”。
上图①处直接是8分频,而不像②出的1/2/4/8分频。所以我确信是SYSTICK的时钟固定为HCLK时钟的1/8。
我在学习RTThread的时候,看到配置SysTick定制器代码如下
我心里一堆问号,STM32官方手册,明明写了SYSTICK的时钟固定为HCLK时钟的1/8。我使用示波器测量,RTThread的配置是没有问题,可以正常延时的。
02填坑
位2置1,表示时钟频率为AHB,也就是默认的120000000Hz。
位2清0,表示时钟频率为AHB/8,也就是120000000/8Hz。
RTThread配置为内部时钟
之前的文章配置为外部时钟源
这个细节我没有留意,导致我看RTThread代码时有点懵逼。
准确的描述是:
SYSTICK的时钟可以为HCLK时钟的1分频或8分频,在这里我们选用外部时钟源120M,所以SYSTICK的时钟为(120/8)M。
特此更正。
关于这点,STM32的标准外设库提供的SysTick_Config函数,也是使用内部时钟的
static __INLINE uint32_t SysTick_Config(uint32_t ticks) { 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); SysTick->VAL = 0; SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; return (0); }
调用方法,产生1ms中断调用方法
SysTick_Config(SystemCoreClock / 1000);
关于时钟源的选择,除了操作寄存器外,还有库函数可以选择。
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) { assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); if (SysTick_CLKSource == SysTick_CLKSource_HCLK) { SysTick->CTRL |= SysTick_CLKSource_HCLK; } else { SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; } }
除上外,我找到了其他证据来说明,SYSTICK的时钟可以为HCLK时钟的1分频或8分频。
在STM32CubeMx配置软件中,可以选择1分频或8分频。
03修改代码验证
把涉及的代码修改成1分频的。
void delay_ms(uint16_t nms) { uint32_t temp; SysTick->LOAD = RCC_Clocks.HCLK_Frequency/1000*nms-1; SysTick->VAL=0X00;//清空计数器 SysTick->CTRL=0X01; SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); do { temp=SysTick->CTRL;//读取当前倒计数值 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达 SysTick->CTRL=0x00; //关闭计数器 SysTick->VAL =0X00; //清空计数器 }
然后调用
GPIO_SetBits(GPIOE,GPIO_Pin_4); //熄灭LED灯 delay_ms(500);//延时500ms GPIO_ResetBits(GPIOE,GPIO_Pin_4);//点亮LED灯 delay_ms(500);//延时500ms
就踩到另一个坑,延时不准。
原因是:此时SYSTICK时钟频率是120MHz的24位的倒计数定时器,也就是说一个周期,最多定时139.810125ms。不能延时500ms。
这里再更正之前的一个错误,如下图
这个计数器的值,我们减去了1,这样才更准确。
到此,关于“如何解决SysTick定时器错误问题”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341