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

发布时间:2026/9/27 6:45:02
使用通用定时器实现延时函数遇到的问题 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 ){;}}

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询