在延时函数里,对一次计数结束进行判断时,出现了失误,导致延时时长出现异常。
先说明函数设计想法,主要while结束判断条件设计,要保证计数器在工作和计数到0结束。因此对SysTick->CTRL寄存器有两标志位要进行判断。
计数到0,[16]置1。重点是[16]读取后会清零,因此用一个temp变量进行一次读取,再分别判断标志位。
错误代码:
void delay_us(u32 us)
{
u32 temp = 0;
SysTick->LOAD = (u32)us * base_us; //设置重载值
SysTick->VAL = 0x00; //计数值清零
SysTick->CTRL = 0x01; //开始计时,无中断
do
{
temp = SysTick->CTRL; //注意:[16]读后清零
}
while((temp & 0x01) && !(SysTick->CTRL & (1 << 16))); //此处while第二个条件不合理
SysTick->VAL = 0x00; //计数值清零
SysTick->CTRL = 0x00; //关闭计数
}
错误原因:在while第二个判断条件又使用了SysTick->CTRL即直接用寄存器内容进行对计数到0的判断。因为在之前已经temp = SysTick->CTRL;读取了一次,这时[16]已清零。已无判断意义,导致延时出现异常
正确代码:
void delay_us(u32 us)
{
u32 temp = 0;
SysTick->LOAD = (u32)us * base_us; //设置重载值
SysTick->VAL = 0x00; //计数值清零
SysTick->CTRL = 0x01; //开始计时,无中断
do
{
temp = SysTick->CTRL; //注意:[16]读后清零
}
while((temp & 0x01) && !(temp & (1 << 16))); //用temp对寄存器的标志位进行判断,合理
SysTick->VAL = 0x00; //计数值清零
SysTick->CTRL = 0x00; //关闭计数
}
关键字:systick 使用出错
引用地址:
systick使用出错总结
推荐阅读最新更新时间:2024-03-16 16:09
STM32的SYSTICK详解
什么是SYSTICK: 这是一个24位的系统节拍定时器system tick timer,SysTick,具有自动重载和溢出中断功能,所有基于Cortex_M3处理器的微控制器都可以由这个定时器获得一定的时间间隔。 作用: 在单任务引用程序中,因为其架构就决定了它执行任务的串行性,这就引出一个问题:当某个任务出现问题时,就会牵连到后续的任务,进而导致整个系统崩溃。要解决这个问题,可以使用实时操作系统(RTOS). 因为RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。这样SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有
[单片机]
【stm32f407】SysTick实现延时
一. SysTick介绍: CM4内核的处理和CM3一样,内部都包含了一个SysTick定时器,SysTick 是一个24 位的倒计数定时器,当计到0 时 ,将 从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息。我们就是利用STM32的内部SysTick来实现延时的,这样既不占用中断,也不占用系统定时器 通常SysTick可以通过中断的方式来实现,后续会增加,但是目前只是通过轮询的方式去实现 二. 寄存器介绍 SysTick有4个寄存器 对应的代码在core_cm4.h中 typedefstruct { __IO uint32_t CTRL
[单片机]
SysTick定时器和delay延迟函数
一,什么是Systick定时器 Systick定时器也叫滴答定时器,是内核级别的24位倒计数简单定时器,常用做延迟和系统心跳时钟(如:UCOS) 优点:节省MCU资源,不需要浪费一个定时器,只要不清除Systick使能位,就不会停止,即使在睡眠模式下也能工作 捆绑在NVIC中断优先级管理,能产生Systick异常(中断),可设置中断优先级 二,Systick相关寄存器 CTRL: Systick控制和状态寄存器 LOAD: Systick重装载寄存器 VAL: Systick当前值寄存器 CALIB: Systick校准值寄存器 定时器工作方式: 每经过一个Systic
[单片机]
STM32F407学习笔记——Systick中断
#include GPIO_TypeDef* io_led=GPIOC; const u16 pin_led=GPIO_Pin_1; static __IO uint32_t TimingDelay; void Led_Init() { GPIO_InitTypeDef GPIO_init_l; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); GPIO_init_l.GPIO_Pin=GPIO_Pin_1; GPIO_init_l.GPIO_Mode=GPIO_Mode_OUT; GPIO_init_l.GPIO_OType=GPIO_OTyp
[单片机]
STM32学习笔记之SysTick
#define SYSTICK_COUNTFLAG 16 //初始化延迟函数 void delay_init(void) { uint32_t ticks; ticks = SystemFrequency/1000; if (ticks SYSTICK_MAXCOUNT) while (1); SysTick- LOAD = (ticks & SYSTICK_MAXCOUNT) - 1; NVIC_SetPriority (SysTick_IRQn, (1 __NVIC_PRIO_BITS) - 1); SysTick- VA
[单片机]
stm32F407的Systick的问题
最近买了一款stm32f407zgt6的核心板,毫不犹豫地写了一个用定时器点亮led灯的程序(由于程序比较简单就不贴上来了)。在进行1秒闪烁功能实现时,明显发现了led的闪烁时间不对,刚开始是拿手机进行简单的计时,结果显示的是大约3秒的延时(测了10秒亮了两次),在仔细检查代码后,确定不是代码问题(因为代码是用的野火的示例代码) SystemCoreClock是系统预设的系统时钟,在System_stm32f4xx.c文件中查的,f407对应的系统时钟是168mhz 由SysTick_Init()函数,通过计算处理肯定能得到精确的定时,后通过定时器控制GPIO引脚连接至示波器检测,在高电平延时1ms的情况下,
[单片机]
利用STM32的SysTick设计精确延时函数
在项目中使用I2C接口传感器时要求有比较精确的延时,在网上搜了下,如果不想用中断SysTick定时器可以做到,找到如下资料: 主要仿照原子的《STM32不完全手册》。SYSTICK 的时钟固定为HCLK 时钟的1/8,在这里我们选用内部时钟源72M,所以SYSTICK的时钟为9M,即SYSTICK定时器以9M的频率递减。SysTick 主要包含CTRL、LOAD、VAL、CALIB 等4 个寄存器, SysTick- CTRL 位段 名称 类型 复位值 描述 16 COUNTFLAG R 0 如果在上次读本寄存器后systick已为0,则该位为1,若 读该位自动清零 2 CLKSOURCE RW
[单片机]
stm32 设置systick中断抢先式优先级
最近使用STM32时希望将systick的中断优先级降低,但是CMSIS里给出的例子都是类似 view plain copy NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPrio rity = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_I
[单片机]