范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

STM32嵌入式系统延时函数8

  自己学习总结用,有些乱勿怪
  1、delay 文件夹代码介绍
  delay 文件夹内包含了 delay.c 和 delay.h 两个文件,这两个文件用来实现系统的延时功能,
  其中包含 7 个函数:
  void delay_osschedlock(void);
  void delay_osschedunlock(void);
  void delay_ostimedly(u32 ticks);
  void SysTick_Handler(void);
  void delay_init(u8 SYSCLK);
  void delay_ms(u16 nms);
  void delay_us(u32 nus);
  前面 4 个函数,仅在支持操作系统(OS)的时候,需要用到,而后面 3 个函数,则不论是否支持 OS 都需要用到。在介绍这些函数之前,我们先了解一下编程思想:CM4 内核的处理和 CM3 一样,内部都包含了一个 SysTick 定时器,SysTick 是一个 24 位的倒计数定时器,当计到 0 时,将从 RELOAD寄存器中自动重装载定时初值。只要不把它在 SysTick 控制及状态寄存器中的使能位清除,就永不停息。SysTick 在《STM32xx 中文参考手册》里面基本没有介绍,其详细介绍,请参阅《STM32F3 与 F4 系列Cortex M4内核编程手册》第230 页。我们就是利用 STM32的内部 SysTick来实现延时的,这样既不占用中断,也不占用系统定时器。这里我们将介绍的是 ALIENTEK 提供的最新版本的延时函数,该版本的延时函数支持在任意操作系统(OS)下面使用,它可以和操作系统共用 SysTick 定时器。这里,我们以 UCOSII 为例,介绍如何实现操作系统和我们的 delay 函数共用 SysTick 定时器。首先,我们简单介绍下 UCOSII 的时钟:ucos 运行需要一个系统时钟节拍(类似 "心跳"),而这个节拍是固定的(由 OS_TICKS_PER_SEC 宏定义设置),比如要求 5ms 一次(即可设置:OS_TICKS_PER_SEC=200),在 STM32 上面,一般是由 SysTick 来提供这个节拍,也就是 SysTick要设置为 5ms 中断一次,为 ucos 提供时钟节拍,而且这个时钟一般是不能被打断的(否则就不准了)。
  因为在 ucos 下 systick 不能再被随意更改,如果我们还想利用 systick 来做 delay_us 或者delay_ms 的延时,就必须想点办法了,这里我们利用的是时钟摘取法。以 delay_us 为例,比如delay_us(50),在刚进入 delay_us 的时候先计算好这段延时需要等待的 systick 计数次数,这里为 50*21(假设系统时钟为 168Mhz,因为 systick 的频率为系统时钟频率的 1/8,那么 systick每增加 1,就是 1/21us),然后我们就一直统计 systick 的计数变化,直到这个值变化了 50*21,一旦检测到变化达到或者超过这个值,就说明延时 50us 时间到了。这样,我们只是抓取 SysTick计数器的变化,并不需要修改 SysTick 的任何状态,完全不影响 SysTick 作为 UCOS 时钟节拍的功能,这就是实现 delay 和操作系统共用 SysTick 定时器的原理。
  2、操作系统支持宏定义及相关函数
  当需要 delay_ms 和 delay_us 支持操作系统(OS)的时候,我们需要用到 3 个宏定义和 4个函数,宏定义及函数代码如下:
  //本例程仅作 UCOSII 和 UCOSIII 的支持,其他 OS,请自行参考着移植
  //支持 UCOSII
  #ifdef OS_CRITICAL_METHOD
  //OS_CRITICAL_METHOD 定义了,说明要支持 UCOSII
  #define delay_osrunning
  OSRunning
  //OS 是否运行标记,0,不运行;1,在运行
  #define delay_ostickspersec OS_TICKS_PER_SEC //OS 时钟节拍,即每秒调度次数
  #define delay_osintnesting OSIntNesting
  //中断嵌套级别,即中断嵌套次数
  #endif
  //支持 UCOSIII
  #ifdef CPU_CFG_CRITICAL_METHOD
  //CPU_CFG_CRITICAL_METHOD 定义了,说明要支持 UCOSIII
  #define delay_osrunning
  OSRunning
  //OS 是否运行标记,0,不运行;1,在运行
  #define delay_ostickspersec OSCfg_TickRate_Hz //OS 时钟节拍,即每秒调度次数
  #define delay_osintnesting OSIntNestingCtr
  //中断嵌套级别,即中断嵌套次数
  #endif
  //us 级延时时,关闭任务调度(防止打断 us 级延迟)
  void delay_osschedlock(void)
  {
  #ifdef CPU_CFG_CRITICAL_METHOD //使用 UCOSIII
  OS_ERR err;
  OSSchedLock(&err);
  //UCOSIII 的方式,禁止调度,防止打断 us 延时
  #else
  //否则 UCOSII
  OSSchedLock();
  //UCOSII 的方式,禁止调度,防止打断 us 延时
  #endif
  }
  //us 级延时时,恢复任务调度
  void delay_osschedunlock(void)
  {
  #ifdef CPU_CFG_CRITICAL_METHOD //使用 UCOSIII
  OS_ERR err;
  OSSchedUnlock(&err);
  //UCOSIII 的方式,恢复调度
  #else
  //否则 UCOSII
  OSSchedUnlock();
  //UCOSII 的方式,恢复调度
  #endif
  }
  //调用 OS 自带的延时函数延时
  //ticks:延时的节拍数
  void delay_ostimedly(u32 ticks)
  {
  #ifdef CPU_CFG_CRITICAL_METHOD //使用 UCOSIII 时
  OS_ERR err;
  OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);//UCOSIII 延时采用周期模式
  #else
  OSTimeDly(ticks);
  //UCOSII 延时
  #endif
  }
  //systick 中断服务函数,使用 ucos 时用到
  void SysTick_Handler(void)
  {
  if(delay_osrunning==1)
  //OS 开始跑了,才执行正常的调度处理
  {
  OSIntEnter();
  //进入中断
  OSTimeTick();
  //调用 ucos 的时钟服务程序
  OSIntExit();
  //触发任务切换软中断
  }
  }
  以上代码,仅支持 UCOSII 和 UCOSIII,不过,对于其他 OS 的支持,也只需要对以上代
  码进行简单修改即可实现。
  支持 OS 需要用到的三个宏
  #define delay_osrunning OSRunning //OS 是否运行标记,0,不运行;1,在运行
  #define delay_ostickspersec OS_TICKS_PER_SEC //OS 时钟节拍,即每秒调度次数
  #define delay_osintnesting OSIntNesting //中断嵌套级别,即中断嵌套次数
  宏定义:delay_osrunning,用于标记 OS 是否正在运行,当 OS 已经开始运行时,该宏定义值为 1,当 OS 还未运行时,该宏定义值为 0。
  宏定义:delay_ ostickspersec,用于表示 OS 的时钟节拍,即 OS 每秒钟任务调度次数。
  宏定义:delay_ osintnesting,用于表示 OS 中断嵌套级别,即中断嵌套次数,每进入一个中断,该值加 1,每退出一个中断,该值减 1。
  支持 OS 需要用到的 4 个函数,即 :
  函数:delay_osschedlock,用于 delay_us 延时,作用是禁止 OS 进行调度,以防打断 us 级延时,导致延时时间不准。
  函数:delay_osschedunlock,同样用于 delay_us 延时,作用是在延时结束后恢复 OS 的调度,继续正常的 OS 任务调度。
  函数:delay_ostimedly,则是调用 OS 自带的延时函数,实现延时。该函数的参数为时钟节拍数。
  函数:SysTick_Handler,则是 systick 的中断服务函数,该函数为 OS 提供时钟节拍,同时可以引起任务调度。以上就是 delay_ms 和 delay_us 支持操作系统时,需要实现的 3 个宏定义和 4 个函数。
  3、delay_init 函数
  该函数用来初始化 2 个重要参数:fac_us 以及 fac_ms;同时把 SysTick 的时钟源选择为外部时钟,如果需要支持操作系统(OS),只需要在 sys.h 里面,设置 SYSTEM_SUPPORT_OS 宏的值为 1 即可,然后,该函数会根据 delay_ostickspersec 宏的设置,来配置 SysTick 的中断时间,并开启 SysTick 中断。具体代码如下[ 这里介绍两个版本的delay_int,一个是M3的72MHz和M4的168MHZ]:
  开启 SysTick 中断。具体代码如下:
  //初始化延迟函数
  //当使用 OS 的时候,此函数会初始化 OS 的时钟节拍
  //SYSTICK 的时钟固定为 HCLK 时钟的 1/8
  void delay_init()
  {
  #if SYSTEM_SUPPORT_OS
  //如果需要支持 OS.
  u32 reload;
  #endif
  SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
  //选择外部时钟 HCLK/8
  fac_us=SystemCoreClock/8000000;
  //为系统时钟的 1/8
  #if SYSTEM_SUPPORT_OS
  //如果需要支持 OS.
  reload=SystemCoreClock/8000000; //每秒钟的计数次数 单位为 M  1
  reload*=1000000/delay_ostickspersec;  2
  //根据 delay_ostickspersec 设定溢出时间
  //reload 为 24 位寄存器,最大值:16777216,在 168M 下,约合 0.7989s 左右
  fac_ms=1000/delay_ostickspersec;  3
  (这里是168M下,因为这里直接把每秒的计数次数变成了秒的计算,1的reload=21次每us,第二行reload=21*1000000/200=105000,下面3的定时器时间,即最好系统时间单元是5ms,而105000/21us=5000us=5ms,也是5ms一次中断。即168M下105000次递减一次中断是5ms,而reload最大值=16777216,在168M下是24位寄存器的理论值,它的延时是16777216/21us=798915.0476us=0.7989s)
  //代表 OS 可以延时的最少单位
  SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;
  //开启 SYSTICK 中断
  SysTick->LOAD=reload;
  //每 1/delay_ostickspersec 秒中断一次
  SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
  //开启 SYSTICK
  #else
  fac_ms=(u16)fac_us*1000;
  //非 OS 下,代表每个 ms 需要的 systick 时钟数
  #endif
  }
  另一个M3的版本
  void delay_init()
  {
  #if SYSTEM_SUPPORT_OS //如果需要支持OS.
  u32 reload;
  #endif
  SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
  fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
  #if SYSTEM_SUPPORT_OS //如果需要支持OS.
  reload=SystemCoreClock/8000000; //每秒钟的计数次数 单位为M
  reload*=1000000/delay_ostickspersec; //根据delay_ostickspersec设定溢出时间
  //reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右
  ( ①设置滴答定时器时钟源,F103为72M,72M/8=9M;
  ②用当前时钟源9M,9M/S=9/us;故1us计数器跳动9次;
  ③同②;
  ④根据delay_ostickspersec设置溢出时间,在默认值下,delay_ostickspersec=200;
  reload在后边将会当做计数初值,放入重装载计数器,故它为溢出所需的计数次数;
  reload=1/200*1000000*9;
  溢出时间为1/200s,在乘以1000000,变为us级别,再乘以1us跳动次数;
  (一秒钟跳200次(设定计时);每次0.005s,即5ms;0.005s有多少个us,即0.005*1000000=5000个;1us跳9次,故在乘以9,等于45000次,装入SysTick->LOAD这个寄存器;
  说白了就是:滴答定时器1us跳9次,你将45000次放入SysTick->LOAD这个寄存器,它就开始倒计时,滴答定时器进入它的中断的时间是1/200s=5ms,也是45000/9us=5000us=5ms,也就是5ms进一次中断。以最大reload=16777216/9us=1864135.111us=1.86s)
  SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);这一句把SysTick的时钟选择外部时钟,SysTick 的时钟源自 HCLK 的 8 分频,假设我们外部晶振为 8M,然后倍频到 72M,那么 SysTick 的时钟即为 9Mhz,也就是SysTick 的计数器 VAL 每减 1,就代表时间过了 1/9us。
  fac_us=SystemCoreClock/8000000;这句话就是计算在 SystemCoreClock 时钟频率下延时
  1us 需要多少个 SysTick 时钟周期。
  fac_ms=(u16)fac_us*1000;就是计算延时 1ms 需要多少个 SysTick 时钟周期,它自然是 1us
  的 1000 倍。
  在不使用 OS 的时候:fac_us为 us 延时的基数,也就是延时 1us时候SysTick->LOAD 所应设置的值。fac_ms 为 ms 延时的基数,也就是延时 1ms,SysTick->LOAD 所应设置的值。fac_us为 8 位整形数据,fac_ms 为 16 位整形数据。
  当使用 OS 的时候,fac_us还是 us 延时的基数,不过这个值不会被写到 SysTick->LOAD寄存器来实现延时,而是通过时钟摘取的办法实现的。而 fac_ms 则代表 ucos自带的延时函数所能实现的最小延时时间(如 delay_ostickspersec=200,那么 fac_ms 就是 5ms)
  )
  fac_ms=1000/delay_ostickspersec; //代表OS可以延时的最少单位
  SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
  SysTick->LOAD=reload; //每1/delay_ostickspersec秒中断一次
  SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
  #else
  fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
  #endif
  }

