Forum: Mikrocontroller und Digitale Elektronik LCD mit PIC16 ansteuern


von Martin S. (drunkenmunky)


Lesenswert?

Hi,
ich versuche mit einem PIC16F887 das LCD auf dem PICDEM 2 PLUS DEMO 
BOARD anzusteuern. Habe das Programm größtenteils von dem Beispiel 
übernommen. Die Initialisierung und die Steueranweisungen für den Cursor 
funktionieren auch, nur Text schreiben mit der lcd_puts() Funktion 
funktioniert nicht. Kann mal bitte jemand drüberschauen?
1
/* This is a simple demo project written for use with
2
 * the HI-TECH Software PICC compiler. It may be compiled
3
 * and run on the Microchip PICDEM 2 PLUS DEMO BOARD.
4
 * Features demonstrated include driving the LCD display and
5
 * the A2D converter. 
6
 
7
 Additional files required for this demo are included in the
8
 PIC\SAMPLES directories:
9
 DELAY\delay.c
10
 DELAY\delay.h
11
 lcd.c
12
 lcd.h
13
 */
14
15
#include <htc.h>
16
#include <stdio.h>
17
//#include <pic16f887.h>
18
#include "lcd.h"
19
#include "delay.h"
20
//#include "picdem2_lcd_htc.h"
21
22
/* this is the maximum value of an A2D conversion. */
23
#define MAXVOLTAGE 5
24
25
void init(void){
26
  lcd_init(FOURBIT_MODE);
27
  ADON=1;  /* enable A2D converter */
28
  ADIE=0;  /* not interrupt driven */
29
  ADCON1=0x0E;
30
  ADCON0=1;
31
  TRISB=0x00;  // Set PORTB in output mode
32
  T1CON=0x31;  // turn on timer 1
33
  TMR1IE=1;  // timer 1 is interrupt enabled
34
  PEIE=1;    // enable peripheral interrupts
35
  GIE=1;    // turn on interrupts
36
}
37
38
void interrupt isr(void){
39
  if(TMR1IE && TMR1IF){
40
    PORTB++;
41
    TMR1IF=0;
42
  }
43
}
44
45
void main(void){
46
  unsigned char last_value;
47
  unsigned char volts;
48
  unsigned char decivolts;
49
  unsigned char outString[20];
50
51
  init();
52
  lcd_clear();
53
  DelayMs(500);
54
  DelayMs(500);
55
  DelayMs(500);
56
  lcd_puts("test");  
57
      
58
  while(1)
59
  {
60
    
61
  }
62
}
63
64
65
66
/*
67
 *  LCD interface example
68
 *  Uses routines from delay.c
69
 *  This code will interface to a standard LCD controller
70
 *  like the Hitachi HD44780. It uses it in 4 or 8 bit mode
71
 *  
72
 */
73
74
#include  <htc.h>
75
//#include <pic16f887.h>
76
#include  "lcd.h"
77
 
