Forum: Mikrocontroller und Digitale Elektronik MSP430 LCD Problem


von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich sitze nun schon seit knapp zwei Wochen an einer vermeintlich simplen 
Aufgabe.

Ich habe mein MSP430 Launchpad mit einem LCD verbunden, siehe Anhang.

Das Display verfügt über einen Samsung S6A0069 Controller. Diesen 
versuche ich mit folgender Funktion gemäß Datenblatt zu initialisieren:
1
void init_s6a0069()
2
{
3
  P1DIR = 0xFF;
4
  P2DIR |= BIT0 + BIT1 + BIT2;
5
  
6
  P2OUT = 0x00;  // RS = EN = RW = 0;
7
   
8
  delay_ms(40);  // Delay after power on
9
  
10
  P1OUT = 0x3C;  // Function Set
11
  delay_us(40);
12
  
13
  P1OUT = 0x0F;  // Display ON/OFF
14
  delay_us(40);
15
  
16
  P1OUT = 0x01;  //Display Clear
17
  delay_ms(2);
18
  
19
  P1OUT = 0x04;  // Entry MOde Set
20
  delay_us(1);
21
}

Danach sollte zumindest mal der Cursor blinken, stattdessen ist die 
rechte Seite des Displays erleuchtet (man sieht das im Bild). Und das 
auch nur wenn ich das Display kippe.

Die Delay-Funktionen funktionieren, dass habe ich mit einem Oszilloskop 
geprüft. Die Bits werden auch richtig gesetzt und die Verkabelung habe 
ich schon unzählige Male überprüft.

Das Display sollte laut Datenblatt auch mit 3 Volt auskommen.


Weiß Jemand was ich hier eventuell noch falsch mache?

Viele Grüße,
Michael

von Tim H. (msp430h)


Lesenswert?

Hallo Michael,

könntest du beifügen welchen MSP430 du nutzt und wie du das LCD 
angeschlossen hast?!

Vill liegt ein Problem dadrin das ein Pin den du belegt hast nicht als 
IO konfiguriert ist.

Die angaben wie ein Pin Standard Belegt sind findest du im Datenblatt 
deines MSP430.

gruß

tim

von Michael (Gast)


Lesenswert?

Hallo Tim,

danke für deine Antwort.

Das Launchpad nutzt den MSP430G2553, meine Pinbelegung sieht wie folgt 
aus:

P1.0   DB0
P1.1   DB1
P1.2   DB2
P1.3   DB3
P1.4   DB4
P1.5   DB5
P1.6   DB6
P1.7   DB7

P2.0   E
P2.1   RS
P2.2   RW

Gruß,
Michael

von Easy (Gast)


Lesenswert?

Michael schrieb:
> Weiß Jemand was ich hier eventuell noch falsch mache?

Wirf einen Blick in die Beschreibung
http://www.cloverdisplay.com/pdf/S6A0069.pdf
Dort findest du Beispiele fürs BUS-Timing. Achte besonders auf das E 
Signal.

Bei einem parallelen BUS gibt es (fast) immer ein Strobe. Das ist hier 
E.

von Michael (Gast)


Lesenswert?

Hallo zusammen,

ich habe Neuigkeiten, habe eine Bibliothek gefunden und ausprobiert:
1
#include <msp430g2553.h>
2
3
// Definitions
4
#define DR P1OUT = P1OUT | BIT4 // define RS high
5
#define CWR P1OUT = P1OUT & (~BIT4) // define RS low
6
#define READ P1OUT = P1OUT | BIT5 // define Read signal R/W = 1 for reading
7
#define WRITE P1OUT = P1OUT & (~BIT5) // define Write signal R/W = 0 for writing
8
#define ENABLE_HIGH P1OUT = P1OUT | BIT6 // define Enable high signal
9
#define ENABLE_LOW P1OUT = P1OUT & (~BIT6) // define Enable Low signal
10
11
// Function Prototypes
12
void data_write(void);
13
void data_read(void);
14
void check_busy(void);
15
void send_command(unsigned char cmd);
16
void send_data(unsigned char data);
17
void send_string(char *s);
18
void lcd_init(void);
19
20
//===================================================================================//
21
// DATA_WRITE
22
//===================================================================================//
23
void data_write(void)
24
{
25
  ENABLE_HIGH;
26
  __delay_cycles(40000);
27
  ENABLE_LOW;
28
}
29
30
//===================================================================================//
31
// DATA_READ
32
//===================================================================================//
33
void data_read(void)
34
{
35
  ENABLE_LOW;
36
  __delay_cycles(40000);
37
  ENABLE_HIGH;
38
}
39
40
//===================================================================================//
41
// DATA_WRITE
42
//===================================================================================//
43
void check_busy(void)
44
{
45
  P1DIR &= ~(BIT3); // make P1.3 as input
46
  while ((P1IN & BIT3) == 1)
47
  {
48
    data_read();
49
  }
50
  P1DIR |= BIT3; // make P1.3 as output
51
}
52
53
//===================================================================================//
54
// SEND_COMMAND
55
//===================================================================================//
56
void send_command(unsigned char cmd)
57
{
58
  check_busy();
59
  WRITE;
60
  CWR;
61
  P1OUT = (P1OUT & 0xF0) | ((cmd >> 4) & 0x0F); // send higher nibble
62
  data_write(); // give enable trigger
63
  P1OUT = (P1OUT & 0xF0) | (cmd & 0x0F); // send lower nibble
64
  data_write(); // give enable trigger
65
}
66
67
//===================================================================================//
68
// SEND_DATA
69
//===================================================================================//
70
void send_data(unsigned char data)
71
{
72
  check_busy();
73
  WRITE;
74
  DR;
75
  P1OUT = (P1OUT & 0xF0) | ((data >> 4) & 0x0F); // send higher nibble
76
  data_write(); // give enable trigger
77
  P1OUT = (P1OUT & 0xF0) | (data & 0x0F); // send lower nibble
78
  data_write(); // give enable trigger
79
}
80
81
//===================================================================================//
82
// SEND_STRING
83
//===================================================================================//
84
void send_string(char *s)
85
{
86
  while (s)
87
  {
88
    send_data(*s);
89
    s++;
90
  }
91
}
92
93
//===================================================================================//
94
// LCD_INIT
95
//===================================================================================//
96
void lcd_init(void)
97
{
98
  P2OUT &= 0x00;
99
  P2DIR &= 0x00;
100
101
  P1DIR |= 0xFF;
102
  P1OUT &= 0x00;
103
  send_command(0x33);
104
  send_command(0x32);
105
  send_command(0x28); // 4 bit mode
106
  send_command(0x0E); // clear the screen
107
  send_command(0x01); // display on cursor on
108
  send_command(0x06); // increment cursor
109
  send_command(0x80); // row 1 column 1
110
}

