hi all,
from the datasheet (in my case atmega16):
Using the ADC Interrupt Flag as a trigger source makes the ADC start a new conversion as soon as the ongoing conversion has finished. The ADC then operates in Free Running mode, constantly sampling and updating the ADC Data Register. The first conversion must be started by writing a logical one to the ADSC bit in ADCSRA. In this mode the ADC will perform successive conversions independently of whether the ADC Interrupt Flag, ADIF is cleared or not.
turning this feature "on" i get this error in linux when connecting my device:
[ 1173.796651] usb 4-1: new low speed USB device using uhci_hcd and address 44
[ 1173.850848] usb 4-1: device descriptor read/64, error -71
is it possible to make it work with obdev-usb?
pat
Free Running Mode possible?
There's nothing special with AVR-USB and free running mode of the ADC. It looks as if your code crashes, maybe because you enabled an interrupt which has no vector assigned or the vector is called recursively.
If you need an interrupt for the ADC, you must make sure it enables global interrupts within several cycles after interrupt start AND that it does not trigger again after enabling the interrupts.
If you need an interrupt for the ADC, you must make sure it enables global interrupts within several cycles after interrupt start AND that it does not trigger again after enabling the interrupts.
it's true, i am new to avr so it might be my code
//sbi(ADCSRA, ADIE); //Enable ADC conversion complete interrupt
working ([ 2732.974342] usb 3-1: configuration #1 chosen from 1 choice)
sbi(ADCSRA, ADIE); //Enable ADC conversion complete interrupt
not working ([ 2720.042034] usb 3-1: device not accepting address 12, error -71)
i found another post in this forum saying that a low priority interrupt:
#define UTIL_INTERRUPT(signame) \
void signame (void) __attribute__ ((interrupt)); \
void signame (void)
UTIL_INTERRUPT(XXX_vect)
{
... interrupt implementation
}
not sure if it would be necessary in my case?
![Rolling Eyes :roll:](images/smilies/icon_rolleyes.gif)
//sbi(ADCSRA, ADIE); //Enable ADC conversion complete interrupt
working ([ 2732.974342] usb 3-1: configuration #1 chosen from 1 choice)
sbi(ADCSRA, ADIE); //Enable ADC conversion complete interrupt
not working ([ 2720.042034] usb 3-1: device not accepting address 12, error -71)
Code: Select all
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include "usbdrv.h"
#ifndef BV
#define BV(bit) (1<<(bit))
#endif
#ifndef cbi
#define cbi(reg,bit) reg &= ~(BV(bit))
#endif
#ifndef sbi
#define sbi(reg,bit) reg |= (BV(bit))
#endif
#define ADC_PRESCALE_DIV64 0x06 ///< 0x06 -> CPU clk/64
#define ADC_PRESCALE ADC_PRESCALE_DIV64
#define ADC_PRESCALE_MASK 0x07
#define ADC_MUX_MASK 0x1F
void adcfrm(void)
{
DDRA = 0x00; // set all pins to input
PORTA = 0x00; // make sure pull-up resistors are turned off
sbi(ADCSRA, ADEN); //Enable the ADC
sbi(ADCSRA, ADATE); //Enable free-running mode
ADCSRA = ((ADCSRA & ~ADC_PRESCALE_MASK) | ADC_PRESCALE_DIV64);
SFIOR &= 0x1F;
sbi(ADMUX,REFS0);cbi(ADMUX,REFS1);
ADMUX = 0; //Initial channel selection
sbi(ADCSRA, ADIE); //Enable ADC conversion complete interrupt
sbi(ADCSRA, ADSC); //Start first conversion in Free-running mode
sei(); //Enable global interrupts
//Now the conversions are running
}
void initCoreHardware(void)
{
// --------------------- Init USB
DDRD = 0xe0;
PORTD = 0x70;
usbDeviceConnect();
wdt_enable(WDTO_1S);
usbReset();
usbInit();
cbi(MCUCR, ISC11);
sbi(MCUCR, ISC10);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
TCCR1B = 3;
TCNT1 = 0;
sbi(TIFR, TOV1);
sei();
}
int main(void)
{
initCoreHardware();
adcfrm();
while(1) {
wdt_reset();
usbPoll();
}
return 0;
}
i found another post in this forum saying that a low priority interrupt:
#define UTIL_INTERRUPT(signame) \
void signame (void) __attribute__ ((interrupt)); \
void signame (void)
UTIL_INTERRUPT(XXX_vect)
{
... interrupt implementation
}
not sure if it would be necessary in my case?
If you enable the interrupt, you must supply an implementation for the vector. Otherwise the reset vector is called.
Where in your code do you read the ADC data? If you don't need the accuracy of an interrupt, you may poll for it instead. Leave ADIE zero and check for ADIF regularly. If it is set, write a "1" to it and read the ADC value.
Where in your code do you read the ADC data? If you don't need the accuracy of an interrupt, you may poll for it instead. Leave ADIE zero and check for ADIF regularly. If it is set, write a "1" to it and read the ADC value.