sekundenzähler mit timer

Gast #622305
Lesenswert?

hi

ich hab hier noch 2 Probleme:

1. Erro: C:\cvavr\code\1.c(56) declaration syntax error
das bezieht sicha uf folgende Zeile:
interrupt [10] void timer0 int0(void)
was hab ich hier vergessen?

2. Er meckert bei lcd_putsf(zaehler1); das der typ int incompatible mit 
flash unsigned char * ist. Wie kann ich denn int auf den LCD ausgeben? 
Ein fester Text geht ohne Probleme.

Hoffe ich habs nicht toal versaut ich hab vor etwa 2 Jahren das letzte 
mal mit Timer und interrupt gearbeitet und meine Unterlagen von damals 
sind leider nicht mehr ganz komplett.

Vielen dank für eure Hilfe schonmal im Vorraus

mfg

Chris
Angehängte Dateien:
#622972
Lesenswert?

Zu 2.: Schau Dir bitte mal die Dokumentation zu den Ausgabefunktionen 
an. puts gibt grundsätzlich einen Character-String aus. Und der 
übergebene Datentyp ist ein Zeiger auf das erste String-Element, also 
ein "char*". Die Bibliotheksfunktion lcd_putsf erwartet anscheinend aber 
einen im Flash befindlichen String, so dass es ein "flash char*" sein 
muss. Ein Integer ist aber weder das eine noch das andere. Der muss erst 
in einen Character-String umgewandelt werden. Das kann man entweder 
direkt mit einem Derivat von printf machen oder mit einer 
Konvertierungsfunktion, die aus dem Integer zunächst einen 
Character-String macht (z.B. itoa) und anschließend den String mit puts 
ausgeben.

Du scheinst allerdings generell Verständnisprobleme zu haben, u.a. was 
die Ausgabe auf einem Display angeht. Du solltest Dir klar werden, dass 
ein alphanumerisches Display grundsätzlich ASCII-Zeichen erwartet und 
dass man keine Zahlenwerte einfach so ausgeben kann. Wenn Du einen 
Integer-Wert von 12345 hast, dann muss dieser erst in die Zeichen '1', 
'2', '3', '4', '5' und '\0' (oder in Kurzschreibweise in den String 
"12345") umgewandelt werden. Der Nullterminator '\0' ist erforderlich, 
damit die Ausgabefunktion weiß, wo der String aufhört. Die Hochkommata 
'' zeigen, dass es sich bei dem eingeschlossenen Zeichen um einen 
einzelnen ASCII-Character (bzw. ein Steuerzeichen) handelt, während die 
doppelten Anführungszeichen "" einen ASCII-Character-String 
Kennzeichnen, der bereits den Nullterminator enthält.
Gast #622978
Lesenswert?

uiuiui

1. da hab ich ja mal gar net aufgepasst duck

2. war mir irgendwie klar aber ich weiss noch net so recht wie ich einen 
int zu nen char bekomme. Was für funktionen gibts da? Derivat sagt mir 
gar nix und eine Konvertierungsfunktion kenn ich (noch) nicht.

mfg

chris
#622985
Lesenswert?

chris wrote:
> uiuiui
>
> 1. da hab ich ja mal gar net aufgepasst *duck*
Ab in die Ecke!

> 2. war mir irgendwie klar aber ich weiss noch net so recht wie ich einen
> int zu nen char bekomme. Was für funktionen gibts da?
Hab ich doch geschrieben: itoa macht vermutlich ungefähr das, was Du 
haben willst.

> Derivat sagt mir gar nix
Ein Derivat einer Funktion ist lediglich eine Funktion, die von der 
Ausgangsfunktion abgeleitet ist, aber u.U. einen anderen Funktionsumfang 
hat. Die printf-Funktionen leiten sich z.B. genaugenommen alle von 
fprintf ab.

> und eine Konvertierungsfunktion kenn ich (noch) nicht.
Siehe oben... itoa und seine Verwandtschaft stehen übrigens in der 
stdlib.h.

Ach ja, das Lesen der Library-Dokumentation und auch eines vernünftigen 
C-Buches kann (und will) Dir hier wahrscheinlich keiner abnehmen...
Gast #622990
Lesenswert?

hi

habs jetzt mal so probiert:

itoa(zaehler1, byte*);
lcd_puts(byte);

