SujetTP3-2018: lcd_user.c

File lcd_user.c, 6.9 KB (added by franck, 9 years ago)
Line 
1/*******************************************************************************
2 * lcdr_user.c - Controleur pour LCd HD44780 ( 20x4 )
3 ******************************************************************************/
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8#include <stdint.h>
9#include <string.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <fcntl.h>
13#include <sys/mman.h>
14
15/*******************************************************************************
16 * GPIO Pins
17 ******************************************************************************/
18#define RS 7
19#define E 27
20#define D4 22
21#define D5 23
22#define D6 24
23#define D7 25
24
25#define GPIO_INPUT 0
26#define GPIO_OUTPUT 1
27
28#define RPI_BLOCK_SIZE 0xB4
29#define RPI_GPIO_BASE 0x20200000
30
31struct gpio_s
32{
33 uint32_t gpfsel[7];
34 uint32_t gpset[3];
35 uint32_t gpclr[3];
36 uint32_t gplev[3];
37 uint32_t gpeds[3];
38 uint32_t gpren[3];
39 uint32_t gpfen[3];
40 uint32_t gphen[3];
41 uint32_t gplen[3];
42 uint32_t gparen[3];
43 uint32_t gpafen[3];
44 uint32_t gppud[1];
45 uint32_t gppudclk[3];
46 uint32_t test[1];
47};
48volatile struct gpio_s* gpio_regs;
49
50/*******************************************************************************
51 * GPIO Operations
52 ******************************************************************************/
53
54int gpio_setup ( void ){
55
56 int mmap_fd = open ("/dev/mem", O_RDWR | O_SYNC );
57 if ( mmap_fd < 0 ) {
58 return -1;
59 }
60
61 gpio_regs = mmap ( NULL, RPI_BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, RPI_GPIO_BASE );
62 if ( gpio_regs == MAP_FAILED ) {
63 close ( mmap_fd );
64 return -1;
65 }
66
67 return 0;
68}
69
70void gpio_teardown ( void ){
71 munmap((void*)gpio_regs, RPI_BLOCK_SIZE);
72}
73
74
75void gpio_config(int gpio, int value)
76{
77 gpio_regs->gpfsel[gpio/10] = ( gpio_regs->gpfsel[gpio/10] & ~(0x7 << ((gpio % 10) * 3)) )
78 | (value << ((gpio % 10) * 3));
79}
80
81void gpio_update(int gpio, int value)
82{
83 if( value )
84 gpio_regs->gpset[gpio/32] = (0x1 << (gpio % 32) );
85 else
86 gpio_regs->gpclr[gpio/32] = (0x1 << (gpio % 32) );
87}
88
89/*******************************************************************************
90 * LCD's Instructions ( source = doc )
91 ******************************************************************************/
92
93#define B_0000 0
94#define B_0001 1
95#define B_0010 2
96#define B_0011 3
97#define B_0100 4
98#define B_0101 5
99#define B_0110 6
100#define B_0111 7
101#define B_1000 8
102#define B_1001 9
103#define B_1010 a
104#define B_1011 b
105#define B_1100 c
106#define B_1101 d
107#define B_1110 e
108#define B_1111 f
109
110/* On veut definir une macro HEX()
111 * qui prend en argument deux nombres de 4 bits exprimes en binaire
112 * representant resp. les 4 bits de poids fort et les 4 bits de poids faible d'un entier sur 8bits
113 * qui rend l'entier.
114 * p. ex: HEX(0000,0010) rend 2
115 * p. ex: HEX(0001,0000) rend 16
116 *
117 * QUESTION: expliquez comment ca marche ....
118 */
119#define __HEX(h,l) 0x##h##l
120#define _HEX(h,l) __HEX(h,l)
121#define HEX(h,l) _HEX(B_##h,B_##l)
122
123/* QUESTION: que fait cette macro ?
124 */
125#define BIT(b,n) (((n)>>(b))&1)
126
127/* commands */
128#define LCD_CLEARDISPLAY HEX(0000,0001)
129#define LCD_RETURNHOME HEX(0000,0010)
130#define LCD_ENTRYMODESET HEX(0000,0100)
131#define LCD_DISPLAYCONTROL HEX(0000,1000)
132#define LCD_CURSORSHIFT HEX(0001,0000)
133#define LCD_FUNCTIONSET HEX(0010,0000)
134#define LCD_SETCGRAMADDR HEX(0100,0000)
135#define LCD_SETDDRAMADDR HEX(1000,0000)
136
137/* flags for display entry mode : combine with LCD_ENTRYMODESET */
138#define LCD_EM_RIGHT HEX(0000,0000)
139#define LCD_EM_LEFT HEX(0000,0010)
140#define LCD_EM_DISPLAYSHIFT HEX(0000,0001)
141#define LCD_EM_DISPLAYNOSHIFT HEX(0000,0000)
142
143/* flags for display on/off control : combine with LCD_DISPLAYCONTROL */
144#define LCD_DC_DISPLAYON HEX(0000,0100)
145#define LCD_DC_DISPLAYOFF HEX(0000,0000)
146#define LCD_DC_CURSORON HEX(0000,0010)
147#define LCD_DC_CURSOROFF HEX(0000,0000)
148#define LCD_DC_BLINKON HEX(0000,0001)
149#define LCD_DC_BLINKOFF HEX(0000,0000)
150
151/* flags for display/cursor shift : combine with LCD_CURSORSHIFT */
152#define LCD_CS_DISPLAYMOVE HEX(0000,1000)
153#define LCD_CS_CURSORMOVE HEX(0000,0000)
154#define LCD_CS_MOVERIGHT HEX(0000,0100)
155#define LCD_CS_MOVELEFT HEX(0000,0000)
156
157/* flags for function set : combine with LCD_FUNCTIONSET */
158#define LCD_FS_8BITMODE HEX(0001,0000)
159#define LCD_FS_4BITMODE HEX(0000,0000)
160#define LCD_FS_2LINE HEX(0000,1000)
161#define LCD_FS_1LINE HEX(0000,0000)
162#define LCD_FS_5x10DOTS HEX(0000,0100)
163#define LCD_FS_5x8DOTS HEX(0000,0000)
164
165/*******************************************************************************
166 * LCD's Operations
167 ******************************************************************************/
168
169/* generate E signal */
170void lcd_strobe(void)
171{
172 /* A completer */
173}
174
175/* send 4bits to LCD */
176void lcd_write4bits(int data)
177{
178 /* first 4 bits */
179 gpio_update(D7, BIT(7,data));
180 /* a completer */
181 lcd_strobe();
182
183 /* second 4 bits */
184 /* a completer */
185 lcd_strobe();
186 usleep(50); /* le délai minimum est de 37us */
187}
188
189void lcd_command(int cmd)
190{
191 gpio_update(RS, 0);
192 lcd_write4bits(cmd);
193 usleep(2000); /* delai nécessaire pour certaines commandes */
194}
195
196void lcd_data(int character)
197{
198 gpio_update(RS, 1);
199 lcd_write4bits(character);
200}
201
202/* initialization
203 * Question : commenter ces initialisations:
204 *
205 * LCD_FUNCTIONSET | LCD_FS_4BITMODE | LCD_FS_2LINE | LCD_FS_5x8DOTS
206 * LCD_DISPLAYCONTROL | LCD_DC_DISPLAYON | LCD_DC_CURSOROFF
207 * LCD_ENTRYMODESET | LCD_EM_RIGHT | LCD_EM_DISPLAYNOSHIFT
208 */
209void lcd_init(void)
210{
211 gpio_update(E, 0);
212 lcd_command(HEX(0011,0011)); /* initialization */
213 lcd_command(HEX(0011,0010)); /* initialization */
214 lcd_command(LCD_FUNCTIONSET | LCD_FS_/* a completer */ );
215 lcd_command(LCD_DISPLAYCONTROL | LCD_DC_/* a completer */ );
216 lcd_command(LCD_ENTRYMODESET | LCD_EM_/* a completer */ );
217}
218
219void lcd_clear(void)
220{
221 lcd_command(LCD_CLEARDISPLAY);
222 lcd_command(LCD_RETURNHOME);
223}
224
225void lcd_message(char* txt)
226{
227 int i, j;
228 for(i=0; i<20 && i<strlen(txt); i++){
229 lcd_data(txt[i]);
230 }
231}
232/*******************************************************************************
233 * Finally, the main function
234 ******************************************************************************/
235int main(int argc, char** argv)
236{
237 /* arg */
238 if( argc < 2 ){
239 fprintf(stderr, "ERROR: must take a string as argument\n");
240 exit(1);
241 }
242
243 /* Retreive the mapped GPIO memory */
244 if( gpio_setup() == -1 ){
245 perror("ERROR: gpio_setup\n");
246 exit(1);
247 }
248
249 /* Setting up GPIOs to output */
250 gpio_config(RS, GPIO_OUTPUT);
251 gpio_config(E , GPIO_OUTPUT);
252 gpio_config(D4, GPIO_OUTPUT);
253 gpio_config(D5, GPIO_OUTPUT);
254 gpio_config(D6, GPIO_OUTPUT);
255 gpio_config(D7, GPIO_OUTPUT);
256
257 /* initialization */
258 lcd_init();
259 lcd_clear();
260
261 /* print app argument */
262 lcd_message(argv[1]);
263
264 /* Release the GPIO memory mapping */
265 gpio_teardown();
266
267 return 0;
268}