油耗水平持续下降,为啥负积分10万的车企却越来越多?5月24日,工信部发布乘用车企业平均燃料消耗量与新能源汽车积分并行管理实施情况年度报告(2021)。报告显示,在积分考核约束和积分收益激励下,我国汽车行业的平均油耗持续下降,单车平韩国5G普及率超20,即将完全关闭2G网络IT之家5月28日消息韩国信息通信技术部周二表示,已批准LGUplus公司在6月底前逐步淘汰其2G服务的计划,这将标志着韩国旧有电信网络将完全终止。LGUplus表示,将通过为移动诺基亚谈造车只聚焦5G网络这一端百度在沪成立云计算公司2021年5月28日精选资讯如下互联网新鲜事盲盒手办备货量同比增长1000据某物流平台数据显示,已有数百万吨618预售商品备入仓库,规模同比增长100。其中,盲盒手办备货量同比暴增长三角新能源汽车产业链联盟成立近日,由上汽集团吉利控股集团奇瑞集团江苏省汽车工程学会联合牵头,成立了长三角新能源汽车产业链联盟(以下简称联盟)。来自三省一市共73家新能源汽车产业链企业共同响应成立,涉及电池电机微软SurfaceDuo双屏安卓手机推送5月更新修复恼人BugIT之家5月29日消息外媒报道,近期,微软发布了SurfaceDuo的2021年5月安卓系统更新,北美地区升级到版本号2021。419。70,欧洲地区升级到版本号2021。419。李劲松行业对保险科技的理解不能简单停留在技术和保险业结合的层面北京商报讯(记者陈婷婷周菡怡)5月30日,北京商报记者从业内获悉,中国精算师协会副秘书长李劲松在2021第四届华夏时报保险科技峰会上表示,不能将保险科技视为对消费者割韭菜的武器。在微信又更新了惊喜!炸屎特效绝了你知道吗?最近微信又更新了,还是那句老话解决了一些已知问题,但实际上这次更新,给我们带来了很多有趣的玩法!表情碰撞特效当你和朋友一人发屎一人发炸弹时,屏幕上就会出现炸屎特效!简直魔厉害了!2021年这5大最好的安卓手机机皇来袭,您在用哪款呢?哈喽,您好!我是原呵呵,点点关注吧,更多精彩内容等着您智能手机市场是一场激烈的竞赛您可以选择运行iOS操作系统的Apple其iPhone,或者选择许多生产基于其AndroidOS的当一个微信号可以同时登陆在两个手机上,将是一种什么体验?一直以来,大家都以为一个微信号只能在一个手机上登陆,如果想要同时登陆在两个设备上,也只能是一个手机和一个平板或者一个手机和一个电脑上,从来都不能同时在两个手机上登陆。如果,你现在还30万级座驾,这三款都是狠货,最快零百3秒多,关键均由华系制造30万级预算选车,你会怎么考虑呢?大部分朋友可能都会去看各大豪华品牌,入手新能源座驾的,也按耐不住去往特斯拉4S店的步伐。但是,在该价位中,咱们自己的华系车其实也有不少可选车型比如这?暗示折叠屏会成为一大趋势吗?折叠屏这几年的风特别大。先是三星带头推出三星GalaxyZFoldGalaxyZFlip和GalaxyZFold2。随即刮起了折叠屏的热潮。虽然是万元起步的售价,但是销售额依然增长
Quest好评游戏WarplanesWW1Fighters登陆PicoNeo3(映维网2021年10月22日)日前,来自VR游戏开发商HomeNetGames的VR空战游戏战机一战英豪(WarplanesWW1Fighters)已正式登陆PicoNeo3。值建筑业的革命,NOXInnovations用HoloLens提供虚拟设计施工服务(映维网2021年10月20日)当微软首次发布HoloLens技术时,赛义德埃斯拉米(SaeedEslami)正在一家大型建筑公司的技术部门工作。埃斯拉米马上意识到可以利用这种混合Ecolab利用HoloLens2和Dynamics365确保工厂食品安全和生产质量(映维网2021年10月20日)Ecolab的食品安全解决方案有助于安全生产超过25的世界加工食品和44的全球牛奶供应。这相当于数以千计依靠世界一流现场服务来确保每天生产安全优质食2021世界VR产业大会影创副董胡金鑫云端大地图,赋能新工业声明新闻稿非映维官方稿,法律问题一律与映维无关在本届2021世界VR产业大会上,影创科技集团副董事长胡金鑫在VR制造业主题论坛上发表了主题演讲AR眼镜的实时三维重建在工业中的应用。BowenEngineering用HoloLens改善水务电力工厂的设计施工(映维网2021年10月20日)位于美国印第安纳州印第安纳波利斯的BowenEngineering是一家专注于工业领域和市政工程的承包商,例如污水处理厂和发电厂等等。为了进一步提升欧莱雅用HoloLens2和Dynamics365提高工厂生产效率优化运营(映维网2021年10月20日)欧莱雅以其美容产品的质量和种类闻名于世,而这是位于150个国家的众多员工所努力工作的结果。为了帮助员工提高效率和生产效率,欧莱雅在HoloLens2重定义汽修,奔驰加拿大全面部署HoloLens2Dynamics365混合现实查看引用信息源请点击映维网将在加拿大全面部署微软HoloLens2和Dynamics365RemoteAssist(映维网2021年10月22日)奔驰加拿大日前宣布,将全面部署开创学习大数据可以做什么高考的大幕刚刚落下,考生们又将面临着另一个考验志愿填报,其中大数据相关的专业成了今年的关注热点,很多考生就想知道学习大数据出来可以做什么,有什么岗位能选择,今天我将为大家带来学习大大数据编程入门Java基础语法Java是一门面向对象编程语言,不仅吸收了C语言的各种优点,还摒弃了C里难以理解的多继承指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java可以编写桌面应用程序We大数据编程入门Java变量类型在Java中,变量是极其重要的一部分,用来存储程序运行期间产生的一些临时数据,今天将为大家带来Java变量类型。一什么是变量在程序运行期间,随时可能产生一些临时数据,应用程序会将这如何学习大数据随着大数据时代的发展,越来越多的人想要学习大数据,但是又不知道从哪里开始学起,首先在学习大数据之前你需要了解大数据到底是什么?对于大数据,它不是某个专业也不是某一门编程语言,它是由