aber so recht klappen will das net der sagt mir was von invalid 
expression? Der fehler sagt mir aber wiederrum gar nix :(

mfg

chris
#622993
Lesenswert?

Kleiner Zusatztipp noch, nachdem ich mir das Programm mal kurz 
angeschaut habe: Das ganze funktioniert möglicherweise nicht, weil die 
Zählvariable, die im Interrupt Handler und im Hauptprogramm verwendet 
wird, nicht volatile deklariert ist.

Mach aus dem
1
int zaehler = 0;
mal ein
1
volatile int zaehler;
Das "= 0" kannste weglassen, da globale Variablen sowieso automatisch 
mit 0 initialisiert werden.
Gast #623009
Lesenswert?

hi

danke das du net alles verraten hast hab zwar ziemlich geflucht beim 
suchen aber dennoch alles gefunden. Er compiliert alles aber ich hab 
grad meinen Programmer nicht zur hand wäre cool wenn du mal drüber 
gucken könntest ob das so klappen könnte. Werd in einer Stunde es dann 
selbst probieren können.

mfg

Chris
Angehängte Dateien:
#623011
Lesenswert?

1
SREG = 0x00;
2
//...
3
SREG = 0b10000000;
Um Himmels Willen, wo hast Du das denn her? Als 
Hochsprachen-Programmierer hast Du am SREG ÜBERHAUPT nix zu 
manipulieren! Einzige (indirekte) Ausnahme (die in Deinem Programm 
übrigens fehlt): Die globale Freigabe (und im Bedarfsfall auch Sperrung) 
der Interrupts im Programm mit (CVAVR-Syntax)
1
#asm("sei") //Interrupts global freigeben
2
#asm("cli") // Interrupts global sperren
Das Löschen des I-Bit im SREG beim Sprung in einen Interrupt-Handler 
(und auch das Setzen beim Sprung zurück ins Hauptprogramm) macht die 
Controller-Hardware selber. Das ist quasi im AVR eingebaut, dass ein 
Interrupt-Handler im Prinzip nicht durch einen anderen Interrupt 
unterbrechbar ist.

EDIT:
Der Rest sieht eigentlich nicht schlecht aus (kann jetzt bis auf das 
fehlende #asm("sei") im Hauptprogramm) keine groben Fehler mehr 
entdecken.
Gast #623049
Lesenswert?

hi

also habs jetzt mal so geändert das mit der Interrupt im Interrupt 
deaktivieren hab ich aber 100%ig sicher anders gelernt auf dem selben 
Controller aber ich glaub dir mal mehr ;)

Leider funktioniert das Programm immer noch nicht. Er macht das Display 
leer und das wars dann.

mfg

Chris
#623062
Lesenswert?

chris wrote:
> hi
>
> also habs jetzt mal so geändert das mit der Interrupt im Interrupt
> deaktivieren hab ich aber 100%ig sicher anders gelernt auf dem selben
> Controller
Wo bzw. bei wem hast Du das gelernt? Würd mich echt interessieren, wo 
man so einen Quatsch beigebracht bekommt.


> aber ich glaub dir mal mehr ;)
Oh, danke...

> Leider funktioniert das Programm immer noch nicht. Er macht das Display
> leer und das wars dann.
Das sieht nach falscher Initialisierung aus. Der Aufruf
1
lcd_init (16);
kommt mir ziemlich spanisch vor. was für ein LCD ist das denn? Ich hab 
jetzt kein CodeVision hier, um nachzusehen. Mit den Funktionen aus der 
lcd.h hab ich nie gearbeitet.
Gast #623068
Lesenswert?

hi

den Quatsch hab ich (und jetzt nicht lachen) in der Berufschule gelernt.

lcd_init(16); stimmt auf jeden fall es ist ein 2x16 Zeichen Display und 
zwar dieses:

http://www.reichelt.de/?SID=25@hH6cyX8AAAIAAHVGhn486eb9528efb83aef6a4dd6c533529ea;ACTION=3;LA=4;GROUP=A5212;GROUPID=3006;ARTICLE=53941;START=0;SORT=artnr;OFFSET=16

wenn ich mit lcd_putchar(char c) ein zeichen ausgebe klappt das auch 
deswegen geh ich davon aus das die Initialisierung richtig ist.

hab dir mal die lcd hilfe von codevision angehängt. Aber wie gesagt 
meiner Meihnung nach ist das alles richtig.

Werd jetzt mal eben zaehler1 einen festen Wert zuweisen und gucken ob er 
den ausgibt.

mfg

chris
Angehängte Dateien:
Gast #623098
Lesenswert?

Hallo,

das dein ganzes Display vollgeschrieben wird ligt wohl daran das du das 
lcd_gotoxy (0,0); nur einmal vor der while(1) Schleife hast, setz es 
direkt vor die Ausgabe, dann wird nur die Stelle aktualisiert.

