Timer zählt nicht

Kleene

Neues Mitglied
05. Juli 2011
18
0
0
Sprachen
Hey
sieht irgendwer einen Fehler? der timer zählt nicht!

ISR(INT0_vect)
{
zeit = TCNT0;
uart_puts(zeit);
TCNT0 = 0;
//Timer
DDRB = 0xff;
PORTB = 0;
TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00); // steigende Flanke
EIMSK |= (0<<INT0);
}
 
Hallo,

ganz klar ist mir dein Sourcecode nicht, hier mal ein paar Anmerkungen oder Fragen, vielleicht können wir ja das Problem so lösen.

Hast du den externen Interrupt INT0 zuvor freigegeben und auch die Interrupts global freigegeben?

Bezüglich der Timer-Initialisierung müsste man wissen, welchen Mikrocontroller du verwendest.

Mit
EIMSK |= (0<<INT0);
am Ende der ISR bewirkst du nichts. Du möchtest den Interrupt wahrscheinlich deaktivieren, das machst du mit
EIMSK &= ~(1<<INT0);

Wie stellst du fest, welcher Wert in TCNT0 steht, bzw. wie stellst du fest, dass der Timer läuft?

Dirk
 
Hey
erstmal danke für die antwort!

jab der intterupt ansicht funktioniert ;)... ATMEAG 88 PA!

oh ne das muss raus(quasi noch vom alten übergeblieben habs nur nich bemerkt weils ja sowieso falsch war) danke ;)

ISR(INT0_vect)
{
zeit = TCNT0;
uart_puts(zeit);
TCNT0 = 0;
//Timer
DDRB = 0xff;
PORTB = 0;
TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00); // steigende Flanke
}

ich lasse ihn über eine schnittstelle ausgeben...bzw jetzt sehe ich auch im stuido das er nich mitzählt ;)

TCNT0 bleibt während des ablaufs die gaze zeit auf 0x00
 
ahh mit dem EIMSK wollte ich den interrupt bloß zurück setzen... so das er halt nich sofort wieder ausgeführt wird sondern erst wenn wieder eine steigende flanke kommt!

und ich hab eig gelesen das das automatisch passiert ...
 
Du erwartest ,dass dir jemand 3 Stunden nach deinem letzten Post schon eine fertige Antwort auf den Tisch legt ?

Viele leute hier / vermutlich die meisten Aktiven sind am Arbeiten und können nur in ihrer Freizeit auf die Probleme hier eingehen... hab etwas mehr Geduld ..

Prinzipiell würde ich in ner ISR Routine NIE !!! ein puts reinpacken ... Normal ist ein puts um Zeichen wie "Hallo dies ist ein Text"+\0 auszugeben ... bist du sicher dass du ein Puts nutzen willst hierfür ?


Weil dein "zeit" muss ja nen Int oder ein Char sein somit hast du nur irgendwie eine Dezimal Zahl drin ...

wenn da nun auf nen normalen "puts" typisch irgendwie sowas
Code:
void puts( const unsigned char *data )
{

  while( *data != '\0' )
  {

    sw_putChar( *data++ );
  }
}

das könnte schon mal tierisch crashen weil dann rennt dein puts durch deinen speicher bis er ne \0 findet .. ^^

probier mal als Init für den Timer0
sowas


Code:
 TCCR0B = 0x00; //stop
 var = TCNT0;

 TCNT0 = 0x0; //set count
 TCCR0A = 0x00; 
 TCCR0B = 0x03; //start timer

du solltest vor du den Timer ausliest ihn auch erst mal stoppen .. TCCR0B = 0 ...

wenn du dann einen Breakpoint auf das TCCR0A = 0x00 setzt und var ist immer auf 0 wenn du zum Breakpoint kommst dann hast du keinen main clock :p

sonst kann eben noch sein, dass dein INT0 einfach nicht kommt ...

Aber mich stört da einfach am meisten der "puts" .. rein vom bauchgefühl her ^^

gruß
Manuel


(grad keine zeit im Datenblatt die rauszusuchen wie die heißen ...)
 
hat keiner ne idee?

Ich kann Manuel zustimmen,
nicht alle haben jetzt Ferien oder Urlaub ... also ein bisschen Zeit zum Antworten lassen.

Ich vermute den Fehler in zwei Bereichen,
  • einmal könntest du in der Routine mit der Usart-Übertragung hängen, so dass der Timer0 nie initialisiert wird (hat ja Manuel schon etwas dazu geschrieben) oder
  • du wertest den Timer/Counter nicht richtig aus.
