我现在看原子哥关于systick定时器的写法,就是关于系统延时delay_ms,delay_us的实现方法,然后发现,原子哥中的写法中,并没有使用到SysTick_Handler这个中断函数,但是我在网上查到了另外一种写法,实现延时的方法是在SysTick_Handler这个中断函数中实现,那么,我在这里,有一个解释,不知道原子大哥咱不赞同:
第一种写法是使用的,STK_VAL的值减到0的时候,会重新装载STK_LOAD的值,然后产生一次中断,非原子哥例程就是在这个中断中,写了一个延时的函数出来;而原子哥的写法,主要是依据的是,STK_VAL的值减到0的时候,会重新装载STK_LOAD的值,并且STK_CSR的第16位会由0置位成1,原子哥就是利用的判断STK_CSR的第16位的改变,来写出的延时函数的,从而实现延时。
网上的例程,我摘抄一点出来作为对比:
配置systick寄存器:
void SysTick_Configuration(void)
{
SYSTICK_CURRENT=0; //当前值寄存器
SYSTICK_RELOAD=20000; //重装载寄存器,系统时钟20M中断一次1mS
SYSTICK_CSR|=0x06;// HCLK作为Systick时钟,Systick中断使能位
}
中断处理:
void SysTick_Handler(void) //中断函数
{
extern unsigned long TimingDelay; // 延时时间,注意定义为全局变量
SYSTICK_CURRENT=0;
if (TimingDelay != 0x00)
TimingDelay--;
}
利用systick的延时函数:
unsigned long TimingDelay; // 延时时间,注意定义为全局变量
void Delay(unsigned long nTime) //延时函数
{
SYSTICK_CSR|=0x07; // 使能SysTick计数器
TimingDelay = nTime; // 读取延时时间
while(TimingDelay != 0); // 判断延时是否结束
SYSTICK_CSR|=0x06;// 关闭SysTick计数器
}
然后,基于这样的认识,我对原子哥的例程中进行了修改
void delay_init(u8 SYSCLK)
{
///SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟 HCLK/8 ///为清空CLKSOURCE位而选择外部时钟源
SysTick->CTRL&=0xfffffff9;
fac_us=SYSCLK/8;
fac_ms=(u16)fac_us*1000;
}
红色是我修改的地方,就是将SysTick的中断给关了,依然ok。
请问各位,不知道小弟的这种认识是不是正确的。
|