JanH
Gast #623103
Lesenswert?

hi

ja is klar das klappt dann auch und er zeigt dann auch die 1 1x an.

Die Frage bleibt aber immer noch warum gehen die Interrupt und Timer 
net? Ich vemrut das ich irgendwo ein Register vergessen hab wüsste aber 
nicht welches.

mfg

Chris
#623283
Lesenswert?

hi

nicht wundern bins immer noch der chris nur endlich mal angemeldet ;)

mein programm hab ich mal wieder angehängt.

Viel geändert hat sich eigentlich nicht weil ich eben nicht weiss woran 
es noch liegen kann. Ich geh irgendwie immer noch davon aus das ich 
vergessen hab ein Register irgendwo zu setzten vllt. kann das mal wer 
checken und mir sicher sagen das ich KEINS vergessen hab sonst les ich 
noch 10x alle Blätter die ich hier rumliegen hab und such nach welchen 
die es gar nicht gibt g

mfg

chris
Angehängte Dateien:
#623296
Lesenswert?

Sag mal:
Wie lange hast du eigentlich gewartet, bis du festgestellt
hast, das das nicht geht.

Wenn die 8Mhz stimmen, dann dauert es immerhin etwas
mehr als 4 Minuten, bis die Anzeige kommt.


8000000 / 256 = 31250 Hz       // wegen Vorteiler
31250 / 256 = 122 Hz           // weil der Timer jedesmal bis 256
                               // zählen muss, bis zum Overflow
122 / 31250 = 0.0039Hz         // weil du bestimmt hast, das 31250
                               // Overflows passieren muessen

 1 / 0.0039 = 256 Sekunden = ~ 4.2 Minuten
#623304
Lesenswert?

hi

öhhhh da hab ich mich irgendwo gewaltig verrechnet. man o man ich hab 
immer nur ein paar sekunden gewartet g

werd das ganze jetzt nochmal durchrechnen danke für den tipp

formatieren tu ich ihn dann wenn ich net dauernd was drin ändern muss so 
hats eh keinen sinn vorallem noch bei so kurzen codes

mfg

chris

edit: so jetzt klappts hab bei if 122 verwendet um einen ca. 
sekundentakt hinzubekommen. Es ist aber im moment ein ca. 6 
Sekundentakt. Vermute mal da stimmt was mit dem Takt noch nicht muss da 
mal gucken
#623326
Lesenswert?

Ich schätze mal, dass dein Mega nicht mit 8Mhz sondern
mit 1 Mhz läuft.

Wie komme ich auf 1 Mhz?
Alle Mega (soweit ich weiss), werden mit aktiviertem
internem Taktgenerator ausgeliefert und der läuft nun
mal mit ca. 1 Mhz.
Damit ein angeschlossener Quarz auch benutzt wird, muss
an den Fusebits gedreht werden.
#623337
Lesenswert?

hi

so einen gedanken hatte ich auch aber ich weiss grad nicht wie ich an 
die fusebits ran komm? ich hab einen sp12 programmer.

myavr workbench SE hab ich nur die demo der unterstützt den mega8535 
nicht. Codevision unterstützt sp12 nicht. Mit welchen Programm komm ich 
sonst an die Fusebits? und mit avrdude womit ich die programme immer 
hochschieb komm ich mit den fusebits nicht klar.

mfg

chris
#624970
Lesenswert?

hi

also das mit den fusebits hat jetzt geklappt mit avrdude (glaub ich 
zumindest wenn ich die Ausgabe richtig interpretier):

C:\Dokumente und Einstellungen\Administrator>avrdude -p m8535 -c sp12 -P 
lpt1 lfuse:w:0x60:m

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 
0.00s

avrdude: Device signature = 0x1e9308

avrdude: safemode: Fuses OK

avrdude done.  Thank you.


C:\Dokumente und Einstellungen\Administrator>avrdude -p m8535 -c sp12 -P 
lpt1 hfuse:w:0xd9:m

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 
0.00s

avrdude: Device signature = 0x1e9308

avrdude: safemode: Fuses OK

avrdude done.  Thank you.


leider dauert es immer noch ~8sekunden bis er 1 hochzählt.

wer hat noch nen tipp?

mfg

chris
#624984
Lesenswert?

hi

genau damit bin ich auf 0x60 gekommen ;) hab aber eben gemerkt das 0x4e 
evtl. besser wäre aber auch das geht leider nicht weiterhin ~8sekunden

hab grad mal das programm umgestrikt

#define xtal 1000000

und selbst so braucht er noch ~8sekunden