Jedenfalls läuft der Timer sofort, wenn eines der Prescalerbits CS[02..00] gesetzt ist. Das einzigste was undefiniert den Timer wieder stoppen kann ist ein "richtiger" RESET oder wenn das Register TCCROB überschrieben wird. Starte doch einfach mal den Timer nach int main(void) oder entferne testweise die Usart-Übertragung.

Vielleicht stellst du auch mal dein komplettes Programm rein, so dass man mehr sagen kann.

Dirk
 
Hey

so war das doch garnich gemeint :eek: ...ich seh doch wieviele leute sich das problem angeguckt haben ;)...mir war nur ein wenig langweilig ;) sorry

aber danke für die antworten!!! =)...also das puts ist schon weg ;)

aber vielen dank für die antworten!!! ...hat funkt. timer läuft =)
 
Hey

jetzt hab ich das nächste problem :eek:

also ums mal kurz zu erläutern ich will eine geschwindigkeit mit einer lichtschranke messen... das bedeutet ich hab immer hell und dunkle phasen

der interrupt soll bei jeder steigenden Flanke aufgerufen werden

ISR(INT0_vect)
{
//Timer
TCCR0B = 0x00; //Timer stopped
zeit = TCNT0;
TCNT0 = 0;
// TCCR0A = 0x00
DDRB = 0xFF;
PORTB = 0;
TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00); // steigende Flanke
EIMSK &= ~(1 << INT0); // Interrupt zurück setzen
}

//Interrupt_1
DDRD = 0x00;
EICRA |= (1<<ISC11) | (0<<ISC10) ;
EIMSK |= (1<<INT0);
sei();

Problem: er springt nur am anfang bzw. einmal rein dann nie wieder?!

Danke =)
 
Problem: er springt nur am anfang bzw. einmal rein dann nie wieder?!

Hallo,

hiermit
EIMSK &= ~(1 << INT0); // Interrupt zurück setzen
deaktivierst du den externen Interrupt INT0, die ISR wird dann nur einmalig aufgerufen. Du möchtest wahrscheinlich das Interruptanforderungsflag löschen, das brauchst du nicht, der AVR macht das beim Rücksprung aus der ISR selber.

Dirk
 
Danke für deine antwort

ich hab einiges geändert bzw rausgeschmissen...
das einzige was noch nicht bzw. wieder (vorher wars wahrscheinlich nicht richtig ;)) nicht funktioniert ist der timer! vllt fällt dir ja noch was ein =) wäre super!
ich poste einfach mal den ganzen code ausgeschlossen der UART...manche zeilen sind rein zum testen da und eig unnütz also nicht beachten ; )

#define F_CPU 7370000UL

#define LED_PORT PORTC
#define LED_PIN PC3
#define OUT_PORT PORTC
#define OUT0 PC2
#define OUT1 PC3
#define OUT2 PC4
#define OUT3 PC1
#define OUT4 PC0

#define IN_PORT1 PINB
#define IN_PORT2 PIND
#define IN10 PB0
#define IN11 PB2
#define IN20 PD6
#define IN21 PD7


#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

volatile int zeit = 0;

int hilf = 0;

ISR(INT0_vect)
{
//Timer
zeit = TCNT0;
TCNT0 = 0;
}

int main()
{
char wort[100] = {'H','a','l','l','o',' ','W','e','l','t','\n','\0'};
int zahl = 467;
//char wort[10];
TCNT0 = 0x00;


if(zeit != hilf)
{
hilf = zeit;
uart_puts(zeit);
}

DDRC = (1<<PC3) | (1 << PC4);
PORTC = (1<<LED_PIN); //Led leuchten
PORTD = (1<<PD2) | (1<<PD3) ; // Pullup

//Interrupt_1
DDRD = 0x00;
EICRA |= (1<<ISC11) | (0<<ISC10) ; // fallende Flanke
EIMSK |= (1<<INT0);

sei();

//Timer
DDRB = 0xFF;
PORTB = 0;
TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00); // steigende Flanke
TCCR0B = 0x00; //Timer stopped


uart_init();

while (1) // Blinken
{

PORTB = TCNT0; // Counter ausgeben
_delay_us(100000);
PORTC |= (1<<PC3); //LED an
_delay_us(100000);
PORTC &= ~(1<<PC3); // LED aus

uart_putc(zeit);
//uart_puts(wort);
}
}
 
ok ^^ diese zeile natürlich löschen

TCCR0B = 0x00; //Timer stopped

