MSP430F55 LCD Ansteuerung

OP #4392415
Lesenswert?

Hallo, kann mir jemand sagen, wo mein Fehler steckt?
Möchte gerne ein LCD mit einem MSP430 ansteuern.

Die Pin Konfiguration lautet:


E = P8.2
RS = P3.7
R/W = GND
D4 = P1.3
D5 = P1.2
D6 = P4.3
D7 = P4.0
1
#include <msp430x552x.h>
2
#include <stdio.h>
3

4
void LCD_init(void);
5
void DelayMs(int Ms);
6
void LCD_cmd4(unsigned char cmd);
7
void LCD_dat4(unsigned char byte);
8

9
unsigned char i;
10
const unsigned char Msg1[] = "LCD Test";
11
const unsigned char Msg2[] = "MSP430";
12

13
void main()
14
{
15
 WDTCTL = WDTPW + WDTHOLD;  // Stop watchdog timer
16
 P1DIR = 0x0C;                             // Set D4 und D5 as Outout
17
 P3DIR = 0x80;                             // Set RS
18
 P4DIR = 0x06;                             // Set D6 und D7 as Output
19
 P8DIR = 0x04;                             // Set EN
20
 DelayMs(500);                             // Delay
21
 LCD_init();                               // LCD Init
22
 DelayMs(500);                             // Delay
23

24
 while(1)
25
  {
26
   LCD_cmd4(0x80);
27
   for(i=0;i<16;i++)
28

29
   {
30
    LCD_dat4(Msg1[i]);
31
    DelayMs(5);
32
   }
33

34
   LCD_cmd4(0xc0);
35
   for(i=0;i<16;i++)
36

37
    {
38
     LCD_dat4(Msg2[i]);
39
     DelayMs(5);
40
    }
41
  }
42
}
43

44
void LCD_init(void)
45
 {
46

47
  LCD_cmd4(0x28);              // 28 for four Bit mode
48
  DelayMs(500);                // Delay
49
  LCD_cmd4(0x0C);              // Turns the Display on
50
  DelayMs(500);                // Delay
51
  LCD_cmd4(0x1C);              // Cursor move to right
52
  DelayMs(500);                // Delay
53
  LCD_cmd4(0x01);              // Clear the Display
54
  DelayMs(500);                // Delay
55
 }
56

57
void LCD_cmd4(unsigned char cmd)
58
 {
59
  P3OUT = 0x00;                  // RS=0
60
  P1OUT = cmd;                   // Display Output D4,D5 = CMD set
61
  P4OUT = cmd;                   // Display Output D6,D7 = CMD set
62
  P8OUT = 0x04;                  // En = 1;
63
  P8OUT = 0x00;                  // En = 0;
64
  cmd = (cmd<<4) & 0xF0;         //?????????
65
  P1OUT = cmd;                   // Display Output D4,D5 = CMD set
66
  P4OUT = cmd;                   // Display Output D6,D7 = CMD set
67
  P8OUT = 0x80;                  // En = 1;
68
  P8OUT = 0x00;                  // En = 0;
69
  DelayMs(5);                    // Delay
70
 }
71

72
void LCD_dat4(unsigned char byte)
73
 { 
74
   P3OUT = 0x80;                 // RS=0
75
   P1OUT = byte;                 // Display Output D4,D5 = Byte set
76
   P4OUT = byte;                 // Display Output D6,D7 = Byte set
77
   P8OUT = 0x04;                 // En = 1;
78
   P8OUT = 0x00;                 // En = 0;
79
   byte = (byte<<4) & 0xF0;      // ?????????
80
   P1OUT = byte;                 // Display Output D4,D5 = Byte set
81
   P4OUT = byte;                 // Display Output D6,D7 = Byte set
82
   P8OUT = 0x04;                 // En = 1;
83
   P8OUT = 0x00;                 // En = 0;
84
   DelayMs(3);
85
 }
86

87
void DelayMs(int Ms)
88
 {
89
  int i;
90
  while(Ms>0)
91
    {
92
     for(i=0;i<104;i++);
93
     Ms--;
94
    }
95
  }

--

Bitte Code in [ c ] [ /c ] -Tags packen.

-rufus
Persönliche Seite #4392509
Lesenswert?

AMHM M. schrieb:
> Hallo, kann mir jemand sagen, wo mein Fehler steckt?

Die Fehlerbeschreibung fehlt. Du beschreibst nur, was Du tust, nicht 
aber, was Du erreichen willst, und auch nicht, was schief geht.


Wobei ... das hier macht ziemlich sicher nicht das, was Du willst:
1
  P1OUT = cmd;                   // Display Output D4,D5 = CMD set
2
  P4OUT = cmd;                   // Display Output D6,D7 = CMD set

Was ist an P1 und an P4?
1
D4 = P1.3
2
D5 = P1.2
3
D6 = P4.3
4
D7 = P4.0

Was passiert, wenn Du P1 und P4 so beschreibst?

Von "cmd" werden die Bits 0, 2 und 3 ausgegeben, Bit 0 an D7, Bit 2 an 
D5 und Bit 3 sowohl an D4 als auch an D6.
#4392559
Lesenswert?

AMHM M. schrieb:
> kann mir jemand sagen, wo mein Fehler steckt?

Du hast Netiquette: Klare Beschreibung des Problems nicht gelesen.

> Möchte gerne ein LCD

Irgendein LCD? Oder ein bestimmtes?

> mit einem MSP430 ansteuern.

Irgendein MSP430? Oder ein bestimmter?


Amateur schrieb:
>> void LCD_dat4(unsigned char byte)
>
> Diese Zeile sollte als Bleistift, für eine maximal, mittelprächtige
> Parameterbezeichnung, archiviert werden.

Wenn der Zweck dieser Funktion ist, ein Byte zu senden, dann ist der 
Name des Parameters selbst gar nicht mal so schlecht.
OP #4392573
Lesenswert?

Also es handelt sich um eine Msp430f5529.
Das LcD ist ein herkömmliches von Conrad.
Wenn ihr wollt, kann ich das Datenblatt einfügen. Hat aber einen HD44780 
Controller.

