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.