aber es funktioniert trotzdem nicht :(
 
Hallo,

den USART solltest du zuerst initialisieren (usart_init), danach auf den USART zugreifen. Die Routinen usart_puts und usart_putc sollten auch das richtige Usart-Modul im AVR ansprechen.

Du verwendest auch wieder "usart_puts(zeit)". "zeit" ist volatile int und kein Null-terminierter String.

Noch ein Hinweis zum Schreiben der Beiträge:
Wenn du einen Fehler in deinem Beitrag gefunden hast, kannst du den Beitrag ändern und musst nicht einen weiteren Beitrag schreiben. Wenn du editierst, wird es übersichtlicher.

Dirk
 
du meinst "usart_init()" vor die if abfrage setzten ?

"
Die Routinen usart_puts und usart_putc sollten auch das richtige Usart-Modul im AVR ansprechen.

hm? also die funkt. wunderbar leider nur mit nem textstring aber immerhin

int uart_putc(unsigned char c)
{
while (!(UCSR0A & (1<<UDRE0))) /* warten bis Senden moeglich */
{
}

UDR0 = c; /* sende Zeichen */
return 0;
}

void uart_puts (char *s)
{
while (*s)
{ /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
uart_putc(*s);
s++;
}
}
Du verwendest auch wieder "usart_puts(zeit)". "zeit" ist volatile int und kein Null-terminierter String.

was soll mir das sagen ? :eek: :confused:
 
was soll mir das sagen ?

das soll dir das sagen was ich in meinem Post lang und breit erklärt habe *g*.

Du hast eine Variable "zeit" gehst immer wenn diese != 0 ist in deine Funktion puts wie schön drin steht "solange *s != '\0'..." die Routine hoppelt dir durch dein Kompletten Speicher des AVRs bis es eine '\0' findet ...solange springt er in deiner puts rum.

Du musst dir ja vorstellen dass der Speicher von deinem Atmel (das Ram) über Adressen angesprochen wird ... und hinter *s steht ja nur ne Adresse.

dein s++ (wo du übrigends auch uart_putc(*s++); schreiben könntest ... erhöt dir nun die Adresse solange bis er eben bei der 0 ankommt und bis er die findet kann das lange dauern ... ;)... somit wird da hauptsächlich müll rauskommen ... wenn du eine Zeit ausgeben magst solltest du etwas wie ItoA (Int to Ascii) nutzen. Dann kannst du auch die Ausgeben (sonst kriegst du in den meisten Terminals nur ein viereck ... weil er das Zeichen nicht darstellen kann).

Ich nehme um Ints auszugeben und dergleichen mittlerweile fast nur noch printf (ja speicher fresser aber ist mir an der stelle egal...)

Natürlich solltest du wie Dirk auch schon sagte deinen Uart Init Aufrufen vor du irgendwas ausgeben willst ...

Code:
if(zeit != hilf)
{
hilf = zeit;
uart_puts(zeit);
}

das rufst du davor auf ... ich weiß auch nicht ob das den zweck erfüllt den du willst aber ok.

Dann bitte deine Codes die du Postest in [ CODE] [ /CODE] einfügen ...

So long,

gruß,
Manuel
 
Code:
volatile int zeit = 0;
volatile int hilf = 0;

ISR(INT0_vect)
{
	//Timer	
	zeit = TCNT0;
	TCNT0 = 0;
	hilf = 1;
}

int main()
{
	char wort[100] = {'H','a','l','l','o',' ','W','e','l','t','\n','\0'};
	int zahl = 467;
	//char wort[10];
	//TCNT0 =  0x00;

	uart_init();

	if( hilf != 0)
	{
		uart_putc(zeit);
		hilf = 0;
	}


  	//int16_t i = -12345;
    
	DDRC = (1<<PC3) | (1 << PC4);
	//DDRC = (1<<LED_PIN)|(1<<OUT0)|(1<<OUT1) | (1 << PC4);	// C = ausgang
	PORTC = (1<<LED_PIN);									//Led leuchten
	
	
	PORTD = (1<<PD2) | (1<<PD3)				; 				// Pullup
	//PORTB = (1<<PB0)|(1<<PB2); 							// Pullup
	
	//Interrupt_1
	DDRD = 0x00;
	EICRA |=  (1<<ISC11) | (0<<ISC10) ;						// fallende Flanke	
	EIMSK |= (1<<INT0); 
		
	sei();

	//Timer
	//DDRB  = 0xFF; 
	//PORTB = 0;
	TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);	 	// steigende Flanke
	//EIMSK &= ~(1 << INT0);								// Interrupt zurück setzen 
	//TCCR0B = 0x00;									    //Timer stopped


	while (1)  // Blinken
	{

		PORTB = TCNT0;										// Counter ausgeben
		_delay_us(100000);	
		PORTC |= (1<<PC3);									//LED an
		_delay_us(100000);
		PORTC &= ~(1<<PC3); 							 	// LED aus
		
	   	uart_puts(wort);
	}
}

