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
> interrupt [10] void timer0 int0(void)
Fällt Dir gar nichts auf? Also entweder entscheiden: timer0 ODER int0
als Name für die ISR ODER timer0_int0 (macht aber vermutlich nicht
viel Sinn).
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.
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
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...
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
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
intzaehler=0;
mal ein
1
volatileintzaehler;
Das "= 0" kannste weglassen, da globale Variablen sowieso automatisch
mit 0 initialisiert werden.
> itoa(zaehler1, byte*);
Wie gesagt, schau Dir die Dokumentation an (v.a., welche Parameter itoa
und andere Funktionen erwarten). Außerdem ist byte ein in einer
Header-Datei definierter Datentyp, den Du nicht einfach als
Variablennamen verwenden kannst!
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
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.
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
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.
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
hi
so habs eben mal so probiert da schreibt er mir das ganze display mit
1er voll also die lcd ausgabe ist richtig. Liegt dann wohl irgendwo am
Timer oder Interrupt.
mfg
chris
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
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
Sicher, dass der Timer 0 Overflow Interrupt die Nummer 10 hat? Ich weiß
jetzt nicht auswendig, wie die Vektornummern beim CodeVision
implementiert sind... Hast Du es mal mit einer 9 versucht?
hi
laut meinen Ausdruck aus der Berufschule ist es 10. Aber wie schonv
orhin gesehen ist da net alles ganz richtig ;)
Werd das mal probieren danke
mfg
chris
> hab grad noch folgendes gefunden:>> interrupt [TIM0_OVF] void timer0(void)
das ist sicher schon mal besser, als da irgendwelche
Zahlenkonstanten im Programm zu haben, die je nach µc
anders sein müssen.
Wie sieht dein Programm jetzt aus?
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
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
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
hi
so jetzt nochmal das ganze wieso dauert das jetzt 6-7 sekunden (grob
geschätz) bis er 1 hochzählt? das ich aufs tausendsel genau eine Sekunde
so nicht hinbekomm ist mir klar aber 600-700% ist doch etwas viel ;)
mfg
chris
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.
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
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
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?
Hast du mal das hier ausprobiert?
http://palmavr.sourceforge.net/cgi-bin/fc.cgi
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
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
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
mfg
chris
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.
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
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