Möchte natürlich nicht nur ein Byte sondern einen Text wie oben 
angegeben anzeigen lassen.
OP #4392586
Lesenswert?

Rufus Τ. F. schrieb:
> Dann lies doch mal die verschiedenen Hinweise, die Dir gegeben wurden.
> Deine Initialisierung und Ansteuerung von Port1 und Port4 sind
> fehlerhaft.
>
> Wieso eigentlich zerstückelst Du die vier Datenleitungen des Displays
> auch noch so hochgradig ungeschickt? Hättest Du die nicht alle vier an
> einen Port hängen können?

Weil alle anderen Port bzw Pins vergeben sind. Habe mir eine 
Leiterplatte herstellen lassen und dabei nicht soweit gedacht, aber 
leider ist das so.

Ich habe mir deinen Hinweis angeschaut,
Verstehe ich leider nicht, kannst du mir einen Tipp geben, wie ich es 
verstehen kann :-)
#4392595
Lesenswert?

AMHM M. schrieb:
Ds hier:
> P1OUT = byte;                 // Display Output D4,D5 = Byte set
>    P4OUT = byte;                 // Display Output D6,D7 = Byte set

schreibt alle 8 Bit von byte auf Port 1 und Port 4.
Du haast bei beiden Ports nur zwei Pins als Ausgang definiert. Nur sind 
das nicht D4 und D5. bzw D6 und D7 wie es in Deinem Kommentar steht. Die 
Bits sind Dank Deiner Verwurstelung ganz anders. Das mußt Du hier: 
LCD_dat4 und auch in LCD_cmd4 wieder entwursteln.
Persönliche Seite #4392598
Lesenswert?

AMHM M. schrieb:
> Verstehe ich leider nicht, kannst du mir einen Tipp geben, wie ich es
> verstehen kann :-)

Du willst VIER unterschiedliche Bits eines Bytes ausgeben, die an 
bestimmten Positionen im Byte untergebracht sind.
Vermutlich willst Du die Bits 0..3 ausgeben.

Diese vier Bits sollen an den Datenleitungen D4..7 des Displays landen.

Wenn Du an beide Ports exakt denselben Wert ausgibst, entsprechen sich 
alle Bits dieser Ports.

Du aber verwendest diese Portzuordnung:

D4 = P1.3
D5 = P1.2
D6 = P4.3
D7 = P4.0

Da P1.3 und P4.3 gleich sind, steuerst Du D4 und D6 des Displays mit dem 
gleichen Wert an. Bit 1 Deines Werts hingegen verschwindet im Nirvana.

Das geht in die Hose. Du musst bei beiden Zugriffen die Bits vorher 
korrekt anordnen, bevor Du sie auf die Ports ausgibst.

Wenn Du Bit 0 und Bit 1 Deines Datenbytes an D4 und D5 des Displays 
ausgeben willst, musst Du diese beiden Bits in Deinem Datenbyte so 
anordnen, daß sie an P1.3 und P1.2 auftauchen.
1
uint8_t Portwert = 0;
2

3
if (cmd & (1 << 0))
4
  Portwert |= (1 << 3);
5
if (cmd & (1 << 1))
6
  Portwert |= (1 << 2);
7

8
P1OUT = Portwert;

Und entsprechend musst Du die Bits 2 und 3 Deines Datenbytes, die Du an 
D6 und D7 ausgeben willst, so anordnen, daß sie auf P4.3 und P4.0 
landen.
OP #4392648
Lesenswert?

Rufus Τ. F. schrieb:
> AMHM M. schrieb:
>> Verstehe ich leider nicht, kannst du mir einen Tipp geben, wie ich es
>> verstehen kann :-)
>
> Du willst VIER unterschiedliche Bits eines Bytes ausgeben, die an
> bestimmten Positionen im Byte untergebracht sind.
> Vermutlich willst Du die Bits 0..3 ausgeben.
>
> Diese vier Bits sollen an den Datenleitungen D4..7 des Displays landen.
>
> Wenn Du an beide Ports exakt denselben Wert ausgibst, entsprechen sich
> alle Bits dieser Ports.
>
> Du aber verwendest diese Portzuordnung:
>
> D4 = P1.3
> D5 = P1.2
> D6 = P4.3
> D7 = P4.0
>
> Da P1.3 und P4.3 gleich sind, steuerst Du D4 und D6 des Displays mit dem
> gleichen Wert an. Bit 1 Deines Werts hingegen verschwindet im Nirvana.
>
> Das geht in die Hose. Du musst bei beiden Zugriffen die Bits vorher
> korrekt anordnen, bevor Du sie auf die Ports ausgibst.
>
> Wenn Du Bit 0 und Bit 1 Deines Datenbytes an D4 und D5 des Displays
> ausgeben willst, musst Du diese beiden Bits in Deinem Datenbyte so
> anordnen, daß sie an P1.3 und P1.2 auftauchen.
>
>
1
> uint8_t Portwert = 0;
2
> 
3
> if (cmd & (1 << 0))
4
>   Portwert |= (1 << 3);
5
> if (cmd & (1 << 1))
6
>   Portwert |= (1 << 2);
7
> 
8
> P1OUT = Portwert;
9
>
>
> Und entsprechend musst Du die Bits 2 und 3 Deines Datenbytes, die Du an
> D6 und D7 ausgeben willst, so anordnen, daß sie auf P4.3 und P4.0
> landen.


Also ist genau diese Zeile falsch.
cmd = (cmd<<4) & 0xF0;

Und es müsste heißen:

cmd = (cmd & (1 << 0))
Portwert |= (1 << 3);

cmd = (cmd & (1 << 1))
Portwert |= (1 << 2);

cmd = (cmd & (1 << 2))
Portwert |= (4 << 3);

cmd = (cmd & (1 << 3))
Portwert |= (4<< 0);

Habe Ich das richtig verstanden.
Wenn ja, bedanke ich mich sehr bei euch,
Hoffe es funktioniert und das ist das einzigste Problem gewesen. Kann es 
erst morgen testen :-)
#4392666
Lesenswert?

