1

I am using an ATtiny402 for an experiment in ADC. In my current configuration, I am using the PA6 pin as the output pin and the PA2 pin as the analog input pin. In PA2 a potentiometer is connected. In the current experiment if the analog input value is greater than or equal to a threshold value the LED will blink, and if the value is less than the threshold value the LED will be off.

In the current program the ADC0.RES is always returning 0xFFC0 if I monitor the register by the debugger. I have checked the PA2 pin by an oscilloscope, and the input signal is not always HIGH(+5V) if I rotate the potentiometer. But the LED is always blinking even if I set the analog input voltage to 0V, and it is kind of strange.

Am I missing something or what is the bug in my code?

#define F_CPU 20000000UL // CLK frequency is configured to 20 MHz by protected write
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

FUSES = {
    .WDTCFG = 0x00, // WDTCFG {PERIOD=OFF, WINDOW=OFF}
    .BODCFG = 0x00, // BODCFG {SLEEP=DIS, ACTIVE=DIS, SAMPFREQ=1KHz, LVL=BODLEVEL0}
    .OSCCFG = 0x02, // OSCCFG {FREQSEL=20MHZ, OSCLOCK=CLEAR}
    .TCD0CFG = 0x00, // TCD0CFG {CMPA=CLEAR, CMPB=CLEAR, CMPC=CLEAR, CMPD=CLEAR, CMPAEN=CLEAR, CMPBEN=CLEAR, CMPCEN=CLEAR, CMPDEN=CLEAR}
    .SYSCFG0 = 0xC4, // SYSCFG0 {EESAVE=CLEAR, RSTPINCFG=UPDI, CRCSRC=NOCRC}
    .SYSCFG1 = 0x07, // SYSCFG1 {SUT=64MS}
    .APPEND = 0x00, // APPEND {APPEND=User range:  0x0 - 0xFF}
    .BOOTEND = 0x00, // BOOTEND {BOOTEND=User range:  0x0 - 0xFF}
};

LOCKBITS = 0xC5; // {LB=NOLOCK}

#define LED_ON  PORTA.OUT |= (1<<PIN6) ; //PA6 output 1
#define LED_OFF PORTA.OUT &= ~(1<<PIN6) ; //PA6 ouptut 0
#define LED_TOGGLE  PORTA.OUTTGL |= (1<<PIN6)  ; //toggle PA6 pin 

uint16_t adcVal = 0 ;
uint16_t thresholdVal = 0xFFC0 ; 

void clock_conf(){
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, !CLKCTRL_PEN_bm); // prescaler disabled
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSC20M_gc); //20MHz clock
}

void io_config(){
    PORTA.DIR = 0b01000000 ; //PA6 output pin
    PORTA.PIN2CTRL = 0b0000100 ; //PA2 digital input buffer and pull-up is disabled
}

void adc_init(){
    ADC0.CTRLA = ADC_FREERUN_bm;                    //Set ADC to free running Mode
    ADC0.CTRLA |= ADC_ENABLE_bm ;                   //enable ADC

    ADC0.CTRLB = ADC_SAMPNUM_ACC64_gc;                //SET the ADC to sum 64 samples
    ADC0.CTRLC = ADC_SAMPCAP_bm | ADC_REFSEL1_bm;    //Select VDD as the reference
    ADC0.CTRLD = ADC_INITDLY_DLY256_gc;                //Set the init delay before first sample
    ADC0.MUXPOS = ADC_MUXPOS_AIN2_gc;                //SET PA2 as the input for the ADC
    ADC0.INTCTRL = ADC_RESRDY_bm;                    //enable the result ready interrupt

    ADC0.COMMAND = ADC_STCONV_bm;                    // Start the conversion
}

ISR(ADC0_RESRDY_vect){
    adcVal =  ADC0.RES ;
}

int main(void) {

    io_config()  ;
    clock_conf() ;
    adc_init()  ;

    sei()  ;

    while (1) {
        if(adcVal >= thresholdVal){
             LED_ON ;
             _delay_ms(500 ) ;
             LED_OFF ;
             _delay_ms(500) ;
        }
        if(adcVal < thresholdVal) {
            LED_OFF ;
        }
    }
}
  • It seemed that the clock was fast for the ADC. So added DIV128 Prescaler in ADC0.CTRLC and it worked. In the code modified ADC0.CTRLC |= (1< – Ahmad Yeaseen Khan Jul 27 '22 at 07:56
  • If this solved your issue, please consider to write an own answer and mark it (later), or delete this question. You could add citations from the data sheet that support your finding. – the busybee Jul 27 '22 at 08:55

0 Answers0