首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加速AVR ISR

加速AVR ISR
EN

Stack Overflow用户
提问于 2022-06-16 16:21:29
回答 3查看 75关注 0票数 0

我想知道是否有可能加快ISR而不改变预标度。我有一个有两个比较寄存器A和B的计时器。

COMPA用于PWM输出,从22%到100%。这是一个固定的频率,我不允许改变它,至少不太多。

现在,我想使用COMPB的速度约为4倍,但固定的占空比为50%。

如果我在TIMSK0中为TIMSK0设置了attiny13位,我能做以下工作来加快速度吗?还是我误会了什么?

代码语言:javascript
复制
ISR(TIM0_COMPB_vect){
    switch (timing){
        case 0:
            OCR0B = 63;
            PORTB ^= (1 << PB3);
            timing = 1;
            break;
        case 1:
            OCR0B = 127;
            PORTB ^= (1 << PB3);
            timing = 2;
            break;
        case 2:
            OCR0B = 191;
            PORTB ^= (1 << PB3);
            timing = 3;
            break;
        case 3:
            OCR0B = 255;
            PORTB ^= (1 << PB3);
            timing = 0;
            break;
    }
}

任何帮助都很感激。Thanx :D

EN

回答 3

Stack Overflow用户

发布于 2022-06-16 17:33:51

通过创造性地使用正常模式,您可以非常有效地完成这一任务。

诀窍是设置预调用者得到一个时钟周期,这个时钟周期是您想要的可变占空比PWM信号运行时间的两倍。因此,例如,如果您希望在1 2Mhz时使用PWM,请将预调用程序设置为2 2Mhz。

假设可变占空比PWM在引脚A上,固定的50% 4x时钟信号在引脚B上(您也可以交换这些信号并更新代码,一切都将继续工作)。

  1. 为“进行比较匹配B”和“溢出”启用中断。

  1. 力销A高与力比较匹配。(或者,您可以跳过这一步,而在步骤7中使用期望占空比的逆值)

Toggle on match.

  1. 将“A”的COM位设置为

  1. COM位留给B关闭。假设您已将此引脚的DDR设置为普通GPIO.

128.

  1. BOCR设置为

  1. 将WGM计时器模式设置为0 -“普通模式”.

  1. A设置OCR,无论您希望变量占空比是什么。请注意,您可能需要在这里为0和/或255的极值设置特例,这取决于您想要发生的事情(只需使用GPIO转动OFF的引脚ON )。

您可以在任何时候重复步骤6,随时更改A的占空比,并且它将在下一个TOP上更新。

完成这些步骤后,A引脚将在预调用者时钟的1/2处输出所需的占空比,而B将在2倍于预调用方时钟(即A周期的所需4倍)时输出50%的负载。

下面是ISR代码(请注意,我不确定在attiny13头中调用的是什么TOV向量,它有时在AVR中是不同的,因此您可能不得不编辑TIM0_OVF_vect名称).

代码语言:javascript
复制
ISR(TIM0_COMPB_vect,TIM0_OVF_vect){
    PINB |= (1 << PB3);   // Compiles to a single cycle SBI
}

看看这是怎么回事?

注意,在PIN寄存器中设置一个位实际上会切换PORT位。这是记录在数据表中的AVR GPIOs的一个怪癖。

希望这足够快。如果您真的想挤出每一个最后的周期,您甚至可以从中断向量中保存RJMP的两个周期,方法是将ISR编译的单个SBI指令直接编译到带有尾随RETI的中断向量表中,但这要复杂得多!

票数 0
EN

Stack Overflow用户

发布于 2022-06-17 06:19:47

只关注C代码方面,就可以将其优化为:

代码语言:javascript
复制
ISR(TIM0_COMPB_vect)
{
  static const uint8_t OCR[4] = {63,127,191,255};
  OCR0B = OCR[timing];

  PORTB ^= 1u << PB3;

  timing++;
  if(timing==4)
    timing=0;
}

在gcc AVR -O3上进行分解(所有变量/寄存器不稳定),这会使指令量从~50减少到~20,因此它的速度大约是原来的两倍,占用的内存也更少。

票数 0
EN

Stack Overflow用户

发布于 2022-06-17 15:56:26

如果您只想要提供的代码的最快的等效版本,那么它就是.

代码语言:javascript
复制
ISR(TIM0_COMPB_vect){
    OCR0B += 64;
    PINB |= (1 << PB3);
}

  • OCR0B将每4次溢出一次,这是定义的行为。也许明智的做法是将OCR0B初始化为一些非零的数字,比如1,以避免边缘情况。
  • 避免了所有变量和仅访问内存的寄存器访问。
  • 避免了所有的比较和缓存。
  • --切换引脚的方法--向下编译成单个SBI指令,而不是推送、加载、异或、存储、弹出序列。h 214f 215

...but再次指出,如果它不能工作,并且除非您使用两种“立即OCR更新”模式之一,那么在计时器周期中间更新OCR将不会有任何影响。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72648995

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档