Linux下控制GPIO控制12864液晶屏(ST7565控制器,DM8168)

首先加载驱动模块,应用程序通过调用API实现GPIO控制功能。

驱动函数:

  1 /*
  2 * fileName: st7565_driver.c
  3 * just for LCD12864 driver
  4 * GP1_14(46) -> D6(SCK)
  5 * GP1_15(47) -> D7(SDA)
  6 * GP1_27(59) -> RST
  7 * GP1_28(60) -> RS
  8 */
  9 
 10 #include <linux/device.h>
 11 #include <linux/fs.h>
 12 #include <linux/module.h>
 13 #include <linux/kernel.h>
 14 #include <linux/init.h>
 15 #include <linux/moduleparam.h>
 16 #include <linux/list.h>
 17 #include <linux/cdev.h>
 18 #include <linux/proc_fs.h>
 19 #include <linux/mm.h>
 20 #include <linux/seq_file.h>
 21 #include <linux/ioport.h>
 22 #include <linux/delay.h>
 23 #include <asm/io.h>
 24 #include <linux/io.h>
 25 #include <mach/gpio.h>
 26 #include <linux/device.h>
 27 #include <linux/platform_device.h>
 28 
 29 #include <linux/delay.h>
 30 
 31 // ASCII code
 32 #include "font.h"
 33 
 34 #define DRIVERNAME  "lcd12864"
 35 
 36 // PANEL CON
 37 #define CTRL_MODULE_BASE_ADDR    0x48140000
 38 #define conf_gpio46              (CTRL_MODULE_BASE_ADDR + 0x0B04)
 39 #define conf_gpio47              (CTRL_MODULE_BASE_ADDR + 0x0B08)
 40 #define conf_gpio59              (CTRL_MODULE_BASE_ADDR + 0x0AB8)
 41 #define conf_gpio60              (CTRL_MODULE_BASE_ADDR + 0x0ABC)
 42 
 43 #define WR_MEM_32(addr, data)    *(unsigned int*)OMAP2_L4_IO_ADDRESS(addr) = (unsigned int)(data)
 44 #define RD_MEM_32(addr)          *(unsigned int*)OMAP2_L4_IO_ADDRESS(addr)
 45 
 46 // LCD spec
 47 #define _delay_ms(n)   mdelay(n)  
 48 #define ST7565_X_SIZE  128
 49 #define ST7565_Y_SIZE  64
 50 #define u8  unsigned char
 51 #define u16 unsigned int
 52 
 53 #define LCD_SCK_H  gpio_set_value(46, 1);
 54 #define LCD_SCK_L  gpio_set_value(46, 0);
 55 #define LCD_SDA_H  gpio_set_value(47, 1);
 56 #define LCD_SDA_L  gpio_set_value(47, 0);
 57 #define LCD_CS_H
 58 #define LCD_CS_L
 59 #define LCD_RST_H  gpio_set_value(59, 1);
 60 #define LCD_RST_L  gpio_set_value(59, 0);
 61 #define LCD_RS_H   gpio_set_value(60, 1);
 62 #define LCD_RS_L   gpio_set_value(60, 0);
 63 
 64 static        dev_t  lcd_dev;
 65 static struct cdev   lcd_cdev;
 66 static struct class  *lcd_class = NULL;
 67 static int gpio[4];
 68 
 69 static int     lcd12864_open(struct inode *inode, struct file *file);
 70 static int     lcd12864_close(struct inode *inode, struct file *file);
 71 static ssize_t lcd12864_write(struct file *file, const char *buf, size_t count, loff_t *offset);
 72 
 73 // ST7565 gpio config
 74 static void store_gpio_pin(void)
 75 {
 76     // store gpio pinmux
 77     gpio[0] = RD_MEM_32(conf_gpio46);
 78     gpio[1] = RD_MEM_32(conf_gpio47);
 79     gpio[2] = RD_MEM_32(conf_gpio59);
 80     gpio[3] = RD_MEM_32(conf_gpio60);
 81 }
 82 
 83 static void recover_gpio_pin(void)
 84 {
 85     // recover gpio pinmux
 86     WR_MEM_32(conf_gpio46, gpio[0]);
 87     WR_MEM_32(conf_gpio47, gpio[1]);
 88     WR_MEM_32(conf_gpio59, gpio[2]);
 89     WR_MEM_32(conf_gpio60, gpio[3]);
 90     gpio_free(gpio[0]);
 91     gpio_free(gpio[1]);
 92     gpio_free(gpio[2]);
 93     gpio_free(gpio[3]);
 94 } 
 95 
 96 static void config_gpio_pin(void)
 97 {
 98     // config gpio direction
 99     WR_MEM_32(conf_gpio46, 2); 
100     gpio_request(46, "gpio46_en");       // request gpio46
101     gpio_direction_output(46, 0);
102 
103     WR_MEM_32(conf_gpio47, 2); 
104     gpio_request(47, "gpio47_en");       // request gpio47
105     gpio_direction_output(47, 0);
106 
107     WR_MEM_32(conf_gpio59, 1); 
108     gpio_request(59, "gpio59_en");       // request gpio59
109     gpio_direction_output(59, 0);   
110 
111     WR_MEM_32(conf_gpio60, 1); 
112     gpio_request(60, "gpio60_en");       // request gpio60
113     gpio_direction_output(60, 0);   
114 }
115 
116 // ST7565 basic driver
117 void ST7565_WrByte(u8 chr, u8 dir)
118 {
119     u8 i=0;
120     if(dir == 0){ LCD_RS_L;}
121     else { LCD_RS_H;}
122     for(i = 0; i < 8; i++){
123         LCD_SCK_L;
124         if(chr & 0x80){ LCD_SDA_H;}    
125         else { LCD_SDA_L;}
126         chr = (chr << 1);
127         LCD_SCK_H;
128     }
129 }
130 
131 void ST7565_PgSet(u8 clm, u8 pag)
132 {
133     u8 lsb = 0;
134     u8 msb = 0;
135     lsb = clm & 0x0F;        // 
136     msb = clm & 0xF0;       // 
137     msb = msb >> 4;            // 
138     msb = msb | 0x10;        // 
139     pag = pag | 0xB0;        //
140     ST7565_WrByte(pag, 0);    // 
141     ST7565_WrByte(msb, 0);    // 
142     ST7565_WrByte(lsb, 0);     // 0 - 127
143 }
144 
145 void ST7565_Clear(void)
146 {
147     u8 i = 0;
148     u8 j = 0;
149 //    LCD_CS_L;
150     for(i=0; i < ST7565_Y_SIZE/8; i++){
151         ST7565_PgSet(0, i);
152         for(j=0; j < ST7565_X_SIZE; j++){
153             ST7565_WrByte(0x00, 1);    
154         }        
155     }    
156 //    LCD_CS_H;
157 }
158 
159 void ST7565_Init(void)
160 {
161 //    LCD_CS_L;
162     LCD_RST_L;
163     _delay_ms(1);
164     LCD_RST_H;
165 
166     ST7565_WrByte(0xE2, 0);         // software rst
167     _delay_ms(1);
168     ST7565_WrByte(0x2C, 0);      // burst stage1
169     _delay_ms(1);    
170     ST7565_WrByte(0x2E, 0);      // burst stage2
171     _delay_ms(1);
172     ST7565_WrByte(0x2F, 0);      // burst stage3
173     _delay_ms(1);
174     ST7565_WrByte(0x25, 0);      // 
175     ST7565_WrByte(0x81, 0);      // 
176     ST7565_WrByte(0x16, 0);      // 
177     ST7565_WrByte(0xA2, 0);      //
178     ST7565_WrByte(0xC8, 0);      //
179     ST7565_WrByte(0xA0, 0);      //
180     ST7565_WrByte(0x40, 0);      //
181     ST7565_WrByte(0xAF, 0);      // open display
182 
183 //    LCD_CS_H;
184     ST7565_Clear();
185 }
186 
187 void ST7565_DispChr(u8 xpos, u8 ypos, char chr)
188 {
189     u8 i=0;
190     ST7565_PgSet(xpos, ypos);
191     for(i=0; i<6; i++){          
192         // six bytes
193         ST7565_WrByte(ascii_0806[0][(chr- )*6 + i], 1);
194     }
195 }
196 
197 // lcd file operations
198 static int lcd12864_open(struct inode *inode, struct file *file)
199 {
200     store_gpio_pin();
201     config_gpio_pin();
202 
203     ST7565_Init();
204     return 0;
205 }
206 
207 static int lcd12864_close(struct inode *inode, struct file *file)
208 {
209     recover_gpio_pin();
210     return 0;
211 }
212 
213 static ssize_t lcd12864_write(struct file *file, const char *buf, size_t count, loff_t *offset)
214 {
215     unsigned char cnt=0;
216     unsigned char raw;     // y
217     unsigned char col;     // x
218 
219     char *data = NULL;    
220 
221     if(count == 0)
222         ST7565_Clear();
223     else{
224         data = (char *)kzalloc(count, GFP_KERNEL);  // kmalloc to kzalloc
225         memcpy(data, buf, count);
226         raw = *data;
227         col = *(data+1);
228         while(cnt < (count-2)){
229             // offset
230             ST7565_DispChr(col+6*cnt, raw, *(data+cnt+2)); 
231             cnt++;  // char++ 
232         }
233         kfree(data);        
234         data = NULL;      
235     }
236 
237     return count;
238 }
239 
240 static struct file_operations lcd12864_fops = 
241 {
242     .owner = THIS_MODULE,
243     .open  = lcd12864_open,
244     .release = lcd12864_close,
245     .write = lcd12864_write,
246 };
247 
248 static int __init LCD12864_init(void)
249 {
250     int result;
251 
252     result = alloc_chrdev_region(&lcd_dev, 0, 1, DRIVERNAME);
253     if(result < 0){
254         printk("Error registering led_gpio character device\n");
255         return -ENODEV;
256     }
257     printk("st7565_driver major#: %d, minor#: %d\n", MAJOR(lcd_dev), MINOR(lcd_dev));
258 
259     cdev_init(&lcd_cdev, &lcd12864_fops);
260     lcd_cdev.owner = THIS_MODULE;
261     lcd_cdev.ops = &lcd12864_fops; 
262 
263     result = cdev_add(&lcd_cdev, lcd_dev, 1);
264     if(result){
265         unregister_chrdev_region(lcd_dev, 1);
266         printk("Error adding led_gpio.. error no:%d\n", result);
267         return -EINVAL;
268     }
269     lcd_class = class_create(THIS_MODULE, DRIVERNAME);
270     device_create(lcd_class, NULL, lcd_dev, NULL, DRIVERNAME);
271 
272     printk(DRIVERNAME " initialized!\n");
273 
274     return 0;
275 }
276 
277 static void __exit LCD12864_exit(void)
278 {
279     printk(KERN_EMERG "lcd12864 driver exit!\n");
280     cdev_del(&lcd_cdev);
281     unregister_chrdev_region(lcd_dev, 1);
282     device_destroy(lcd_class, lcd_dev);
283     class_destroy(lcd_class);
284 }
285 
286 module_init(LCD12864_init);
287 module_exit(LCD12864_exit);
288 MODULE_LICENSE("GPL");

