发新帖本帖赏金 3.00元(功能说明)我要提问
123下一页
返回列表
打印
[STM32F4]

基本定时器做延时功能,急急急

[复制链接]
2613|46
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
想用STM32F407做一个定时器精准延时功能。
采取的方式是 先初始化定时器  : TIM3_Int_Init
但先不使能定时器:                    TIM_Cmd(TIM3,ENABLE);
其他定时器相关代码正常配置。
定时器中断处理函数为   :
      void TIM3_IRQHandler(void)//单中断 是10us
            {       
                       if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET )
                        {
                                global_t++;
                        }
                        TIM_ClearITPendingBit(TIM3,TIM_FLAG_Update);//清除中断标志位
                 }
其中 global_t为全局变量。
再编写延时函数
     void delay_us6(unsigned int  T)
       {
            TIM_Cmd(TIM3,ENABLE); //使能定时器3
             while(global_t <= T)
              {
               }
              global_t=0;       //上述代码起到定时的作用。
              TIM_Cmd(TIM3,DISABLE); //失能定时器3
    }
  即每次调用此函数,都会启动定时器 即可实现 T us延时功能。
-----------------------------------------------------------------------------------------
但是现在 的实验现象+debug:
代码卡在while(global_t <= T)处。global_t为1,
说明 仅执行触发了一次定时器中断。
没有在whil循环判断时,同时定时器进行多次中断向上计数溢出,
未达到理想实验效果
来触发中断处理函数增加global_t +1的操作。
问题:是否在此while循环时,定时器无法运行?

使用特权

评论回复
来自 2楼
liusheng1998|  楼主 | 2023-3-9 21:16 | 只看该作者
此贴结贴
谢谢各位大神 尤其感谢@xch @Prry 两位。
提供的延时方案都可以实现。
通过分析仪能检测到微秒延时的IO翻转。
我的延时不准的原因是,CAN发送的时候需要一定的时间来实现,甚至它不受到延时的限制!
我暂时不明白这里出现了什么问题。
但是延时确实正常的功能。谢谢大家
我没有早点换用分析仪器检测。示波器也没用明白。迟迟没有验证单独延时功能。

使用特权

评论回复
板凳
liusheng1998|  楼主 | 2023-2-24 11:10 | 只看该作者
求教各位大神,小弟想了一天了,不知道问题出在哪里,是不是方案想得有问题,异想天开了

使用特权

评论回复
地板
liusheng1998|  楼主 | 2023-2-24 11:18 | 只看该作者
如果 定时器不能做延时,什么可以做?!
苦恼啊

使用特权

评论回复
5
呐咯密密| | 2023-2-24 13:26 | 只看该作者
liusheng1998 发表于 2023-2-24 11:18
如果 定时器不能做延时,什么可以做?!
苦恼啊

从你给的代码部分,没啥问题,用基本定时器做延时也是可以的,一般用的最多的是滴答定时器(SysTick),你另外测试一下单独的定时器有没有问题

使用特权

评论回复

打赏榜单

liusheng1998 打赏了 1.00 元 2023-02-24
理由:微表敬意

6
香水城| | 2023-2-24 14:05 | 只看该作者
你看看定时器是否正常工作了,中断是否可以正常进入。

使用特权

评论回复
评论
liusheng1998 2023-2-24 14:25 回复TA
好滴 我再看一下我自己的工程项目中的问题。看是不是哪里配置出问题了,或者代码冲突了 
7
liusheng1998|  楼主 | 2023-2-24 14:06 | 只看该作者
本帖最后由 liusheng1998 于 2023-2-25 10:40 编辑
呐咯密密 发表于 2023-2-24 13:26
从你给的代码部分,没啥问题,用基本定时器做延时也是可以的,一般用的最多的是滴答定时器(SysTick), ...

谢谢帮助,
1.滴答定时器件做微秒级别的定时,只能做到百毫秒级别,我的需求是最少做到10us的级别的。
所以没有采用滴答定时器方案。但是我有放在我的整体工程代码中尝试过。
2.针对你说的单独定时器检测,我目前再 正点原子的定时器历程中进行测试,
经过我刚刚在源程序代码的框架下修改发现,我的思路代码没有问题。实验效果满足我的设想
//主函数中初始化及while(1)循环如下

TIM3_Int_Init(5000-1,8400-1);        //定时器时钟84M,分频系数8400,所以84M/8400=10Khz的计数频率,计数5000次为500ms  
        while(1)
{
      LED0 =! LED0;        
      Delay_us(4);        
};
延时函数
void Delay_us(int T)
        {
     TIM_Cmd(TIM3,ENABLE);
      while(t<=T)
       { }
     t=0;
     TIM_Cmd(TIM3,DISABLE);
        }
中断溢出处理函数
void TIM3_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
        {
                LED1=!LED1;//DS1翻转
    t++;
    //printf("%d\r\n",t);
        }

        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}


实验效果 LED0 2秒翻转一次。:主循环的延时代码 Delay_us(4) 生效
              LED1 1秒翻转一次。:TIM3中断处理函数生效:
             if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
               {
                   LED1=!LED1;//DS1翻转这里可行的原因是:因为设置的进入中断的周期是1ms。 如果我要设置1us,就会失败


使用特权

评论回复
8
呐咯密密| | 2023-2-24 14:31 | 只看该作者
liusheng1998 发表于 2023-2-24 14:06
谢谢帮助,
1.滴答定时器件做微秒级别的定时,只能做到百毫秒级别,我的需求是最少做到10us的级别的。
所 ...

滴答定时器可以做us的级别的定时的,你可以参考一下别人的代码

使用特权

评论回复
9
xch| | 2023-2-24 15:53 | 只看该作者
volatile uint32_t global_t =0;
......
disable_irq();
while(global_t <= T){
__WFI()
enable_irq();
};
enable_irq();
.........
              {
               }

使用特权

评论回复
10
icecut| | 2023-2-24 15:53 | 只看该作者
global_t 被寄存器缓存了?
用volatile关键字定义变量,相当于告诉编译器,这个变量的值会随时发生变化,每次使用时都需要去内存里
重新读取它的值,并不要随意针对它作优化。

使用特权

评论回复
11
kktron| | 2023-2-24 15:53 | 只看该作者
global_t  怎么定义的?

__IO

使用特权

评论回复
12
mcu5i51| | 2023-2-24 16:35 | 只看该作者
优化掉了,加变体修饰

使用特权

评论回复
13
liusheng1998|  楼主 | 2023-2-24 20:39 | 只看该作者
本帖最后由 liusheng1998 于 2023-2-25 16:43 编辑
mcu5i51 发表于 2023-2-24 16:35
优化掉了,加变体修饰

好滴,谢谢你的意见。
已经加了 extern volatile global_t;
但是我的编译器的优化等级是最低的,查验后发现 并不是这里的问题。

使用特权

评论回复
14
liusheng1998|  楼主 | 2023-2-24 21:24 | 只看该作者
本帖最后由 liusheng1998 于 2023-2-24 22:19 编辑
xch 发表于 2023-2-24 15:53
volatile uint32_t global_t =0;
......
disable_irq();
谢谢 已经这么改了下,但是还是不对劲

使用特权

评论回复
15
liusheng1998|  楼主 | 2023-2-24 21:25 | 只看该作者
kktron 发表于 2023-2-24 15:53
global_t  怎么定义的?

__IO

定义的全局变量 在main.c里面定义的,int global_t=0;
然后在 子文件里面 extern int global_t;

使用特权

评论回复
16
liusheng1998|  楼主 | 2023-2-24 21:48 | 只看该作者
volatile 我也加了,现在没报错了。但是还是代码只发送了一次!!!!!!!!!!!
为什么  为什么  为什么!!!!!

使用特权

评论回复
17
Prry| | 2023-2-24 22:53 | 只看该作者
本帖最后由 Prry 于 2023-2-24 22:58 编辑

不进中断,说明定时器配置有问题;另外,你这个用法明显不行,10us的中断,cpu都不用干活了,都一直在干中断了。可以这样改进:
1.任一定时器,设置分频,1us计时一次,设为最大溢出(尽可能降低中断占用CPU资源,比如65535us);
2.中断一次就是65536us,全局变量g_tick记录;
3.g_tick*65535+当前定时器计数值__HAL_TIM_GET_COUNTER(&htim1),为总的us计数值;
4.主循环取值两次相减就可以做us延时了。

使用特权

评论回复

打赏榜单

liusheng1998 打赏了 1.00 元 2023-02-25
理由:聊表谢意^^

18
Prry| | 2023-2-24 22:55 | 只看该作者
单纯做延时,不用时基的话,可以不使能中断,单纯配置1us计时即可,节约中断资源。可以这样实现(定时器配置自己撸):
void delay_us(uint32_t us)
{
    uint32_t cnt = 0;
    uint32_t last_cnt = 0;
   
       while (cnt < us)
         {
                if (last_cnt != __HAL_TIM_GET_COUNTER(&htim1))
                {
                        last_cnt = __HAL_TIM_GET_COUNTER(&htim1);
                        cnt++;
                }
        }
}

使用特权

评论回复
19
vikey_zhu| | 2023-2-25 09:14 | 只看该作者
  while(global_t <= T)改成  while(global_t >= T),

223263f960d1cf166.png (77.88 KB )

223263f960d1cf166.png

使用特权

评论回复
20
liusheng1998|  楼主 | 2023-2-25 10:28 | 只看该作者
Prry 发表于 2023-2-24 22:53
不进中断,说明定时器配置有问题;另外,你这个用法明显不行,10us的中断,cpu都不用干活了,都一直在干中 ...

好的谢谢 ,您的说法很有道理。
1.“10u的中断,CPU就不用干活了” 我的中断向上计数确实是这么做的
2改进方案中
2.1中断执行的周期是65535us,即65535us才进一次中断,执行内容是 全局变量 g_tick++;
2.2【当前定时器计数值】读取TIM_CNT寄存器,表示此次计数循环某时刻的值。
        g_tick*65535+CNT 是实际运行 总微秒数。
3.两次相减做us延时操作,我不太明白。可以在点拨一下吗?谢谢!

使用特权

评论回复
21
lvyunhua| | 2023-2-25 11:11 | 只看该作者
liusheng1998 发表于 2023-2-25 10:28
好的谢谢 ,您的说法很有道理。
1.“10u的中断,CPU就不用干活了” 我的中断向上计数确实是这么做的{:ton ...

1.不知道你的CPU主频是多少,定时器最小计时一次是多少us?
2.不用中断,先定义一个全局变量global_tt=0,然后开启定时器,while循环里实时读取TIM_CNT寄存器值赋给global_t, 然后while条件判断global_t-global_tt<T,如果一直为真说明延时没有到,当条件达到退出循环后,将global_t的值复位global_tt即可,楼主有时间可以试试看。

使用特权

评论回复
发新帖 本帖赏金 3.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

70

帖子

1

粉丝