Forum: Compiler & IDEs 6 x 7-Segment 2 x Schieberegister mit SPI Atmega 8 GCC


von Emil (Gast)


Lesenswert?

Hi Leute,

habe folgendes (mit 6 statt 5 Spalten, LEDs als 7 Segment 
Anzeigen)gebaut:
http://www.mikrocontroller.net/articles/Datei:LED_Matrix_8x5.png


und versucht mit Peter Danneggers Code:

Beitrag "DCF77 Uhr in C mit ATtiny26"

eine 6 x 7 Segment Anzeige zu realisieren (also ohne uhr und mit Atmega 
88 f den Tiny).

Diese soll 3 zweistellige Variablen  [3 x (00 - 99)] ausgeben können.
Leider schaffe ich es nicht den Code entsprechend anzupassen, da ich 
gerade erst angefangen habe in C zu programmieren. Ein paar kleine 
Programme wie ADC auf UART und blinkende LED gehen schon (dank des 
tollen µC Forums und der Tutorials), aber hier komme ich nicht weiter. 
Ich verwende einen Atmega88. kann mir bitte jemand sagen wie man sowas 
in c macht?

Gruß

Emil

von Joachim .. (joachim_01)


Lesenswert?

Hm... ist in Peters Code denn überhaupt der Hardware-Teil drin der die 
Matrix treibt? Ich hab (auf die Schnelle) nix gefunden.

Im Grunde brauchst du seinen Code auch gar nicht; auch kann das anpassen 
des Codes der Uhr kann für einne Anfänger schon ein ziemliches Labyrinth 
werden.

Wie immer - brich das Problem in Teile herunter.
So war meine Vorgehensweise mit den '595'ern:
Schritt1: Mach dich mal mit dem Bit-Geschubse vertraut das notwendig ist 
um ein Bitmuster auf dem '595 zu erzeugen; am besten mit entsprechenden 
Vorwiderständen für statische Anzeige damit sie nicht durchbrennen.
Das Datenblatt des '595 hilft dir beim Bitschubsvorgang.

Schritt2: Wenn deine LED-Reihe funktioniert (bzw. 1x 7-Segment, 
statischer Betrieb) dann kannste mal das ganze mit dem zweiten '595 
zeitlich kombinieren und dann allmählich die Taktfrequenz hochnehmen. 
Ein Aha-Effekt wird eintreten.

Schritt3: Nu wird's ernst: Steuer das ganze im Interrupt alle 1/n sek 
an. Widerstände niederohmig machen damit's vernünftig hell wird. Das 
schwierige dabei: Der Takt darf nie anhalten, sonst brennen die Segmente 
durch. Dein Code muß also wirklich schußsicher sein, insbesondere wenn 
noch ne Tastaturabrage o.ä. mit dranhängt...

von Emil (Gast)


Lesenswert?

Hi,

es scheitert schon am Bit Geschubse. Gibts da ein geeignetes Tutorial 
für gcc, so wie beim ADC Tutorial? Hier: 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe#Nutzung_des_ADC
konnte ich reinschauen und alles erklärt sich von allein. F. 
Schieberegister findet man da zwar das Assembler Beispiel: 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe#Nutzung_des_ADC
Aber jetzt mach ich erstmal C.
Kennt ihr eine gute Seite oder habt ihr ein einfaches Beispiel parat?

Gruß

Emil

von Lötlackl *. (pappnase) Benutzerseite


Lesenswert?

Emil schrieb:
> es scheitert schon am Bit Geschubse. Gibts da ein geeignetes Tutorial
> für gcc, so wie beim ADC Tutorial?

Dann dürfte Das hier 
http://www.mikrocontroller.net/articles/Porterweiterungen#Software was 
für Dich sein.

mfg

von emil (Gast)


Lesenswert?

Hi,

vielen Dank **Lötlackl. das Bit - geschubse funktioniert, das Blinkwerk 
blinkt.

Ich habe ja vor meine 7 Segment Anzeigen so anzusteuern:


wert1%2d = 00-99;
wert2%2d = 00-99;
wert3%2d = 00-99;

das dann irgendwie umwandeln in die 16 Bit meiner 2 595er
1
uint8_t Led = 0b00111111; //alle 6 Bausteine an
2
uint8_t Segmente = 0b11111111; // alle 8 Segmente (incl Punkt) an
3
unit16_t Bitwurscht = (LED <<8) | Segmente;

