首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从ISR内部改变PWM占空比

从ISR内部改变PWM占空比
EN

Stack Overflow用户
提问于 2017-10-03 04:16:34
回答 1查看 1.1K关注 0票数 0

我有一些小问题,实现抖动功能,以升级我的ATmega88和它控制的leds的PWM分辨率。我的想法是,使用一个“某种”浮点数,包括两个uint8_t作为“十进制位”,以便例如"255.31“将由"0xff.0x1f”(BYTE_HIGH.BYTE_LOW)表示。

现在,我希望OCR中的值在BYTE_HIGH和BYTE_HIGH+1之间抖动,为此,我需要第二个计数器(除了计时器本身)来生成一个覆盖的任务周期(计时器的占空周期必须在(int) 255字节_LOW循环之后增加)。但是在main()中管理这些东西会导致闪烁,所以我想在一个叫做计时器溢出的ISR中这样做。

我的avr运行在20 MHz,为了获得足够的抖动频率,我不能使用高于8的预分频器。你认为我可能打得太频繁了吗?但是ISR中没有太多的代码。

我能想到的另一个问题是,ISR必须写OCR,它可能同时被计时器读取,但是这种“线程保存”不是因为计时器从来不写到OCR吗?

我没有找到任何关于我的问题适当的,所以我希望得到一些提示。见下面的代码

代码语言:javascript
运行
复制
#include <avr/interrupt.h>
#include <avr/io.h>

#define compare_register OCR2B  //duty cycle

volatile uint8_t dither_count=0;
volatile uint8_t BYTE_HIGH=0;
volatile uint8_t BYTE_LOW=0;

void init_pwm(void){

//some standard pwm initializations
TCCR2A |= (1 << COM2A1);
TCCR2A |= (1 << COM2B1);
// non inverting, fast PWM mode and prescaler to
TCCR2A |= (0 << WGM21) | (1 << WGM20);
TCCR2B |= (1 << CS21);
// set desired pin as an output (not sure, if it's the correct pin, because I left out other pins in use)
DDRD = (1 << DDD3)|(1<<DDD4);

// enable interrupt on timer overflow
TIMSK2 |= (1<<TOIE2);

// enable global interrupts
  sei();
}

ISR(TIMER2_OVF_vect){
  dither_count++;
  if(dither_count<=BYTE_LOW){
    compare_register=BYTE_HIGH+1;
  }else{
    compare_register=BYTE_HIGH;
  }
}

int main(){
init_pwm();
//this or any function dimming the leds
  BYTE_HIGH=10;
  BYTE_LOW=1;
}

从理论上讲,这是可行的,但不幸的是,它在现实中行不通。ISR会被调用,但不会按需要执行。我是否在ISR中正确调用变量?如果有人能看到我做过的基本错误,我会很高兴,特别是因为我没有任何用于调试的串行接口.

编辑:同时我发现,很明显ISR会卡住并阻止在我的主要函数中执行的任何代码.

EN

回答 1

Stack Overflow用户

发布于 2017-10-04 20:52:20

我在Arduino Uno上试过你的程序。这个板基于一个ATmega328P,除了一些额外的内存外,它基本上与您的Mega88 (相同的数据表)相同。我首先在main()末尾添加了以下行

代码语言:javascript
运行
复制
init_pwm();

// Blink the LED on PB5.
DDRB |= _BV(PB5);
for (;;) {
    PINB |= _BV(PB5);
    _delay_ms(400);
}

第一行显然需要PWM才能工作。LED闪烁只是一个测试,看看程序是否卡在ISR中。结果是:事实并非如此。LED就像预期的那样闪烁。PWM输出在作用域上看起来也没问题。注意,与代码中的注释相反,您是在相位正确的PWM模式下配置计时器,而不是在快速PWM模式下。计时器周期为2×255个定时器时钟周期,而不是256个。

我分解了二进制程序,并试图计算服务中断所需的CPU周期数。通过在-Os优化级别编译的程序,我得到了大约50个。考虑到中断触发每个2×255×8 = 4080 cycles,这大约是用于服务中断的CPU功率的1.2%。

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

https://stackoverflow.com/questions/46537133

复制
相关文章

相似问题

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