LCDデバイスドライバ
ソフトウェアとハードウェアの分担
マイクロコンピュータと周辺コントローラの間でのバスインターフェース接続では,
図8のような標準インターフェースでは,
しかし,
LCDに文字を出力する概要
HD44780の詳細な使い方については液晶購入時に同時に添付されるデータシートを参照してください。図7の接続回路に対応したLCDデバイスドライバのソースコードはリスト1の通りとなります。
リスト1 LCDデバイスドライバのプログラム
1 #include <linux/module.h>
2 #include <linux/init.h>
3 #include <linux/device.h>
4 #include <linux/ctype.h>
5 #include <linux/poll.h>
6 #include <linux/delay.h>
7 #include <asm/io.h>
8
9 #define PFC_PDCR 0xa4000106UL
10 #define PFC_PECR 0xa4000108UL
11 #define PORT_PDDR 0xa4000126UL
12 #define PORT_PEDR 0xa4000128UL
13 #define TMU_TOCR 0xfffffe90UL
14
15 static int lcd_major;
16
17 // PTD6
18 static void lcd_enable(int enable) {
19 if(enable) {
20 ctrl_outb(ctrl_inb(PORT_PDDR) | 0x40, PORT_PDDR);
21 } else {
22 ctrl_outb(ctrl_inb(PORT_PDDR) & ~0x40, PORT_PDDR);
23 }
24 }
25
26 // PTD7
27 static void lcd_rs(int rs) {
28 if(rs) {
29 ctrl_outb(ctrl_inb(PORT_PDDR) | 0x80, PORT_PDDR);
30 } else {
31 ctrl_outb(ctrl_inb(PORT_PDDR) & ~0x80, PORT_PDDR);
32 }
33 }
34
35 // D4=PTE1 D5=PTE3 D6=PTD5 D7=PTD1
36 static void lcd_data(int data) {
37 if(data & 0x10) {
38 ctrl_outb(ctrl_inb(PORT_PEDR) | 0x02, PORT_PEDR);
39 } else {
40 ctrl_outb(ctrl_inb(PORT_PEDR) & ~0x02, PORT_PEDR);
41 }
42 if(data & 0x20) {
43 ctrl_outb(ctrl_inb(PORT_PEDR) | 0x08, PORT_PEDR);
44 } else {
45 ctrl_outb(ctrl_inb(PORT_PEDR) & ~0x08, PORT_PEDR);
46 }
47 if(data & 0x40) {
48 ctrl_outb(ctrl_inb(PORT_PDDR) | 0x20, PORT_PDDR);
49 } else {
50 ctrl_outb(ctrl_inb(PORT_PDDR) & ~0x20, PORT_PDDR);
51 }
52 if(data & 0x80) {
53 ctrl_outb(ctrl_inb(PORT_PDDR) | 0x02, PORT_PDDR);
54 } else {
55 ctrl_outb(ctrl_inb(PORT_PDDR) & ~0x02, PORT_PDDR);
56 }
57 }
58
59 static void lcd_out8(int data) {
60 lcd_enable(1);
61 lcd_rs(0);
62 lcd_data(data);
63 udelay(83);
64 lcd_enable(0);
65 udelay(4000);
66 }
67
68 static void lcd_out4(int rs, int data) {
69 lcd_enable(1);
70 lcd_rs(rs);
71 lcd_data(data);
72 udelay(83);
73 lcd_enable(0);
74 udelay(83);
75 lcd_enable(1);
76 lcd_data(data << 4);
77 udelay(83);
78 lcd_enable(0);
79 if(rs == 0) {
80 udelay(4000);
81 } else {
82 udelay(83);
83 }
84 }
85
86 static ssize_t lcd_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) {
87 ssize_t n, d;
88 unsigned char c;
89
90 lcd_out4(0, 0x01);
91 d = 0;
92 for(n = 0;n < count;n++) {
93 copy_from_user(&c, buf + n, 1);
94 if(c >= ' ') {
95 if(d == 16) lcd_out4(0, 0x80 + 0x40);
96 if(d < 32) lcd_out4(1, (int)c & 0xff);
97 d++;
98 }
99 }
100 return count;
101 }
102
103 static const struct file_operations lcd_fops = {
104 .owner = THIS_MODULE,
105 .write = lcd_write,
106 };
107
108 #define CHRDEV "lcd"
109 static int __init lcd_init (void) {
110 lcd_major = register_chrdev(0, CHRDEV, &lcd_fops);
111 ctrl_outw(0x5404, PFC_PDCR);
112 ctrl_outw(0x0044, PFC_PECR);
113 ctrl_outb(0x01, TMU_TOCR);
114 lcd_rs(0);
115 lcd_enable(0);
116 lcd_data(0);
117 udelay(4000);
118 lcd_out8(0x30);
119 udelay(4000);
120 lcd_out8(0x30);
121 udelay(4000);
122 lcd_out8(0x30);
123 udelay(4000);
124 lcd_out8(0x20);
125 lcd_out4(0, 0x28); // Function set
126 lcd_out4(0, 0x0c); // Display on
127 lcd_out4(0, 0x06); // Entry mode
128 lcd_out4(0, 0x01);
129 printk(KERN_INFO "LCD Device Driver\n");
130 return 0;
131 }
132
133 static void __exit lcd_cleanup (void) {
134 unregister_chrdev(lcd_major, CHRDEV);
135 ctrl_outb(0x00, TMU_TOCR);
136 printk(KERN_INFO "LCD Device Driver Exit\n");
137 }
138
139 module_init(lcd_init);
140 module_exit(lcd_cleanup);
141
142 MODULE_LICENSE("GPL");
LCD制御で行う処理の概要は,
LCDに対して文字を出力するには,