total lieb das du mir so ausfürhlich antwortest aber ich kann mit der ausgabe ja noch nicht wirklich was machen weil der timer nicht funktioniert... somitgeht er natürlich nicht in die if verzweigung und ruft die uartputc garnich auf ... ich machs zur probe mal mit ner einfach zahl und ohne if abfrage aber wäre voll super wenn du wegen dem timer auch noch ne idee hast =) ich bin absolut ratlos
 
wuahhh ^^ okee öhm also das was du jetzt da hast ist irgendwie total wirr *gg*

bedenke,

dein Programm Arbeitet von main runter bis in die while(1)...
Code:
	if( hilf != 0)
	{
		uart_putc(zeit);
		hilf = 0;
	}
dort läuft dein Timer doch noch garnicht ...

somit wird zeit auch nie etwas haben ...


dann zeit ist ein Int also 16 Bit ... putc schickt 1 Char = 8 Bit es könnte zwar was rauskommen aber es wird nur müll sein ...


Code:
TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);	 	// steigende Flanke
steigende Flanke ? ich glaub der Kommentar ist falsch ^^ ... mach dort zudem mal kein |= sondern nur ein = ich weiß nicht ob das der gcc sonst hier richtig macht ...


Code:
PORTB = TCNT0;	// Counter ausgeben

hier hast du das selbe problem wie oben 16 bit in 8 bit casten wird dir nicht das geben was du willst ... (portB ist 8Bit).


Dein Interrupt hast du ja sowieso abgeschalten ...


Aber irgendwie muss der dann auf Port B etwas tun ...


ich kenne den gcc nicht mehr so gut .. nutze ihn nicht mehr aber ich meine mich zu erinnern dass man bei delay_us begrenzt war .. deine 100000 kommt mir arg hoch vor .. nutz lieber die delay_ms und nimm ne kleinere Zahl (da bin ich mir nicht sicher aber ...) bzw 100ms zum Testen is eh schon wenig ^^

gehen deine Portpins an PortC hoch Blinkt die LED?

Bzw ...
Schalte mal dein DDRB auf 0xFF :p ...... da du das ausremarkt hast wird dort sowieso nie was zu sehn sein ^^

gruß,

Manuel
 
Hallo,

die if-Abfrage ist niemals wahr, da hier "hilf" immer 0 ist. Der externe Interurpt INT0 wird erst danach initialisiert, aber selbst wenn davor, bist du viel zu schnell über die if-Abfrage drüber, bevor eine Flanke erkannt und die ISR aufgerufen wird

Du machst in der While(1)-Schleife eine Ausgabe des Timer-Wertes auf PortB, Direction von PortB ist aber INPUT.

Dirk
 
ist dich sache geklärt wenn ich die If-Abfrage einfach weiter nach untern schiebe nach der timer initiallisierung? ...geändert hats nichts ^^

teigende Flanke ? ich glaub der Kommentar ist falsch ^^
der Kommentar ist richtig

hier hast du das selbe problem wie oben 16 bit in 8 bit casten wird dir nicht das geben was du willst ... (portB ist 8Bit).

hier hast du das selbe problem wie oben 16 bit in 8 bit casten wird dir nicht das geben was du willst ... (portB ist 8Bit).
TCNT0 sind auch nur 8 bit



Code:
//Timer
	TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);	 	// steigende Flanke
	
		if( hilf != 0)
	{
		uart_putc(zeit);
		hilf = 0;
	}
der timer ist nicht abgeschaltet also bei mir nicht ka sorry habs evtl nochmal geändert ka

ich kenne den gcc nicht mehr so gut .. nutze ihn nicht mehr aber ich meine mich zu erinnern dass man bei delay_us begrenzt war .. deine 100000 kommt mir arg hoch vor .. nutz lieber die delay_ms und nimm ne kleinere Zahl (da bin ich mir nicht sicher aber ...) bzw 100ms zum Testen is eh schon wenig ^^

das klappt alles led leuchten ... hab schon verschiedene werte ausprobiert wenn das alles noch nich funkt. würde würde ich mich bestimt noch nicht um den timer kümmern ; )...das hoffe ich zumindest :D

und ich habe erstmal alles unnütze was ich noch nicht brauche auskommentiert damit ich da überall fehler ausschliessen kann ; )
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)