为什么我需要在atmega2560上的ADC中添加巨大的延迟来切换通道?

问题描述 投票:0回答:1

我有这段代码,它需要多个 adc 转换并以串行方式发送它们,如果我在 set_ADMUX() 之后不添加 3 ms 延迟,则 ADC 样本不是通道的正确样本,但我认为这是一个太大的延迟正常情况下,代码如下:


//setup adc
void set_adc(void) {
  ADCSRA = (( 1<<ADEN ) | ( 1<<ADATE ) | ( 1<<ADIE ) | (1 << ADSC) ); // enable adc, auto trigger, interrupt enable, start first rilevation
  ADCSRB = (( 1<<ADTS2 ) | ( 1<<ADTS0 )); // Timer/Counter 1 Compare Match B 
  ADMUX = (1 << REFS0) | (1 << ADLAR); //set Voltage reference to Avcc (5v), left adjust converted value, if this is commented we use AREF
}

//timer for adc conversions
uint16_t ticks;
void set_timer1 ( uint16_t ticks )
{
  TCCR1A  = 0;
  TCCR1B  = 0;
  TCNT1   = 0;
  TIMSK1  = 0;
  TCCR1B  = ( 1 << WGM12 ) ;  // configure for CTC mode 4 OCR1A=TOP
  OCR1A   = ticks;  // set CTC TOP value
  TCCR1B |= ( 1 << CS10 ); // start timer, give it a clock, fcpu/1
}

//set channel for adc
volatile uint8_t i=0;
void set_ADMUX(void){ 
  switch(i){
    case 0:
        ADMUX = (1 << REFS0) | (1 << ADLAR);
        break;
    case 1:
        ADMUX = (1 << REFS0) | (1 << ADLAR) | (1 << MUX0);
        break;
    case 2:
        ADMUX = (1 << REFS0) | (1 << ADLAR) | (1 << MUX1);
        break;
    case 3:
        ADMUX = (1 << REFS0) | (1 << ADLAR) | (1 << MUX0) | (1 << MUX1);
        break;
    case 4:
        ADMUX = (1 << REFS0) | (1 << ADLAR) | (1 << MUX2);
        break;
    case 5:
        ADMUX = (1 << REFS0) | (1 << ADLAR) | (1 << MUX2) | (1 << MUX0);
        break;
    case 6:
        ADMUX = (1 << REFS0) | (1 << ADLAR) | (1 << MUX2) | (1 << MUX1);
        break;
    case 7:
        ADMUX = (1 << REFS0) | (1 << ADLAR) | (1 << MUX2) | (1 << MUX1) | (1 << MUX0);
        break;
  }
}

//adc interrupt
uint32_t key=0x55aa;
volatile uint8_t sample_count=0;
volatile uint8_t send_flag=0;
uint8_t buffull_count=0;
ISR(ADC_vect) {
  while(channel_buffer[i]!=1){
      i++;  
      if(i>=8){
          i=0;
          }
      }
  set_ADMUX();  
  _delay_ms(3);//<-------------------------------------------------------------
  switch(i){
      case 0:
        if(mode==1){
            buffer1[sample_count]=ADCH;
            }
        channel=1;
        //printf("1");
        break;
      case 1:
        if(mode==1){
            buffer2[sample_count]=ADCH;
            }
        channel=2;
        //printf("2");
        break;
      case 2:
        if(mode==1){
            buffer3[sample_count]=ADCH;
            }
        channel=3;
        //printf("3");
        break;
      case 3:
        if(mode==1){
            buffer4[sample_count]=ADCH;
            }
        channel=4;
        //printf("4");
        break;
      case 4:
        if(mode==1){
            buffer5[sample_count]=ADCH;
            }
        channel=5;
        //printf("5");
        break;
      case 5:
        if(mode==1){
            buffer6[sample_count]=ADCH;
            }
        channel=6;
        //printf("6");
        break;
      case 6:
        if(mode==1){
            buffer7[sample_count]=ADCH;
            }
        channel=7;
        //printf("7");
        break;
      case 7:
        if(mode==1){
            buffer8[sample_count]=ADCH;
            }
        channel=8;
        //printf("8");
        break;
      }
  if(mode==0){  
    printf("%d\n", channel);
    printf("%d\n", ADCH);
    structure.seq++;
    }  
  if(mode==1){sample_count++;}
  if(sample_count==BUFFER_SIZE-1){
        buffull_count++;
        sample_count=0;
        if(buffull_count==num_channels){
            sample_count=0; 
            if(mode==1){
              send_flag=1;
              buffull_count=0;
              }
            }
    }
  i++;
  TIFR1 = ( 1<<OCF1B ); // clear Compare Match B Flag
}



我思考过一些adc设置问题,或者ISR的错误使用,但找不到确切的原因,较小的延迟不起作用

在被告知后,我将代码缩减为仅涉及 ADC 的内容。

我使用的是atmega 2560,数据表:https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf

c microcontroller atmega adc
1个回答
0
投票

问题是我的逻辑,如@lxop

等待 ADC 转换完成,然后在读取结果之前更新多路复用器

我将 set_ADMUX 移至 ISR 的末尾,现在一切正常,谢谢大家

© www.soinside.com 2019 - 2024. All rights reserved.