AMHM M. schrieb:
> Also ist genau diese Zeile falsch.
> cmd = (cmd<<4) & 0xF0;

Nein.

Das Alles ist falsch:

AMHM M. schrieb:
> P3OUT = 0x80;                 // RS=0
>    P1OUT = byte;                 // Display Output D4,D5 = Byte set
>    P4OUT = byte;                 // Display Output D6,D7 = Byte set
>    P8OUT = 0x04;                 // En = 1;
>    P8OUT = 0x00;                 // En = 0;
>    byte = (byte<<4) & 0xF0;      // ?????????
>    P1OUT = byte;                 // Display Output D4,D5 = Byte set
>    P4OUT = byte;                 // Display Output D6,D7 = Byte set
Persönliche Seite #4392766
Lesenswert?

Vergleiche doch einfach mal, was ich geschrieben habe
1
if (cmd & (1 << 0))
2
  Portwert |= (1 << 3);
3
if (cmd & (1 << 1))
4
  Portwert |= (1 << 2);

mit dem, was Du daraus gemacht hast:
1
cmd = (cmd & (1 << 0))
2
Portwert |= (1 << 3);
3

4
cmd = (cmd & (1 << 1))
5
Portwert |= (1 << 2);
6

7
cmd = (cmd & (1 << 2))
8
Portwert |= (4 << 3);
9

10
cmd = (cmd & (1 << 3))
11
Portwert |= (4<< 0);

Kannst Du versuchen, mir zu erklären, wie Du darauf gekommen bist, und 
was das mit dem, was ich geschrieben habe, zu tun hat?
OP #4392775
Lesenswert?

Also, das erste habe ich von dir kopiert:

If cmd = (cmd & (1 << 0))
Portwert |= (1 << 3);

If cmd = (cmd & (1 << 1))
Portwert |= (1 << 2);

If cmd = (cmd & (1 << 2))
Portwert |= (4 << 3);

If cmd = (cmd & (1 << 3))
Portwert |= (4<< 0);

Der erste Bit 1 << 0 soll an Port 1.3

Der zweite Bit 1 << 1 soll an Port 1.2

Das dritte Bit 1 << 2 soll an Port 4.3

Das vierte Bite 1 << 3 soll an Port 4.0
Persönliche Seite #4392783
Lesenswert?

AMHM M. schrieb:
> Also, das erste habe ich von dir kopiert:
>
> If cmd = (cmd & (1 << 0))
> Portwert |= (1 << 3);

Hast Du nicht. Sieh doch nochmal genau hin.

> If cmd = (cmd & (1 << 0))

hat mit

> if (cmd & (1 << 0))

nur sehr wenig Ähnlichkeiten.

Und schaff' Dir ein Buch über die von Dir verwendete Programmiersprache 
an, wenn Dich deren Syntax derartig herausfordert.
OP #4392799
Lesenswert?

Route 6. schrieb:
> AMHM M. schrieb:
>> Also ist genau diese Zeile falsch.
>> cmd = (cmd<<4) & 0xF0;
>
> Nein.
>
> Das Alles ist falsch:
>
> AMHM M. schrieb:
>> P3OUT = 0x80;                 // RS=0
>>    P1OUT = byte;                 // Display Output D4,D5 = Byte set
>>    P4OUT = byte;                 // Display Output D6,D7 = Byte set
>>    P8OUT = 0x04;                 // En = 1;
>>    P8OUT = 0x00;                 // En = 0;
>>    byte = (byte<<4) & 0xF0;      // ?????????
>>    P1OUT = byte;                 // Display Output D4,D5 = Byte set
>>    P4OUT = byte;                 // Display Output D6,D7 = Byte set

Sorry, war wohl so verzweifelt, dass ich nur noch Sterne gesehen habe.
Route 66 meinte aber das alles wäre falsch.
OP #4392821
Lesenswert?

Ich hoffe es :-)

P1Out = cmd;
P4Out = cmd;

Hier ordne ich es dem ganzen Port zu und das ist falsch.

Ich muss es wie du es mir versucht hast beizubringen bzw ich es 
verstanden habe einzeln zuordnen.

Also mit:

If (cmd & (1 << 0))
Portwert |= (1 << 3);
If (cmd & (1 << 1))
Portwert |= (1 << 2);
If (cmd & (1 << 2))
Portwert |= (4 << 3);
If (cmd & (1 << 3))
Portwert |= (4<< 0);
OP #4392856
Lesenswert?

If (cmd & (1 << 0))
Portwert |= (1 << 3);
If (cmd & (1 << 1))
Portwert |= (1 << 2);
If (cmd & (1 << 2))
Portwert |= (4 << 3);
If (cmd & (1 << 3))
Portwert |= (4<< 0);

Dachte mit dem Ausdruck gebe ich es an das jeweilige Port.....
1. Bit an Port 1.3 D4
2. Bit an Port 1.2 D5
3. Bit an Port 4.3 D6
4. Bit an Port 4.0 D7
OP #4392876
Lesenswert?

uint8_t PortwertA = 0;

if (cmd & (1 << 0))
  Portwert |= (1 << 3);
if (cmd & (1 << 1))
  Portwert |= (1 << 2);

