[DM8168]Linux下控制GPIO控制12864液晶屏(ST7565控制器)
首先加载驱动模块,应用程序通过调用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 --*/
应用程序:
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 }