【发布时间】:2023-03-04 12:59:01
【问题描述】:
我在实现抖动功能以升级我的 ATmega88 的 PWM 分辨率和它控制的 LED 时遇到一些问题。 我的想法是,使用“一种”浮点数,由两个 uint8_t 作为“小数位”组成,例如“255.31”将由“0xff.0x1f”(BYTE_HIGH.BYTE_LOW)表示。
现在我希望 OCR 中的值在 BYTE_HIGH 和 BYTE_HIGH+1 之间抖动,为此我需要第二个计数器(除了定时器本身)来生成覆盖的占空比(定时器的占空比必须在之后递增(int) 255-BYTE_LOW 周期)。但是在 main() 中管理这些东西会导致闪烁,因此我想在称为计时器溢出的 ISR 中执行此操作。
我的 avr 以 20 MHz 运行,为了获得足够的抖动频率,我不能使用高于 8 的预分频器。您认为我可能过于频繁地调用 ISR 吗?但是 ISR 中没有太多代码。
我能想到的另一个问题是,ISR 必须写入可能被计时器同时读取的 OCR,但这不是这种“线程保存”,因为计时器从不写入 OCR ?
我没有适当地找到任何与我的问题有关的东西,所以我希望得到一些提示。请参阅下面的代码
#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 显然卡住了,会阻塞在我的 main 函数中执行的任何代码......
【问题讨论】:
-
你的意思是
if (dither_count == 255)?请注意,测试是无用的:dither_count++无论如何都以 256 为模。 -
@EdgarBonet 你是对的,但我不知道,谢谢!您看到一般错误吗?
-
@EdgarBonet 这个顺便说一句不成功,我刚刚试过......