API函数:

 1 #ifndef API_LCD12864_H
 2 #define API_LCD12864_H
 3 #include <stdio.h>
 4 
 5 #ifdef __cplusplus
 6 extern "C" {
 7 #endif
 8 
 9 #define u8  unsigned char
10 #define u16 unsigned int
11 
12 int api_lcd12864_open(void);
13 int api_lcd12864_close(int fd_lcd);
14 int api_lcd12864_dispstr(int fd_lcd, u8 row, u8 col, char *str);
15 
16 #ifdef __cplusplus
17 }
18 #endif
19 
20 #endif
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <fcntl.h>
 5 #include <unistd.h>
 6 #include <sys/types.h>
 7 #include <sys/stat.h>
 8 #include "api_lcd12864.h"
 9 
10 // #define u8  unsigned char
11 // #define u16 unsigned int
12 
13 #define DEVICENAME "/dev/lcd12864"
14 
15 int api_lcd12864_open(void)
16 {
17     int fd_lcd;
18     if((fd_lcd = open(DEVICENAME, O_RDWR)) <= -1){
19         printf("open device error\n");
20         return -1;
21     }
22     return fd_lcd;
23 }
24 
25 int api_lcd12864_close(int fd_lcd)
26 {
27     if(0 == close(fd_lcd))
28         return 0;
29     else
30         return -1;
31 }
32 
33 int api_lcd12864_dispstr(int fd_lcd, u8 row, u8 col, char *str)
34 {
35     unsigned int cnt;
36     char ret;
37     char *data = NULL;
38 
39     cnt = 2+(strlen(str));
40     data = (char *)malloc(cnt);
41 
42     *data = row;
43     *(data+1) = col;     
44  
45     memcpy(data+2, str, cnt-2);
46 
47     if(write(fd_lcd, data, cnt) < 0){
48         printf("write error\n");        
49         ret = -1;
50     }
51     else{
52         ret = 0;
53     }
54     
55     free(data);
56     data = NULL;
57     
58     return ret;
59 }
60 
61 
62 /*--
63 void ST7565_DispStr(u8 xpos, u8 ypos, u8 *str)
64 {
65     u8 i=0;  // the num of bytes
66     LCD_CS_L;
67     while(*(str+i) != ‘\0‘){
68         // offset
69         ST7565_DispChr(xpos+6*i, ypos, *(str+i)); 
70         i++;  // char++ 
71     }
72     LCD_CS_H;
73 }
74 --*/
75 /*--
76 void ST7565_DispNum(u8 xpos,u8 ypos, u32 num, u8 len)
77 {
78     LCD_CS_L;
79     while(len > 0){
80         // ascii
81         ST7565_DispChr(xpos+6*(--len), ypos, num%10 + ‘0‘); 
82         num = num / 10;
83     }
84     LCD_CS_H;
85 }
86 --*/
View Code

应用程序:

 1 /*- test for Lcd12864 -*/
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <string.h>
 5 #include <unistd.h>
 6 #include <time.h>
 7 #include "api_lcd12864.h"
 8 int main(void)
 9 {
10     int fd_lcd;
11 //    unsigned int num=0;
12     char date_str[30];
13     char num_str1[20];
14     char num_str2[20];
15     time_t rawtime;
16     struct tm *timeinfo; 
17 
18 //    int delay = 10;
19     
20     fd_lcd = api_lcd12864_open();
21 //    my_tt = time(&NULL);
22     
23     if(fd_lcd < 0){
24         printf("fd_lcd open failed!\n");
25         return -1;
26     }
27     
28     api_lcd12864_dispstr(fd_lcd, 0, 0, "hello, linux");
29 
30     printf("Hello, LCD displaying!\n");
31 
32 //    api_lcd12864_close(fd_lcd);
33 
34     while(1){
35 //        sprintf(num_str, "%d", num);      
36         time(&rawtime);
37         timeinfo = localtime(&rawtime);
38         strcpy(date_str, asctime(timeinfo));
39         
40 //        printf("Time is: %s\n", date_str);
41 
42         memcpy(num_str1, date_str+0, 11);
43         num_str1[11] = \0;
44         api_lcd12864_dispstr(fd_lcd, 1, 0, num_str1);  // Web Feb 13
45 
46         memcpy(num_str2, date_str+11, 13);
47         num_str2[13] = \0;
48         api_lcd12864_dispstr(fd_lcd, 2, 0, num_str2);  // 09:49:30 2014
49 
50 //        if(num == 65535) num=0;
51 //        num ++;
52         usleep(200000);
53     }
54 
55     api_lcd12864_close(fd_lcd);
56     
57     return 0;
58 }

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。