【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
#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是因为这两个程序都不是我自己的自写程序,所以我加上了标识符方便我自己区分。
你们也可以更改成自己的名称,但是注意要在程序内也更改相印的名称。
阅读全文
0 0
- 【STM32小案例 07 】STM32完美可用的延时程序,自用延时程序库,直接调用
- STM32延时us程序
- STM32的精确延时
- 【STM32】STM32之timer2的精准延时
- 关于STM32的延时问题
- STM32精确延时
- STM32-I2C-appcat延时
- STM32-I2C-appcat延时
- STM32 粗延时总结
- STM32 延时函数封装
- stm32微秒延时实现
- STM32 自定义延时函数
- STM32 延时函数解析
- stm32中的延时函数
- STM32延时注意事项
- STM32的几种延时方法
- STM32 REG设置注意延时
- stm32使用systick精确延时
- 静态链表--简单操作
- 图灵奖设立50周年,向伟大的计算机科学家们致
- 常用采样方法
- Matlab、C混合编程(Matlab调用C)
- Cocos Creator Shader工具
- 【STM32小案例 07 】STM32完美可用的延时程序,自用延时程序库,直接调用
- CPU
- 关于Navicate life 修改表中字段,删除字段,修改字段无响应的处理。
- Lesson 2:作业5:描述cpu的速度与硬盘的容量
- c语言
- 2017图灵奖获得者Tim Berners-Lee:必须让全球剩下80%地区尽快上网
- jvisualvm安装visualgc插件(java.net网站已关闭)
- 剑指offer--从尾到头打印链表
- ExtJS4给tree的结点添加点击事件