Forum: Mikrocontroller und Digitale Elektronik Bitfolgen generieren


von Stefan Ruff (Gast)


Angehängte Dateien:

Lesenswert?

Schoenen guten Tag

Ich bin noch ziemlich neu in der Mikrocontroller Programmierung,
beschaeftige mich aber in letzter Zeit relativ intensiv damit. Ich habe
nun versucht ein C-File zu schreiben mit dem ich ueber einen 8 Bit
Timer und Output Compare Interrupt eine bestimmte Bitfolge zu
generieren(nicht togglen) was leider nicht funktioniert.
Beim compilieren bekomme ich auch keinerlei Fehlermeldungen oder
Warnungen und ich habe schon ueber den OC2 getestet(ueber Oszi) ob der
Timer funktioniert, und er funktioniert.
Der Fehler muss also wo anders liegen aber ich komm beim besten Willen
nicht drauf.
Falls also jemand Lust und Zeit hat mal drueber zu schauen, waere ich
sehr dankbar.

Danke
MfG Stefan

PS: -ich benutze einen Atmega 128
    -File im Anhang

von Jörg Wunsch (Gast)


Lesenswert?

Hmm, ein bißchen wirr sieht mir der Code aus.

Ich gehe mal der Reihe nach durch:

> #include <stdio.h>

Wird gar nicht benötigt.

> #include <io.h>

Bitte #include <avr/io.h> schreiben.

>  sbi(PORTB,PINB2);

sbi() sollte in neuem Code nicht mehr benutzt werden.  Ein Standard-C
Konstrukt ist:

  PORTB |= (1 << PORTB2);

AVR-GCC bietet für die Bitschieberei noch _BV():

  PORTB |= _BV(PORTB2);

PINB2 sollte dem PINB-Register vorbehalten bleiben (Bit-Eingabe),
entweder PORTB2 oder einfach nur 2 schreiben, sonst verwirrt das eher.

>  if (counter == 0x00)
>  {
>    output_index = 0;
>  }

