使用Systick做延时
这个声明函数
void TimingDelay_Decrement(void);
void Systick_Delay(uint32_t delayTime);
void SysTick_Configuration(uint32_t Reload);配置systick
void SysTick_Configuration(uint32_t Reload)
{
/*before initializtion,disable systick timer*/
SYSTICK_Cmd (FALSE);
SYSTICK_Reload_Config(Reload);
/*write ST_CV any valer,clear ST_CV*/
SYSTICK_Counter_Updata();
/*select SCLK as the clock source of the system tick timer */
SYSTICK_Clock_Config(SYSTICK_SYS_CLOCK_DIV_1);
/*enable system timer IRQ&interrupt flag*/
SYSTICK_Systick_INT_Enable(TRUE);
/*Configuration system timer Interrupt Priority*/
INT_Interrupt_Priority_Config(INT_SysTick,2,0);
/*enable systick timer*/
SYSTICK_Cmd(TRUE);
/*enable system timer Interrupt*/
INT_Interrupt_Enable(INT_SysTick,TRUE);
INT_All_Enable (TRUE);
}void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
/**
*@brief :Inserts a delay time.
*@param in : delayTime: specifies the delay time length, in milliseconds.
*@param out :None
*@retval :None
*/
void Systick_Delay(uint32_t delayTime)
{
TimingDelay = delayTime;
while(TimingDelay != 0);
}
CM3、CM4的内核中都有个24位的SysTick定时器。这两个MCU里边的SysTick大同小异 //使用中断定时
void SysTick_Init(void)
{
if (SysTick_Config(SystemCoreClock / 100000)
{
while(1);
}
}
/*
时钟频率是72MHz,T = 1 / (72 * 1000000),
SystemCoreClock / 100000 = 720.如果想每10us产生一个中断,则传入的参数是720。
因为时钟频率是72M,所以T = 1/(72 * 1000000),所以在systick计数器每计数一次的时间是T,所以想要多少个T,直接在SysTick_Config(uint32_t ticks),中给参数ticks即可。假如想每1us中断一次,则ticks = 72,即SystemCoreClock / 1000000.**注意在老版本的系统时钟常数是SystemFrequency。而在以后的版本是SystemCoreClock。移植到ucosii的时候要注意。**
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk)return (1);
// Reload value impossible
SysTick->LOAD= (ticks & SysTick_LOAD_RELOAD_Msk) - 1; // set reload register
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);// set Priority for Cortex-M0 System Interrupts
SysTick->VAL = 0; // Load the SysTick Counter Value
SysTick->CTRL= SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; // Enable SysTick IRQ and SysTickzz Timer
return (0); // Function successful
}
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos) // SysTick LOAD: RELOAD Mask
SysTick->LOAD= (ticks & SysTick_LOAD_RELOAD_Msk) - 1;这句是systick配置函数的重装值的设置,结合上面可知SysTick_LOAD_RELOAD_Msk这个值和ticks
是为了对RELOAD寄存器的配置。计数的值就是ticks。
因为传入的ticks是720,即720计数。而时钟频率是72MHz,所以每次计数的结果是10us。
*/
//中断服务函数
void SysTick_handler(void)
{
TimeDelay_Decrement();
}
//时钟每10us中断一次,进入中断函数,然后中断函数调用TimeDelay_Decrement()函数。
//其中TimeDelay是全局变量
void TimingDelay_Decrement(void)
{
if (TimeDelay != 0x00)
{
TimeDelay--;
}
}
//延时函数
void Delay_us(_IO u32 nTime)
{
TimeDelay = nTime;
while (TimeDelay != 0);
}
/************************************************************************************
*在主函数中首先调用SysTick_Init()。这个函数作用是配置时钟初始值,即多久中断一次。
*Enable SysTick IRQ and SysTick Timer,这是SysTick_Config函数中的注释。可以看出
*在这个函数最后使能中断和时间计时器。所以不需要我们单独配置CTRL寄存器的TICKINT为去使能中断了。
*TICKINT类型 RW复位值 0 描述:当该位是1的时候,SysTick倒数到0的时候产生SysTick异常请求
*,当该位是0 的时候,无动作。也可以通过读取COUNTFLAG标志位来确定计数器是否递减到0。
*
*这样的话,第一种采用中断延时的方式就搞定啦!
************************************************************************************/
/**********************************************************************************
另外一种更加简洁的编程
*systick的counter从reload值往下减的时候,CTRL寄存器位16:countflag会置1,且读取该位的值可清零。
*所以我们使用软件查询的方式实现延时。
*推荐使用方法。
*
************************************************************************************/
//systick微妙级延时
void SysTick_Delay_Us(_IO uint32_t us)
{
uint32_t i;
SysTick_Config(SystemCoreClock / 1000000)
for (i = 0; i < us; ++i)
{
//当计数器的值减少到0的时候,CTRL寄存器的位16会置1
while (!(SysTick ->CTRL) & (1 << 16));
}
//关闭SysTick定时器
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
//systick毫秒级延时
void SysTick_Delay_Ms(_IO uint32_t ms)
{
uint32_t i;
SysTick_Config(SystemCoreClock / 1000);
for(i = 0; i < ms; i++)
{
//当计数器的值减少到0的时候,CTRL寄存器的位16会置1
//当置1的时候,读取该位会清零
while (!(SysTick->CTRL) & (1 << 16)));
}
//关闭SysTick定时器
SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;
}
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk)return (1); /* Reload value impossible */
SysTick->LOAD= (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);/* set Priority for Cortex-M0 System Interrupts */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL= SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
} Sys-系统,Tick-滴答声,系统滴答滴答很形象地表示了它是一个系统节拍器。SysTick 是一个集成在Cortex内核里的24位的倒计数定时器,当计到0时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息。 SysTick主要有以下几个作用:
1、产生操作系统的时钟节拍;
当RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。这样SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有节奏的“心跳”。
2、便于不同处理器之间程序移植
因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。
3、作为一个闹铃测量时间
可以用作闹钟,作为启动一个特定任务的时间依据。它作为一个闹铃,用于测量时间。要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。
SysTick编程用到以下寄存器:
CTRL SysTick 控制和状态寄存器
LOAD SysTick 重装载值寄存器
VAL SysTick 当前值寄存器
CALIB SysTick 校准值寄存器 SysTick编程步骤。
① 为SysTick设置时钟源
② 为SysTick 装载计数值寄存器设置计数值;
③ 对SysTick当前计数值寄存器置0;
④ 通过对SysTick的CTRL寄存器的位0置位使能SysTick定时器。
页:
[1]