- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在为 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_0
或 sensor_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/
前言 众所周知,对于 16 位 I/O 寄存器(定时器计数器、ICR/OCR、ADC...)的原子和同时读/写高和低部分,AVR 使用影子临时寄存器。例如。在 ATmega8 上读取 TCNT1: u
我想使用 avr-gcc 将全局变量绑定(bind)到未使用的 I/O 寄存器(例如 PORTB),以减少代码大小。我在AVR的应用笔记AVR035中学到了这个技巧(第 14 页)。 在应用笔记中,他
我有一个项目,其中 ATtiny2313V 控制 7x5 LED 矩阵以显示滚动文本。为了显示文本,我构建了一个字体,它与程序的其余部分一起存储在闪存中。 整个程序,包括整个字体,占用 1106 字节
我尝试使用 this Code/Guide在 ATmega1284p 上。 我遇到的问题是链接器不工作,执行后出现以下错误消息(代码为 ATmega88 构建良好): avr-ld -o main.
我原以为 8 位 AVR 平台不需要任何对齐。但是,我在 an LLVM commit 中发现了以下评论: The previous data layout caused issues when de
我想生成一个具有可变频率和固定占空比 (50%) 的 PWM 信号。频率应在 0-25KHz 之间变化。这是用于 ATMEGA32U4 微 Controller 的,我正在使用 Atmel Studi
我想生成一个具有可变频率和固定占空比 (50%) 的 PWM 信号。频率应在 0-25KHz 之间变化。这是用于 ATMEGA32U4 微 Controller 的,我正在使用 Atmel Studi
当我尝试使用 AVR studio 4 调试一小段代码时,出现此错误: Build failed... No build tools defined. 有人能给我一些建议吗? 最佳答案 在 AVRSt
我有一个设置为 CodeVision AVR 项目的遗留代码。我想迁移到 AVR Studio 甚至更好的 NetBeans(使用 AVR 工具链或 WinAVR)。 有什么想法吗? 最佳答案 你应该
我在以 AVR 为目标的 C 中遇到毫秒延迟循环的问题。我在从 Ubuntu 存储库获得的 Linux 上使用 avr-gcc 4.7.0,我也有尝试了新编译的 4.7.2。目标硬件是 XMEGA12
如何启用或禁用 IDE 的自动完成功能 AVR-Studio 5或 AVR-Studio 4 ?我是否必须编辑一些安装文件才能做到这一点? 视频中AVR Studio 5: How to use th
我正在尝试用 Arduino Eclipse 插件替换 Arduino IDE。下载所需的一切并尝试编译最简单的“Hello World”程序后,我在 eclipse 中遇到以下错误: 调用时: wh
我继承了一个链接到一个库的应用程序,该库可能是用 gcc3 构建的。或者也许使用 imagecraft 编译器。这些信息现在已经消失在天堂般的位域中,我只剩下一个 libXXX.a 库来链接我的应用程
我正在尝试通过 USBASP 编程器将一些数据从 PC 发送到 ATmega328P 芯片。 它能够通过 SPI 传输最多 4 个字节。这 4 个字节可以在 USB Setup Packet 中设置(
我正在使用 ATMEGA128 与另一台设备进行通信。为此,我使用带有 ATMEGA128 的 SPI 作为从机。我使用 SS、SCK 和 MOSI 引脚。我面临的问题是,当我必须下载程序时,我必须断
我有以下汇编代码: __asm__ __volatile__ ( "1: subi %0, 1" "\n\t" "brne 1b" : "=d" (__count)
大家好! 我的 DIY 洒水器和鱼缸自动化的 AVR 取得了很好的进展,但我遇到了一个问题,这让我很烦恼。 哪个 if 语句在 AVR 上运行得更快?(在更少的时钟周期内)多少? if(temp_se
我见过的所有示例 AVR 程序都以如下代码开头: .org $0000 rjmp Reset ; ... Reset: ; Start of program 如果我不使用任何中
我正在使用avr-gcc 4.8.2对Atmel ATtiny13a微 Controller 进行编程。 这是我的C代码: #include #include int main(void) {
所以,我使用的是 ATMega168与 NerdKits使用两个中断 INT0 和 INT1 设置并连接一个 LCD。我想附上 Grove Heart Rate Monitor ,我已附加到 PCIN
我是一名优秀的程序员,十分优秀!