Forum: Mikrocontroller und Digitale Elektronik LCD AVR C ROUTINEN


von Ingo L. (grobian)


Lesenswert?

so...
nachdem der Port A nun blinkt habe ich an PortB (Tiny26) ein LCD Display 
angeschlossen. Ich betreibe (oder möchte) es im 4 Bit Modus und die 
Leitungen RS und E sind ebenfalls am Port B an geschlossen. Wie geht es 
nun weiter. Habe hier schon die Dateien lcd.c und lcd.h gefunden aber 
die beziehen sich ja wohl auf den Busbetrieb. Wo finde ich die 
entsprechenden Dateien die ich in mein Programm einbinden muß bzw. 
welche Änderungen
muß ich für meine Hardwareconfigurationen vornehmen??

von Daniel R. (zerrome)


Lesenswert?

Hallo,
was meinst du mit Busbetrieb?

Ich hab mir aus dem Tutorial die lcd.h und lcd.c so umgeschrieben,
dass man da die gewünschten Pins angeben kann, also frei wählen...
Brauchst du das oder was meinst du?

von Ingo L. (grobian)


Lesenswert?

ich denke mal, das wird es sein. Mit Busbetrieb meine ich,dass das 
Display über einen Adressdekoder (z.B. 74ls138) selektiert wird.
Was muß ich in den Routinen ändern??

von Daniel R. (zerrome)


Lesenswert?

Ich Poste einfach mal das was ich da geändert habe...
Is warscheinlich nicht optimal, läuft aber.

Das ist die lcd.c
1
//******************************************************************************** 
2
// sendet ein Datenbyte an das LCD
3
 
4
void lcd_data(unsigned char data8){   
5
 
6
     LCD_RSP |= (1<<LCD_RS);        // RS auf 1 setzen
7
   
8
  setPin();
9
  if(data8 & 128)LCD_D3P |=(1<<LCD_D3);  //hi nibbels  
10
  if(data8 & 64)LCD_D2P  |=(1<<LCD_D2);
11
  if(data8 & 32)LCD_D1P  |=(1<<LCD_D1);
12
  if(data8 & 16)LCD_D0P  |=(1<<LCD_D0);
13
  lcd_enable();
14
 
15
    setPin();
16
  if(data8 & 8)LCD_D3P |=(1<<LCD_D3);    //low nibbels
17
  if(data8 & 4)LCD_D2P |=(1<<LCD_D2);
18
  if(data8 & 2)LCD_D1P |=(1<<LCD_D1);
19
  if(data8 & 1)LCD_D0P |=(1<<LCD_D0);     
20
     lcd_enable();
21
   
22
    waitms(1);
23
}
24
25
//******************************************************************************** 
26
//rücksetzen der Daten pins
27
28
void setPin(void){
29
30
  LCD_D3P &= ~(1<<LCD_D3);  
31
  LCD_D2P &= ~(1<<LCD_D2);
32
  LCD_D1P &= ~(1<<LCD_D1);
33
  LCD_D0P &= ~(1<<LCD_D0);
34
}
35
36
//******************************************************************************** 
37
// sendet einen Befehl an das LCD
38
 
39
void lcd_command(unsigned char cmd8){
40
41
     LCD_RSP &= ~(1<<LCD_RS);        // RS auf 0 setzen
42
 
43
  setPin();
44
  if(cmd8 & 128)LCD_D3P |=(1<<LCD_D3);  //hi nibbels  
45
  if(cmd8 & 64)LCD_D2P  |=(1<<LCD_D2);
46
  if(cmd8 & 32)LCD_D1P  |=(1<<LCD_D1);
47
  if(cmd8 & 16)LCD_D0P  |=(1<<LCD_D0);
48
  lcd_enable();
49
 
50
    setPin();
51
  if(cmd8 & 8)LCD_D3P |=(1<<LCD_D3);    //low nibbels
52
  if(cmd8 & 4)LCD_D2P |=(1<<LCD_D2);
53
  if(cmd8 & 2)LCD_D1P |=(1<<LCD_D1);
54
  if(cmd8 & 1)LCD_D0P |=(1<<LCD_D0);     
55
     lcd_enable();
56
   
57
  waitms(1);
58
}
59
 
60
//********************************************************************************
61
// erzeugt den Enable-Puls
62
63
void lcd_enable(void)
64
{
65
   LCD_ENP |= (1<<LCD_EN);    // kurze Pause (?!?)   
66
   LCD_ENP &= ~(1<<LCD_EN);
67
}
68
69
//******************************************************************************** 
70
// Initialisierung: 
71
// Muss ganz am Anfang des Programms aufgerufen werden.
72
 
73
void lcd_init(void)
74
{
75
     LCD_RSDDR |= (1<<LCD_RS);   //initial der ports (ausgänge schalten)
76
     LCD_ENDDR |= (1<<LCD_EN);   
77
  LCD_D3DDR  |=(1<<LCD_D3);
78
  LCD_D2DDR  |=(1<<LCD_D2);
79
  LCD_D1DDR  |=(1<<LCD_D1);
80
  LCD_D0DDR  |=(1<<LCD_D0); 
81
82
   // muss 3mal hintereinander gesendet werden zur Initialisierung
83
 
84
    waitms(15);          //nach power on warten..
85
86
   setPin();
87
    LCD_D1P |=(1<<LCD_D1);
88
  LCD_D0P |=(1<<LCD_D0);     
89
     LCD_RSP &= ~(1<<LCD_RS);    // RS auf 0
90
     lcd_enable();         //1.
91
  waitms(5);
92
93
     lcd_enable();         //2.
94
     waitms(1);
95
96
     lcd_enable();        //3.
97
     waitms(1);
98
 
99
     
100
     setPin();          // 4 Bit Modus aktivieren      
101
     LCD_D2P |= (1<<LCD_D2);      
102
     lcd_enable();
103
     waitms(1);
104
     
105
     lcd_command(0x28);      // 4Bit / 2 Zeilen / 5x7 char größe
106
     
107
     lcd_command(0x0C);       // Display ein / Cursor aus / kein Blinken 
108
     
109
     lcd_command(0x06);      // inkrement / kein Scrollen
110
 
111
     lcd_clear();
112
}
113
 
114
//********************************************************************************
115
// Sendet den Befehl zur Löschung des Displays
116
 
117
void lcd_clear(void)
118
{
119
   lcd_command(CLEAR_DISPLAY);
120
   waitms(5);
121
}
122
 
123
//********************************************************************************
124
// Sendet den Befehl: Cursor Home
125
 
126
void lcd_home(void)
127
{
128
   lcd_command(CURSOR_HOME);
129
   waitms(5);
130
}
131
132
//******************************************************************************** 
133
// setzt den Cursor in Zeile y (1..2) Spalte x (0..15)
134
 
135
void set_cursor(uint8_t x, uint8_t y)
136
{
137
  uint8_t tmp=0;
138
 
139
  switch (y) {
140
    case 1: tmp=0x80+0x00+x; break;    // 1. Zeile
141
    case 2: tmp=0x80+0x40+x; break;    // 2. Zeile
142
  }
143
  lcd_command(tmp);
144
}
145
146
//******************************************************************************** 
147
// Schreibt einen String auf das LCD
148
 
149
void lcd_string(char *data)
150
{
151
    while(*data) {
152
        lcd_data(*data);
153
        data++;
154
    }
155
}

und das die lcd.h


1
void lcd_data(unsigned char temp1);        //einzelnes Zeichen
2
void lcd_string(char *data);          //string ausgeben
3
void lcd_command(unsigned char temp1);          //komando an lcd
4
void lcd_enable(void);              //leachen der daten
5
void lcd_init(void);              //initialisierung
6
void lcd_home(void);              //cursor at home
7
void lcd_clear(void);              //bildschirm löschen
8
void set_cursor(uint8_t x, uint8_t y);            //cursor positionieren
9
void setPin(void);                //alle 4 Daten pins auf 0 setzen
10
 
11
// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!
12
 
13
#define F_CPU 8000000UL
14
 
15
// LCD Befehle
16
 