Hmm, danach wird der `counter' trotzdem weiter fleißig runtergezählt,
sprich, er geht in den negativen Bereich.  Ich vermute, daß das nicht
Deinen Intentionen entspricht und das hier der eigentliche Bug ist.
Wahrscheinlich müßtest Du den wieder bei 7 anfangen lassen.

>  outb(TCCR2, 0x1D);      // toggle oc2, ctc mode, prescaler auf
1/...,

Davon abgesehen, daß outb() auch nicht mehr benutzt werden sollte, das
Ganze wird mit

   TCCR2 = _BV(COM20) | _BV(WGM21) | _BV(CS22) | _BV(CS20);

ein Stück verständlicher.  Prescaler 1/1024.

>  OCR2   = 150;

Besser den Präprozessor rechnen lassen.  Mal in der Annahme von 1 MHz
Takt (interner RC-Oszillator):

#define FOSC 1000000L
#define PRESCALE2 1024

#define OCR2VAL 154 /* milliseconds */
   OCR2 = OCR2VAL * (FOSC / PRESCALE2) / 1000;

>  init_timer();
>
>   while (counter != 0)
>   {}

Hmm, init_timer() hat counter soeben auf 0 gesetzt, warum sollte die
Warteschleife also einen Wert != 0 vorfinden?

>   Bits[0]=0x00;
...
>   Bits[6]=0x00;

Davon abgesehen, daß ein Byte pro Bit ziemliche Platzverschwendung
ist, sollte diese Initialisierung nicht schon vor dem Start des Timers
erfolgen?

Eine Möglichkeit wäre eine echte Initialisierung bei der Definition
der
Variablen:

Bits[] = {0, 0xff, 0, 0xff, 0, 0xff, 0, 0xff, 0};

#define NBITS (sizeof(Bits) / sizeof(Bits[0]))

Dann benutzt Du statt der magischen 7 immer NBITS und hast auf diese
Weise eine Konstante, die sich automatisch selbst an die Größe des
Arrays Bits[] anpaßt.

>    return(0);

Hier fällst Du aus main() heraus und hoffst, daß die eingebaute
Funktion exit() in der Tat eine Endlosschleife mit gestatteten
Interrupts ausführt.  Das ist kein guter Stil, schreibe lieber die
Endlosschleife explizit selbst hin:

   /* Die Interrupts machen den Rest. */
   for (;;)
     ;

von Stefan Ruff (Gast)


Lesenswert?

Danke Joerg

Werd mich jetzt mal mit den ganzen Vorschlaegen auseinandersetzen.
Vielen Dank schon mal.

Mfg Stefan

von Jens (Gast)


Lesenswert?

Da ich an dem Code 'mitschuldig' bin, war ein schneller Hack
zwischendurch und sollte nur einige Dinge aufzeigen, will ich
mal auch etwas zur Aufloesung beitragen.
Damit der Compiler ueberhaupt einen Interruptvektor erzeugt:

#include <avr/signal.h>

einfuegen. Zumindest sehe ich dann im AVR-Studio einen belegten
Interruptvektor, ohne das Include sind alle ausser dem Resetvektor
leer.

Nochmal ein Dank an Joerg aus DD.

Jens

von Thomas K (Gast)


Lesenswert?

@Jörg Wunsch:
Wo steht denn, dass man sbi usw. nicht mehr verwenden sollte?
Und wieso outb? dachte es heißt outp?

von OldBug (Gast)


Lesenswert?


von Jörg Wunsch (Gast)


Lesenswert?

Ich fürchte, es steht noch nirgends geschrieben. ;-)

outb() und outp() sind mittlerweile identisch und beide gleichermaßen
,,nicht für Neuentwicklungen''.  Die von Atmel bevorzugt propagierte
Schreibweise ist die direkte Zuweisung, also

REGISTER = Wert;

avr-gcc/avr-libc konnten dies anfangs nicht, aus dieser Zeit stammen
all die outb/outp/inb/inp Makros.  Auch die sbi/cbi Makros stammen aus
dieser Zeit.  Letztere werden vor allem deshalb nicht mehr empfohlen,
weil sie dem Benutzer suggerieren, daß sie automatisch die
entsprechenden Assemblerbefehle generieren würden.  Das tun sie aber
gar nicht, sondern sie sind vielmehr definiert als

#define sbi(x, y) x |= (1 << (y))

etc.  Bei entsprechend passenden Operanden und eingeschalteter
Optimierung können sie in der Tat in SBI/CBI-Befehle optimiert
werden, aber der Benutzer sollte sich halt über die Randbedingungen im
Klaren sein.  Daher denken wir, daß das explizite Aufschreiben des
entsprechenden C-Codes diesen Denkvorgang eher anstößt als das blinde
Eintippen von sbi() oder cbi().

Das mit dem <avr/signal.h> hatte ich natürlich übersehen.  Allerdings
spuckt der Compiler eigentlich laut und deutlich Warnungen aus, wenn
man das vergißt...

von Jens (Gast)


Lesenswert?

@Joerg:
<avr/signal.h> war ja eingebunden, aber trotzdem hab ich im
AVR-Studio nur leere Interruptvektoren gesehen. Ich such grad
etwas rum und finde die Definition von PORTB2 nicht.? Vielleicht
noch als Hinweis, im Moment wird das Ganze zwar auf einem ATMega128
entwickelt, soll aber spaeter auch auf einem ATMega103 laufen.

Jens

von Thomas K (Gast)


Lesenswert?

aha. danke an euch beide für die aufklärung.
letztes semester war outp und sbi noch gang und gebe auf der uni.
mal schaun ob das dieses semester noch immer so ist. :)

von Jörg Wunsch (Gast)


Lesenswert?

> Ich such grad etwas rum und finde die Definition von PORTB2 nicht.?

$ grep PORTB2 /usr/local/avr/include/avr/*
/usr/local/avr/include/avr/portpins.h:#  define PORTB2 PB2

> ...im Moment wird das Ganze zwar auf einem ATMega128 entwickelt,
> soll aber spaeter auch auf einem ATMega103 laufen.

Dann nimm doch gleich den 128 im M103C-Modus (ist ja der
Auslieferungszustand).

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.