und das muss ich dann noch irgendwie so verwurschteln, dass immer nur 
ein Baustein und seine 1-8 Segmente an sind und dann ein anderer, so 
dass für das auge der Eindruck entsteht, es wär eine statische Anzeige. 
So klar es in der Theorie ist, so unklar und dementsprechend schwer 
fällt mir die Umsetzung in C.
Ich schaffe es schon nicht eine beliebige 8bit breite Bitmaske rüber zu 
schieben, also meine
1
Bitwurscht
.
Da ich, wie erwähnt gerade anfange und nun schon ganz viele tolle Dinge 
mit Sensoren (analog, digital) und deren Messwertverarbeitung und 
Ausgabe mit meinem neuen Spielzeug Atemga8 gemacht habe, dachte ich kann 
es ja nicht so schwer sein ein paar LEDs geordnet blinken zu lassen... 
denkste!
Ich komm nicht weiter und die lust verlässt mich so langsam, hat von 
euch schonmal jemand sowas gemacht und kann mir weiter helfen?

Gruß

Emil

von Karl H. (kbuchegg)


Lesenswert?

emil schrieb:


> Ich schaffe es schon nicht eine beliebige 8bit breite Bitmaske rüber zu
> schieben, also meine
1
Bitwurscht
.

Dann musst du da eben damit anfangen.

Du brauchst eine Funktion, der du einen uint16_t übergibst und die die 
16 Bit eines nach dem anderen raustaktet.

Warum willst du eigentlich die beiden Bytes erst mal zu einem 16 Bit 
Wert zusammensetzen nur um sie dann in dieser Funktion wieder 
auseinander zu dröseln? Übergib halt die beiden Teile getrennt an die 
Funktion oder mach dir eine Funktion der du die beiden 8 Bit Einheiten 
nacheinander geben kannst, dann braucht sich die Funktion auch nicht die 
Finger dabei brechen um das wieder in leicht verdauliche 8 Bit Einheiten 
zu zerlegen :-)


Alles was du brauchst ist eine Schleife, die die 8 Bit eines nach dem 
anderen an den Ausgabeport legt. D.h eigentlich: die am Ausgabeport den 
Pin auf 0 oder auf 1 setzt, je nachdem ob das Bit welches gerade drann 
ist 0 oder 1 ist. Und dazwischen wird mit der Clock Leitung einmal 
gewackelt. Ein Bit fragt man ab, indem man die Bitposition mit einer 
Maske 'freimaskiert' und sich ansieht, ob das Ergebnis 0 oder nicht 0 
ist. Genau wie man es beim Abfragen von Tastern auch macht. Dort fragst 
du ab, ob ein Bit im PINx Register 0 oder 1 ist und hier ist es halt 
anstelle eines PINx Registers eine 8 Bit Variable. Aber der Vorgang ist 
genau der Gleiche bis auf den Umstand, dass man die Sache mit der Maske 
ein wenig intelligenter macht:
1
void Send( uint8_t value )
2
{
3
  uint8_t Maske = 0x01;
4
  uint8_t i;
5
6
   Maske = 0x01;
7
   for( i = 0; i < 8; i++ )
8
   {
9
     if( value & Maske )
10
       Setze Ausgabepin auf 1
11
     else
12
       Setze Ausgabepin auf 0
13
14
     Clock Pin auf 1
15
     Clock Pin auf 0
16
17
     Maske = Maske << 1;
18
  }
19
}

Und schon hast du eine Funktion, die einen 8 Bit Wert an das 
Schieberegister rausgibt. Um 16 Bit ruaszugeben rufst du die halt 2 mal 
auf. Denn 2 mal 8 Bit sind auch 16 Bit
1
   Send( LED );
2
   Send( Segment );

Und damit das 595 dann die reingetakteten Daten auch auf den Ausgang 
legt, musst du noch, nachdem die Daten reingetaktet sind, einmalig mit 
dem RCLK Ausgang wackeln. Das bringt den 595 dazu, die Daten dann auch 
auf die Ausgänge zu schalten.
1
   Send( LED );
2
   Send( Segment );
3
4
   Setze RCLK auf 1
5
   Setze RCLK auf 0

und das wars.
Die 16 Bit sind in die, hoffentlich kaskadierten, Schieberegister 
geladen und die SR wurden angewiesen ihre Ausgänge entsprechend der 
Daten durchzuschalten.
WEnn jetzt in LED bzw. Segment noch das richtige drinnen steht, kannst 
du gezielt jedes einzelne Segment ein/ausschalten, indem du jeweils 
wieder eine komplett neue Belegung in die SR lädst.

von Karl H. (kbuchegg)


Lesenswert?

> Schieberegister findet man da zwar das Assembler Beispiel:
> http://www.mikrocontroller.net/articles/AVR-GCC-Tu...
> Aber jetzt mach ich erstmal C.

Ist schon klar, dass du C machst. Aber das Prinzip, in welcher 
Reihenfolge was gemacht werden muss, ist ja in C auch nicht anders als 
in Assembler.
Das 595 funktioniert ja deswegen auch nicht anders.

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.