Die main-Funktion sieht wie folgt aus:
1
void main(void)
2
{
3
  WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer
4
  init_clock();
5
  lcd_init();
6
  send_string("Hello");
7
  send_command(0xC0);
8
  send_string("World");
9
10
  while (1)
11
  {
12
13
  }
14
15
  // return 0;
16
}

Auf dem Display erscheint tatsächlich "Hello World", allerdings nur 
einmal, danach verblasst es und nur noch die rechte Display-Hälfte ist 
mit schwarzen Kästchen gesetzt.

Da ist wohl noch irgend etwas faul, aber zumindest mal ein Anfang. 
Vielleicht liegt es auch am Display, das ist nämlich schon rund 12 Jahre 
alt.

Beste Grüße,
Michael

von TimerA3 (Gast)


Lesenswert?

Michael schrieb:
> Auf dem Display erscheint tatsächlich "Hello World"

Und, wo ist der Unterschied in der Ansteuerung zu deinen ersten 
Versuchen? Es ist nämlich nicht verboten, zu verstehen, was man tut. 
;-)))

von Michael (Gast)


Lesenswert?

Der Unterschied zum ersten Versuch ist das anschließende "Triggern" des 
Enable-Signals, das hat bei meinem Versuch gefehlt.

Ein kleiner, aber feiner Unterschied.

von TimerA3 (Gast)


Lesenswert?

Michael schrieb:
> allerdings nur
> einmal, danach verblasst es

Wie darf man sich das vorstellen? Du gibst nur einmal den Text aus und 
die CPU tritt auf der Stelle. Wird das Display jetzt langsam 
unleserlich?
Oder passiert das erst mit einem anderen Programm, was wir hier nicht 
sehen?

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Das Display wird langsam unleserlich, siehe Anhang.

Ein anderes Programm gibt es nicht, es wird nur die oben genannte 
main-function abgearbeitet.

Vermutlich muss ich den internen RAM kontinuierlich beschreiben. Mich 
wundert nur, dass die rechte Display Hälfte einen höheren Kontrast hat.

von TimerA3 (Gast)


Lesenswert?

Das liegt am Display. Prüf einmal die Spannungen und ob nach Datenblatt 
alle Pins richtig gepuffert und geblockt sind. Muss fürn Kontrast was 
getan werden?

von LCD-Anfänger (Gast)


Lesenswert?

Michael schrieb:
> void check_busy(void)
> {
>   P1DIR &= ~(BIT3); // make P1.3 as input
>   while ((P1IN & BIT3) == 1)
>   {
>     data_read();
>   }
>   P1DIR |= BIT3; // make P1.3 as output
> }

Unglaublich was für ein Mist im Internet steht.

Hier wird der LCD Port gelesen nachdem der Enable weggenommen
wurde (geschieht in data_read() ). Das geht nur durch Zufall gut.

(P1IN & BIT3) kann niemals 1 sein. Entweder 0x08 oder 0x00;

1
unsigned char val;
2
do
3
{
4
  ENABLE_HIGH;
5
  __delay_cycles(xxx);
6
  val = (P1IN & BIT3)
7
  ENABLE_LOW;
8
} while (val);

von Michael (Gast)


Lesenswert?

@TimerA3:
Ich habe die PINS DB0 - DB3 nicht auf GND gezogen, die floaten. Könnte 
das ein Grund sein? Ansonsten habe ich alles nach Datenblatt 
angeschlossen.

@LCD-Anfänger:
Danke für den Hinweis. Ich habe die Bibliothek von hier:
http://wenda.soso.io/questions/3256974/microcontroller-lcd-4-bits-mode

von LCD-Anfänger (Gast)


Lesenswert?

LCD-Anfänger schrieb:

>> void check_busy(void)
>> {
>>   P1DIR &= ~(BIT3); // make P1.3 as input
>>   while ((P1IN & BIT3) == 1)
>>   {
>>     data_read();
>>   }
>>   P1DIR |= BIT3; // make P1.3 as output
>> }
>

Ich bessere nach:
1
unsigned char val;
2
3
P1DIR &= ~(BIT3); // make P1.3 as input
4
do
5
{
6
  ENABLE_HIGH;
7
  __delay_cycles(xxx);
8
  val = (P1IN & BIT3);
9
  ENABLE_LOW;
10
} while (val);
11
P1DIR |= BIT3; // make P1.3 as output

von der_thorben (Gast)


Lesenswert?

sieht eher nach falscher pinbelegung aus, kurzschluss oder kein 
richtiges definitiertes potenzial

von TimerA3 (Gast)


Lesenswert?

Ja, die hochohmigen Ausgänge können ein Problem sein. Nimm die internen 
Pull Widerstände vom MSP.

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.