uint8_t PortwertB = 0;
If (cmd & (1 << 2))
Portwert |= (4 << 3);
If (cmd & (1 << 3))
Portwert |= (4<< 0

 {
  P3OUT = 0x00;                  // RS=0
  P1OUT = PortwertA;             // Display Output D4,D5 = CMD set
  P4OUT = PortwertB;             // Display Output D6,D7 = CMD set
  P8OUT = 0x04;                  // En = 1;
  P8OUT = 0x00;                  // En = 0;
  cmd = (cmd<<4) & 0xF0;         //?????????
  P1OUT = PortwertA;             // Display Output D4,D5 = CMD set
  P4OUT = PortwertB;             // Display Output D6,D7 = CMD set
  P8OUT = 0x80;                  // En = 1;
  P8OUT = 0x00;                  // En = 0;
  DelayMs(5);                    // Delay
 }

So vielleicht?
Persönliche Seite #4392899
Lesenswert?

Das kommt (von den Flüchtigkeitsfehlern abgesehen) dem Ziel schon etwas 
näher. Zwar brauchst Du keine zwei Variablen, aber das ist erst mal 
egal.

Hintergrundinformation:

Das Display ist mit vier Datenleitungen angeschlossen, aber Du möchtest 
8-Bit-Werte an das Display übertragen. Im 4-Bit-Modus müssen die beiden 
Hälften eines Bytes nacheinander an die gleichen Datenleitungen 
ausgegeben werden. Und zwar, so steht's im Datenblatt, erst die vier 
oberen Bits und dann die vier unteren Bits.

Du hast jetzt (mit einiger Nachhilfe) den Teil hinbekommen, der die 
unteren vier Bit Deines Werts "cmd" an das Display ausgibt.

Das ist der zweite Teil der Übung, Du brauchst dasselbe für die oberen 
vier Bits, und den Teil musst Du zuerst ausführen.

Mach Dir eine Kopie von Deinem Code, und pass' ihn so an, daß nicht die 
unteren, sondern die oberen vier Bits an das Display ausgegeben werden.

Kannst Du nachvollziehen, was dazu nötig ist?
OP #4392942
Lesenswert?

uint8_t PortwertA = 0;

if (cmd & (1 << 0))
  Portwert |= (1 << 3);
if (cmd & (1 << 1))
  Portwert |= (1 << 2);

uint8_t PortwertB = 0;
If (cmd & (1 << 2))
Portwert |= (4 << 3);
If (cmd & (1 << 3))
Portwert |= (4<< 0

 {
  P3OUT = 0x00;                  // RS=0
  P1OUT = PortwertA;             // Display Output D4,D5 = CMD set
  P4OUT = PortwertB;             // Display Output D6,D7 = CMD set
  P8OUT = 0x04;                  // En = 1;
  P8OUT = 0x00;                  // En = 0;
  cmd = (cmd>>4) & 0xF0;         //?????????
  P1OUT = PortwertA;             // Display Output D4,D5 = CMD set
  P4OUT = PortwertB;             // Display Output D6,D7 = CMD set
  P8OUT = 0x80;                  // En = 1;
  P8OUT = 0x00;                  // En = 0;
  DelayMs(5);                    // Delay
 }
 {
  P3OUT = 0x00;                  // RS=0
  P1OUT = PortwertA;             // Display Output D4,D5 = CMD set
  P4OUT = PortwertB;             // Display Output D6,D7 = CMD set
  P8OUT = 0x04;                  // En = 1;
  P8OUT = 0x00;                  // En = 0;
  cmd = (cmd & 0x0F;             //?????????
  P1OUT = PortwertA;             // Display Output D4,D5 = CMD set
  P4OUT = PortwertB;             // Display Output D6,D7 = CMD set
  P8OUT = 0x80;                  // En = 1;
  P8OUT = 0x00;                  // En = 0;
  DelayMs(5);                    // Delay
 }

Ich bin mir nicht sicher :-(((
#4392961
Lesenswert?

Sorry musste für mein Gehalt arbeiten...

Meine Kritik bezog sich auf den Namen "byte" für einen 
Übergabeparameter. Wundert mich auch, dass dein Compiler nicht über 
einen reservierten Bezeichner meckert bzw. dessen Fehlen moniert.

Die bisherige Diskussion erweckt in mir den Gedanken, dass: "Kopieren 
geht über Studieren", hier einen zu hohen Stellenwert hat.
Persönliche Seite #4392968
Lesenswert?

Nein. Jetzt hast Du den falschen Codeblock verdoppelt.

Die zwei interessanten Hälften sind rund um Deine mit vielen 
Fragezeichen versehene Zeile angeordnet.


1
  uint8_t Portwert;
2

3
  P3OUT = 0x00; // RS=0
4

5
  ... hier fehlt der Code zur Ausgabe von Bit 7..4 
6

7
  P8OUT = 0x04; // En = 1;
8
  P8OUT = 0x00; // En = 0;
9

10
  cmd = (cmd << 4) & 0xF0; //?????????
11

12
  Portwert = 0;
13

14
  if (cmd & (1 << 0))      // Bit 0
15
    Portwert |= (1 << 3);  // an P1.3
16
  if (cmd & (1 << 1))      // Bit 1 
17
    Portwert |= (1 << 2);  // an P1.2
18

19
  P1OUT = Portwert;     
20

21
  Portwert = 0;
22

23
  if (cmd & (1 << 2))      // Bit 2
24
    Portwert |= (4 << 3);  // ** das ist falsch, wieso schiebst Du hier den Wert 4?
25
  if (cmd & (1 << 3))      // Bit 3
26
    Portwert |= (4<< 0);   // ** das ist auch falsch  
27

28
  P4OUT = Portwert;
29

30
  P8OUT = 0x80; // En = 1;
31
  P8OUT = 0x00; // En = 0;
32
  DelayMs(5); // Delay
33
}


An diesem Fragment solltest Du vielleicht schon mehr erkennen können.

Klar ist jedenfalls eines: Durch diese ausgesprochen ungeschickte Art 
des Anschlusses des Displays machst Du Dir das Leben ausgesprochen 
schwer.
OP #4393006
Lesenswert?

uint8_t Portwert;

  P3OUT = 0x00; // RS=0

 cmd = (cmd & 0x0F

  P8OUT = 0x04; // En = 1;
  P8OUT = 0x00; // En = 0;

  cmd = (cmd << 4) & 0xF0; //?????????

  Portwert = 0;

  if (cmd & (1 << 0))      // Bit 0
    Portwert |= (1 << 3);  // an P1.3
  if (cmd & (1 << 1))      // Bit 1
    Portwert |= (1 << 2);  // an P1.2

  P1OUT = Portwert;

  Portwert = 0;

  if (cmd & (1 << 2))      // Bit 2
    Portwert |= (4 << 3);  // **Bit 2 soll doch auf Port 4.3 geschrieben 
werden
  if (cmd & (1 << 3))      // Bit 3
    Portwert |= (4<< 0);   // ** soll doch Port 4.0 sein

  P4OUT = Portwert;

  P8OUT = 0x80; // En = 1;
  P8OUT = 0x00; // En = 0;
  DelayMs(5); // Delay
}
OP #4393028
Lesenswert?

Jeder fängt mal klein an.
Kannst du mir bitte den Code mal per PN oder so zukommen lassen,
damit ich ihn genaustens analysiere, weil anscheinend habe ich das nicht 
richtig verstanden, weil sonst bringt das ja nicht viel. Das wäre sehr 
großzügig von dir.
Ich finde es ja absolut klasse, dass du dich überhaupt mit mir 
beschäftigst.

Sie gibt den Inhalt der Variable Portwert an Port4 aus.
OP #4393318
Lesenswert?

AMHM M. schrieb:
> Jeder fängt mal klein an.
> Kannst du mir bitte den Code mal per PN oder so zukommen lassen,
> damit ich ihn genaustens analysiere, weil anscheinend habe ich das nicht
> richtig verstanden, weil sonst bringt das ja nicht viel. Das wäre sehr
> großzügig von dir.
> Ich finde es ja absolut klasse, dass du dich überhaupt mit mir
> beschäftigst.
>
> Sie gibt den Inhalt der Variable Portwert an Port4 aus.

Rufus Τ. F. schrieb:
> AMHM M. schrieb:
>> Portwert |= (4 << 3);  // **Bit 2 soll doch auf Port 4.3 geschrieben
>> werden
>
> Aua. Aua.
>
> Das tut echt weh.
>
> Sorry, aber bist Du Dir sicher, Dir die richtige Aufgabe gesucht zu
> haben?
>
> Was bitte macht die Zuweisung, die ein paar Zeilen weiter unten steht?
>
> P4OUT = Portwert;
>
> Wozu mag das gut sein?

Eine weitere Frage, bei mir gibt er uint8_t als undefiniert an,
obwohl ich stdint.h eingebunden habe? Hast du eventuell auch dafür eine 
erklärung? ------> Ok, habe ich doch hinbekommen. Bräuchte nur für oben 
Hilfe.
Persönliche Seite #4393813
Lesenswert?

AMHM M. schrieb:
> Sie gibt den Inhalt der Variable Portwert an Port4 aus.

Immerhin. Warum aber schiebst Du dann den Wert 4?

Darf an Port4 nur eine 4 ausgegeben werden?

Zum Verständnis:

Der Wert eines Bits entspricht der Zweierpotenz seiner Nummer.

Bit 0 hat den Wert 2^0
Bit 1 hat den Wert 2^1
Bit 2 hat den Wert 2^2
Bit 3 hat den Wert 2^3

etc.

Das bedeutet, daß die Bitnummer gleich der Potenz ist. Praktisch, nicht?

2^0 ist 1.
2^1 ist 2, und den Rest der Reihe solltest Du jetzt selbst 
vervollständigen können.

Es gibt unterschiedliche Philosophien, wie man in der C-Programmierung 
solche Bitkonstanten schreibt, bei der hier im Forum überwiegend 
vertretenen AVR-Fraktion ist es gebräuchlich, das durch Verwendung des 
Schiebeoperators in Verbindung mit der Bitnummer zu erledigen.


Bit 0, das den Wert 1 (also 2^0) hat, ist gleichbedeutend mit 1 << 0.

Bit 1 ist gleichbedeutend mit 1 << 1.

Der Schiebeoperator verdoppelt den Wert des links von ihm stehenden 
Ausdrucks sooft, wie rechts von ihm angegeben ist.

1 << 1 verdoppelt also den Wert von 1 genau einmal.

Folglich verdoppelt 1 << 3 den Wert von 1 dreimal, das Resultat also 
beträgt wieviel?

Dieses Resultat (das Du jetzt bitte herausfinden sollst, damit ich sehe, 
daß Du verstanden hast, was ich hier schreibe) hat den Wert von Bit 3.

Eine andere Art und Weise mit Bitkonstanten umzugehen ist es, gleich 
deren Wert zu verwenden, aber das erfordert Übung und Erfahrung, 
weil man diese Werte nämlich erkennen muss. Das ist eine 
Abstraktionsebene mehr, die für ungeübte das, was gemeint ist, 
versteckt.

Oder würdest Du erkennen, daß mit

if (cmd & 0x80)

das Bit 7 von cmd ausgewertet wird?

Oder welches Bit mit (cmd & 64) gemeint ist?

Eben. Deswegen habe ich hier bewusst die Schiebe-Schreibweise in 
Verbindung mit Bitnummern verwendet.
OP #4393923
Lesenswert?

Rufus Τ. F. schrieb:
> Der Schiebeoperator verdoppelt den Wert des links von ihm stehenden
> Ausdrucks sooft, wie rechts von ihm angegeben ist.
>
> 1 << 1 verdoppelt also den Wert von 1 genau einmal.
>
> Folglich verdoppelt 1 << 3 den Wert von 1 dreimal, das Resultat also
> beträgt wieviel?

Achso, ich dachte ich gebe unten wirklich die Portnummer, also Adresse 
4.3 und Adresse 4.0.
Aber ich muss ja, nur angeben, wieoft der Bit nach links verschoben 
werden muss.

uint8_t Portwert;

  P3OUT = 0x00; // RS=0

 cmd = (cmd & 0x0F

  P8OUT = 0x04; // En = 1;
  P8OUT = 0x00; // En = 0;

  cmd = (cmd << 4) & 0xF0; //?????????

  Portwert = 0;

  if (cmd & (1 << 0))      // Bit 0
    Portwert |= (1 << 3);  // an P1.3
  if (cmd & (1 << 1))      // Bit 1
    Portwert |= (1 << 2);  // an P1.2

  P1OUT = Portwert;

  Portwert = 0;

  if (cmd & (1 << 2))      // Bit 2
    Portwert |= (1 << 3);  // Bit wird um 3 Stellen nach links 
verschoben also Bit 3

  if (cmd & (1 << 3))      // Bit 3
    Portwert |= (1 << 0);  // Bit wird um 0 Stellen nach links 
verschoben also Bit 0

  P4OUT = Portwert;

  P8OUT = 0x80; // En = 1;
  P8OUT = 0x00; // En = 0;
  DelayMs(5); // Delay
}

Rufus Τ. F. schrieb:
> if (cmd & 0x80)
>
> das Bit 7 von cmd ausgewertet wird?
>
> Oder welches Bit mit (cmd & 64) gemeint ist?
>
> Eben. Deswegen habe ich hier bewusst die Schiebe-Schreibweise in
> Verbindung mit Bitnummern verwendet.

if (cmd & 0x80) ist natürlich binär 10000000, also 7 Bit
if (cmd & 0x64) iat binär 01100100, also Bit 6,5 und 3

Richtig?
OP #4394039
Lesenswert?

1
#include <msp430x552x.h>
2
#include <stdio.h>
3
#include <stdint.h>
4

5
void LCD_init(void);
6
void DelayMs(int Ms);
7
void LCD_cmd4(unsigned char cmd);
8
void LCD_dat4(unsigned char byte);
9

10
unsigned char i;
11
const unsigned char Msg1[] = "LCD Test";
12
const unsigned char Msg2[] = "MSP430";
13

14
void main()
15
{
16
 WDTCTL = WDTPW + WDTHOLD;  // Stop watchdog timer
17
 P1DIR = 0x0C;                             // Set D4 und D5 as Outout
18
 P3DIR = 0x80;                             // Set RS
19
 P4DIR = 0x06;                             // Set D6 und D7 as Output
20
 P8DIR = 0x04;                             // Set EN
21
 DelayMs(500);                             // Delay
22
 LCD_init();                               // LCD Init
23
 DelayMs(500);                             // Delay
24

25
 while(1)
26
  {
27
   LCD_cmd4(0x80);
28
   for(i=0;i<16;i++)
29

30
   {
31
    LCD_dat4(Msg1[i]);
32
    DelayMs(5);
33
   }
34

35
   LCD_cmd4(0xc0);
36
   for(i=0;i<16;i++)
37

38
    {
39
     LCD_dat4(Msg2[i]);
40
     DelayMs(5);
41
    }
42
  }
43
}
44

45
void LCD_init(void)
46
 {
47

48
  LCD_cmd4(0x28);              // 28 for four Bit mode
49
  DelayMs(500);                // Delay
50
  LCD_cmd4(0x0C);              // Turns the Display on
51
  DelayMs(500);                // Delay
52
  LCD_cmd4(0x1C);              // Cursor move to right
53
  DelayMs(500);                // Delay
54
  LCD_cmd4(0x01);              // Clear the Display
55
  DelayMs(500);                // Delay
56
 }
57

58
void LCD_cmd4(unsigned char cmd)
59
 {
60
  uint8_t Portwert;        // Variable deklarieren ohne Vorzeichen Integer 8-Bit Typ
61

62
    P3OUT = 0x00;          // RS=0
63

64
   cmd = (cmd & 0x0F);      // Unteren 4 Bits an die Datenleitung senden
65

66
    P8OUT = 0x04;          // En = 1;
67
    P8OUT = 0x00;          // En = 0;
68

69
    cmd = (cmd << 4) & 0xF0;    // Unteren 4 Bits an die Datenleitung senden
70
    Portwert = 0;          // Variable löschen
71

72
    if (cmd & (1 << 0))      // Bit 0
73
      Portwert |= (1 << 3);    // Um 3 Stellen nach links verschieben (P1.3)
74
    if (cmd & (1 << 1))      // Bit 1
75
      Portwert |= (1 << 2);    // Um 2 Stellen nach links verschieben (P1.2)
76

77
    P1OUT = Portwert;        // Variable gibt Inhalt an P1
78
    Portwert = 0;          // Variable löschen
79

80
    if (cmd & (1 << 2))          // Bit 2
81
      Portwert |= (1 << 3);      // Um 3 Stellen nach links verschieben (4.3)
82
    if (cmd & (1 << 3))          // Bit 3
83
      Portwert |= (1 << 0);     // Um  0Stellen nach links verschieben (4.0)
84

85
    P4OUT = Portwert;        // Variable gibt Inhalt an P4
86

87
    P8OUT = 0x80;          // En = 1;
88
    P8OUT = 0x00;         // En = 0;
89
    DelayMs(50);           // Verzögerung
90
  }
91

92

93
void LCD_dat4(unsigned char byte)
94
 {
95
  uint8_t PortwertA;
96

97
   P3OUT = 0x80;                 // RS=0
98

99
   byte = (byte & 0x0F);      // Obere vier bytes in die Variable schreiben?
100

101
   P8OUT = 0x04;                 // En = 1;
102
   P8OUT = 0x00;                 // En = 0;
103

104
   byte = (byte<<4) & 0xF0;      // ?????????
105

106
   PortwertA = 0;
107

108
       if (byte & (1 << 0))      // Bit 0
109
         PortwertA |= (1 << 3);  // an P1.3
110
       if (byte & (1 << 1))      // Bit 1
111
         PortwertA |= (1 << 2);  // an P1.2
112

113
       P1OUT = PortwertA;
114

115
       PortwertA = 0;
116

117
       if (byte & (1 << 2))      // Bit 2
118
         PortwertA |= (1 << 3);  // Bit wird um 3 Stellen nach links  verschoben also Bit 3
119

120
       if (byte & (1 << 3))      // Bit 3
121
         PortwertA |= (1 << 0);  // Bit wird um 0 Stellen nach links  verschoben also Bit 0
122

123
       P4OUT = PortwertA;
124

125
   P8OUT = 0x04;                 // En = 1;
126
   P8OUT = 0x00;                 // En = 0;
127
   DelayMs(3);
128
 }
129

130
void DelayMs(int Ms)
131
 {
132
  int i;
133
  while(Ms>0)
134
    {
135
     for(i=0;i<104;i++);
136
     Ms--;
137
    }
138
  }

--

Mit den [ c ] [ /c ] -Tags wird das gleich viel lesbarer.
-rufus
Persönliche Seite #4394762
Lesenswert?

hate this schrieb:
> Wir haben hier kein AVR Krimskarms und sollten daher die besseren
> #define nutzen.

Kann man so machen (würde ich selbst auch so handhaben, aber mein Code 
dient nicht Lehrzwecken), da hier aber auch viele AVR-affine Menschen 
mitlesen, hielt ich es für das allgemeine Verständnis für sinnvoller. So 
können auch nicht-MSP430-Nutzer das Problem verstehen (das mit einem 
MSP430 nur sehr entfernt am Rande zu tun hat).
OP #4395282
Lesenswert?

Rufus Τ. F. schrieb:
> hate this schrieb:
>> Wir haben hier kein AVR Krimskarms und sollten daher die besseren
>> #define nutzen.
>
> Kann man so machen (würde ich selbst auch so handhaben, aber mein Code
> dient nicht Lehrzwecken), da hier aber auch viele AVR-affine Menschen
> mitlesen, hielt ich es für das allgemeine Verständnis für sinnvoller. So
> können auch nicht-MSP430-Nutzer das Problem verstehen (das mit einem
> MSP430 nur sehr entfernt am Rande zu tun hat).

Dafür bin ich dir auch dankbar. Hast du aber nochmal ein Fehler 
gefunden, warum es nicht geht?
OP #4397133
Lesenswert?

Route 6. schrieb:
> AMHM M. schrieb:
>> Dafür bin ich dir auch dankbar. Hast du aber nochmal ein Fehler
>> gefunden, warum es nicht geht?
>
> Viele...
> Nur mal zwei:
> 1. du mußt erst das High-Nibble und dann dal Low-Nibble ausgeben,
> 2. Du mußt Dich mal entscheiden:
>
> AMHM M. schrieb:
>> P8OUT = 0x80;          // En = 1;
>>     P8OUT = 0x00;         // En = 0;
>
>> P8OUT = 0x04;          // En = 1;
>>     P8OUT = 0x00;          // En = 0;

Okay, High nibble verstandlich.
das Enable auch.

Was denn sonst, dass es Soviele sind.
#4397248
Lesenswert?

AMHM M. schrieb:
> Was denn sonst, dass es Soviele sind.

Dein Code zeugt einfach von Deiner Schlampigkeit und das ist eine sehr 
schlechte Tugend für einen Programmierer.

Schau dir den Programmtext langsam und sorgfältig Zeile für Zeile an.
Verstehe jede Zeile.
Korrigiere Tippfehler.
Korrigiere logische Fehler.
Lösche Überflüssige Zeilen.
Bringe den Rest in die richtige Reihenfolge.
Ergänze Fehlendes.

Und schon läuft der Laden!
OP #4398994
Lesenswert?

Route 6. schrieb:
> AMHM M. schrieb:
>> Was denn sonst, dass es Soviele sind.
>
> Dein Code zeugt einfach von Deiner Schlampigkeit und das ist eine sehr
> schlechte Tugend für einen Programmierer.
>
> Schau dir den Programmtext langsam und sorgfältig Zeile für Zeile an.
> Verstehe jede Zeile.
> Korrigiere Tippfehler.
> Korrigiere logische Fehler.
> Lösche Überflüssige Zeilen.
> Bringe den Rest in die richtige Reihenfolge.
> Ergänze Fehlendes.
>
> Und schon läuft der Laden!

Das habe ich ich jetzt mal gemacht und für jede Zeile eine Kommentar 
hinzugefügt, wie ich es verstanden habe.

{
uint8_t Portwert;    // Variable Integer 8-Bit Typ

P3OUT = 0x00;        // RS=0

// Muss hier nich das Enable kurz auf high gesetzte werden?

cmd = (cmd << 4) & 0xF0;  // Oberen 4 Bits an die Datenleitung

P8OUT = 0x04;      // En = 1;
P8OUT = 0x00;      // En = 0;

cmd = (cmd & 0x0F);    // Untere 4 Bits an die Datenleitung senden
Portwert = 0;      // Variable löschen

if (cmd & (1 << 0))    // Bit 0
    Portwert |= (1 << 3);  // Um 3 Stellen nach links (P1.3)
    if (cmd & (1 << 1))  // Bit 1
Portwert |= (1 << 2);    // Um 2 Stellen nach links (P1.2)

P1OUT = Portwert;    // Variable gibt Inhalt an P1
Portwert = 0;      // Variable löschen

if (cmd & (1 << 2))        // Bit 2
    Portwert |= (1 << 3);    // Um 3 Stellen nach links (4.3)
if (cmd & (1 << 3))        // Bit 3
    Portwert |= (1 << 0);   // Um  0Stellen nach links (4.0)

P4OUT = Portwert;     // Variable gibt Inhalt an P4

P8OUT = 0x04;      // En = 1;
P8OUT = 0x00;       // En = 0;
DelayMs(50);       // Verzögerung
}
#4400315
Lesenswert?

1
 1 {
2
 2 uint8_t Portwert;    // Variable Integer 8-Bit Typ
3
 3 
4
 4 P3OUT = 0x00;        // RS=0
5
 5 
6
 6 // Muss hier nich das Enable kurz auf high gesetzte werden?
7
 7 
8
 8 cmd = (cmd << 4) & 0xF0;  // Oberen 4 Bits an die Datenleitung
9
 9 
10
10 P8OUT = 0x04;      // En = 1;
11
11 P8OUT = 0x00;      // En = 0;
12
12 
13
13 cmd = (cmd & 0x0F);    // Untere 4 Bits an die Datenleitung senden
14
14 Portwert = 0;      // Variable löschen
15
15 
16
16 if (cmd & (1 << 0))    // Bit 0
17
17     Portwert |= (1 << 3);  // Um 3 Stellen nach links (P1.3)
18
18     if (cmd & (1 << 1))  // Bit 1
19
19 Portwert |= (1 << 2);    // Um 2 Stellen nach links (P1.2)
20
20 
21
21 P1OUT = Portwert;    // Variable gibt Inhalt an P1
22
22 Portwert = 0;      // Variable löschen
23
23 
24
24 if (cmd & (1 << 2))        // Bit 2
25
25     Portwert |= (1 << 3);    // Um 3 Stellen nach links (4.3)
26
26 if (cmd & (1 << 3))        // Bit 3
27
27     Portwert |= (1 << 0);   // Um  0Stellen nach links (4.0)
28
28 
29
29 P4OUT = Portwert;     // Variable gibt Inhalt an P4
30
30 
31
31 P8OUT = 0x04;      // En = 1;
32
32 P8OUT = 0x00;       // En = 0;
33
33 DelayMs(50);       // Verzögerung
34
34 }

Hallo!
In der Zeile 4 unterscheidest Du, ob Du ein Steuerwort an den 
Displaycontroller oder Daten zum Anzeigen übergeben willst. Es wird nur 
ein Draht auf Low oder High gesetzt.
Deshalb ist Deine Frage in Zeile 6 Unsinn.

Zeile 8 ist falsch kommentiert: es wird nur die Variable "cmd" verändert 
und nichts an irgendwelche Datenleitungen übergeben.

Zeilen 10, 11: Du hast Deine Daten für das Display so verwurstelt, dass 
jetzt noch kein Enable kommen darf, erst müssen die Bitzuordnungen 
enwirrt werden.

Zeile 13: dito zu Zeile 8

zwischen Zeile 14 und 21 entwirrst Du zwei Bits und gibst sie an den 
Port P1 aus. In den Zeilen 22 bis 29 das gleiche an Port P4 also 2 Bits 
entwirren und ausgeben.

Dann folgt in Zeile 31, 32 das Enable. Das LCD muß jetzt mit 4(!) Bits 
klar kommen. Es will aber immer 8 haben. Ich würde mich auch weigern.

Die Initialisierungssequenz zum 4-Bit-Modus solltest Du Dir auch noch 
mal ansehen. Das LCD erwartet zuerst 8-Bit-Kommandos (am 4-Bit 
Anschluss):
3xReset und dann den Umschaltbefehl in den 4-Bit-Modus.

Deine Delays sind wohl eher aus Verzweiflung entstanden als aus 
Sachkenntnis.
Gast #4401225
Lesenswert?

> Zeile 8 ist falsch kommentiert: es wird nur die Variable "cmd" verändert
> und nichts an irgendwelche Datenleitungen übergeben.
>
> Zeilen 10, 11: Du hast Deine Daten für das Display so verwurstelt, dass
> jetzt noch kein Enable kommen darf, erst müssen die Bitzuordnungen
> enwirrt werden.
>
> Zeile 13: dito zu Zeile 8
>
> zwischen Zeile 14 und 21 entwirrst Du zwei Bits und gibst sie an den
> Port P1 aus. In den Zeilen 22 bis 29 das gleiche an Port P4 also 2 Bits
> entwirren und ausgeben.
>
> Dann folgt in Zeile 31, 32 das Enable. Das LCD muß jetzt mit 4(!) Bits
> klar kommen. Es will aber immer 8 haben. Ich würde mich auch weigern.
>
> Die Initialisierungssequenz zum 4-Bit-Modus solltest Du Dir auch noch
> mal ansehen. Das LCD erwartet zuerst 8-Bit-Kommandos (am 4-Bit
> Anschluss):
> 3xReset und dann den Umschaltbefehl in den 4-Bit-Modus.
>
> Deine Delays sind wohl eher aus Verzweiflung entstanden als aus
> Sachkenntnis.

Hi,

so jetzt habe ich es nochmal korrigiert, vorallem die Initialisierung.
Das sollte soweit passen. Des Weiteren habe ich versucht, die Routine zu 
ändern. Jedoch funktioniert es immer noch nicht, kannst du bitte nochmal 
drüber gucken? Den Quellcode habe ich als Textdatei, sonst wird es zu 
unübersichtlich.
Angehängte Dateien:
OP #4401241
Lesenswert?

Sorry, aber in der Textdatei ist bei Enable P8Out = 0x80, was natürlich 
nicht stimmt, sondern P8Out = 0x04, da es auf P8.2 liegt.

Wenn die Initialisierung stimmt, müsste doch eigentlich der Cursor 
blinken, wenn ich es mit dem Befehl 0x0F einstellen ohne das der 
restliche Part des LCD "funktioniert"
#4402067
Lesenswert?

Hallo!
Ich sehe schon viele Fortschritte, aber...

Wo soll ich nur beginnen?

Zunächst: Du gibst im 4-Bit-Modus erst das Low-Nibble und dann das 
High-Nibble aus. Das gehört in LCD_cmd4 und LCD_dat4 genau anders herum.
Du brauchst auch keine zwei Dummy-Variablen PortwertA und PortwertB, 
eine genügt.

Die Initialisierung erfolgt als 8-Bit Ausgabe - die ist tricky.
Das ganze ist hier etwas schwierig zu beschreiben. Ich versuchs mal:
Du musst jedes Steuerwort bis zur Umschaltung als einzelne 4-Bit Ausgabe 
und nicht als zwei mal 4-Bit Ausgabe machen (Ja, hört sich bescheuert 
an).
Das Dsiplay ergänzt selbst die fehlenden 4 Bit durch 0000 im Low-Nibble.
Jedes Display sollte dazu Pull-Down-Widerstände an offenen 
Datenleitungen haben. Man könnte zur Sicherheit D0-D3 am LCD auch auf 
Low legen.

Das hört sich alles etwas wirr an, ist aber so.

Für die ersten vier Kommandos brauchst Du also eine besondere Prozedur.
Erst danach werden alle Ausgaben in zwei mal 4 Bit gemacht.

Nebenbei: (oder Internet-Denglisch BTW)
Deine zwei Prozeduren LCD_cmd4 und LCD_dat4 unterscheiden sich nur in 
einer Zeile, braucht es dazu zwei Prozeduren oder genügt ein 
Übergabeparameter für die Unterscheidung cmd/dat?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren