PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lcd4bit_4lines.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 #include "pic24_all.h"
31 
32 
33 /** \file
34 Demonstrates a 4-line 20x4 Character LCD using the industry
35 standard parallel interface in 4-bit mode.
36 Assumes a 5V LCD; digital-only IO pins are assumed
37 to be used for the four-bit data bus because they are
38 5V input tolerant.
39 
40 Tested with Hantronix HDM20416L-M.
41 */
42 
43 #define RS_HIGH() _LATB9 = 1
44 #define RS_LOW() _LATB9 = 0
45 #define CONFIG_RS() CONFIG_RB9_AS_DIG_OUTPUT()
46 
47 #define RW_HIGH() _LATB13 = 1
48 #define RW_LOW() _LATB13 = 0
49 #define CONFIG_RW() CONFIG_RB13_AS_DIG_OUTPUT()
50 
51 #define E_HIGH() _LATB14 = 1
52 #define E_LOW() _LATB14 = 0
53 #define CONFIG_E() CONFIG_RB14_AS_DIG_OUTPUT()
54 
55 #define LCD4O _LATB5
56 #define LCD5O _LATB6
57 #define LCD6O _LATB7
58 #define LCD7O _LATB8
59 #define LCD7I _RB8
60 
61 #define CONFIG_LCD4_AS_INPUT() CONFIG_RB5_AS_DIG_INPUT()
62 #define CONFIG_LCD5_AS_INPUT() CONFIG_RB6_AS_DIG_INPUT()
63 #define CONFIG_LCD6_AS_INPUT() CONFIG_RB7_AS_DIG_INPUT()
64 #define CONFIG_LCD7_AS_INPUT() CONFIG_RB8_AS_DIG_INPUT()
65 
66 #define CONFIG_LCD4_AS_OUTPUT() CONFIG_RB5_AS_DIG_OUTPUT()
67 #define CONFIG_LCD5_AS_OUTPUT() CONFIG_RB6_AS_DIG_OUTPUT()
68 #define CONFIG_LCD6_AS_OUTPUT() CONFIG_RB7_AS_DIG_OUTPUT()
69 #define CONFIG_LCD7_AS_OUTPUT() CONFIG_RB8_AS_DIG_OUTPUT()
70 
71 #define GET_BUSY_FLAG() LCD7I
72 
73 
74 
75 /**
76  Functions above this line must be redefined for
77  your particular PICmicro-to-LCD interface
78 */
79 
80 //Configure 4-bit data bus for output
81 void configBusAsOutLCD(void) {
82  RW_LOW(); //RW=0 to stop LCD from driving pins
83  CONFIG_LCD4_AS_OUTPUT(); //D4
84  CONFIG_LCD5_AS_OUTPUT(); //D5
85  CONFIG_LCD6_AS_OUTPUT(); //D6
86  CONFIG_LCD7_AS_OUTPUT(); //D7
87 }
88 
89 //Configure 4-bit data bus for input
90 void configBusAsInLCD(void) {
91  CONFIG_LCD4_AS_INPUT(); //D4
92  CONFIG_LCD5_AS_INPUT(); //D5
93  CONFIG_LCD6_AS_INPUT(); //D6
94  CONFIG_LCD7_AS_INPUT(); //D7
95  RW_HIGH(); // R/W = 1, for read
96 }
97 
98 //Output lower 4-bits of u8_c to LCD data lines
99 void outputToBusLCD(uint8_t u8_c) {
100  LCD4O = u8_c & 0x01; //D4
101  LCD5O = (u8_c >> 1)& 0x01; //D5
102  LCD6O = (u8_c >> 2)& 0x01; //D6
103  LCD7O = (u8_c >> 3)& 0x01; //D7
104 }
105 
106 //Configure the control lines for the LCD
107 void configControlLCD(void) {
108  CONFIG_RS(); //RS
109  CONFIG_RW(); //RW
110  CONFIG_E(); //E
111  RW_LOW();
112  E_LOW();
113  RS_LOW();
114 }
115 
116 //Pulse the E clock, 1 us delay around edges for
117 //setup/hold times
118 void pulseE(void) {
119  DELAY_US(1);
120  E_HIGH();
121  DELAY_US(1);
122  E_LOW();
123  DELAY_US(1);
124 }
125 
126 /* Write a byte (u8_Cmd) to the LCD.
127 u8_DataFlag is '1' if data byte, '0' if command byte
128 u8_CheckBusy is '1' if must poll busy bit before write, else simply delay before write
129 u8_Send8Bits is '1' if must send all 8 bits, else send only upper 4-bits
130 */
131 void writeLCD(uint8_t u8_Cmd, uint8_t u8_DataFlag,
132  uint8_t u8_CheckBusy, uint8_t u8_Send8Bits) {
133 
134  uint8_t u8_BusyFlag;
135  uint8_t u8_wdtState;
136  if (u8_CheckBusy) {
137  RS_LOW(); //RS = 0 to check busy
138  // check busy
139  configBusAsInLCD(); //set data pins all inputs
140  u8_wdtState = _SWDTEN; //save WDT enable state
141  CLRWDT(); //clear the WDT timer
142  _SWDTEN = 1; //enable WDT to escape infinite wait
143  do {
144  E_HIGH();
145  DELAY_US(1); // read upper 4 bits
146  u8_BusyFlag = GET_BUSY_FLAG();
147  E_LOW();
148  DELAY_US(1);
149  pulseE(); //pulse again for lower 4-bits
150  } while (u8_BusyFlag);
151  _SWDTEN = u8_wdtState; //restore WDT enable state
152  } else {
153  DELAY_MS(10); // don't use busy, just delay
154  }
156  if (u8_DataFlag) RS_HIGH(); // RS=1, data byte
157  else RS_LOW(); // RS=0, command byte
158  outputToBusLCD(u8_Cmd >> 4); // send upper 4 bits
159  pulseE();
160  if (u8_Send8Bits) {
161  outputToBusLCD(u8_Cmd); // send lower 4 bits
162  pulseE();
163  }
164 }
165 
166 //These definitions are for a Hantronix 20x4 LCD
167 #define GOTO_LINE1() writeLCD(0x80,0,1,1)
168 #define GOTO_LINE2() writeLCD(0xC0,0,1,1)
169 #define GOTO_LINE3() writeLCD(0x94,0,1,1)
170 #define GOTO_LINE4() writeLCD(0xD4,0,1,1)
171 
172 // Initialize the LCD, modify to suit your application and LCD
173 void initLCD() {
174  DELAY_MS(50); //wait for device to settle
175  writeLCD(0x20,0,0,0); // 4 bit interface
176  writeLCD(0x28,0,0,1); // 2 line display, 5x7 font
177  writeLCD(0x28,0,0,1); // repeat
178  writeLCD(0x06,0,0,1); // enable display
179  writeLCD(0x0C,0,0,1); // turn display on; cursor, blink is off
180  writeLCD(0x01,0,0,1); // clear display, move cursor to home
181  DELAY_MS(3);
182 }
183 
184 //Output a string to the LCD
185 void outStringLCD(char *psz_s) {
186  while (*psz_s) {
187  writeLCD(*psz_s, 1, 1,1);
188  psz_s++;
189  }
190 }
191 
192 
193 int main (void) {
194  configBasic(HELLO_MSG); // Set up heartbeat, UART, print hello message and diags
195 
196  configControlLCD(); //configure the LCD control lines
197  initLCD(); //initialize the LCD
198 
199  GOTO_LINE1(); // cursor to 1st line
200  outStringLCD("Line 1");
201  GOTO_LINE2(); // cursor to 2nd line
202  outStringLCD("Line 2");
203  GOTO_LINE3(); // cursor to 3rd line
204  outStringLCD("Line 3");
205  GOTO_LINE4(); // cursor to 4th line
206  outStringLCD("Line 4");
207  while (1) {
208  doHeartbeat();
209  }
210 }