Hallo zusammen, Habe ein kleines Problem meinen Timer sowie meinen ADC zusammen laufen zu lassen. Also Timer alleine läuft. Genauso wie der ADC...jedoch wenn Ich beide laufen lassen will, kommt komischerweise nur der Timer. Der ADC wandelt dann dummerweise nicht mehr!? Hat da jemand einen Rat? Grüße Martin
//---------------------------------------------------------------------- ----------------------------- // Interrupt Service Routine --> AD - Converter //---------------------------------------------------------------------- ----------------------------- ISR(ADC_vect) { uint8_t AD_LOW; uint8_t AD_HIGH; ADCSRA |= (0<<ADIE); // Disable ADC Interrupt if (ADC_Active_Channel == 6) { ADC_Active_Channel = 0; } switch(ADC_Active_Channel) { case 0:break; // ADC0 unused case 1:break; // ADC1 unused case 2:break; // ADC2 unused case 3: LEM_Result = ADCW; break; case 4: //VD_Output_Result = ADCW; AD_LOW = ADCL; AD_HIGH = ADCH; PORTD = AD_LOW; break; case 5: VD_Input_Result = ADCW; break; default:break; } ADC_Active_Channel++; ADMUX = (0b11111111 & ADC_Active_Channel); // Set next channel ADCSRA |= (1<<ADIE); // Enable ADCSRA |= (1<<ADSC); // Start Conversion }
int main(void) { /***** Ports ******/ //0 = Input ; 1 = Output // The Port B Data Direction Register DDRB |= (1<<PB2)|(1<<PB1); DDRC |= (0<<PC5)|(0<<PC4)|(0<<PC3); //|(0<<PC2)|(0<<PC1)|(0<<PC0); DDRD |= (1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0); /***** Timer *****/ //---------------------------------------------------------------------- ------------------------------------------------- Inital_Timer = 34; TCCR1A |= (1<<WGM11)|(0<<WGM10); TCCR1B |= (1<<WGM13)|(0<<WGM12); TCCR1B |= (0<<CS12)|(0<<CS11)|(1<<CS10); ICR1H = 00; ICR1L = 136; TCCR1A |= (1<<COM1A1)|(0<<COM1A0); TCCR1A |= (1<<COM1B1)|(1<<COM1B0); OCR1AH = 00; OCR1AL = Inital_Timer; OCR1BH = 00; OCR1BL = (Inital_Timer + 5); TIMSK1 |= (1<<ICIE1); TIMSK1 |= (1<<OCIE1B); TIMSK1 |= (1<<OCIE1A); TIMSK1 |= (1<<TOIE1); /***** AD Converter *****/ //--------------------------------------------------------- ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0); // 8MHz / 64 = 125kHz || 110 = 64 ADMUX |= (0<<REFS1)|(1<<REFS0); ADMUX |= (0<<ADLAR); ADC_Active_Channel = 0; ADMUX = (0b11111111 & ADC_Active_Channel); //ADCSRB |= (0<<ACME)|(1<<ADTS2)|(1<<ADTS1)|(0<<ADTS0); // Timer.1 Overflow //ADCSRA |= (0<<ADATE); ADCSRA |= (1<<ADEN); // ADC Enable ADCSRA |= (1<<ADSC); // Start Single Conversion ADCSRA |= (1<<ADIE); // Enable ADC Interrupt sei(); // set all Interrupts free while(1) { //state_Machine(); //change_States(); } return(0); }
Martin28 schrieb: > Das ist das der Code den Ich Compiliere... Da fehlen dann aber noch diverse ISRs. Wenn du die nicht hast, dann soft-resettet dein Programm ständig.
Stefan Ernst schrieb: > Da fehlen dann aber noch diverse ISRs. Wenn du die nicht hast, dann > soft-resettet dein Programm ständig. Also die für den Timer meist jetzt? ADC_ISR steht ja...
Martin28 schrieb: > ADCSRA |= (0<<ADIE); // Disable ADC Interrupt Was erwartest du denn davon? > ADMUX = (0b11111111 & ADC_Active_Channel); Oder davon? http://www.mikrocontroller.net/articles/Bitmanipulation Dein Programm funktioniert hinten und vorne nicht. mfg.
Thomas Eckmann schrieb: >> ADCSRA |= (0<<ADIE); // Disable ADC Interrupt > Was erwartest du denn davon? Davon würde Ich erwarten das der AD Wandler in dieser Zeit bis das ADIE bit wieder 1 gesetzt wird nicht mit ner neuen Wandlung beginnt. In dieser Zeit schreibe Ich mein Ergebnis der Wandlung aus dem Datenregister. Thomas Eckmann schrieb: >> ADMUX = (0b11111111 & ADC_Active_Channel); > Oder davon? Den Multiplexer auf den nächsten Kanal umstellen... Das es nicht funktioniert habe Ich ja auch schon erwähnt. Aber Merci für den Link...
Martin28 schrieb: > 0b11111111 & ADC_Active_Channel ADC_Active_Channel = 0; 1111 1111 &0000 0000 =0000 0000 Damit stellst du MUX auf 0 und schaltest die Referenz auf AREF, also extern. Du darfst im Register nur die Mux-Bits verändern. Martin28 schrieb: > ADCSRA |= (0<<ADIE); Das verändert gar nichts. Wenn du etwas mit 0 ODER-verknüpfst, ändert sich der Wert nicht. Das ist ja auch der "Trick", mit dem man ein einzelnes Bit setzt. 0101 0101 |0000 0010 =0101 0111 ^ Wenn das "ADCSRA |= (0<<ADIE)" so wie du dir das vorstellst funktionieren würde, wäre das Ergebnis dieses Beispiels aber 0000 0000 Arbeite den Link intensiv durch. Das ist elementar. Im Moment interpretierst du diesen Quatsch (XYZ |= (0 << ABC), den man leider andauernd sieht, auch noch vollkommen falsch. mfg.
Danke für die ausführliche Erklärung Thomas. Werde mir das auf jeden Fall genau ansehen. Grüße Martin
Habe das mit dem umstellen des Multiplexers geändert. Sieht jetzt so aus: ADMUX = (ADMUX & ~(0x1F)) | (ADC_Active_Channel & 0x1F); Die übrigen ISR Routinen wie oben erwähnt eingebaut: (zur Vollständigkeit) damit kein Softreset durchgeführt wird. ISR(TIMER1_CAPT_vect { TIFR1 |=(1<<ICF1); } ISR(TIMER1_COMPA_vect) { TIFR1 |=(1<<OCF1A); } ISR(TIMER1_COMPB_vect) { TIFR1 |=(1<<OCF1B); } ISR(TIMER1_OVF_vect) { TIFR1 |=(1<<TOV1); } Aber komischerweise laufen die immer noch nicht zusammen...wo könnte noch eine Fehlerquelle sein? Bin hier grad bisschen am verzweifeln Grüße Martin
Im obigen post ist die Klammer ISR(TIMER1_CAPT_vect) { TIFR1 |=(1<<ICF1); } natürlich geschlossen...
Wenn du vernünftige Hilfe willst, dann poste den ganzen Code. Vollständig. Wir können uns natürlich noch 25 andere Szenarien ausdenken, was in deinem Code noch alles schief gegangen sein könnte. Einfacher ist es aber für dich und für uns, wenn du ganz banal dein C-File nimmst und als Anhang anhängst.
Aber mal ein Schnellschusss
1 | ADCSRA |= (1<<ADEN); // ADC Enable |
2 | ADCSRA |= (1<<ADSC); // Start Single Conversion |
3 | ADCSRA |= (1<<ADIE); // Enable ADC Interrupt |
Ich würde das mal aus logischen Gründen umdrehen. Erst den ADC einschalten dann den ADC konfigurieren und erst dann, wenn eingeschaltet und konfiguriert ist, erst dann starte ich den ADC. Ich weiß nicht, ob es was ändert. Aber es wäre zumindest erst mal DIE logische Reihenfolge der Ereignisse. Und im Zweifelsfall hat es sich noch immer bewährt, wenn man sich erst mal daran hält.
int main(void) { /***** Ports ******/ //0 = Input ; 1 = Output // The Port B Data Direction Register DDRB |= (1<<PB2)|(1<<PB1); DDRC |= (0<<PC5)|(0<<PC4)|(0<<PC3); DDRD |= (1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0); /***** Timer *****/ //---------------------------------------------------------------------- ------------ Inital_Timer = 17; TCCR1A |= (1<<WGM11)|(0<<WGM10); TCCR1B |= (1<<WGM13)|(0<<WGM12); TCCR1B |= (0<<CS12)|(0<<CS11)|(1<<CS10); ICR1H = 00; ICR1L = 69; TCCR1A |= (1<<COM1A1)|(0<<COM1A0); TCCR1A |= (1<<COM1B1)|(1<<COM1B0); OCR1AH = 00; OCR1AL = Inital_Timer; TIMSK1 |= (1<<ICIE1); TIMSK1 |= (1<<OCIE1B); TIMSK1 |= (1<<OCIE1A); /***** AD Converter *****/ //---------------------------------------------------------------------- ----------- ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0); / // 8MHz / 64 = 125kHz || 110 = 64 ADMUX |= (0<<REFS1)|(1<<REFS0); ADMUX |= (0<<ADLAR); ADC_Active_Channel = 0; ADMUX = (ADMUX & ~(0x1F)) | (ADC_Active_Channel & 0x1F); //ADCSRB |= (0<<ACME)|(1<<ADTS2)|(1<<ADTS1)|(0<<ADTS0); // Timer.1 Overflow ADCSRA |= (1<<ADEN); // ADC Enable ADCSRA |= (1<<ADSC); // Start Single Conversion ADCSRA |= (1<<ADIE); // Enable ADC Interrupt sei(); // set all Interrupts free while(1) { // state_Machine(); // change_States(); } return(0); }
//---------------------------------------------------------------------- ----------------------------- // Interrupt Service Routine --> AD - Converter //---------------------------------------------------------------------- ----------------------------- ISR(ADC_vect) { /* if (ADC_Active_Channel == 6) { ADC_Active_Channel = 0; } */ switch(ADC_Active_Channel) { case 0:break; // ADC0 unused case 1:break; // ADC1 unused case 2:break; // ADC2 unused case 3: //LEM_Result = ADCW; AD_LOW = ADCL; AD_HIGH = ADCH; PORTD = AD_LOW; break; case 4: VD_Output_Result = ADCW; break; case 5: VD_Input_Result = ADCW; break; /* AD_LOW = ADCL; AD_HIGH = ADCH; PORTD = AD_LOW; */ default:break; } ADCSRA |= (1<<ADSC); // Start Conversion } //---------------------------------------------------------------------- ----------------------------- // Interrupt Service Routine --> Timer.1 //---------------------------------------------------------------------- ----------------------------- ISR(TIMER1_CAPT_vect) { TIFR1 |=(1<<ICF1); } ISR(TIMER1_COMPA_vect) { TIFR1 |=(1<<OCF1A); } ISR(TIMER1_COMPB_vect) { TIFR1 |=(1<<OCF1B);
Und wenn du jetzt noch sagst, welcher AVR das ist, dann könnte man den Code mal in den Simulator überführen und nachsehen, was da wirklich passiert, bzw. auf den realen Chip, denn auch der Simulator ist nicht fehlerfrei.
Manchmal sieht man den Wald vor lauter Bäumen nicht!!! ISR(ADC_vect) { /* if (ADC_Active_Channel == 6) { ADC_Active_Channel = 0; } */ switch(ADC_Active_Channel) { case 0:break; // ADC0 unused case 1:break; // ADC1 unused case 2:break; // ADC2 unused case 3: //LEM_Result = ADCW; AD_LOW = ADCL; AD_HIGH = ADCH; PORTD = AD_LOW; break; case 4: VD_Output_Result = ADCW; break; case 5: VD_Input_Result = ADCW; break; /* AD_LOW = ADCL; AD_HIGH = ADCH; PORTD = AD_LOW; */ default:break; } ADC_Active_Channel++; ADMUX = (ADMUX & ~(0x1F)) | (ADC_Active_Channel & 0x1F); ADCSRA |= (1<<ADSC); // Start Conversion }
ADC_Active_Channel++; ADMUX = (ADMUX & ~(0x1F)) | (ADC_Active_Channel & 0x1F); Komischerweise hatte Ich das rausgelöscht...Fehler gefunden! Läuft jetzt!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.