拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

使用通用定时器实现延时函数遇到的问题

使用通用定时器实现延时函数遇到的问题 1 需求使用TIM2定时器实现毫秒级延迟实现原理定义全局计数器定时器中断触发中断服务函数在中断里对计数器加一操作直到累加的数值和期望延时的数字相同2 实现流程需要用到的外设有TIM2定时器通过0.96寸OLED屏幕IIC通信通过延时显示不同字符串来验证延时功能是否正常3 代码实现流程先准备好测试用字符串hello world1 hello world2 12345678987654321 三个字符串 然后在显示函数之间插入要使用的延时函数主函数主要进行调用写好的功能函数和初始化等函数具体的实现和声明等操作在功能文件中编写本次实验重点部分在Tim文件的实现Tim文件的具体实现流程是初始化tim外设比如开启始终配置分频数 计数值等配置优先级分组优先级配置然后是能定时器中断编写中断服务函数然后中断函数里进行计数器加一操作易错点delay_ms延时函数的实现最开始我直接使用全局计数器和需要进行延时的数值进行比较导致功能无法正常工作后来查资料才知道上电之后计数器就在运行了所以如果直接使用这个值是错误的要在进入延时函数的时候获取到的计数值然后进行当前计数值和最开始的这个计数值比较如果达到了延时需要的数值就结束循环这种实现属于阻塞CPU的操作延时期间CPU不能作其他操作非阻塞方式就是采用轮询的方式看当前的计数值与开始值的差值比如这段伪代码// 使用示例不要直接调用Delay_ms用标记判断 uint32_t tick_start; tick_start tim_ms; if(tim_ms - tick_start 500) { // 500ms到了执行oled刷新 }4 实验代码展示//main函数#include stm32f10x.h // Device header//#include Delay.h#include OLED.h#include Tim2.hint main(void){OLED_Init();Tim2_Init();//实现延迟函数 如果是在操作系统中 就可以使用systick来进行延时操作OLED_ShowChar(1,1,A);OLED_ShowString(2,1, hello world1);delay_ms(1000);OLED_ShowString(2,1, hello world2);delay_ms(1000);OLED_ShowString(2,1, 1234567898765432);// 最长16位//OLED_Clear();while(1){}}//定时器函数#include stm32f10x.h#include Tim2.hvolatile uint32_t tim_ms 0; // 全局毫秒计数器void Tim2_Init(void){TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;NVIC_InitTypeDef NVIC_InitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);// 72M时钟PSC71, ARR999 → 1ms溢出中断TIM_TimeBaseInitStruct.TIM_Period 999; // ARRTIM_TimeBaseInitStruct.TIM_Prescaler 71; // PSCTIM_TimeBaseInitStruct.TIM_ClockDivision TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_RepetitionCounter 0;TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStruct);TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);TIM_Cmd(TIM2, ENABLE);NVIC_InitStruct.NVIC_IRQChannel TIM2_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority 1;NVIC_InitStruct.NVIC_IRQChannelSubPriority 1;NVIC_InitStruct.NVIC_IRQChannelCmd ENABLE;NVIC_Init(NVIC_InitStruct);}// 定时器中断服务函数每1ms进来一次void TIM2_IRQHandler(void){if(TIM_GetITStatus(TIM2,TIM_IT_Update) ! RESET){TIM_ClearITPendingBit(TIM2,TIM_IT_Update);tim_ms; // 毫秒计数1}}//毫秒延迟函数void delay_ms(uint32_t num){uint32_t start tim_ms; // 保存进入函数时的时间点while( (tim_ms - start) num ){;}}
返回列表