完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
#简介
在之前的实验中,我们只用到的delay函数通过while语句做循环的方式来占用时间,达到延时的目的。但是这种方式延时的时间不好把控,无法应用于更加精确的场合,所以势必还要引入今天要说的系统定时器。 Systick系统定时器采用24位向下递减的方式进行,也就是其单次计时总共能够计数2^24=16777216次,计数一次用时1/systick,单位为秒(s)。其中,systick可以为系统时钟sysclk或者系统时钟的8分频。当定时器设置好初值后,则由初值往下以此递减计数,计数至0则从LOAD寄存器中自动重装初值(若事先开启中断,则计数至0可触发中断响应) #寄存器 定时器中共有四个寄存器,顺序如下: ##CTRL寄存器 如图,其中ENABLE就是定时器的使能位,通过它来控制定时器的开和关;CLKSOURCE用于确定时钟源,其中的内核时钟就是我们的系统时钟,外部时钟就是系统时钟的8分频;COUNTFLAG为计数状态标志位,计数完毕则为1,常用于判断。 ##LOAD寄存器 LOAD寄存器就是用于存放重载值。 ##VAL寄存器 VAL寄存器可以读取当前计数的值,也可对其进行写,但要注意这时会将COUNTFLAG清零。 ##CALIB寄存器 这个寄存器主要是用于校准……平时也不用咋设置,大家知道有这么个东西就行。 #配置步骤 (1)设置Systick的时钟源 (2)设置初始值(如需要中断,则记得打开中断) (3)清零当前计数器的值 (4)打开Systick定时器 #函数封装代码 ##初始化函数 u16 tic_us=0; u32 tic_ms=0; void SysTick_Init(u8 SYSCLK) //第一步:设置时钟源 变量系统时钟的单位为MHz { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //采取8分频 tic_us=SYSCLK/8; //定时1us所需的计数次数 tic_ms=(u16)tic_us*1000; //定时1ms所需要的计数次数 } 初始化主要是进行第一步的操作,即设置定时器的时钟源,顺便定义一下之后需要使用的变量tic_us和tic_ms ##us延时函数 void delay_nus(u32 nus) //定义一个延时单位为us的函数,输入变量为我们所希望延迟的时间,单位为微秒 { SysTick->LOAD=nus*tic_us; //第二步:设置初始值 SysTick->VAL=0x00; //第三步:将当前计数值清零 SysTick->CTRL|=0x01; //第四步:打开定时器,开始倒数。 while(!(SysTick->CTRL&(1<<16))) { } SysTick->CTRL&=~0x01; //关闭定时器 SysTick->VAL=0x00; //将当前计数值清零 } ##ms延时函数 void delay_nms(u16 nms) //定义一个延时单位为ms的函数,输入变量单位为毫秒 { SysTick->LOAD=(u32)nms*tic_ms; //第二步:设置初始值 SysTick->VAL=0x00; //第三步:将当前计数值清零 SysTick->CTRL|=0x01; //第四步:打开定时器,开始倒数。 while(!(SysTick->CTRL&(1<<16))) { } SysTick->CTRL&=~0x01; //关闭定时器 SysTick->VAL=0x00; //将当前计数值清零 } ###带循环的ms延时函数 由于单次计数最多延时798ms,未必能够满足我们在一些场合下的延时需求,所以我们在ms延时的基础上加入循环。 void delay_ms(u16 nms) //当所需延时较长时,单次delay_nms无法满足,所以这里采用循环 { int i; u8 circul=nms/700; //单次最多延时798ms,这里取700,不超过798 circul为循环次数 u16 remain=nms%700; for(i=0;i delay_nms(700); //每次延时700ms } if(remain) { delay_nms(remain); //延时剩余时间 } } 我们之所以不写带循环的us函数,主要是因为以us为单位,如果所需计数次数较多的话可以用delay_nms或delay_ms完成。当然,如果追求精度的话也可以仿照上面的函数在写一个带循环的us延时函数。 #示例程序 #include "stm32f4xx.h" #include "led.h" #include "bit_operation.h" #include "Systick.h" int main() { SysTick_Init(168); //系统时钟为168M RCC_HSE_Config(8,336,2,7); LED_Init(); led2=0; while(1) { led2=~led2; delay_nms(500); //延时500ms } } 根据实验现象呢~一周期为0.92s,不过我是用手机手动测的时间,误差较大,相信实际的时间肯定会是比较精确的。此外,需要注意的是,系统时钟与SysTick_Init(168)中的参数要相匹配,否则结果会有比较大的出入。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1752 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1611 浏览 1 评论
1052 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
721 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1666 浏览 2 评论
1926浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
711浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
560浏览 3评论
584浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
544浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-19 02:28 , Processed in 0.731999 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号