17
#define CLEAR_DISPLAY 0x01
18
#define CURSOR_HOME   0x02
19
20
//******************************************************** 
21
// Pinbelegung für das LCD, an verwendete Pins anpassen !!
22
23
#define LCD_RSDDR    DDRC    //rs und en ,ddr ,port ,pin
24
#define LCD_ENDDR    DDRB 
25
26
#define LCD_RSP      PORTC    
27
#define LCD_ENP      PORTB
28
29
#define LCD_RS       PC2
30
#define LCD_EN       PB2
31
32
//********************************************************
33
#define LCD_D0DDR    DDRB    //4 daten ,pins ,ddr ,port
34
#define LCD_D1DDR    DDRC
35
#define LCD_D2DDR    DDRB
36
#define LCD_D3DDR    DDRB
37
38
#define LCD_D0P      PORTB
39
#define LCD_D1P      PORTC
40
#define LCD_D2P      PORTB
41
#define LCD_D3P      PORTB
42
43
#define LCD_D0       PB1
44
#define LCD_D1       PC3
45
#define LCD_D2       PB5
46
#define LCD_D3       PB0
47
48
//********************************************************
49
#include "D:\avr\AVR\cprogs\libs\lcd\lcd.c"

von Ingo L. (grobian)


Lesenswert?

ich bin was c betrifft hier absoluter neuling, von daher mal die frage:

ich habe wie folgt angeschlossen:
1  Vss  GND
2  Vcc  5V
3  Vee  GND
4  RS  PB4 am AVR
5  RW  GND
6  E  PB5 am AVR
7  DB0  nicht angeschlossen
8  DB1  nicht angeschlossen
9  DB2  nicht angeschlossen
10  DB3  nicht angeschlossen
11  DB4  PB0 am AVR
12  DB5  PB1 am AVR
13  DB6  PB2 am AVR
14  DB7  PB3 am AVR


wo muß ich ändern??

von Daniel R. (zerrome)


Lesenswert?

Also erstmal in der lcd.h

Als Beispiel:

#define LCD_RSDDR    DDRB
#define LCD_ENDDR    DDRB

#define LCD_RSP      PORTB
#define LCD_ENP      PORTB

#define LCD_RS       PB4
#define LCD_EN       PB5

für die beiden Ports RS und EN

LCD_D0 wäre bei dir dann PB0 und so weiter...

Wichtig ist das der eigentliche Port z.B. LCD_RS und die beiden 
dazugehörigen anderen defines übereinstimmen (LCD_RSP und LCD_RSDDR).

von Karl H. (kbuchegg)


Lesenswert?

Da du die lcd Routinen hier aus dem gcc Tutorial benutzt.
In der lcd.h gibt es einen Abschnitt
1
// Pinbelegung für das LCD, an verwendete Pins anpassen
2
#define LCD_PORT      PORTD
3
#define LCD_DDR       DDRD
4
#define LCD_RS        PD4
5
#define LCD_EN        PD5

dort trägst du die Pinbelegung ein.
Dein LCD hängt am Port B. Also wird das wohl heissen
1
#define LCD_PORT      PORTB
mit dem Port einher geht das Data Direction Register
1
#define LCD_DDR       DDRB

Die Datenleitungen sind beim Tutorial Code fix auf Bit 0 bis
Bit4. Das passt mit deiner Belegung überein.

Deine RS Leitung hängt am Pin PB4. Also schreibst du das auch so rein
1
#define LCD_RS        PB4

und deine Enable-Leitung vom LCD geht auf Pin PB5
1
#define LCD_EN        PB5

Ist doch nicht so schwer, oder?

von Ingo L. (grobian)


Lesenswert?

na ja dafür,dass ich erst seit zwei Tagen dabei bin und es immerhin 
schon blinkt und läuft...geht doch oder??

von Ingo L. (grobian)


Lesenswert?

Ähhhhhh......wo finde ich die Dateien lcd.h und lcd.c ??

von Karl H. (kbuchegg)


Lesenswert?

Ingo Laabs wrote:
> Ähhhhhh......wo finde ich die Dateien lcd.h und lcd.c ??

Dazu müsste man erst mal wissen, welche do dir aus dem
Netz geholt hast. Die sind nicht beim Compiler dabei.

LCD Routinen gibt es wie Sand am Meer.
zb hier 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#LCD-Ansteuerung
oder auch hier 
Beitrag "Re: LCD AVR C ROUTINEN"
oder diese hier http://homepage.hispeed.ch/peterfleury/avr-software.html

