第一种方式是正点原子的,正点原子的SysTick->LOAD=(u32)nms*fac_ms,应该再减1,作者程序未减,第二种方式是野火的,第三种是慧净的,与原子一样多计1us,第四种是小马飞控通过中断实现systick延时,上传以作记录。
1.正点原子初始化使用misc.c里的库函数SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)初始化systick时钟源为
9MHz,总的延时赋值给24位LOAD寄存器,延时时间受限制,最大0xFFFFFF/9=1864135us,SysTick-
>LOAD=nus*fac_us-1=1864134us,从0开始; 同理0xFFFFFF/9/1000=1864ms,SysTick->LOAD=nms*fac_ms-1=1863ms
2.慧净电子直接控制寄存器systick-》ctrl,同样设时钟源为9MHz,只是在ms延时的时候,与正点原子区别是嵌套的是us的
函数,循环us实现的延时,延时时间us有限制,ms无限制,因为无16为寄存器load。
3.小马四轴飞控init初始化函数通过直接配置寄存器ctrl和load,设置了系统时钟源72MHz,中断和LOAD寄存器值为72(
1us),然后通过每中断一次,时间减1的方式实现延时us和ms,延时时间不受限制
4.野火没有初始化函数,systick.h中直接调用了core_cm3.h(里面有库函数SysTick_Config,默认systick时钟源为72MHz)
,在us和ms延时函数中分别调用了SysTick_Config,设Load寄存器值分别为72(1us)和72000(1ms),通过循环实现时
间延时,值不受限制。
总而言之,1.设置时钟源方式(SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)+寄存器CTRL),2.设置寄存器方
式(static __INLINE uint32_t SysTick_Config(uint32_t ticks)+寄存器LOAD直接赋值) ,3,延时方式(直接赋值load寄存器+
循环+中断)
systick.h文件:
#ifndef __SYSTICK_H
#define __SYSTICK_H
#include "stm32f10x.h"
#include "core_cm3.h"
//24位LOAD寄存器最大延时1864ms,正点原子部分
void delay_init(void);
void delay_ms(u16 nms);
void delay_us(u32 nus);
//延时不受限制,野火部分
void SysTick_Delay_us(uint32_t us);
void SysTick_Delay_ms(uint32_t ms);
#endif /* __SYSTICK_H */
systick.c文件:
#include "systick.h"
//正点原子:
//正点原子使用misc.c里的库函数SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)初始化systick时钟为9MHz,
//24位LOAD寄存器,延时时间受限制,最大0xFFFFFF/9=1864135us,SysTick->LOAD=nus*fac_us-1=1864134us,从0开始; 同理0xFFFFFF/9/1000=1864ms,SysTick->LOAD=nms*fac_ms-1=1863ms
static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数
void delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
}
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us-1; //时间加载,SysTick->LOAD为24位寄存器,所以,最大延时为:nus<=1864135us
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms-1; //时间加载(SysTick->LOAD为24bit),最大延时为:nms<=1864ms
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//野火:
//使用core_cm3.h里的库函数SysTick_Config初始化systick时钟为72MHz(默认时钟),延时不受限制
#if 0
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
// 判断 tick 的值是否大于 2^24,如果大于,则不符合规则
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);
// 初始化reload寄存器的值
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;//72-1或72000-1
// 配置中断优先级,配置为15,默认为最低的优先级
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
// 初始化counter的值为0
SysTick->VAL = 0;
// 配置 systick 的时钟为 72M
// 使能中断
// 使能systick
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | //时钟源 72或9MHz
SysTick_CTRL_TICKINT_Msk | //中断使能
SysTick_CTRL_ENABLE_Msk; // 计时使能
return (0);
}
#endif
void SysTick_Delay_us(uint32_t us)
{
uint32_t i;
SysTick_Config(72);
for(i=0; i<us; i++)
{
while( !((SysTick->CTRL) & (1<<16)) );
}
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
void SysTick_Delay_ms(uint32_t ms)
{
uint32_t i;
SysTick_Config(72000);
for(i=0; i<ms; i++)
{
while( !((SysTick->CTRL) & (1<<16)) );
}
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
//慧净电子:
void delay_init(void)
{
SysTick->CTRL&=0xfffffffb;//控制寄存器,选择外部时钟即系统时钟的八分之一(HCLK/8;72M/8=9M)
}
//1us 延时函数
void Delay_us(u32 Nus)
{
SysTick->LOAD=Nus*9-1; //时间加载 72M主频 跟原子一样也是没有减1,多计1us
SysTick->CTRL|=0x01; //开始倒数
while(!(SysTick->CTRL&(1<<16))); //等待时间到达
SysTick->CTRL=0X00000000; //关闭计数器
SysTick->VAL=0X00000000; //清空计数器
}
void Delayms(u32 Nms)
{
while(Nms--)
{
Delay_us(1000);
}
}
//小马四轴飞控:
#include "systick.h"
u32 count;
void SysTick_Init(void)
{
SysTick->LOAD = (uint32_t)(SystemCoreClock/1000000 - 1UL);//72
SysTick->VAL = 0UL;//0
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |SysTick_CTRL_TICKINT_Msk;//设置72MHz,使能中断
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;//禁止systick启动
}
void delay_us(u32 time)
{
if(time<=0)
return;
count = time;
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;//使能
while(count!=0);
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
void delay_ms(u32 time)
{
if(time<=0)
return;
count = time*1000;
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while(count!=0);
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
//systick中断处理函数
void SysTick_Handler(void)
{
if(count!=0){
count--;
}
}