Forum: Projekte & Code LCD-Modul 2x16 am STM32F4Discovery-Board


von m.n. (Gast)


Angehängte Dateien:

Lesenswert?

Mit dem angefügten Programm 'STM32F4_lcd.c' läßt sich ein LCD-Modul 2x16 
am STM32F4-Discovery-Board betreiben. Verwendet werden dazu die Pins 
PortD9 - PortD15 gemäß gezeigtem Schaltbild.
Alle Anschlüsse lassen sich über einen 10-poligen Steckverbinder kompakt 
verdrahten, wenn der freie Pin 'NC' mit dem Anschluß '5V' verbunden wird 
(diagonal verlegtes Kabel). Die Anzeige wird dann aus dem USB-Anschluß 
mit versorgt. Falls diese Spannung merklich unter +5V liegt 
(Hintergrundbeleuchtung schwach, geringer Kontrast), ist es ratsam, für 
Board und LCD eine externe 5V-Stromversorgung anzuschließen.

Beim Programm ist zu kontrollieren, ob die Funktion 'warte_1us()' auch 
etwa die gewünschte Verzögerung bringt. Falls die bestehenden 
Einstellungen des SysTick-Timers nicht passen oder dieser garnicht 
aktiviert ist, muß man u. U. diese Funktion anpassen/ergänzen.

Das Programm kann für einfache Ausgaben verwendet werden. Entwickelt 
wurde es für die  Anzeige von Messwerten eines reziproken 
Frequenzzählers.
Beitrag "reziproker Frequenzzähler mit STM32F4Discovery"

von m.n. (Gast)


Angehängte Dateien:

Lesenswert?

Schon länger wollte ich mit einem Foto zeigen, wie kompakt und einfach 
der Anschluß eines LCD-Moduls ist. Hier ist es.
Es können auch größere Module bis 2x40 oder auch 4x20 angesteuert 
werden, wenn man beachtet, wo die jeweiligen Zeilen im Display-Speicher 
abgelegt sind.

von Wolfgang (Gast)


Lesenswert?

Hallo m.n.

Ich hage gerade deinen Quellcode an einem STM32F10x ausprobiert, an Port 
C.
Habe dementsprechend den Code angepasst, leider ohne Erfolg.
Hat dieser Code bei dir funktioniert?

MfG Wolfgang

/*
  LCD-Pin   Funktion    Discovery-Board

    1         GND            GND-Pin
    2         +5V        +5V über NC-Pin
    3       Kontrast    Diode->GND (ca.0,7V Vorsp.)
    4         RS              PC1
    5         R/W             PC2
    6         E               PC3
    7       D0(GND)
    8       D1(GND)
    9       D2(GND)
    10      D3(GND)
    11        D4              PC4
    12        D5              PC5
    13        D6              PC6
    14        D7              PC7

*/


#include "stm32f10x.h"

#define LCD_CMD     GPIO_Pin_1        // 0 = CMD, 1 = Zeichenausgabe
#define LCD_READ    GPIO_Pin_2       // 0 = Schreiben, 1 = Status lesen
#define LCD_STROBE  GPIO_Pin_3       // Schreibimpuls E fuers LCD
#define ZEILE1      0x7f              // jeweils 1 addieren fuer 1. 
Spalte
#define ZEILE2      0xbf              // dto.
#define BUSY_FLAG   0x80              // Bit7 vom LCD-Status


void warte_1us(void)
{

volatile uint32_t t2;
  while(SysTick->VAL <1000);
  t2 = SysTick->VAL - 140;
  while(SysTick->VAL > t2);
}


// Routinen zur Ausgabe auf LCD 2x16

uint8_t lcd_status(void)    // oberstes Bit ist busy-flag, Rest: Adresse
{
  uint8_t temp = 0;
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | 
GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    // auf 
Eingang schalten
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIOC->ODR |= LCD_READ;             // PortC lesen
  GPIOC->ODR &= ~LCD_CMD;             // PortC lesen
  warte_1us();
  GPIOC->ODR |= LCD_STROBE;
  warte_1us();
  temp = (GPIOC->IDR >> 8) & 0xf0;    // oberes nibble zuerst
  GPIOC->ODR &= ~LCD_STROBE;
  warte_1us();
  GPIOC->ODR |= LCD_STROBE;
  warte_1us();
  temp |= (GPIOC->IDR >> 12) & 0x0f;  // unteres nibble zuletzt
  GPIOC->ODR &= ~LCD_STROBE;
  GPIOC->ODR &= ~LCD_READ;
  warte_1us();
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   // wieder als 
Ausgang verwenden
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  warte_1us();

  return(temp);                       // busy-flag + Adresse
}


