- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 20 von 20

Thema: Atmega8 mit 16Mhz betreiben.

  1. #11
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.05.2004
    Alter
    38
    Beiträge
    388
    Anzeige

    Praxistest und DIY Projekte
    Ich benutze myAVR Workpad und als Progammer mySmartUSB.
    Board ist selbsthergestellt. Codeoptimierung hat Workpad nicht

    Workpad motz beim von mir geposteten Code nicht.
    Ich habe ihn dennoch so abgeändert wie du es vorgeschlagen hat.

    Mit meinem Code(Auch mit dem der deine änderungen enthält) bekomme ich momentan ein ausgangssignal von 2ms High und ca 26.5ms Low.
    Eigentlich sollte es 1.5ms high und 18.5ms Low sein.

  2. #12
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.11.2003
    Beiträge
    1.112
    @Besserwessi
    Es war zu Beginn etwas verwirrend, denn Timer hätte auch eine variable sein können. BTW, mit Semikolon ist es keine Präprozessoranweisung... Aber natürlich hast Du Recht, denn jetzt ist es klarer.

    @hosti
    Kommentier mal alles unnötige aus der ISR. Die wird alle 163 Takte aufgerufen! Möglicherweise gehen hier ein paar IRQs verloren... Dass der Compiler keine Warnungen meldet, wundert mich.
    Besser noch: wähle wie oben beschrieben einen Prescaler von 8 und ändere die TCNT0 Werte.
    Gruß

  3. #13
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.05.2004
    Alter
    38
    Beiträge
    388
    Mein Code sieht nun wie folgt aus, aber das funktioniert gar nicht mehr...
    Ich kriegs irgendwie echt nicht hin

    Code:
    #include <avr/io.h>         // I/O Port definitions 
    #include <avr/interrupt.h>   // Interrupt macros 
    
    #define F_CPU 16000000 
    
    #define timer 96							//0.01ms
    //
    
    volatile int ms1 = 0;
    volatile int ms2 = 0;
    volatile int ms3 = 0;
    
    void timer_init(void) 
    {
    	
    	TCCR0 |= (1<<CS01);		//Prescaler 8
    	TCNT0 = timer;
    	TIMSK |= (1<<TOIE0);									//Interupts aktivieren
    	TIFR |= (1<<TOV0);
    
    };
    
    ISR(TIMER0_OVF_vect) 
    {
    	TCNT0 = timer;	
    	//Endausschlag LINKS
    	if(ms1>=150)
    		PORTB &= ~(1<<PORTB1);
    	else
    		PORTB |= (1<<PORTB1);
    	if(ms1<=2000)
    		ms1++;
    	else
    		ms1 = 0;
    
    	TCNT0 = timer;			
    
    		
    	if(ms2>=150)
    		PORTB &= ~(1<<PORTB2);
    	else
    		PORTB |= (1<<PORTB2);
    	if(ms2<=2000)
    		ms2++;
    	else
    		ms2 = 0;
    
    		
    	if(ms3>=150)
    		PORTB &= ~(1<<PORTB3);
    	else
    		PORTB |= (1<<PORTB3);
    	if(ms3<=2000)
    		ms3++;
    	else
    		ms3 = 0;
    };
    
    int main(void) 
    {
    	sei();
    	timer_init();
    	
    	DDRB |= (1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3);			//B... AUSGANG
    	PORTB &= ~((1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3));		//B.. Low
    
    													//GLOBALE INTERUPTS AKTIVIERT
    	while(1)
    	{
    	
    	}
    
    }

  4. #14
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.11.2003
    Beiträge
    1.112
    Probier das:
    Code:
    #include <avr/io.h>         // I/O Port definitions
    #include <avr/interrupt.h>   // Interrupt macros
    
    #define F_CPU 16000000
    
    #define timer 235                     //0.01ms
    
    volatile int ms1 = 0;
    volatile int ms2 = 0;
    volatile int ms3 = 0;
    
    void timer_init(void){
       TCNT0 = timer;
       TIMSK |= (1<<TOIE0);                           //Interupts aktivieren 
       sei();
       TCCR0 |= (1<<CS01);      //Prescaler 8
    }
    
    ISR(TIMER0_OVF_vect){
       TCNT0 = timer;   
       //Endausschlag LINKS
    	if(ms1>=150){
    		PORTB &= ~(1<<PORTB1);
    		if(ms1<=2000)
    			ms1++;
    		else
    			ms1 = 0;
    	}
    	else
          PORTB |= (1<<PORTB1);
    /*      
       if(ms2>=150)
          PORTB &= ~(1<<PORTB2);
       else
          PORTB |= (1<<PORTB2);
       if(ms2<=2000)
          ms2++;
       else
          ms2 = 0;
    
          
       if(ms3>=150)
          PORTB &= ~(1<<PORTB3);
       else
          PORTB |= (1<<PORTB3);
       if(ms3<=2000)
          ms3++;
       else
          ms3 = 0;
    */
    }
    
    int main(void){
       DDRB |= (1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3);         //B... AUSGANG
       PORTB &= ~((1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3));      //B.. Low
    
                                           //GLOBALE INTERUPTS AKTIVIERT
    	timer_init();
    	while(1){
       
      	}
       	return 0;
    }

  5. #15
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.05.2004
    Alter
    38
    Beiträge
    388
    danke für deine bemühungen.
    Mit dieser methode passiert leider garnichts. Der Pin wird einfach auf High gelegt(mehr oder weniger)

  6. #16
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.11.2003
    Beiträge
    1.112
    Ja sicher, hab ich wohl was Vergessen...
    Code:
    #include <avr/io.h>         // I/O Port definitions
    #include <avr/interrupt.h>   // Interrupt macros
    
    #define F_CPU 16000000
    
    #define timer 238                     //0.01ms
    
    volatile int ms1 = 0;
    volatile int ms2 = 0;
    volatile int ms3 = 0;
    
    void timer_init(void){
       TCNT0 = timer;
       TIMSK |= (1<<TOIE0);                           //Interupts aktivieren 
       sei();
       TCCR0 |= (1<<CS01);      //Prescaler 8
    }
    
    ISR(TIMER0_OVF_vect){
       TCNT0 = timer;   
       //Endausschlag LINKS
    	if(ms1>=150){
    		PORTB &= ~(1<<PORTB1);
    		if(ms1<=3800)
    			ms1++;
    		else{
    			ms1 = 0;
    		}
    	}
    	else
          PORTB |= (1<<PORTB1);
    	  ms1++;
    /*      
       if(ms2>=150)
          PORTB &= ~(1<<PORTB2);
       else
          PORTB |= (1<<PORTB2);
       if(ms2<=2000)
          ms2++;
       else
          ms2 = 0;
    
          
       if(ms3>=150)
          PORTB &= ~(1<<PORTB3);
       else
          PORTB |= (1<<PORTB3);
       if(ms3<=2000)
          ms3++;
       else
          ms3 = 0;
    */
    }
    
    int main(void){
       DDRB |= (1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3);         //B... AUSGANG
       PORTB &= ~((1<<PORTB1) | (1<<PORTB2) | (1<<PORTB3));      //B.. Low
    
                                           //GLOBALE INTERUPTS AKTIVIERT
    	timer_init();
    	while(1){
       
      	}
       	return 0;
    }
    Jetzt aber.
    Die 3800 kannst Du noch etwas optimieren.
    Gruß

    PS Mit der OCUnit geht es wirklich besser.

  7. #17
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.05.2004
    Alter
    38
    Beiträge
    388
    Danke dir, das gibt mir ein gutes signal. Nicht perfekt aber kommt nahe hin.
    Nur habe ich auch jetz wieder abweichungen zum theoretischen Zeit Wert.
    Also ich meine wen ich in einer bestimmten Zeit Interupts abfange und mir dann berechne das ich meine Variable auf einen bestimmten Wert hochzählen muss um z.B. 1.5ms zu bekommen. Wieso habe ich den praktisch abweichungen?

    EDIT:
    Betreffen der OCUnit(HardwarePWM?)
    Ich hab das schon einmal probiert aber nicht alle 3 PWM's des Atmega sauber zum laufen gekriegt.

  8. #18
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.05.2004
    Alter
    38
    Beiträge
    388
    Siehe obiges Edit:

  9. #19
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.11.2003
    Beiträge
    1.112
    Hi!
    Ja, aber ich hatte gehofft, dass sie jetzt geringer sind. Das wäre zu prüfen.
    Für solche Abweichungen kann es viele Möglichkeiten geben: IRQs werden übergangen, weil die ISR zu lange dauert, Timer werden nicht sofort initialisiert (auf gewünschten Wert gesetzt), Resets werden ständig ausgelöst, Quarz ist falsch gewählt oder fehlerhaft.
    Für lange ISR sind natürlich der eigene Code verantwortlich aber es hängt auch am Compiler, wieviel Code dieser daraus macht. Daher fragte ich ja auch, ob Du die Optimierung eingeschaltet hast. Der GCC hat davon verschiedene. Probier doch einfach mal den.
    Ansonsten ist Deine Lösung leider wirklich nicht zu empfehlen.
    Wenn man eine PWM per Hardware hinbekommt, dann sind die anderen nur noch Makulatur, weil sie identisch sind. Gut, es gibt Unterschiede zwischen 8 und 16Bit Countern.
    Gruß

  10. #20
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.05.2004
    Alter
    38
    Beiträge
    388
    Ich finde einfach komisch das der code auf einem Atmega644 mit 16Mhz perfekt funktioniert hat und auf dem atmega8 nicht mehr.
    Klingt für mich einfach irgendwie nach falsch eingestelltem Quarz

Seite 2 von 2 ErsteErste 12

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress