1 | #include <msp430x24x.h>
|
2 |
|
3 | #define LCM_4DIR P4DIR
|
4 | #define LCM_4OUT P4OUT
|
5 | #define LCM_5DIR P4DIR
|
6 | #define LCM_5OUT P4OUT
|
7 |
|
8 | //
|
9 | // Define symbolic LCM - MCU pin mappings
|
10 | // We've set DATA PIN TO 4,5,6,7 for easy translation
|
11 | //
|
12 | #define LCM_PIN_RS BIT1 // Px.0
|
13 | #define LCM_PIN_EN BIT0 // Px.1
|
14 | #define LCM_PIN_D7 BIT0 // Px.7
|
15 | #define LCM_PIN_D6 BIT1 // Px.6
|
16 | #define LCM_PIN_D5 BIT2 // Px.5
|
17 | #define LCM_PIN_D4 BIT3 // Px.4
|
18 |
|
19 |
|
20 | #define LCM_P4_MASK ((LCM_PIN_D7 | LCM_PIN_D6 | LCM_PIN_D5 | LCM_PIN_D4))
|
21 | #define LCM_P5_MASK ((LCM_PIN_RS | LCM_PIN_EN))
|
22 |
|
23 | #define FALSE 0
|
24 | #define TRUE 1
|
25 |
|
26 | //
|
27 | // Routine Desc:
|
28 | //
|
29 | // This is the function that must be called
|
30 | // whenever the LCM needs to be told to
|
31 | // scan it's data bus.
|
32 | //
|
33 | // Parameters:
|
34 | //
|
35 | // void.
|
36 | //
|
37 | // Return
|
38 | //
|
39 | // void.
|
40 | //
|
41 | void PulseLcm()
|
42 | {
|
43 | //
|
44 | // pull EN bit low
|
45 | //
|
46 | LCM_5OUT &= ~LCM_PIN_EN;
|
47 | __delay_cycles(200);
|
48 |
|
49 | //
|
50 | // pull EN bit high
|
51 | //
|
52 | LCM_5OUT |= LCM_PIN_EN;
|
53 | __delay_cycles(200);
|
54 |
|
55 | //
|
56 | // pull EN bit low again
|
57 | //
|
58 | LCM_5OUT &= (~LCM_PIN_EN);
|
59 | __delay_cycles(200);
|
60 | }
|
61 |
|
62 |
|
63 |
|
64 | //
|
65 | // Routine Desc:
|
66 | //
|
67 | // Send a byte on the data bus in the 4 bit mode
|
68 | // This requires sending the data in two chunks.
|
69 | // The high nibble first and then the low nible
|
70 | //
|
71 | // Parameters:
|
72 | //
|
73 | // ByteToSend - the single byte to send
|
74 | //
|
75 | // IsData - set to TRUE if the byte is character data
|
76 | // FALSE if its a command
|
77 | //
|
78 | // Return
|
79 | //
|
80 | // void.
|
81 | //
|
82 | void SendByte(char ByteToSend, int IsData)
|
83 | {
|
84 | //
|
85 | // clear out all pins
|
86 | //
|
87 | LCM_4OUT &= (~LCM_P4_MASK);
|
88 | //
|
89 | // set High Nibble (HN) -
|
90 | // usefulness of the identity mapping
|
91 | // apparent here. We can set the
|
92 | // DB7 - DB4 just by setting P1.7 - P1.4
|
93 | // using a simple assignment
|
94 | //
|
95 | LCM_4OUT |= (ByteToSend & 0xF0);
|
96 |
|
97 | if (IsData == TRUE)
|
98 | {
|
99 | LCM_5OUT |= LCM_PIN_RS;
|
100 | }
|
101 | else
|
102 | {
|
103 | LCM_5OUT &= ~LCM_PIN_RS;
|
104 | }
|
105 |
|
106 | //
|
107 | // we've set up the input voltages to the LCM.
|
108 | // Now tell it to read them.
|
109 | //
|
110 | PulseLcm();
|
111 | //
|
112 | // set Low Nibble (LN) -
|
113 | // usefulness of the identity mapping
|
114 | // apparent here. We can set the
|
115 | // DB7 - DB4 just by setting P1.7 - P1.4
|
116 | // using a simple assignment
|
117 | //
|
118 | LCM_4OUT &= (~LCM_P4_MASK);
|
119 | LCM_4OUT |= ((ByteToSend & 0x0F) << 4);
|
120 |
|
121 | if (IsData == TRUE)
|
122 | {
|
123 | LCM_5OUT |= LCM_PIN_RS;
|
124 | }
|
125 | else
|
126 | {
|
127 | LCM_5OUT &= ~LCM_PIN_RS;
|
128 | }
|
129 |
|
130 | //
|
131 | // we've set up the input voltages to the LCM.
|
132 | // Now tell it to read them.
|
133 | //
|
134 | PulseLcm();
|
135 | }
|
136 |
|
137 |
|
138 | //
|
139 | // Routine Desc:
|
140 | //
|
141 | // Set the position of the cursor on the screen
|
142 | //
|
143 | // Parameters:
|
144 | //
|
145 | // Row - zero based row number
|
146 | //
|
147 | // Col - zero based col number
|
148 | //
|
149 | // Return
|
150 | //
|
151 | // void.
|
152 | //
|
153 | void LcmSetCursorPosition(char Row, char Col)
|
154 | {
|
155 | char address;
|
156 |
|
157 | //
|
158 | // construct address from (Row, Col) pair
|
159 | //
|
160 | if (Row == 0)
|
161 | {
|
162 | address = 0;
|
163 | }
|
164 | else
|
165 | {
|
166 | address = 0x40;
|
167 | }
|
168 |
|
169 | address |= Col;
|
170 |
|
171 | SendByte(0x80 | address, FALSE);
|
172 | }
|
173 |
|
174 |
|
175 | //
|
176 | // Routine Desc:
|
177 | //
|
178 | // Clear the screen data and return the
|
179 | // cursor to home position
|
180 | //
|
181 | // Parameters:
|
182 | //
|
183 | // void.
|
184 | //
|
185 | // Return
|
186 | //
|
187 | // void.
|
188 | //
|
189 | void ClearLcmScreen()
|
190 | {
|
191 | //
|
192 | // Clear display, return home
|
193 | //
|
194 | SendByte(0x01, FALSE);
|
195 | SendByte(0x02, FALSE);
|
196 | }
|
197 |
|
198 |
|
199 | //
|
200 | // Routine Desc:
|
201 | //
|
202 | // Initialize the LCM after power-up.
|
203 | //
|
204 | // Note: This routine must not be called twice on the
|
205 | // LCM. This is not so uncommon when the power
|
206 | // for the MCU and LCM are separate.
|
207 | //
|
208 | // Parameters:
|
209 | //
|
210 | // void.
|
211 | //
|
212 | // Return
|
213 | //
|
214 | // void.
|
215 | //
|
216 | void InitializeLcm(void)
|
217 | {
|
218 | //
|
219 | // set the MSP pin configurations
|
220 | // and bring them to low
|
221 | //
|
222 | LCM_5DIR |= LCM_P5_MASK;
|
223 | LCM_5OUT &= ~(LCM_P5_MASK);
|
224 |
|
225 |
|
226 | //
|
227 | // wait for the LCM to warm up and reach
|
228 | // active regions. Remember MSPs can power
|
229 | // up much faster than the LCM.
|
230 | //
|
231 | __delay_cycles(100000);
|
232 |
|
233 |
|
234 | //
|
235 | // initialize the LCM module
|
236 | //
|
237 | // 1. Set 4-bit input
|
238 | //
|
239 | LCM_5OUT &= ~LCM_PIN_RS;
|
240 | LCM_5OUT &= ~LCM_PIN_EN;
|
241 |
|
242 | LCM_5OUT = 0x20;
|
243 | PulseLcm();
|
244 |
|
245 | //
|
246 | // set 4-bit input - second time.
|
247 | // (as reqd by the spec.)
|
248 | //
|
249 | SendByte(0x28, FALSE);
|
250 |
|
251 | //
|
252 | // 2. Display on, cursor on, blink cursor
|
253 | //
|
254 | SendByte(0x0E, FALSE);
|
255 |
|
256 | //
|
257 | // 3. Cursor move auto-increment
|
258 | //
|
259 | SendByte(0x06, FALSE);
|
260 | }
|
261 |
|
262 |
|
263 | //
|
264 | // Routine Desc
|
265 | //
|
266 | // Print a string of characters to the screen
|
267 | //
|
268 | // Parameters:
|
269 | //
|
270 | // Text - null terminated string of chars
|
271 | //
|
272 | // Returns
|
273 | //
|
274 | // void.
|
275 | //
|
276 | void PrintStr(char *Text)
|
277 | {
|
278 | char *c;
|
279 |
|
280 | c = Text;
|
281 |
|
282 | while ((c != 0) && (*c != 0))
|
283 | {
|
284 | SendByte(*c, TRUE);
|
285 | c++;
|
286 | }
|
287 | }
|
288 |
|
289 |
|
290 | //
|
291 | // Routine Desc
|
292 | //
|
293 | // main entry point to the sketch
|
294 | //
|
295 | // Parameters
|
296 | //
|
297 | // void.
|
298 | //
|
299 | // Returns
|
300 | //
|
301 | // void.
|
302 | //
|
303 | void main(void)
|
304 | {
|
305 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
|
306 |
|
307 | InitializeLcm();
|
308 |
|
309 | ClearLcmScreen();
|
310 |
|
311 | PrintStr("Hello World!");
|
312 |
|
313 | while (1)
|
314 | {
|
315 | __delay_cycles(1000);
|
316 | }
|
317 |
|
318 | }
|