void lcd_impuls(void)       // Schreibimpuls mit Mindestlaenge
{
  warte_1us();
  GPIOC->ODR |= LCD_STROBE;
  warte_1us();
  GPIOC->ODR &= ~LCD_STROBE;
  warte_1us();
}

void lcd_nibble(char c)     // 4-bit-Wert an PC4-PC7 ausgeben
{
uint16_t temp;
  temp = GPIOC->ODR & ~(GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | 
GPIO_Pin_7);
  temp |= ((c<<8) & (GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | 
GPIO_Pin_7));
  GPIOC->ODR = temp;
  lcd_impuls();
}

void lcd_out(char z,char mode)      // Ausgabe von Daten (mode==1) oder 
CMDs (mode==0)
{
  while(lcd_status() & BUSY_FLAG);  // vor neuer Ausgabe busy-flag 
abwarten
  if(mode) GPIOC->ODR |= LCD_CMD;
  else GPIOC->ODR &= ~LCD_CMD;
  lcd_nibble(z);
  z <<= 4;
  lcd_nibble(z);
}

void lcd_cmd(char z)        // einen LCD-Befehl ausgeben
{
  lcd_out(z,0);
}

void lcd_zeichen(char z)    // ein Zeichen ausgeben
{
  lcd_out(z,1);
}

void lcd_string(char *s)    // Zeichenkette auf LCD
{
signed char temp;
  while((temp=*s++) != 0) {
     lcd_zeichen(temp);
  }
}

void lcd_init_nibble(char c)  // 4-bit-Wert ausgeben LCD_INIT
{
uint16_t temp = 65000;
  lcd_nibble(c);
  while(temp--) warte_1us();  // bei Init genug Zeit lassen
}

void lcd_zeile1(char *s)    // komplette Zeile ausgeben
{
  lcd_cmd(ZEILE1+1);        // 1.Zeile, 1.Spalte
  lcd_string(s);
}
void lcd_zeile2(char *s)    // komplette Zeile ausgeben
{
  lcd_cmd(ZEILE2+1);        // 2.Zeile, 1.Spalte
  lcd_string(s);
}

void lcd_init(void)         // Port D9 - PortD 15 werden gebraucht
{
uint16_t temp;
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

  // Ausgänge von PortC Pins 1, 2, 3, 4, 5, 6, 7 push-pull output*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 
|GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  temp = 3000;
  while(temp--) warte_1us();    // nach Reset genug Zeit lassen

  lcd_init_nibble(0x30);
  lcd_init_nibble(0x30);
  lcd_init_nibble(0x30);
  lcd_init_nibble(0x20);
  lcd_cmd(0x28);                // im 4-bit mode
  lcd_cmd(0x0f);
  lcd_cmd(0x01);

  temp = 3000;
  while(temp--) warte_1us();    // nach init genug Zeit lassen

  lcd_cmd(ZEILE1+1);            // 1.Zeile, 1.Spalte
            //1234567890123456
  lcd_string("    1.Zeile     ");
  lcd_cmd(ZEILE2+1);            // 2.Zeile, 1.Spalte
  lcd_string("    2.Zeile     ");
}

von Mitlesa (Gast)


Lesenswert?

Wolfgang schrieb:
> Habe dementsprechend den Code angepasst, leider ohne Erfolg.

>>    11        D4              PD12
>>    12        D5              PD13
>>    13        D6              PD14
>>    14        D7              PD15

versus
1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

???

von Mitlesa (Gast)


Lesenswert?

Mitlesa schrieb:
> ???

Hab mich wohl verguckt ....

von m.n. (Gast)


Lesenswert?

Wolfgang schrieb:
> Habe dementsprechend den Code angepasst, leider ohne Erfolg.
> Hat dieser Code bei dir funktioniert?

Ja, aber mit PortD.
Irgendwann hatte ich ihn noch geändert. Er steht weiter unten unter dem 
Schaltbild: http://mino-elektronik.de/FM_407/fmeter_407.htm#a5
Für den Kontrast wird DAC1 verwendet.

Was funktioniert denn und was nicht?

von Mitlesa (Gast)


Angehängte Dateien:

Lesenswert?

m.n. schrieb:
> Was funktioniert denn und was nicht?

Vielleicht sollte man das Timing etwas päpstlicher ausfallen lassen?

von m.n. (Gast)


Lesenswert?

Mitlesa schrieb:
> Vielleicht sollte man das Timing etwas päpstlicher ausfallen lassen?

Ich denke 65 ms (bzw. 10 ms) pro Ausgabe sind langsam genug.

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.