Ich krieg das mit den Zähler nicht. Ich hab mir dieses Programm zusammen-gestellt. Ich wollte erstmal zum lernen, das der Timer hochzählt und das auf der LCD zu sehen ist. Die Impulse kommen v. einen Durchfluss-mengenmesser (2500/1Liter)der an PORTD3 angeschlossen ist.Das Programm hab ich mit den CodeWizzard erstellt. Leider kommt auf d. LCD nicht mal ne 1. Bin für jeden (ausführlichen) Tipp oder Codeschnipsel dankbar. ;----------------------------------------------------------------------- -- ; Titel : test timer 1 ;----------------------------------------------------------------------- -- ; Funktion : ; Schaltung : ;----------------------------------------------------------------------- -- ; Prozessor : ATmega8 ; Takt : 3686400 Hz ; Sprache : Assembler (GNU) ; Datum : 15.1.2009 ; Version : 1.0 ; Autor : ; Programmer: ; Port : ;----------------------------------------------------------------------- -- ; created by myAVR-CodeWizard ;----------------------------------------------------------------------- -- ; .include "avr.h" begin: rjmp main ; 1 POWER ON RESET reti ; 2 Int0-Interrupt reti ; 3 Int1-Interrupt reti ; 4 TC2 Compare Match reti ; 5 TC2 Overflow reti ; 6 TC1 Capture rjmp onTimer1Cmp ; 7 Timer1 Interrupt bei Vergleichswert reti ; 8 TC1 Compare Match B reti ; 9 TC1 Overflow reti ;10 TC0 Overflow reti ;11 SPI, STC Serial Transfer Complete reti ;12 UART Rx Complete reti ;13 UART Data Register Empty reti ;14 UART Tx Complete reti ;15 ADC Conversion Complete reti ;16 EEPROM Ready reti ;17 Analog Comparator reti ;18 TWI (I²C) Serial Interface reti ;19 Store Program Memory Ready ;----------------------------------------------------------------------- - ; Initialisierungen ;----------------------------------------------------------------------- - main: ;--- Stack Initialisierung --- ldi r16,hi8(RAMEND) out SPH,r16 ldi r16,lo8(RAMEND) out SPL,r16 ; Ports initialisieren cbi DDRD,3 ; PORTD3 auf Eingang mit PullUp sbi PORTD,3 ;--- Timer 1 initialisieren --- ldi r16,0b00000111 ; Teiler 1/exR ori r16,0b00001000 ; Modus: Zählen bis Vergleichswert (WGM12=1) out TCCR1B,r16 ; Teiler+Modus schreiben ldi r16,lo8(1000) ; Vergleichswert speichern ldi r17,hi8(1000) out OCR1AH,r17 out OCR1AL,r16 in r16,TIMSK ; Interrupt bei Vergleichswert ori r16,0b00010000 out TIMSK,r16 ;--- Interrupts erlauben --- sei ;----------------------------------------------------------------------- - ; Hauptprogramm-Schleife ;----------------------------------------------------------------------- - mainloop: wdr ; ... rjmp mainloop ; Sprung zum Beginn der Hauptprogrammschleife ;-------------------------------------------------------------------- ; onTimer1Cmp - Timer1 Interrupt bei Vergleichswert ; Zyklus unbestimmt ; PE: ... ; PA: ... ;-------------------------------------------------------------------- onTimer1Cmp: ; WAS MUSS HIER REIN ???????????????? ; Hier Interruptbehandlung reti ;Rücksprung ;-------------------------------------------------------------------- ; myWait_ms - Warte-Routine für x-Millisekunden ; ein Millisekundenzyklus dauert 1,052 ms ; PE: r16 = Anzahl der zu wartenden Milisekunden ; PA: r16 = 0 ;-------------------------------------------------------------------- myWait_ms: push r16 ldi r16,1 myWait_ms_3: push r16 ldi r16,5 myWait_ms_2: push r16 ldi r16,255 myWait_ms_1: dec r16 brne myWait_ms_1 pop r16 dec r16 brne myWait_ms_2 pop r16 dec r16 brne myWait_ms_3 pop r16 dec r16 brne myWait_ms ret ;----------------------------------------------------------------------- ------ lcdOut: mov r17, r16 swap r17 andi r16, 0b11110000 or r16,r18 andi r17, 0b11110000 or r17,r18 out PORTD, r16 rcall lcdEnable out PORTD, r17 rcall lcdEnable rcall lcdWait ret ;----------------------------------------------------------------------- - ;----------------------------------------------------------------------- ------ lcdData: ldi r18,0b0000100 ; RS = hi rjmp lcdOut ret ;----------------------------------------------------------------------- - ;-------------------------------------------------------------------- ; Warte-Routine für 5 ms ; die Routine wartet inclusive Aufruf 5,031 ms ;-------------------------------------------------------------------- lcdWait: ldi r16,5 rcall myWait_ms ret ;----------------------------------------------------------------------- - ;----------------------------------------------------------------------- ------ lcdCmd: ldi r18,0b0000000 ; RS = lo rjmp lcdOut ret ;----------------------------------------------------------------------- - ;----------------------------------------------------------------------- ------ lcdOn: ldi r16, 0x0E rcall lcdCmd rcall lcdWait ret ;----------------------------------------------------------------------- - ;----------------------------------------------------------------------- ------ lcdClear: ldi r16, 0b00000001 ; Display löschen rcall lcdCmd rcall lcdWait ret ;----------------------------------------------------------------------- - ;----------------------------------------------------------------------- ------ lcdOff: ldi r16, 0b00001000 rcall lcdCmd rcall lcdWait ret ;----------------------------------------------------------------------- - ;----------------------------------------------------------------------- ------ lcdEnable: sbi PORTD, 3 ; Enable high nop ; kurz warten nop nop cbi PORTD, 3 ; Enable wieder low ret ;----------------------------------------------------------------------- - ;----------------------------------------------------------------------- ------ lcdInit: sbi DDRD,2 ; LCD RS = OUT sbi DDRD,3 ; LCD E = OUT sbi DDRD,4 ; LCD D4 = OUT sbi DDRD,5 ; LCD D5 = OUT sbi DDRD,6 ; LCD D6 = OUT sbi DDRD,7 ; LCD D7 = OUT cbi PORTD,2 ; LDC RS = Low ; warte bis PowerUp ldi r18,20 powerUp: rcall lcdWait dec r18 brne powerUp ; Power-Up Wartezyklus min 30 ms ; sende Resetsequenz kompatibel zu HD44780 Industriestandard ldi r16,0b00110000 ; Reset-Sequenz Teil 1 out PORTD,r16 rcall lcdEnable ; Enable-Impuls rcall lcdWait ldi r16,0b00110000 ; Reset-Sequenz Teil 2 out PORTD,r16 rcall lcdEnable ; Enable-Impuls rcall lcdWait ldi r18,100 ; Wartezyklus bei RESET LCD min 100 µs resetLCD: nop nop nop dec r18 brne resetLCD ldi r16,0b00110000 ; Reset-Sequenz Teil 3 out PORTD,r16 rcall lcdEnable ; Enable-Impuls rcall lcdWait ; sende init 1 ldi r16, 0b00100000 ; 4 Bit Modus aktivieren out PORTD, r16 rcall lcdEnable ; Enable-Impuls rcall lcdWait ldi r16, 0b00101000 rcall lcdCmd ; Function Set 4 Bit, 2 Zeilen, 5x7 rcall lcdOff rcall lcdClear ldi r16, 0x06 rcall lcdCmd ; Entry Mode Set, increase+shifted rcall lcdOn ret ;----------------------------------------------------------------------- - ;----------------------------------------------------------------------- - ; Sendet einen mit 0x00 abgeschlossenen String von Flash an UART ; PE: Z=StartAdresse ;----------------------------------------------------------------------- - lcdString: push r16 push r30 push r31 lcdString1: lpm r16,Z+ cpi r16,0 breq lcdString2 rcall lcdData rjmp lcdString1 lcdString2: pop r31 pop r30 pop r16 ret ;----------------------------------------------------------------------- - ; wandelt ein Byte in die in die einzelnen Ziffern um (unsigned) ; PE: ; r16 binärwert (0...255) ; PA: FF 99 1 ; r1 Ergebnis (einer) 5 9 1 ; r2 Ergebnis (zehner) 5 9 0 ; r3 Ergebnis (hunderter) 2 0 0 ;----------------------------------------------------------------------- - lcdZahl: mov r1,r16 ; Zwischenspeicher und Einer-Stelle clr r3 clr r2 hundert: ldi r16,100 ; solange die 100 in die Restzahl (r1) passt cp r1,r16 brlo zehner sub r1,r16 ; 100 abziehen und inc r3 ; Hunderter-Stelle erhöhen rjmp hundert zehner: ldi r16,10 ; wie bei den Hundertern cp r1,r16 brlo einer sub r1,r16 inc r2 rjmp zehner einer: ; der_Rest_sind_die_Einer ldi r21,0x30 ; 30 hex für Zahl mov r16,r3 add r16,r21 ; hunderter + 30 hex rcall lcdData mov r16,r2 add r16,r21 ; zehner + 30 hex rcall lcdData mov r16,r1 add r16,r21 ; einer + 30 he rcall lcdData ret ;----------------------------------------------------------------------- -
Mir ist ja nicht ganz klar, wie der Timer benutzt werden soll (Meine Vermutung: In der Interruptroutine müssen die Zählregister für den Durchflußwert erhöht werden), aber ich würde trotzdem empfehlen, zuerst eine manuelle Ausgabe auf das LCD einzubauen, um zu sehen, ob es richtig initialisiert wird. Das ist immer ein kritischer Punkt beim HD44780, und noch mehr bei seinen diversen "kompatiblen" Nachbauten.
Wie meinst du das. Mit einen Taster hochzählen? Der Timer soll eigentlich die Impulse v. Mengenmesser zählen u. auf LCD anzeigen.Die LCD Ausgabe an sich funktioniert. Das habe mich mir de "Hallo" ausprobiert. Ich hab ehrlich gesagt so gut wie keine Ahnung v.d. Programmiererei. Bis jetzt hab ich nur eine Temperaturmessung mit Auswertung hingegreigt. Nun wollt ich eben noch den Verbrauch messen u. anzeigen. Find auch nirgens ein passendes Programm dazu.
Sehe ich das richtig, daß das Hauptprogramm nichts macht, außer den Watchdog zurücksetzen? Und dir Interrupr-Routine auch nicht? Also, ein Ansatz von mir, in der Hoffnung, daß ich richtig rate: Der Counter ist so konfiguriert, daß Impulse am externen Zähleingang ihn hochzählen. Habe ich jetzt aber nicht nach Datenblatt kontrolliert. Wenn ein bestimmter Wert erreicht wird, wird der Interrupt ausgelöst. Nach tausend Impulsen, wenn ich das richtig sehe. Nun aber muß in der Interruptroutine (ISR) "onTimer1Cmp" aber auch etwas passieren: Die niederwertigste Zählvariable muß erhöht werden, auf Überlauf geprüft und ggf. der Übertrag in die nächsthöhere Zählvariable für die Impulse ausgeführt. Dann muß eine Ausgabe auf dem Display erfolgen; dies macht man am Besten in der Hauptprogrammschleife (main loop), da zeitaufwendig. Schließlich muß der Zählerstand auch ausgegeben werden.
Bernd S. wrote: > Durchfluss-mengenmesser (2500/1Liter)der an PORTD3 angeschlossen ist.Das > Programm hab ich mit den CodeWizzard erstellt. Was fürn Wizzard? > Leider kommt auf d. LCD > nicht mal ne 1. Kein Wunder, Du initialisierst nirgends das LCD und gibst auch nichts aus. Es reicht nicht, Routinen irgendwo in den Flash zu knallen, man muß sie auch aufrufen. Das LCD verhält sich also völlig korrekt und das Programmm auch. Und nächstes Mal Quelltext als Anhang (*.asm). Peter
Zum Wizzard-der ist beim Programm "myworkpadplus" v. MyAVR drin. ____________________________________________________________________ lcdInit: sbi DDRD,2 ; LCD RS = OUT sbi DDRD,3 ; LCD E = OUT sbi DDRD,4 ; LCD D4 = OUT sbi DDRD,5 ; LCD D5 = OUT sbi DDRD,6 ; LCD D6 = OUT sbi DDRD,7 ; LCD D7 = OUT cbi PORTD,2 ; LDC RS = Low Ist das denn nicht d. Initialisierung fürs LCD? Es ist so. Ich hab mir das TWI-Projekt bei "MYAVR" gekauft (Hardware,Software usw). Der Beschreibung nach soll ja alles ganz einfach sein. Hab das Programm aus dem Lehrheft übernommen u. nach mehreren Startschwierigkeiten läuft das jetzt auch.Die Temp. wird in einstellbaren Abständen gemessen u. gespeichert. Ich lese dann die Daten aus und stell sie in einen Diagramm dar. Das ganze sollte zur Auswertung d. Heizung sein. Nun nützt mir das aber alles nichts, wenn ich den Ölverbrauch nicht messen kann. Deshalb habe ich einen Mengenmesser beschafft, d. den Verbrauch anzeigen soll. Nur so kann ich Änderungen, z.B. durch elektronische Thermostate erkennen und auswerten. Da ich wirklich keine Ahnung v. programmieren habe,hänge ich eben an der Mengenmessung. Hab nun überall nach einen Programm gesucht, bin aber nicht fündig geworden. Das Programm oben ist so ein kläglicher Vesuch. Ich habe auch nicht vor ein grosser Programmierer zu werden. Möchte eben nur dieses Projekt zu Ende bringen. Wenn mir jemand so ein Programm erstellen könnte, würde ich auch gern dafür bezahlen. Das ist keine Faulheit von mir, nur Ahnungslosigkeit.
Bernd S. wrote: Bernd S. wrote: > lcdInit: sbi DDRD,2 ; LCD RS = OUT ... > Ist das denn nicht d. Initialisierung fürs LCD? Schon, aber es wird nirgends aufgerufen, also ist es toter Code. Dein PC führt ja auch nicht einfach sämtliche Programme aus, die auf Deiner Festplatte stehen. > Hab > nun überall nach einen Programm gesucht, bin aber nicht fündig geworden. Programme sucht man nicht, man schreibt sie. > Ich habe auch nicht vor > ein grosser Programmierer zu werden. Möchte eben nur dieses Projekt zu > Ende bringen. Dann sag ich mal, Deine Chancen stehen schlecht. Etwas Hilfe gibt man gerne mal, aber ein Programm für nen Ahnungslosen komplett zu schreiben, das ist richtig harte Arbeit. D.h. sowas wird richtig teuer. Peter
> Ich habe auch nicht vor > ein grosser Programmierer zu werden. Möchte eben nur dieses Projekt zu > Ende bringen. Das Problem ist nicht ein grosser Programmierer zu werden. Das Problem, so wie ich das sehe ist, das dir so ziemlich alle Grundlagen fehlen. Ein Wizard ist nun mal kein Ersatz für fehlendes Wissen. Hast du einen C-Compiler für dein System? Damit könnten wir uns dann erst mal von ein paar Details lösen, die man in der Assemblerprogrammierung können muss. Und die laufende Wartung für dich würde auch einfacher werden. Frage an die Community: Diese Durchflussmesser, wie funktionieren die? Ich stell mir das so vor: da ist ein Schaufelrad drinnen und bei jeder Umdrehung wird ein mech. Kontakt geschlossen. Sprich: Mit Prellen ist zu rechnen.
> Diese Durchflussmesser, wie funktionieren die? > Ich stell mir das so vor: da ist ein Schaufelrad drinnen und bei jeder > Umdrehung wird ein mech. Kontakt geschlossen. Sprich: Mit Prellen ist zu > rechnen. Das ist typenabhängig. Es gibt auch optische Durchflußmesser mit integrierter Auswertelektronik, deren Signal ist im Allgemeinen prellfrei. Ein elektronikloser Durchflußmesser kann auch induktiv arbeiten und Spannungsimpulse liefern, wenn ein Magnet an einer Spule vorbeiläuft.
Habe mich jetzt nochmal mit den Zähler versucht. Bei jeden Tastendruck soll der Zähler 1 hochzählen und auf Lcd ausgeben. Leider kommt bei jeden Tastendruck eine andere Ausgabe: 001 00101 00111 00101 usw. Vielleicht hat einer mal Zeit und könnte den Code anschauen.
Bernd S. wrote: > Habe mich jetzt nochmal mit den Zähler versucht. Bei jeden Tastendruck > soll der Zähler 1 hochzählen und auf Lcd ausgeben. Leider kommt bei > jeden Tastendruck eine andere Ausgabe: Das würde ich erwarten, sonst wäre es ja kein Zähler. > 001 > 00101 > 00111 > 00101 usw. Sieht nach Zahlen im Dualsystem aus: http://de.wikipedia.org/wiki/Dualsystem Hast du die Zahlen richtig abgeschrieben, dann ist ein Problem im Programm. Wenn du allerdings nur irgendwelche 01 abgeschrieben hast, ist wahrscheinlich deine Frage erledigt.
Hab jetzt 3x "inc r16 " eingefügt. Da kommt in der Anzeige das gleiche nur mit der Zahl 3 003 0033 00303 00333 Da nehm ich mal an das es Dezimalzahlen sind.
3 Beobachtungen * da deine Ausgabe eigentlich nur 3 Stellen umfassen sollte, dürfte irgendwas mit deine LcdLine1 Funktion nicht stimmen * Wenn du keine weiteren Vorkehrungen triffst, ist ein externer Interrupt als Zähleingang für einen Taster denkbar ungeeignet. Tasten prellen: Du drückst einmal auf die Taste und die Taste generiert mehrere Pulse hintereinander. Ich hab jetzt nicht genau analysiert, wie du den Interrupt freischaltest. Aber nur als Denkanstoss: Was denkst du, wie schnell wird wohl deine Interrupt Routine abgearbeitet und wie schnell kannst du die Taste wieder loslassen? * Wenn du in der Interrupt Routine deinen 'Zähler' im R16 immer wieder auf 0 setzt, dann wird das mit dem Zählen wohl nicht so prickelnd funktionieren. Eigentlich sollte auf deinem Display ständig 001 stehen.
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.