STM32 Systick实现us和ms定时的两种方式

第一种方式是正点原子的,正点原子的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--;
	}
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值