78
static bit fourbit;    // four or eight bit mode?
79
80
#ifdef CHECKBUSY
81
82
unsigned char 
83
lcd_read_cmd_nowait(void)
84
{
85
  unsigned char c, readc;
86
87
  LCD_DATA_TRIS   |=  ~OUTPUT_DATA;  // Set data lines to input
88
89
  LCD_RW = 1; // Read LCD
90
  _delay(2); // short propagation delay
91
92
  if (fourbit) {
93
    LCD_STROBE_READ(readc); // Read high nibble
94
    // Move 4 bits to high nibble while zeroing low nibble
95
    c = ( ( readc << 4 ) & 0xF0 ); 
96
    LCD_STROBE_READ(readc); // Read low nibble
97
        c |= ( readc & 0x0F ); // Or in 4 more bits to low nibble
98
  } else {
99
    LCD_STROBE_READ(readc); 
100
    c = readc;
101
  }
102
  LCD_RW = 0; // Return to default mode of writing LCD
103
  LCD_DATA_TRIS &= OUTPUT_DATA; // Return to default mode of writing LCD
104
105
  return(c);
106
}
107
108
void
109
lcd_check_busy(void) // Return when the LCD is no longer busy, or we've waiting long enough!
110
{
111
  // To avoid hanging forever in event there's a bad or 
112
  // missing LCD on hardware.  Will just run SLOW, but still run.
113
  unsigned int retry; 
114
  unsigned char c;
115
116
  for (retry=1000; retry-- > 0; ) {
117
    c = lcd_read_cmd_nowait();
118
    if (0==(c&0x80)) break; // Check busy bit.  If zero, no longer busy
119
  }
120
}
121
122
#endif
123
124
void
125
lcd_send(unsigned char c)
126
{  
127
  LCD_EN = 1;
128
  if (fourbit) {
129
    LCD_TX(c>>4);  // load upper nibble
130
    LCD_EN = 0;
131
    NOP();
132
    NOP();
133
    LCD_EN = 1;
134
    LCD_TX(c);  // load lower nibble
135
  } else {
136
    LCD_DATA = c;  // load both nibbles
137
  }
138
  LCD_EN = 0;
139
  
140
}
141
142
/* send a command to the LCD */
143
void
144
lcd_cmd(unsigned char c)
145
{
146
  LCD_WAIT; // may check LCD busy flag, or just delay a little, depending on lcd.h
147
  LCD_RS = 0;
148
  lcd_send(c);
149
}
150
151
/* send data to the LCD */
152
void
153
lcd_data(unsigned char c)
154
{
155
  LCD_WAIT; // may check LCD busy flag, or just delay a little, depending on lcd.h
156
  
157
  LCD_RS = 1;
158
  lcd_send(c);
159
  LCD_RS = 0;
160
}
161
162
/* write a string of chars to the LCD */
163
void
164
lcd_puts(const char * s)
165
{
166
  while(*s)
167
    lcd_data(*s++);
168
  
169
}
170
171
/* initialize the LCD */
172
void
173
lcd_init(unsigned char mode)
174
{
175
  char init_value;
176
177
  fourbit    = 0;
178
  if (mode == FOURBIT_MODE){
179
    fourbit = 1;
180
    init_value = 0x3;
181
  }else{
182
    init_value = 0x3F;
183
  }
184
185
#if (_PICDEM2_REVISION_ == 6)
186
  LCD_CTRL &= 0x0F;
187
  // All data and control lines on same TRIS register
188
  LCD_DATA_TRIS   &= (OUTPUT_DATA & OUTPUT_CTRL);
189
  LCD_VCC = 1;  // turn on the power to the LCD
190
#else
191
  LCD_RS = 0;
192
  LCD_EN = 0;
193
  LCD_RW = 0;
194
195
  // Set control lines digital
196
  ADCON1 = 7;
197
198
  // Set control lines to output
199
  LCD_RS_TRIS   = OUTPUT_PIN;
200
  LCD_EN_TRIS   = OUTPUT_PIN;
201
  LCD_RW_TRIS   = OUTPUT_PIN;
202
  // Set data lines to output
203
  LCD_DATA_TRIS   &= OUTPUT_DATA;
204
#endif
205
  __delay_ms(15);
206
  LCD_EN = 1;
207
  LCD_TX(init_value);
208
  LCD_EN = 0;
209
  __delay_ms(5);
210
  LCD_EN = 1;
211
  LCD_DATA |= init_value;
212
  LCD_EN = 0;
213
  __delay_us(200);
214
  LCD_EN = 1;
215
  LCD_DATA |= init_value;
216
  LCD_EN = 0;
217
  __delay_us(200);
218
  
219
  if (fourbit){
220
    LCD_WAIT;  //may check LCD busy flag, or just delay a little, depending on lcd.h
221
    LCD_EN = 1;
222
    LCD_TX(0x2);  // Set 4-bit mode
223
    LCD_EN = 0;
224
    lcd_cmd(0x28);  // Function Set
225
  }else{
226
    lcd_cmd(0x38);
227
  }
228
  lcd_cmd(0xF); //Display On, Cursor On, Cursor Blink
229
  lcd_clear(); //Display Clear
230
  lcd_cmd(0x6); //Entry Mode
231
  lcd_goto(0); //Initialize DDRAM address to zero
232
}

von Martin S. (drunkenmunky)


Lesenswert?

hat niemand eine Idee? Da die Steueranweisungen funktionieren, müssten 
die richtigen Ausgänge verwendet werden.

Was kann ich noch testen? Irgendwie von Hand ein Buchstaben schreiben? 
Hat jemand einen Beispielcode dafür?

Vielen Dank im voraus

von Maik W. (werner01)


Lesenswert?

Servus,

bei einem von beiden muss das rs_signal vorm enable immer gesetzt 
werden.
Machst Du das?

von Martin S. (drunkenmunky)


Lesenswert?

Ja das wird hier gemacht:

 LCD_RS = 1;
 lcd_send(c);
 LCD_RS = 0;

dann wird lcd_send aufgerufen und die zu übertragenden 8 Bit jeweils in 
4 Bit "zerlegt" und übertragen. Muss zwischen den einzelnen 4 Bit das 
LCD_RS Signal auch kurz auf 0 wechseln?

von Martin S. (drunkenmunky)


Lesenswert?

Hab den Fehler gefunden... peinlich, peinlich.

Irgendwie hab ich so lang umgeändert, dass ich irgendwie den Port A und 
D nicht als Ausgang definiert habe.

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.