2017-06-04 88 views
0

我正在嘗試使用ATmega328P製作接近傳感器。我正在使用板載ADC轉換電壓值,如果它高於環境溫度,LED將點亮。無法在atmega328上使用ADC

根據該電路被感測的電壓爲: enter image description here

在該電路中,VOUT是要ADC通道3,並應被感測(認爲導致右側作爲紅外線傳感器的)。

程序啓動時,它會感應30個讀數,並將其平均值用作環境設置。如果任何後續測量結果高於此值,LED應亮起。

但即使將手放在傳感器上方,LED也不會點亮。

我已經測試了只有LED,看看紅外傳感器是否正常。順便說一句。

微控制器的代碼如下:

/* 
* Proximity Sensor IR.c 
* 
* Created: 6/3/2017 2:35:33 PM 
* Author : Rishav 
*/ 

#include <avr/io.h> 
#include <stdio.h> 

#define F_CPU 16000000UL 
#include <util/delay.h> 

int calibration() 
{ 
    unsigned int sum = 0; 

    for (int i=0; i<30; i++) 
     { 
      ADCSRA |= (1<<ADSC); 
      while(!(ADCSRA & (1<<ADIF))); 

      ADCSRA |= (1<<ADIF); 

      sum += (ADCH<<8)|ADCL; 
     } 

    return (sum/30); 
} 

int main(void) 
{ 
    unsigned int val = 0; 

    ADMUX |= (0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(1<<MUX1)|(1<<MUX0);  //setting the multiplexer to ADC3 
    ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); 

    DDRB = 0b00000010; 

    DDRD |= (1<<PCINT22); 
    PORTD |= (1<<PCINT22); 

    int calib_value = calibration(); 

    while (1) 
    {  
     ADCSRA |= (1<<ADSC); 
     while(!(ADCSRA & (1<<ADIF))); 

     val = (ADCH<<8)|ADCL; 

     ADCSRA |= (1<<ADIF); 

     if (val > calib_value) 
      PORTB = 0b00000010; 
    } 
} 

我認爲這是在代碼中的一些問題。請幫忙。

+0

這些行沒有意義,因爲PCINT22在任何一個寄存器中都沒有位:'DDRD | =(1 << PCINT22); PORTD | =(1 << PCINT22);' –

+0

我不使用PCINT,只是使用端口D中的PCINT引腳位置打開IR LED。 – Ris97

+0

你可以用0到7之間的數字代替'PCINT22',它會使你的代碼更加清晰。例如,如果您想控制PD5,請將其替換爲5. –

回答

1

看你的代碼時,我想到有些事情:

  1. 你是真的不完全初始化ADMUXADCSRA寄存器 - 你把一切有隻是「ORed'項。 (ADLAR in ADMUX is not in defined defined,例如,ADCSRA具有更多未定義的位)。
  2. 將參考電壓源設置在ADMUX寄存器中後,應該等待芯片切換,但不切換。最有可能的是,你在calibration的第一次測量將會失敗。解決這個問題的最簡單的方法是做一個第一次測量,其結果你簡單地忽略。 (或者在設置ADC後等待一些ms)。
  3. 你應該經常閱讀之前ADCHADCL(AVR的鎖定寫進一步的結果,結果當讀取ADCL直到ADCH被讀取以及註冊ADC)。您當前的代碼具有這2個寄存器的未定義讀取順序。
0

您必須首先啓用ADC,然後選擇通道和參考電壓。在數據表中很容易忽略這一事實。

通過將ADCSRA中的ADC使能位ADEN置1使能ADC。 直到ADEN置位,電壓基準和輸入通道選擇將不會生效 。 Datasheet page 238.

我沒有檢查所有的設置,但我很確定這一定是您的問題。

實施例順序:

void init_adc() 
{ 
    ADCSRA |= (1<<ADEN);       // enable ADC 
    ADMUX |= (1<<MUX1) | (1<<MUX0);     // channel selection ADC3 - PB3 
    ADMUX &= ~(1<<REFS0);       // VCC as reference 
    ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // setting prescaler to 128 
} 

如前所述一個應讀ADCL第一至:

ADCL必須先讀出,然後ADCH,以確保 數據寄存器的內容屬於到相同的轉換

我建議將此部分移動到一個單獨的功能,如:

uint16_t read_adc() 
{ 
    ADCSRA |= (1<<ADSC); 

    while(!(ADCSRA & (1<<ADIF))); 

    uint8_t adcl = ADCL; 
    uint8_t adch = ADCH; 

    ADCSRA |= (1<<ADIF); 

    return (adch<<8) | adcl; 
}