gpt4 book ai didi

c - AVR C 结合 ADC 读数生成 PWM 输出的问题

转载 作者:太空宇宙 更新时间:2023-11-04 00:09:28 25 4
gpt4 key购买 nike

我正在为 ATMega328P 编写一个程序,它将从多个 ADC channel 获取读数,将它们组合成一个信号并通过 PWM 输出该信号。

我已经使用单次转换模式成功地将我的 ADC 轮询退回到每 channel 50Hz。我正在使用 Timer/Counter2 生成 PWM,并使用 Timer/Counter1 进行计算,以便为 Timer/Counter2 设置比较值。这是定时器/计数器 1 的 ISR:

// Interrupt service routine called to generate PWM compare values
ISR(TIMER1_COMPA_vect)
{
// Grab most recent ADC reading for ADC0
uint32_t sensor_value_0 = adc_readings[0];

// Get current value for base waveform from wavetable stored in sinewave_data
uint32_t sample_value_0 = pgm_read_byte(&sinewave_data[sample_0]);

// Multiply these two values together
// In other words, use the ADC reading to modulate the amplitude of base wave
uint32_t sine_0 = (sample_value_0 * sensor_value_0) >> 10;

// Do the same thing for ADC2
uint32_t sensor_value_1 = adc_readings[1];
uint32_t sample_value_1 = pgm_read_byte(&sinewave_data[sample_1]);
uint32_t sine_1 = (sample_value_1 * sensor_value_1) >> 10;

// Add channels together, divide by two, set compare register for PWM
OCR2A = (sine_0 + sine_1) >> 1;

// Move successive ADC base waves through wavetable at integral increments
// i.e., ADC0 is carried by a 200Hz sine wave, ADC1 at 300Hz, etc.
sample_0 += 2;
sample_1 += 3;

// Wrap back to front of wavetable, if necessary
if (sample_0 >= sinewave_length) {
sample_0 = 0;
}

if (sample_1 >= sinewave_length) {
sample_1 = 0;
}
} // END - Interrupt service routine called to generate PWM compare values

我的问题是没有 PWM 输出。如果我将 sensor_value_0sensor_value_1 设置为 1024 并将另一个 sensor_value_ 设置为从 ADC 读取,我确实得到一个全振幅分量波和一个调幅分量波。但是,如果我为硬编码的模拟振幅选择不同的值,我就没那么幸运了(例如,1023)。任何其他值都不给我 PWM 输出。如果我将两个 sensor_value_ 设置为查看同一个 ADC channel ,我会期望两个分量波的振幅被相同地调制。相反,我没有得到 PWM 输出。最让我困惑的是,如果我为硬编码振幅选择一个正好是 2 的幂的值,那么一切都很好。

整个二的幂部分让我觉得这是一个我没有看到的有点麻烦的问题。你能看出我肯定错过了什么吗?如果有任何提示,我将不胜感激!

(我已经发布了我的整个源代码 here 以使内容尽可能整洁。)

最佳答案

您的问题可能是由您正在开发的 AVR 的架构引起的。 ATMega328p 有 8 位寄存器,类似于大多数其他 AVR 芯片。这意味着您正在使用的 32b 值必须由编译器存储在内存中,并在您每次对它们执行算术运算时分成四个独立的寄存器。事实上,没有一次对多个寄存器执行的算术指令,所以我真的不确定编译器在做什么!

我很想知道您的代码的反汇编是什么,但我的猜测是 gcc 使用 MUL 指令来执行 sample_value_0 * sensor_value_0 代码。该指令对两个 8b 值进行运算并产生一个 16b 值,因此如果您看到对两个结果的倍数产生奇怪依赖的原因,我不会感到惊讶。

我会说尝试通过更改变量的数据类型来重新编写这段代码。将 uint8_t 用于 sensor_value_*sample_value_*,将 uint16_t 用于 sine_*。然后,为确保所有内容都适合 8b OCR2A 寄存器,将分配更改为类似以下内容:

OCR2A = (sine_0 + sine_1) & 0xFF;

关于c - AVR C 结合 ADC 读数生成 PWM 输出的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7862491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com