EDIT:
Denkfehler?
muss ich die kanalumschaltung im ADC ISR machen?
ja, da hatte ich im Beitrag zuvor auch drauf hingewiesen.
EDIT:
Denkfehler?
muss ich die kanalumschaltung im ADC ISR machen?
Das Beispiel hab ich mit dem Timer0 auch ausprobiert, das scheint zu klappen. Nur ist das ein 8-Bit Timer, und löst bei meinem F_CPU 16Mhz natürlich viel zu schnell die ADC-Messungen bzw. Eingangsumschaltung aus.......... und es wird alles blockiert, da nur noch die interrupts laufen
http://www.electronicsplanet.ch/mik.../ATMega16/ATmega16-ADC-Autotrigger-Timer0.htm
ich glaube so wie in diesem Beispiel sollte es gehn....
Wenn ich das dort richtig verstehe, dann wird eine ADC-messung ausgelöst, wenn der Compare wert erreicht wird?
die 1s bleibt natürlich nicht - das is nur zum testen
...
Deswegen dachte ich mir, ich mach das über Interrupt - und auto triggerung, dann bekommt man davon nichts mit.
void init_adc()
{
ADMUX = 0x00;
ADMUX |= (0<<REFS1)|(1<<REFS0);
ADCSRA |= ( (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2) );
//ADCSRA |= (1 << ADSC);
ADCSRA |= (1 << ADIE);
ADCSRA |= (1 << ADEN);
ADCSRA |= (1 << ADATE);
ADCSRB |=(1<<ADTS0)|(1<<ADTS2); //Timer/Counter1 Compare Match B
sei(); // Set the I-bit in SREG
ADCSRA |= (1<<ADSC); // Start the first conversion
while(ADCSRA &(1<<ADSC))
{
;
}
volatile uint16_t dummy = 0;
dummy = ADC;
cli();
}
void timer1_init(void)
{
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1B = 15624; //?
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
}
ISR(ADC_vect)
{
//tu was
TIFR1 |= (1<<OCF1B);
}
void timer1_init(void)
{
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1A = 15624;
// turn on CTC mode
TCCR1A |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
// enable timer compare interrupt:
//TIMSK1 |= (1 << OCIE1B);
}
void init_adc()
{
ADMUX = 0x00;
ADMUX |= (0<<REFS1)|(1<<REFS0);
ADCSRA |= ( (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2) );
//ADCSRA |= (1 << ADSC);
ADCSRA |= (1 << ADIE);
ADCSRA |= (1 << ADEN);
ADCSRA |= (1 << ADATE);
ADCSRB |=(1<<ADTS0)|(1<<ADTS2); //Timer/Counter1 Compare Match B
[B]sei();[/B] // Set the I-bit in SREG
ADCSRA |= (1<<ADSC); // Start the first conversion
while(ADCSRA &(1<<ADSC))
{
;
}
volatile uint16_t dummy = 0;
dummy = ADC;
[B][B]cli();[/B][/B]
}
Bei der Initialisierung des ADC machst du eine Dummy-Messung und pollst ADSC. Da der ADC Interrupt (ADIE Bit gesetzt) aktiviert ist, wird dessen ISR bei Ende der Wandlung ausgeführt. Zum Schluss schaltest du alle Interrupts global aus. Wenn du danach die Interrupts global nicht wieder frei gibst, wird die ADC ISR nicht ausgerufen.
Bezüglich der Timer-Initialisierung muss ich auch erst mal in das Datenblatt schauen, ich habe nur im Moment leider kaum Zeit. Falls sonst niemand zwischenzeitlich helfen kann, schaue ich später noch einmal danach.
Code:void init_adc() { ADMUX = 0x00; ADMUX |= (0<<REFS1)|(1<<REFS0); ADCSRA |= ( (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2) ); //ADCSRA |= (1 << ADSC); ADCSRA |= (1 << ADIE); ADCSRA |= (1 << ADEN); ADCSRA |= (1 << ADATE); ADCSRB |=(1<<ADTS0)|(1<<ADTS2); //Timer/Counter1 Compare Match B [B]sei();[/B] // Set the I-bit in SREG ADCSRA |= (1<<ADSC); // Start the first conversion while(ADCSRA &(1<<ADSC)) { ; } volatile uint16_t dummy = 0; dummy = ADC; [B][B]cli();[/B][/B] }
void timer1_init(void)
{
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count:
OCR1A = 977;
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
//beispiel:
//TCCR1A = // Normal mode (no WGMxy-Bits set)
//(1<<COM1A0) // Toggle A on match
//|(1<<COM1B0) // Toggle B on match
TCCR1A |=(1<<COM1B0); // Toggle B on match
//testoutput
Display_DisplayBinary16(0,0,TCCR1A);
Display_DisplayBinary16(0,20,TCCR1B);
_delay_ms(5000);
}
ISR(ADC_vect)
{
adc_val += ADC;
ISR_ADC_VECT_COUNTER++;
//Display_DisplayDecimal16(80,100,ISR_ADC_VECT_COUNTER);
if(ISR_ADC_VECT_COUNTER==16)
{
if (adc_counter>128)
{
adc_counter=1;
analog_channel=0;
}
analog_channel++;
pcf8574_set_outputs(0,(255-adc_counter));
pcf8574_set_outputs(2,(255-adc_counter));
adc_counter =(adc_counter*2);
ISR_ADC_VECT_COUNTER=0;
adc_val =adc_val /16;
//hier fehlt noch -> ins fifo - buffer schreiben
//Display_DisplayDecimal16(80,80,adc_val);
adc_val=0;
}
TIFR1 |= (1<<OCF1B);
}
void init_adc()
{
ADMUX = 0x00;
ADMUX |= (0<<REFS1)|(1<<REFS0);
ADCSRA |= ( (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2) );
//ADCSRA |= (1 << ADSC);
ADCSRA |= (1 << ADIE);
ADCSRA |= (1 << ADEN);
ADCSRA |= (1 << ADATE);
ADCSRB |=(1<<ADTS0)|(1<<ADTS2); //Timer/Counter1 Compare Match B
}
Ich denke jetzt hab ichs selbst rausgefunden ....
Aber wäre trotzdem toll, wenn du dir das nochmal anschauen könntest, da ich mir nicht 100% sicher bin.........
Ein Problem hatte ich allerdings, als ich in der ADC-ISR nur zu Testzwecken den ADC-WERT aufs Display ausgegeben hab, ist er manchmal hängen geblieben.....
. Der Prescaler ist 64. Der Timer/Counter wird mit 250kHz (4us) getaktet. .
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
Wie kommst du auf Prescaler 64 ?
Code:TCCR1B |= (1 << CS10); TCCR1B |= (1 << CS12);
CSn2 CSn1 CSn0 Description
1 0 1 clk I/O /1024 (From prescaler)
Sollte Prescaler 1024 sein?