Forum: Mikrocontroller und Digitale Elektronik sekundenzähler mit timer


von chris (Gast)


Angehängte Dateien:

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

von chris (Gast)


Angehängte Dateien:

Lesenswert?

sry falsche file angehängt diese stimmt nun ;)

von chris (Gast)


Lesenswert?

hi

hab ich es so arg verboggt das mir gar nicht mehr zu helfen ist?!

mfg

chris

von Johannes M. (johnny-m)


Lesenswert?

> 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).

von Johannes M. (johnny-m)


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.

von chris (Gast)


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

von Johannes M. (johnny-m)


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...

von chris (Gast)


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

von Johannes M. (johnny-m)


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.

von Johannes M. (johnny-m)


Lesenswert?

> 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!

von chris (Gast)


Angehängte Dateien:

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

von Johannes M. (johnny-m)


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.

von chris (Gast)


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

von Johannes M. (johnny-m)


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.

von chris (Gast)


Angehängte Dateien:

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

von chris (Gast)


Angehängte Dateien:

Lesenswert?

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

von JanH (Gast)


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

von chris (Gast)


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

von Johannes M. (johnny-m)


Lesenswert?

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?

von chris (Gast)


Lesenswert?

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

von chris (Gast)


Lesenswert?

hi

hab grad noch folgendes gefunden:

interrupt [TIM0_OVF] void timer0(void)

könnte das auch klappen? Werds mal eben probieren

mfg

chris

von chris (Gast)


Lesenswert?

hi

auch das klappt leider nicht obwohl ich das beim codevision so gefunden 
hab. Also liegts wohl irgendwie auch nicht am interrupt.

mfg

chris

von Karl H. (kbuchegg)


Lesenswert?

> 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?

von Christian D. (chris00)


Angehängte Dateien:

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

von Karl H. (kbuchegg)


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

von Karl H. (kbuchegg)


Lesenswert?

Probier doch mal Folgendes
1
  ...
2
3
  lcd_init (16); 
4
  define_char(char0,0);
5
6
  lcd_gotoxy (0,0);
7
  while (1)
8
  {
9
    lcd_gotoxy( 0, 0 );
10
    itoa( zaehler, n1 );
11
    lcd_puts( n1 );
12
  }
13
}


und bitte: formatier deinen Code anständiger!
So ist das sehr mühsam zu lesen.

von Christian D. (chris00)


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

von Christian D. (chris00)


Angehängte Dateien:

Lesenswert?

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

von Karl H. (kbuchegg)


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.

von Christian D. (chris00)


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

von Christian D. (chris00)


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

von Karl H. (kbuchegg)


Lesenswert?

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

von Christian D. (chris00)


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

von Karl H. (kbuchegg)


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

von Christian D. (chris00)


Lesenswert?

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

von Karl H. (kbuchegg)


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.

von Christian D. (chris00)


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

von Karl H. (kbuchegg)


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

von Christian D. (chris00)


Lesenswert?

hi

wie schon gesagt ;) es geht danke nochmals :)

mfg

chris

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
Noch kein Account? Hier anmelden.