langsam verzweifel ich daran ich kann machen was ich will es ändert sich 
einfach nix :(

mfg

chris

edit: selbst c4 geht nicht auch ~8sekunden
#624985
Lesenswert?

Karl heinz Buchegger wrote:
> Christian Dresel wrote:
>> hi
>>
>> also das mit den fusebits hat jetzt geklappt mit avrdude (glaub ich
>> zumindest wenn ich die Ausgabe richtig interpretier):
>>
>> C:\Dokumente und Einstellungen\Administrator>avrdude -p m8535 -c sp12 -P
>> lpt1 lfuse:w:0x60:m
>>
>
> Hmm. Wo hast du die 0x60 her?
>

OK. Könnte für einen Quarzoszillator stimmen.
Für einen Quarz ist das aber falsch
#624988
Lesenswert?

Christian Dresel wrote:
> hi
>
> genau damit bin ich auf 0x60 gekommen ;) hab aber eben gemerkt das 0x4e
> evtl. besser wäre aber auch das geht leider nicht weiterhin ~8sekunden
>
> hab grad mal das programm umgestrikt
>
> #define xtal 1000000
>
> und selbst so braucht er noch ~8sekunden

Das ist logisch, XTAL kommt in deiner Timer Geschichte
nirgends vor.

Ich denke immer noch, dass das Teil nicht mit 8Mhz fährt.
Rein beim Durchschauen durch den Code ist mir da nämlich
nichts mehr aufgefallen.

Gehn wirs nochmal durch:
Frequenz   8Mhz
Vorteiler  256
Timer 0, also 8 Bit Timer
Nach 122 Interrupts wird erhöht


8000000 / 256   Vorteiler          31250
31250 / 256     weil 8 Bit Timer     122, paar zerquetschte
122 / 122       weil 122 Overflows     1

d.h. der if Teil wird mit einer Frequenz von 1 Hz betreten.
1 / 1 Hz macht daher Intervalle von 1 Sekunde.

Die einzige Möglichkeit wo hier noch was nicht stimmen kann,
ist bei der Ausgangszahl 8000000.
#624994
Lesenswert?

hi

ok hab beim programmieren was ganz wichtiges vergessen:

avrdude -p m8535 -c sp12 -P lpt1 lfuse:w:0xce:m

ist halt nicht gleich

avrdude -p m8535 -c sp12 -P lpt1 -U  lfuse:w:0xce:m

schon doof wenn man einen parameter vergisst ;) jetzt klappt es auf 
jeden fall :) vielen vielen dank für deine lange geduld mit mir g

mfg

chris
#624996
Lesenswert?

Christian Dresel wrote:
> hi
>
> ok aber wenn auch 0x4e und 0xc4 nicht geht was muss ich denn dann
> nehmen?
>
> mehr fällt mir atm. nicht ein
>
> ich geh ja fast davon aus das er die fusebits aus welchen grund auch
> immer gar nicht geschrieben hat. Leider hab ich keine Möglichkeit
> gefunden sie auszulesen

hast du auf deinem Board eine LED?

Wenn ja dann benutze die mit einer ganz einfachen Zählschleife
mal um die Taktfrequenz zumindest grob zu ermitteln.

Eine Schleife

tst1:
   inc r20
   brne tst1

braucht 2 Takte pro Durchlauf. Wird r20 also einmal von 0 bis wieder
0 gezählt, dann sind das 256 * 2 = 512 Takte (das Ziel sind
8 Millionen Takte)

diese innere Schleife muss also 8000000 / 256 = 31250 mal aufgerufen
werden: 31250 passt nicht in 1 Register, also noch eine Schleife
drüber

tst2:
tst1:
    inc r20
    brne tst1

    inc r21
    brne tst2

die innere Schleife braucht für einen Durchmarsch durch r20
512 Takte. Die Aussere Schleife (über r21) braucht daher für
eine Schleifenwiederholung  512 + 2 = 514 Takte. Bei 256
Wiederholungen (einmal r21 von 0 bis wieder 0) daher:
514 * 256 = 131584 Takte

8000000 / 131584 = 60

Du brauchst also nochmal eine Schleife drüber, die diesen 'Kern'
60 mal widerholt:


   ldi  r22, 60
loop1:
   inc r20
   brne loop1
   inc r21
   brne loop1

   dec r22
   brne loop1


davor eine Led einschalten und dahinter die Led wieder ausschalten.
Das sollte dann ca. 1 Sekunde dauern. Wenn nicht, dann läuft der
Mega mit Sicherheit nicht mit 8 Mhz

Könnte wer anderer mal meine Berechnungen durchschauen?

>
> mfg
>
> chris

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren