打印
[STM32G4]

精确定时与指令执行

[复制链接]
787|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
现使用STM32G473芯片,要求实现在固定时间执行不同指令,如5.2ms执行指令A,10.9ms执行指令B,时间希望精确到0.01ms;系统工作频率85MHz,未接32.768KHz晶振,使用系统自带或者自行编写的Delay函数都存在很大误差,而且发现不能用延时来做,因为指令也需要时间来执行。请问有没有什么好的方法?

使用特权

评论回复
沙发
呐咯密密| | 2022-1-6 09:43 | 只看该作者
即使是使用内核的滴答定时器也做不到精准延时,延时函数在开启和关闭滴答定时器确实是需要时间的,这一点我在很多的MCU都做过测试,但是0.01ms也就是10us的精确度使用滴答定时器是可以做到的,但是很麻烦,这种情况使用定时器会更好,定时周期用100us一次,如果是5.2ms就循环52次就可以,这个应该是能达到的,我用定时器做过准确到1us的定时,我当时是需要67.2us的定时,小数点后面会有一点抖动,但是不会超过0.5us

使用特权

评论回复
板凳
LcwSwust| | 2022-1-6 09:44 | 只看该作者
定时器呢            

使用特权

评论回复
地板
NCVRLST|  楼主 | 2022-1-6 09:50 | 只看该作者
呐咯密密 发表于 2022-1-6 09:43
即使是使用内核的滴答定时器也做不到精准延时,延时函数在开启和关闭滴答定时器确实是需要时间的,这一点我 ...

具体该怎么编写程序呢?能不能帮忙提供一下参考程序呢?

使用特权

评论回复
5
呐咯密密| | 2022-1-6 09:56 | 只看该作者
NCVRLST 发表于 2022-1-6 09:50
具体该怎么编写程序呢?能不能帮忙提供一下参考程序呢?

定时器应该会用的吧,就是定时周期为100us就好了,在定时器中断中进行计数,数到52个就执行相应程序

使用特权

评论回复
6
NCVRLST|  楼主 | 2022-1-6 10:29 | 只看该作者
呐咯密密 发表于 2022-1-6 09:56
定时器应该会用的吧,就是定时周期为100us就好了,在定时器中断中进行计数,数到52个就执行相应程序 ...

没这样用过,烦请指导一下,拜托

使用特权

评论回复
7
aple0807| | 2022-1-6 10:35 | 只看该作者
如果你系统中存在任一中断函数,就只能使用定时器中断来解决,并且该中断还必须设为最高优先级。中断响应时间为flash等待周期+12CPU时钟,大约20时钟周期,满足你的精度要求。
如果系统没有其他中断,可以用内核DWT模块的时钟计数器来延时。

使用特权

评论回复
8
呐咯密密| | 2022-1-6 11:00 | 只看该作者
按照你这种应用,属于定时器的基础应用,虽然定时周期是微秒级别,但是你的精确度只要10us就够了,定时器完全可以实现。我先给你贴一个我的代码:
void TIM2_Configuration(void)
{
        NVIC_InitTypeDef   NVIC_InitStructure;
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定义一个TIM_InitTypeDef类型的结构体
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能TIM2时钟
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清中断标志,以备下次中断到来使用

        TIM_TimeBaseStructure.TIM_Period =335;
        TIM_TimeBaseStructure.TIM_Prescaler =7;
        TIM_TimeBaseStructure.TIM_ClockDivision =0; //TIM_CKD_DIV1
        TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;//向上计数
        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);//初始化定时器
        TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能溢出中断
       
        NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        TIM_Cmd(TIM2,ENABLE);//初始化定时器关闭
}
我的主频为了能适配出0.2us精度的定时,设为40M,TIM_Prescaler 设置为7,其实是8分频,也就是0.2us。然后TIM_Period 等于335,也就是计数336次,0.2*336=67.2us。

示波器测量的时间也是67.2us。为了向你展示时间进行中需要执行指令,我在定时器中断中添加了串口发送,可以看到在定时周期内执行力串口发送指令。但是定时依旧准确。
那么回到你的问题,你可以定时100us。你的主频是85M。那么你的预分频值TIM_Prescaler设为850-1,即为10us,TIM_Period 设为10-1,那么你的定时器中断则为100ms执行一次。你在中断中设置一个数,每次进中断都+1.当这个数等于52说明到达5.2ms,你就执行相关程序,当这个数到达109,再执行下一个。



使用特权

评论回复
9
LcwSwust| | 2022-1-6 11:20 | 只看该作者
我觉得没必要频繁中断,定时器可随时修改周期,比如第一次中断把周期设置为5.2ms,第二次中断里执行指令A并把周期设置为5.7ms,第三次中断执行指令B......
若没其它事干,也可不用中断,而是设置好相应的定时周期后死循环等待中断标志。

使用特权

评论回复
10
coody| | 2022-1-6 11:40 | 只看该作者
10us精度,定时器轻松解决。

使用特权

评论回复
11
yljon| | 2022-1-6 13:54 | 只看该作者
路过,学习

使用特权

评论回复
12
kiwis66| | 2022-1-8 10:36 | 只看该作者
定时器应该问题不大吧

使用特权

评论回复
13
aoyi| | 2022-2-6 17:24 | 只看该作者
精确定时的精度是多少呢

使用特权

评论回复
14
zljiu| | 2022-2-6 17:35 | 只看该作者
使用汇编会不会更加精确啊

使用特权

评论回复
15
nawu| | 2022-2-6 17:44 | 只看该作者
最大的误差能有多少呢

使用特权

评论回复
16
gwsan| | 2022-2-6 17:54 | 只看该作者
如何能提高精度呢

使用特权

评论回复
17
tfqi| | 2022-2-6 18:05 | 只看该作者
如何知道一个指令的执行时间呢

使用特权

评论回复
18
tail066| | 2022-2-11 11:15 | 只看该作者
是什么需求要限定指令执行时间

使用特权

评论回复
19
sagade| | 2022-2-11 12:57 | 只看该作者
百度有一篇“一种Cortex-M内核中的精确延时方法”,使用CM3/M4/M7内核的CYCCNT计数器(32位),时间太长了忘记当时测试的精度了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

6

帖子

0

粉丝