IOC_T03: lcd_user.c

File lcd_user.c, 6.9 KB (added by franck, 7 years ago)

Affichage d'un message sur le LCD en mode user

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
31// Q1: A quoi sert le mot clé volatile
32struct gpio_s {
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
54// Q2: Expliquer la présence des drapeaux dans open() et mmap().
55int gpio_setup(void)
56{
57
58 int mmap_fd = open("/dev/mem", O_RDWR | O_SYNC);
59 if (mmap_fd < 0) {
60 return -1;
61 }
62 gpio_regs = mmap(NULL, RPI_BLOCK_SIZE,
63 PROT_READ | PROT_WRITE, MAP_SHARED,
64 mmap_fd,
65 RPI_GPIO_BASE);
66 if (gpio_regs == MAP_FAILED) {
67 close(mmap_fd);
68 return -1;
69 }
70 return 0;
71}
72
73// Q3: pourquoi appeler munmap() ?
74void gpio_teardown(void)
75{
76 munmap((void *) gpio_regs, RPI_BLOCK_SIZE);
77}
78
79void gpio_config(int gpio, int value)
80{
81 int regnum = gpio / 10;
82 int offset = (gpio % 10) * 3;
83 gpio_regs->gpfsel[regnum] &= ~(0x7 << offset);
84 gpio_regs->gpfsel[regnum] |= ((value & 0x7) << offset);
85}
86
87void gpio_write(int gpio, int value)
88{
89 int regnum = gpio / 32;
90 int offset = gpio % 32;
91 if (value&1)
92 gpio_regs->gpset[regnum] = (0x1 << offset);
93 else
94 gpio_regs->gpclr[regnum] = (0x1 << offset);
95}
96
97/*******************************************************************************
98 * LCD's Instructions ( source = doc )
99 * Ces constantes sont utilisées pour former les mots de commandes
100 * par exemple dans la fonction lcd_init()
101 ******************************************************************************/
102
103/* commands */
104#define LCD_CLEARDISPLAY 0b00000001
105#define LCD_RETURNHOME 0b00000010
106#define LCD_ENTRYMODESET 0b00000100
107#define LCD_DISPLAYCONTROL 0b00001000
108#define LCD_CURSORSHIFT 0b00010000
109#define LCD_FUNCTIONSET 0b00100000
110#define LCD_SETCGRAMADDR 0b01000000
111#define LCD_SETDDRAMADDR 0b10000000
112
113/* flags for display entry mode : combine with LCD_ENTRYMODESET */
114#define LCD_EM_RIGHT 0b00000000
115#define LCD_EM_LEFT 0b00000010
116#define LCD_EM_DISPLAYSHIFT 0b00000001
117#define LCD_EM_DISPLAYNOSHIFT 0b00000000
118
119/* flags for display on/off control : combine with LCD_DISPLAYCONTROL */
120#define LCD_DC_DISPLAYON 0b00000100
121#define LCD_DC_DISPLAYOFF 0b00000000
122#define LCD_DC_CURSORON 0b00000010
123#define LCD_DC_CURSOROFF 0b00000000
124#define LCD_DC_BLINKON 0b00000001
125#define LCD_DC_BLINKOFF 0b00000000
126
127/* flags for display/cursor shift : combine with LCD_CURSORSHIFT */
128#define LCD_CS_DISPLAYMOVE 0b00001000
129#define LCD_CS_CURSORMOVE 0b00000000
130#define LCD_CS_MOVERIGHT 0b00000100
131#define LCD_CS_MOVELEFT 0b00000000
132
133/* flags for function set : combine with LCD_FUNCTIONSET */
134#define LCD_FS_8BITMODE 0b00010000
135#define LCD_FS_4BITMODE 0b00000000
136#define LCD_FS_2LINE 0b00001000
137#define LCD_FS_1LINE 0b00000000
138#define LCD_FS_5x10DOTS 0b00000100
139#define LCD_FS_5x8DOTS 0b00000000
140
141/*******************************************************************************
142 * LCD's Operations
143 ******************************************************************************/
144
145/* generate E signal */
146void lcd_strobe(void)
147{
148 gpio_write(E, 1);
149 usleep(1);
150 gpio_write(E, 0);
151}
152
153/* send 4bits to LCD : valable pour les commande et les data */
154
155void lcd_write4bits(int data)
156{
157 /* first 4 bits */
158 gpio_write(D7, data>>7);
159 gpio_write(D6, data>>6);
160 gpio_write(D5, data>>5);
161 gpio_write(D4, data>>4);
162 lcd_strobe();
163
164 /* second 4 bits */
165 gpio_write(D7, data>>3);
166 gpio_write(D6, data>>2);
167 gpio_write(D5, data>>1);
168 gpio_write(D4, data>>0);
169 lcd_strobe();
170}
171
172void lcd_command(int cmd)
173{
174 gpio_write(RS, 0);
175 lcd_write4bits(cmd);
176 usleep(2000); // certaines commandes sont lentes
177}
178
179void lcd_data(int character)
180{
181 gpio_write(RS, 1);
182 lcd_write4bits(character);
183 usleep(1);
184}
185
186/* initialization : pour comprendre la séquence, il faut regarder le cours */
187// Q4: Expliquer le rôle des masques : LCD_FUNCTIONSET, LCD_FS_4BITMODE, etc.
188void lcd_init(void)
189{
190 gpio_write(E, 0);
191 lcd_command(0b00110011); /* initialization */
192 lcd_command(0b00110010); /* initialization */
193 lcd_command(LCD_FUNCTIONSET | LCD_FS_4BITMODE | LCD_FS_2LINE | LCD_FS_5x8DOTS);
194 lcd_command(LCD_DISPLAYCONTROL | LCD_DC_DISPLAYON | LCD_DC_CURSOROFF);
195 lcd_command(LCD_ENTRYMODESET | LCD_EM_RIGHT | LCD_EM_DISPLAYNOSHIFT);
196}
197
198void lcd_clear(void)
199{
200 lcd_command(LCD_CLEARDISPLAY);
201 lcd_command(LCD_RETURNHOME);
202}
203
204// Q5: Expliquez comment fonctionne cette fonction
205void lcd_message(const char *txt)
206{
207 int a[] = { 0, 0x40, 0x14, 0x54 };
208 int len = 20;
209 int i, l;
210
211 for (i = 0, l = 0; (l < 4) && (i < strlen(txt)); l++) {
212 lcd_command(LCD_SETDDRAMADDR + a[l]);
213 for (; (i < (l + 1) * len) && (i < strlen(txt)); i++) {
214 lcd_data(txt[i]);
215 }
216 }
217}
218
219/*******************************************************************************
220 * main : affichage d'un message
221 ******************************************************************************/
222int main(int argc, char **argv)
223{
224 /* arg */
225 if (argc < 2) {
226 fprintf(stderr, "ERROR: must take a string as argument\n");
227 exit(1);
228 }
229
230 /* Retreive the mapped GPIO memory */
231 if (gpio_setup() == -1) {
232 perror("ERROR: gpio_setup\n");
233 exit(1);
234 }
235
236 /* Setting up GPIOs to output */
237 gpio_config(RS, GPIO_OUTPUT);
238 gpio_config(E, GPIO_OUTPUT);
239 gpio_config(D4, GPIO_OUTPUT);
240 gpio_config(D5, GPIO_OUTPUT);
241 gpio_config(D6, GPIO_OUTPUT);
242 gpio_config(D7, GPIO_OUTPUT);
243
244 /* initialization */
245 lcd_init();
246 lcd_clear();
247
248 /* affichage */
249 lcd_message(argv[1]);
250
251 /* Release the GPIO memory mapping */
252 gpio_teardown();
253
254 return 0;
255}