- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 8 von 8

Thema: Brauche Hilfe um Funktion fertig zu stellen

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    04.01.2008
    Beiträge
    41

    Brauche Hilfe um Funktion fertig zu stellen

    Anzeige

    Praxistest und DIY Projekte
    Hallo,
    so ich bin nun schon fast fertig mit dem code für den Ultraschallentfernungsmesser. Nur eins fehlt noch, nämlich die Erkennung von einem timer Überlauf ( der 16 bit timer wird benutzt). Als Neuling bringe ich das nicht auf die Reihe ohne Hilfe. Hier mein Code:



    Code:
    unsigned int messen (void) {
    unsigned int messwert;
    TCNT1 = 0xBB80;          			/* Vorladen auf 48000 */
    PORTC |= (1<<PC5);       			/* Senden */
    TCCR1B = 0x2;            			/* timer starten und Vorteiler auf 8 setzen */
    _wait_us(25);
    PORTC &= ~(1<<PC5); 	 			/* Sender ausschalten*/
    while (1) {
    	if(PINC & (1<<PINC4)) {   		/* Wenn Signal zurückkommt... */
    		TCCR1B = 0x0;    			/* Timer stoppen */
    		messwert = TCNT1 - 48000; 	/* Vorladewert wieder abziehen */
    		messwert *= 0.0172;			/* In Sekunden umrechnen */
    		return messwert;
    	}
    	if (1*) {                        /* Abbruch bei timer Überlauf */
    		return 0;
    	}
    }
    }
    Was noch wichtiges anzumerken ist:
    Ich sende nur einen kurzen Impuls. Das wird später noch geändert werden ,falls sich rausstellen sollte, dass es nicht klappt.
    Sind noch Fehler im Code? Und wie mache ich, dass er dort wo eine eins mit stern (1*, kein falschgeschriebener pointer ) in der If-Bedienung steht, der timer Überlauf erkannt wird und die Funktion 0 zurückgibt?
    Lässt sich noch was optimieren?

    danke schonmal im Vorraus für eure Hilfe

    mfg

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Warum nimmst du nicht den Timer-Interrupt
    Ich weiss nicht welchen Kontroller du hast.
    Eintrag in TIMSK|=(1<<TOIE1)
    TIMER1_OVF_vect{ Hier den Code wenn Überlauf}
    Das wäre für den Mega8.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    04.01.2008
    Beiträge
    41
    Hallo,
    ja ich nehme den mega8, aber ich weiß nicht was ich in die interruptfunktion reinschreiben soll. etwa return 0; ?
    Der Rest stimmt so?

    mfg

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Felix G
    Registriert seit
    29.06.2004
    Ort
    49°32'N 8°40'E
    Alter
    41
    Beiträge
    1.780
    Also wenn du Zeiten messen möchtest, geht das auch einfacher...

    Stell den Timer z.B. auf ein sehr kurzes Zeitintervall ein, also Überlauf nach vielleicht 100µs oder 1ms oder sowas in der Größenordnung (je nachdem was die kürzeste Zeit ist die gemessen werden muss). In der ISR startest du den Timer dann einfach nur neu, und zählst eine Variable hoch, quasi wie eine "Uhr".

    Wenn du in deinem Programm dann eine Zeit messen möchtest, merkst du dir den Wert dieser Variablen zu Beginn des Zeitintervalls. Wenn die Messung beendet werden soll, ziehst du diesen Wert vom aktuellen Wert der Variablen ab, und erhälst so direkt die vergangene Zeit.
    So viele Treppen und so wenig Zeit!

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    04.01.2008
    Beiträge
    41
    Hallo,
    so ich habe meinen code verändert. Da ich nicht weiß inwieweit der Interrupt in die Funktion eingreifen kann, setze ich einen Flag a, der dann in der Funktion messen überprüft wird. Hier mein vollständiger code:
    Code:
    #include<stdlib.h>
    #include<avr/io.h>
    #define F_CPU 8000000
    #include<util/delay.h>
    #include"lcd.h"
    
    volatile char a;
    
    unsigned int messen (void) {
    unsigned int messwert;
    TCNT1 = 0xBB80;          			/* Vorladen auf 48000 */
    PORTC |= (1<<PC5);       			/* Senden */
    TCCR1B = 0x2;            			/* timer starten und Vorteiler auf 8 setzen */
    _wait_us(25);
    PORTC &= ~(1<<PC5); 	 			/* Sender ausschalten*/
    while (1) {
    	if(PINC & (1<<PINC4)) {   		/* Wenn Signal zurückkommt... */
    		TCCR1B = 0x0;    			/* Timer stoppen */
    		messwert = TCNT1 - 48000; 	/* Vorladewert wieder abziehen */
    		messwert *= 0.0172;			/* In Sekunden umrechnen */
    		return messwert;
    	}
    	if (a=1) {                        /* Abbruch bei timer Überlauf */
    		return 0;
    	}
    }
    }
    
    int main (void) {
    TIMSK|=(1<<TOIE1);
    TIMER1_OVF_vect{ a=1;} 
    DDRC |= (1<<PC5);
    DDRD= 0xff;
    
    
    lcd_init(LCD_DISP_ON);   /* lcd initialisieren */
    lcd_clrscr();			 /* Display löschen und cursor auf 1,1 setzen */
    lcd_puts("distance: ");
    while(1) {
    	lcd_gotoxy(11,1);
    	lcd_puts("messen();");
    	lcd_gotoxy(15,1);
    	lcd_puts("cm");
    
    	
    	for(unsigned char i=0;i<256;i++) {   /*warte*/
    		_wait_ms(1);
    	}
    
    }
    }
    Beim compilieren kommten folgende Fehlermeldungen
    ../Ultraschall.c: In function 'messen':
    ../Ultraschall.c:14: warning: implicit declaration of function '_wait_us'
    ../Ultraschall.c:23: warning: suggest parentheses around assignment used as truth value
    ../Ultraschall.c: In function 'main':
    ../Ultraschall.c:31: error: '__vector_8' undeclared (first use in this function)
    ../Ultraschall.c:31: error: (Each undeclared identifier is reported only once
    ../Ultraschall.c:31: error: for each function it appears in.)
    ../Ultraschall.c:31: error: expected ';' before '{' token
    ../Ultraschall.c:46: warning: comparison is always true due to limited range of data type
    ../Ultraschall.c:47: warning: implicit declaration of function '_wait_ms'
    Wie kann ich die Fehler beheben. Kann mir jemand Tipps geben?

    mfg

  6. #6
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die Intterrupt routine muss etwas so aussehen:
    ISR(TIMER1_OVF_vect ) // timer 1 overflow
    { a = 1; }

    Bei den _wait_us noch mal in delay nachsehen.


    Da ist noch ein fieser, C typischer Fehler drin:
    statt if (a=1) muss das if (a==1) heißen.

    Die For-schleife mit wait_ms darf nur bis 254 laufen, oder i müßte als integer gewählt werden.


    Wenn es nur darum geht die Messung beim Timerüberlauf abzubrechen, könnte man auch gleich das interrupt flag abfragen. Dann muß man allerdings während der Zeit alle interrupts per CLI sperren.

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    04.01.2008
    Beiträge
    41
    Hallo,
    ja ich will bei timerüberlauf abbrechen (=return 0; ). In der ersten code-Version habe ich das auch mit einem If-Befehl gemacht. Wenn der Interrupt deaktiviert ist, kann überhaupt noch das interrupt flag gesetzt werden? Muss ich die Interrupts danach wieder aktivieren? Bin bei dem Thema noch sehr unsicher auf den Beinen

    mfg

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Das ISR(TIMER1_OVF_vect){ a=1;} gehört nicht ins main, das ist eine eigene Funktion.
    Nach der if Abfrage a wieder auf 0 setzten und den Timer stoppen. Die if Abfrage in die while-Schleife integrieren.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

Berechtigungen

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

LiFePO4 Speicher Test