【STM32小案例 07 】STM32完美可用的延时程序,自用延时程序库,直接调用

来源:互联网 发布:数据库的外键怎么设置 编辑:程序博客网 时间:2024/05/29 10:07

前面的案例中有很多的小伙伴都私信我关于delay_other.c和delay_other.h头文件的源码。

在这里就直接分享出来。

-------------------------------------------------------------------------------------------


主要就是这四个文件。

-------------------------------------------------------------------------------------------

1. sys_other.c


#include "sys_other.h"void NVIC_Configuration(void){    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2:2位抢占优先级,2位响应优先级}

2. sys_other.h


#ifndef __SYS_H#define __SYS_H#include "stm32f10x.h"//0,不支持ucos//1,支持ucos#define SYSTEM_SUPPORT_UCOS0//定义系统文件夹是否支持UCOS     //位带操作,实现51类似的GPIO控制功能//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).//IO口操作宏定义#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) #define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) //IO口地址映射#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C #define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C #define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C #define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C #define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C #define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    #define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    #define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 #define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 #define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 #define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 #define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 #define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 #define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08  //IO口操作,只对单一的IO口!//确保n的值小于16!#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 #define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 #define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 #define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 #define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 #define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 #define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 #define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 #define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 #define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 #define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入void NVIC_Configuration(void);#endif

3.delay_other.c


#include "delay_other.h"#include "sys_other.h"static u8  fac_us=0;//us延时倍乘数static u16 fac_ms=0;//ms延时倍乘数#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.//systick中断服务函数,使用ucos时用到void SysTick_Handler(void){   OSIntEnter();//进入中断    OSTimeTick();       //调用ucos的时钟服务程序                   OSIntExit();        //触发任务切换软中断}#endif//初始化延迟函数//当使用ucos的时候,此函数会初始化ucos的时钟节拍//SYSTICK的时钟固定为HCLK时钟的1/8//SYSCLK:系统时钟void delay_init() {#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.u32 reload;#endifSysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//选择外部时钟  HCLK/8fac_us=SystemCoreClock/8000000;//为系统时钟的1/8   #ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.reload=SystemCoreClock/8000000;//每秒钟的计数次数 单位为K   reload*=1000000/OS_TICKS_PER_SEC;//根据OS_TICKS_PER_SEC设定溢出时间//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右fac_ms=1000/OS_TICKS_PER_SEC;//代表ucos可以延时的最少单位   SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   //开启SYSTICK中断SysTick->LOAD=reload; //每1/OS_TICKS_PER_SEC秒中断一次SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   //开启SYSTICK    #elsefac_ms=(u16)fac_us*1000;//非ucos下,代表每个ms需要的systick时钟数   #endif}    #ifdef OS_CRITICAL_METHOD//使用了ucos//延时nus//nus为要延时的us数.       void delay_us(u32 nus){u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD;//LOAD的值     ticks=nus*fac_us; //需要的节拍数   tcnt=0;told=SysTick->VAL;        //刚进入时的计数器值while(1){tnow=SysTick->VAL;if(tnow!=told){    if(tnow<told)tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.else tcnt+=reload-tnow+told;    told=tnow;if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.}  };     }//延时nms//nms:要延时的ms数void delay_ms(u16 nms){if(OSRunning==TRUE)//如果os已经在跑了    {  if(nms>=fac_ms)//延时的时间大于ucos的最少时间周期 {   OSTimeDly(nms/fac_ms);//ucos延时}nms%=fac_ms;//ucos已经无法提供这么小的延时了,采用普通方式延时    }delay_us((u32)(nms*1000));//普通方式延时,此时ucos无法启动调度.}#else//不用ucos时//延时nus//nus为要延时的us数.       void delay_us(u32 nus){u32 temp;     SysTick->LOAD=nus*fac_us; //时间加载   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;       //清空计数器 }//延时nms//注意nms的范围//SysTick->LOAD为24位寄存器,所以,最大延时为://nms<=0xffffff*8*1000/SYSCLK//SYSCLK单位为Hz,nms单位为ms//对72M条件下,nms<=1864 void delay_ms(u16 nms){     u32 temp;   SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)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;       //清空计数器      } #endif


4.delay_other.h

#ifndef __DELAY_H#define __DELAY_H    #include "sys_other.h"void delay_init(void); //声明C函数void delay_ms(u16 nms);void delay_us(u32 nus);#endif

----------------------------------------------------------------


这四个文件代码已经给出,如果要使用直接在文件头部调用 #include 头文件即可。

至于为什么我要加上一个other是因为这两个程序都不是我自己的自写程序,所以我加上了标识符方便我自己区分。

你们也可以更改成自己的名称,但是注意要在程序内也更改相印的名称。