von Ingo L. (grobian)


Lesenswert?

habe noch keine aus dem Netz gezogen..suche sie noch..s.o.

von Ingo L. (grobian)


Lesenswert?

So nun läuft mein LCD, habe jetzt nur ein Problem mit der Zeile 
set_cursor.
Ich bekomme den cursor nur in die 2. Zeile mit der Anweisung 
set_cursor(0,2). obwohl der Syntax doch eigentlich Zeile y(1..2) und 
Spalte x(0..15)
ist. Was ist hier falsch??

#define F_CPU 800000UL
#include <avr/io.h>
#include <util/delay.h>
#include <lcd.h>
#include <lcd.c>

int main(void)


lcd_init();

set_cursor(1,0);
lcd_string("ZEILE 1         ");

set_cursor(0,2);
lcd_string("ZEILE 2         ");

von fubu1000 (Gast)


Lesenswert?

Hallo,
ich nehme mal an du benutzt die lcd-routinen von mikrocontroller.net !
Du musst dir die Quellcodes schon mal anschauen, dann ist dir auch klar 
warum du nur mit 2 in die 2.Zeile kommst.
Der erstes aufruf ist übrigens falsch mit setcursor(1,0). Der 
funktioniert nur weil du vorher lcd_init() gemacht hast, der den Cursor 
schon auf Anfang setzt.

da steht nämlich .....

void set_cursor(unsigned char x, unsigned char y)
{
  unsigned char command;

    switch (y)
  {
      case 1:    command=0x80+0x00+x; break;    // 1. Zeile
      case 2:     command=0x80+0x40+x; break;    // 2. Zeile
}

das bedeutet also mit setcursor(0,1) -> 1.Zeile , 1.Zeichen und
setcursor (0,2) -> 2.Zeile , 1.Zeichen.

GRUSS

von Ingo L. (grobian)


Lesenswert?

gibt es da noch weitere kommandos, was kann ich noch bei lcd_init() 
einsetzen??

von Karl H. (kbuchegg)


Lesenswert?

Hier
http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD#Welche_Befehle_versteht_das_LCD.3F
findest du eine Übersicht über die Befehle, die so ein LCD
normalerweise versteht.

von Ingo L. (grobian)


Lesenswert?

Die sind mir bekannt.Ich meinte die kommandos von C aus ..sowie 
set_cursor
Ich kann doch mit sicherheit von c aus auch scrollen oder den cursor 
blinken lassen. sowas meint ich

von Daniel R. (zerrome)


Lesenswert?

Der Controller versteht gewisse Kommandos,

nachzulesen im Datenblatt oder hier :

http://www.mikrocontroller.net/articles/HD44780

von Karl H. (kbuchegg)


Lesenswert?

Ingo Laabs wrote:
> Die sind mir bekannt.Ich meinte die kommandos von C aus ..sowie
> set_cursor
> Ich kann doch mit sicherheit von c aus auch scrollen oder den cursor
> blinken lassen. sowas meint ich

Du hast die Kommandoübersicht.
Was hindert dich daran, dir diese Funktionen selber zu schreiben?
Immerhin bist du auf dem Weg Programmierer zu werden. Gewöhn dich
schon mal daran, dass das auch heisst: Sich selbst Werkzeuge
zu basteln.
"Malen nach Zahlen" war gestern. Heute entwirfst du selbst deine
Motive und mischt auch die Farben selbst.

von Daniel R. (zerrome)


Lesenswert?

Als Tipp :

Die Funktion lcd_command() kann schon Kommandos senden...

Musst jetzt noch ermitteln welchen Hex wert dein Kommando hat :)

von Ingo L. (grobian)


Lesenswert?

Bin dabei. Habe die Ansteuerung schon in Assembler mal geschrieben nur 
fehlt mir noch in C die gewisse Erfahrung da ich mich jetzt als 
Umsteiger betrachte. Denke aber mal ich bekomme das hin. In Assembler 
hat auch alles geklappt. Ist nur alles ein wenig gewöhnungsbedürftig in 
C..trotzdem DANKE :-)

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.