3.关于延时函数的配置
2018-01-02 22:48
302 查看
接下来简单谈下如何配置延时函数(使用SysTick) 参考 http://blog.csdn.net/luodonghuan1/article/details/46573501 关于延时函数有以下几种方案 1.不依赖于硬件,实现软件延时 2.利用SysTick,实现硬件演示,依赖于时钟配置 /***********************************************************************************************/ 1.使用这种延时函数的情况大多是对时序要求不严格的情况,大多都是为了让单片机打发一些时间而已, 然后实现某种功能,比如,初学MCU,第二课,实现延时函数点灯。 以下是一些相对较准的软件延时函数,从来只有相对准确,而没有绝对准确的东西 //微秒延时函数, void delay_us(u16 time) { u16 i=0; while(time--) { i=10; //自己定义 while(i--) ; } } //毫秒延时函数 void delay_ms(u16 time) { u16 i=0; while(time--) { i=12000; //自己定义 while(i--) ; } } /***********************************************************************************************/ 2.此种情况大多应对时序比较严格的情况下,比如为了描述某个IC的时序,就必须要用到这种延时函数了, 当然这并不是绝对的,有些情况下使用SysTick也可能不如软件延时准确,使用软件延时就比较好,一切看需求 扯了这么多,接下来简单谈下怎么配置MS级的延时函数和US级的延时函数 首先说一下 ST中文参考手册中对SysTick介绍的很简单,如果不仔细查找,基本你获取不到很多有关他的信息 以下引用原话 /* 1.RCC 向 Cortex 系统定时器 (SysTick) 馈送 8 分频的 AHB 时钟 (HCLK)。 SysTick 可使用 此时钟作为时钟源,也可使用 HCLK 作为时钟源,具体可在 SysTick 控制和状态寄存器中配置。 2.SysTick 校准值设置为 18750。当 SysTick 时钟设置为 18.75 MHz(HCLK/8, HCLK 设为 150 MHz),会产生 1 ms 时间基准。 */ 好吧,第一句还有点用,看时钟树,意思就是说,SysTick时钟来源于HCLK,可以实现1分频或者8分频, 可以在SysTic寄存器里面配置.这里再简单提一下系统时钟, 有HSE (8M)|| HSI (16M)|| LSE (32.768K)|| LSI(32K) (LSE && LSI 都可以用来做位RTC的时钟,但是LSI只能用来做看门狗时钟) 然后可以选择使用哪种时钟源(HSE || HSI),一般来说都是选择使用HSE最稳定,然后使用PLL实现倍频, 就是 PLL / M * N / P / Q 配置这四个参数,之后就是配置AHB APB1 APB2, 然后不管是接外设还是使用定时器,时钟都来源于这几个,HCLK是来源于SYSTICK的,AHB分频系数一般设置为1 因此HCLK = SYSTICK 其实吧,很多ST官方手册上面都没有介绍,比如SysTick的寄存器,NVIC的寄存器,还有一些其他的东西 SysTick有四个寄存器 __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ 第一个是控制和状态寄存器 (16位,一般只用最低位0,使能) 第二个是重装载寄存器 (24位) 第三个是存储当前值寄存器 (24位) 第四个是自校正寄存器(一般用不到) 以上寄存器具体可以去查下,这里就不给出了 然后就是配置的问题 思路很简单 1.给重装载寄存器装载需要计时的时间 2.把VAL寄存器中的值清零 3.CTRL使能计数 4.等待直到计时完毕 5.失能CTRL 6.清零VAL,为下次计时做准备 是吧,很简单吧,其实我更愿意称呼它为简单的定时器, 然后就是翻译成寄存器了。但是还是要注意几个问题的, 1.重装载需要的时间得根据当前HCLK的频率来设置 其实这一步也不是很懂,看了不管是HAL库还是ATK的配置都是HCLK / 8 * num,num为要延时的时间, 留一个参数入口,这样,LOAD就配置完成了,看下面这个例子,us级的延时函数,如果是ms的话 只需要*1000就行了,但是需要注意寄存器是24位的,使用ms的话168M只能延时798.915ms 然后可参照ATK的代码。 2.最好8分频(如ST官方手册,可以HCLK 8分频 也可以不分频) /*******************************************************************************************/ /** * @brief : Use SysTick to enable delay_us * @param : MAX num : 2^24 * 8 / 168 = 798915 us * * @retval : none */ void delay_us(uint32_t num) { #if CLK_168 //168MHZ SysTick->LOAD = num * 168 / 8 ; //Reload #elif CLK_160 //160MHZ SysTick->LOAD = num * 160 / 8 ; //Reload #elif CLK_80 //80MHZ SysTick->LOAD = num * 80 / 8 ; //Reload #elif CLK_72 //72MHZ SysTick->LOAD = num * 72 / 8 ; //Reload #endif //<CLK_168> SysTick->VAL = 0; //CE SysTick->CTRL |= 1<<0; //Enable SysTick while(!(SysTick->CTRL & 1<<16)); 4000 //Till 0 SysTick->CTRL &= ~(1<<0); //Disable SysTick SysTick->VAL = 0; //CE } /** * @brief : From ATK * @param : MAX num : 65535 ms * * @retval : none */ void delay_ms(uint16_t nms) { uint16_t repeat=nms / 540; uint16_t remain=nms % 540; while(repeat) { delay(540); repeat--; } if(remain) delay(remain); } //Hide /** * @brief : Use SysTick to enable delay_ms * @param : MAX num = 2^24 * 8 / 168 / 1000 = 798.915 ms * * @retval : none */ static void delay(uint32_t num) { #if CLK_168 //168MHZ SysTick->LOAD = num * 168 * 1000 / 8 ; //Reload #elif CLK_160 //160MHZ SysTick->LOAD = num * 160 * 1000 / 8 ; //Reload #elif CLK_80 //80MHZ SysTick->LOAD = num * 80 * 1000 / 8 ; //Reload #elif CLK_72 //72MHZ SysTick->LOAD = num * 72 * 1000 / 8 ; //Reload #endif //<CLK_168> SysTick->VAL = 0; //CE SysTick->CTRL |= 1<<0; //Enable SysTick while(!(SysTick->CTRL & 1<<16)); //Till 0 SysTick->CTRL &= ~(1<<0); //Disable SysTick SysTick->VAL = 0; //CE } /***********************************************************************************************/
相关文章推荐
- 令人头大的单片机延时----这里转一篇关于延时函数的文章看看
- 关于CSR8670如何使用PioSetMapPins32()函数配置额外的IO口
- 关于unity自带延时函数
- 关于郭天祥单片机书上第四十七页延时函数的相关计算问题
- [原创].关于编写Nios II的延时函数的一点心得
- js关于setTimeout实现延时执行函数并进行传参
- 20140627-STM8L101F3P6关于微秒级延时函数不同写法的波形
- 关于PHP-Zend framework2 框架 学习过程。 阅前须知: ZF2中的配置文件是可以静态文件配置来注册和通过相关函数动态注册。 1.EventManager(事件驱动),关于事件驱动,在ZF2相关资料没有详细说明,可以参考ANDROID的事件驱动,MFC的消息响应/事件驱动。
- avr-gcc中关于delay延时函数的应用(原发于2007-11-16)
- 逆向BC3.1的程序后得到DOS下面关于精确延时1ms的函数(理论上可以非常精确延时到10微妙级别)
- 关于linux中的延时函数
- 关于HM打印配置文件中参数的函数
- 【工作总结】一组关于key=value类似配置文件的读写操作函数
- js关于setTimeout实现延时执行函数并进行传参
- 20140627-STM8L101F3P6关于毫秒级延时函数不同写法的波形
- 关于linux中的延时函数
- DOS下面关于精确延时1ms的函数(理论上可以非常精确延时到10微妙级别)
- avr-gcc中关于delay延时函数的应用修改版[ourdev]
- 关于u cos 中延时函数OSTimeDly和任务通信***pend()函数对任务的影响分析
- 关于linux中的延时函数