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 | }
|