我试图从ATMega128开发板上的两个模拟红外传感器读取值,然后通过PWM输出缩放表示。当我将两个PWM波连接到示波器时,它们保持相同,但情况并非如此。我的PWM代码很好,所以我认为问题出在我的代码中,用于读取ADC的通道0和1。
int sens1,sens2,sens3;
volatile const uint8_t adc1 = (1<<ADLAR) | (0<<MUX0)|(0<<MUX1);
volatile const uint8_t adc2 = (1<<ADLAR) | (1<<MUX0)|(0<<MUX1);
void main(void)
{
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
ADMUX |= (1 << REFS0); // Set ADC reference to AVCC
ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading
ADCSRA |= (1 << ADFR); // Set ADC to Free-Running Mode
ADCSRA |= (1 << ADEN); // Enable ADC
ADCSRA |= (1 << ADIE); // Enable ADC Interrupt
sei(); // Enable Global Interrupts
ADCSRA |= (1 << ADSC); // Start A2D Conversions
while (1)
{
}
}
ISR(ADC_vect)
{
static uint8_t firstTime = 1;
static uint8_t val;
val = ADCH*100;
if (firstTime == 1){
firstTime = 0;
}
else if (ADMUX == adc1)
{
ADMUX = adc2;
OCR3A = val;
}
else if (ADMUX == adc2)
{
ADMUX = adc1;
OCR1C = val;
}
}
答案 0 :(得分:0)
我认为您应该在输入频道更改后将firstTime
设置为1。
请参考数据表:
更改频道选择时,用户应观察 遵循以下准则以确保选择正确的频道:
[...] 在自由运行模式下,始终选择之前的频道 开始第一次转换。可以改变频道选择 将一个写入ADSC后的一个ADC时钟周期。但是,最简单的 方法是等待第一次转换完成,然后 更改频道选择。由于下一次转换已经存在 自动启动,下一个结果将反映前一个 频道选择。后续转换将反映新频道 选择。
但为什么要使用Free Run Mode?你想要一个中断。因此,您可以选择源和触发测量并等待中断。然后手动开始下一次测量。
提醒我的另一件事是uint8_t
结果乘以100。
你确定这不会溢出吗?
ADC通道的输入电压范围是多少?
另一个原因可能是采样频率。你选择了一个非常高的预分频器。 ADC需要至少50kHz的时钟。所以你的AVR应该在&gt;运行为6MHz。检查您的保险丝设置是否设置为使用外部时钟源。还有一件事。 Fuse Bits的文档说默认情况下AtMega103兼容模式似乎是活动的。您可以参考日期表,这可能也会影响您的问题。