LCDについて
LCDの概要
現在はLCDが普及して入手しやすい状況になってきました。入手しやすくなったのはいいことですが、
Android端末並みに豪華な表示インターフェースが必要な場合はグラフィックLCDを使いますが、
現在、
LCDのスペック
今回、
- LCDキャラクタディスプレイモジュール(16×2行バックライト無) 
- URL:http://akizukidenshi. com/ catalog/ g/gP-00040 
上記サイトでは、
 
対象とするLCDのデータバス本数は8本ですが、
SH7706LSRとの接続
電源電圧の整合
一昔前まではデジタル回路の電源電圧は5V系統で統一されていましたが、
3.
SH7706LSRのような3,3V系統のマイコンボードに5V電源系統のような異なる電源系統どうしを接続する場合、
 
後継互換コントローラの実際
オリジナルのHD44780は完全に5V電源になっています。今は現物のHD44780が使われることはなく、
コントローラ自体が3.
SH7706LSRとの接続方法について
SH7706LSRとの接続は、
 
液晶駆動用に別途、
 
ただし、
負電源(マイナス電源)発生回路  
負電源発生回路は本格的なものとなると複雑になってしまいますが、
 
原理としては単純であり、
両方のコンデンサ間の経路はD1経由とD2経由がありますが、
SH7706LSRではリアルタイムクロック出力端子があるので、
 
SH7706LSRとの接続例
SH7706LSRとLCDの接続は汎用I/
 
基本的に端子は任意でいいですが、
LCDデバイスドライバ
ソフトウェアとハードウェアの分担
マイクロコンピュータと周辺コントローラの間でのバスインターフェース接続では、
 
図8のような標準インターフェースでは、
しかし、
 
LCDに文字を出力する概要
HD44780の詳細な使い方については液晶購入時に同時に添付されるデータシートを参照してください。図7の接続回路に対応したLCDデバイスドライバのソースコードはリスト1の通りとなります。
  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  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  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に対して文字を出力するには、
デバイスドライバインターフェース
今回はデータ出力処理のみなので、
OSからデータ書き込みリクエストがあるとlcd_
LCDの1行あたりの文字数は16文字なので16文字目でリスト1の95行目ではLCDでの改行処理をしています。ASCIIコードでスペースより小さいコードは制御コードなので、
その他補足事項
最下位層であるLCD端子の個別制御はそれぞれ次の3つの関数で行っています。
CDのE端子の制御はリスト1の18~24行目で行なっています。
LCDのRS端子の制御はリスト1の27~33行目で行なっています。
4本のデータ端子の制御はリスト1の36~57行目で行なっています。
LCDの制御は汎用I/
LCDデバイスドライバのコンパイルと実行
LCDデバイスドライバのコンパイルには、
 1     TARGET:= lcd.ko
 2     
 3     all: ${TARGET}
 4     
 5     lcd.ko: lcd.c
 6             make ARCH=sh CROSS_COMPILE=sh3-linux- -C ../linux-2.6.28.10 M=`pwd` modules
 7     
 8     clean:
 9             make ARCH=sh CROSS_COMPILE=sh3-linux- -C ../linux-2.6.28.10 M=`pwd` clean
10     
11     obj-m:= lcd.o
12     
13     clean-files := *.o *.ko *.order *.mod.[co] *.markers *~コンパイルは以下のように行います。
$ make make ARCH=sh CROSS_COMPILE=sh3-linux- -C ../linux-2.6.28.10 M=`pwd` modules make[1]: Entering directory `/home/general/linux-2.6.28.10' CC [M] /home/general/lcd/lcd.o Building modules, stage 2. MODPOST 1 modules CC /home/general/lcd/lcd.mod.o LD [M] /home/general/lcd/lcd.ko make[1]: Leaving directory `/home/general/linux-2.6.28.10' $
SH7706LSRボードでLCDデバイスドライバを組み込む場合は insmodコマンドで引数にLCDデバイスドライバを指定します。
比較的新しいLinuxカーネルの場合は自動でデバイスファイルを生成してくれますが、
1 /bin/sh
2 
3 r item in `cat /proc/devices`;
4 
5 if [ $item = lcd ]; then
6   mknod /dev/lcd c $major 0
7 fi
8 major=$item
9 ne次回は
次回はSH7706LSRボードでセルフコンパイル可能なSH3用のgccの移植について解説をします。