Hallöchen..
Ich möchte an einem ATmega169 mit integriertem LCD-Controller eine
LCD-Segmentanzeige betreiben.
Die Anschlussbelegung der LCD-Anzeige an den Atmega-Ports ist durch eine
Kontaktfolie vorgegeben, so das ich diesbezüglich keine Änderung
vornehmen kann.
Aus diesem Grund belegt ein Digit (Ziffer) unterschiedliche
COM-Anschlüssen am ATmega (siehe Bild im Anhang). Das macht die
Ansteuerung per Software etwas kompliziert, da man für die Darstellung
einer Ziffer mehrere Ausgaberegister des ATmegas ansprechen muß.
Ich habe ein kleines C-Progrämmchen geschrieben und benutze für die
Ausgabe der einzelnen Ziffern jeweils eine Funktions-Routine (siehe
Code).
Das Programm zeigt abwechselnd die Ziffer "0" und die Ziffer "1" auf der
LCD-Segmentanzeige an.
Die Belegung der Port-Anschlüsse entspricht nicht denen in der
Abbildung.
Das C-Programm funktioniert eigentlich recht gut, aber ich möchte das
ganze doch etwas eleganter und profezioneller lösen. Ich denke da an ein
Array oder so was ähnliches. Aber leider habe ich diesbezüglich keine
Erfahrung und hoffe auf Euch und ein paar Tips für die Programmierung.
Gruß Rolf
Hallo Rolf,
Also wenn es wirklich nur eine 1 1/2 stellige Anzeige ist, würde ich das
genauso machen, wie du es jetzt hast. Du musst ja nur 11 Ziffern
darstellen (1.digit: aus/1; 2.digit: 0-9). Da machst du dir 11
Funktionen, wie du schon angefangen hast und eine Steuerfunktion:
Rolf Degen schrieb:> Ich denke da an ein> Array oder so was ähnliches. Aber leider habe ich diesbezüglich keine> Erfahrung und hoffe auf Euch und ein paar Tips für die Programmierung.
Arrays sind ja keine Hexerei.
Im Grunde geht es doch nur darum, dass du irgendwo her kriegen musst, ob
für ein bestimmte darzustellende Ziffer, das entsprechende Segment auf 0
oder auf 1 gesetzt werden muss.
Das kannst du dir zb Bitcodiert in einem uint8_t ablegen. Ein Array von
derartigen Werten beschreibt dann die notwendigen Kombinationen für alle
Ziffern.
Eine spezielle Funktion holt sich aus dem Array den entsprechenden Wert,
dröselt die Bits wieder auf und setzt die entsprechenden Registerwerte
dementsprechend.
Das ist der Plan. Fangen wir an.
Als erstes überlegen wir uns eine Zuordnung von Bits in einem uint8_t zu
den entsprechenden Segmenten. Die erfinden wir einfach. zb so
1
6
2
*******
3
* *
4
5 * * 0
5
* 4 *
6
*******
7
* *
8
3 * * 1
9
* *
10
*******
11
2
D.h. für eine darzustellende '1' müssen die Bits 0 und 1 auf 1 gesetzt
werden, für eine '2' sind es die Bits 6, 0, 4, 3, 2 etc.
1
uint8_tdigitCodes[10]=
2
{0b01101111,// '0'
3
0b00000011,// '1'
4
0b01011100,// '2'
5
0b00000000,// '3'
6
0b00000000,// '4'
7
0b00000000,// '5'
8
0b00000000,// '6'
9
0b00000000,// '7'
10
0b11111111,// '8'
11
0b00000000,// '9'
12
};
(die noch fehlenden musst du ergänzen)
Soweit so gut. Jetzt wissen wir, welche Elemente eingeschaltet und
welche ausgeschaltet werden müssen. Alles was noch fehlt, ist eine
Funktion, die sich für eine Ziffer das entsprechende Codebyte holt, die
einzelnen Bits rausholt und je nach Wert des Bits, das entsprechende
Digit ein oder aus schaltet
1
voiddigit0(uint8_tvalue)
2
{
3
uint8_tdigitCode;
4
5
if(value>9)// nur zur Sicherheit. Der Fall darf nie
6
value=0// auftreten
7
8
//
9
// hole das Bitmuster der Segmente für diese Ziffer
10
//
11
digitCode=digitCodes[value];
12
13
//
14
// die einzelnen Bits betrachten
15
// sind nur 8, daher erst mal wenig Aufwand
16
//
17
// um den Schreibaufwand gering zu halten, ein 'cleveres' Makro machen
18
//
19
20
#define TEST_DIGIT(digit_bit, port, port_bit ) \
21
if( digitCode & digit_bit ) \
22
port |= (1 << port_bit); \
23
else \
24
port &= ~(1 << port_bit);
25
26
TEST_DIGIT(0x01,LCDDR1,bit_0);// Bit 0
27
TEST_DIGIT(0x02,LCDDR1,bit_1);// Bit 1
28
TEST_DIGIT(0x04,LCDDR6,bit_0);// Bit 2
29
TEST_DIGIT(0x08,LCDDR6,bit_1);// Bit 3
30
TEST_DIGIT(0x10,LCDDR11,bit_0);// Bit 4
31
TEST_DIGIT(0x20,LCDDR11,bit_1);// Bit 5
32
TEST_DIGIT(0x40,LCDDR16,bit_0);// Bit 6
33
TEST_DIGIT(0x80,LCDDR16,bit_1);// Bit 7
34
35
#undef TEST_DIGIT
36
}
Und das wars dann auch schon. Ob die Zuordung und Umsetzung der
einzelnen 'Bits' laut obiger Zeichnung zu den µC Registern und Bits
stimmt, musst du kontrollieren.
Aber jetzt kannst du die Funktion mit einer Zahl von 0 bis 9 aufrufen,
und auf dem LCD müssten die richtigen Segmente dafür eingeschaltet
werden.
Danke für Eure Vorschläge. Werde es mal ausprobieren.
In der LCD-Segmentanzeige werden insgesammt 5 Digits dargestellt. Zwei
sind für die Uhrzeit und die anderen drei für die Temperaturanzeige.
Gruß Rolf
Dann macht der Weg von Karl heinz natürlich mehr Sinn. Du musst dann nur
die Ports und Pins den Segmenten der einzelnen Anzeigen zuweisen und
kannst alles bequem über eine Funktion steuern.