RaspberryPiからaitendoのLCD[C128X64SPI-12P]への文字表示 (1)
タイトル通りAitendoの液晶ディスプレイモジュール[C128X64SPI-12P]に文字表示を行ったので書きます。
でその液晶なんですけど、FSTN液晶モジュール(128x64/SPI)@350円です。実際に買ったのはバックライトと基板付きのC128X64SPI-12P-M@580円のほうです。安いですね。その分、説明書のたぐいは一切付いてきません。ただし、サンプルコードが商品ページにあるのでそれを参考にしました。
用意するもの
- RaspberryPi
- 液晶モジュール
- ソフトウェア
- gcc (Debian 4.6.3-12+rpi1) 4.6.3 (デフォルトではいってるはず)
- wiringPi (インストール方法はwiringPiを使ってC言語でGPIOからLEDを点滅させる)
- フォントデータ (当記事参照)
- プログラムファイル (当記事参照)
- 文字コードへの関心
プログラム
とりあえず動けばいいんです。もうちょっとポインターとか勉強した方が良いですね、はい。
仕様としては、全角16文字x8行、半角なら32文字/行で、半角/全角混在可能です。
lcd_text.c
#include <wiringPi.h> #include <wiringPiSPI.h> #include <stdio.h> #include <iconv.h> #include <string.h> #include <stdlib.h> #define LCD_SDA 12 // GPIO 10 #define LCD_SCL 14 // GPIO 11 #define LCD_A0 6 // GPIO 25 #define LCD_CS 10 // GPIO 8 #define PAGE_SEL 0xB0 // (3) #define COL_SEL 0x10 // (4) #define MAX_BUF 256 unsigned char chardataHan[1024]; unsigned char chardataZen[70688]; void glcd_write_data(unsigned char dat) { digitalWrite(LCD_A0, 1); // 1ならデータ。0ならコマンド。 // unsigned char datr = ~dat; // 白黒反転 wiringPiSPIDataRW(0, &dat, 1); } // コマンドを出力する void glcd_write_cmd(unsigned char cmd) { digitalWrite(LCD_A0, 0); // 1ならデータ。0ならコマンド。 wiringPiSPIDataRW(0, &cmd, 1); } void glcd_init(void) { delay(10); glcd_write_cmd(0xE2); // (14) S/W RESWT glcd_write_cmd(0xA3); // (11) LCD bias(1/7) //glcd_write_cmd(0xAF); // (1) Display ON glcd_write_cmd(0xA0); // (8) segment direction.(normal direction) glcd_write_cmd(0xC8); // (15) Common Direction.(normal direction) glcd_write_cmd(0x22); // (17) Regultion resistor select(0x010) //25 glcd_write_cmd(0x81); // (18) EV Select. glcd_write_cmd(0x2f); // (18) Select EV value.(0x101111) glcd_write_cmd(0x2f); // (16) Power control(VB,VR,VF全部1) glcd_write_cmd(0x40); // (2) Initial display line(0に設定, MAX63) glcd_write_cmd(0xB0); // (3) Set page address(Y=0に設定, MAX15) glcd_write_cmd(0x10); // (4) Set coloumn addr MSB glcd_write_cmd(0x00); // (4) Set coloumn addr LSB(X=0に設定, MAX255) //glcd_write_cmd(0xAF); // (1) Display ON glcd_write_cmd(0xA4); // (10) all pixel ON(normal display) glcd_write_cmd(0xA6); // (9) Inverse Display(normal display) glcd_write_cmd(0xAF); // (1) Display ON } // 座標のセット void glcd_set_axis(int x, int page) { int col; // Selecting Page (3) glcd_write_cmd(PAGE_SEL | page); // Selecting Column col = (x & 0xF0) >> 4; // 上位ビット glcd_write_cmd(COL_SEL | col); // glcd_write_cmd(x & 0x0f); // 下位ビット } // 半角一文字出力 void output_font(char code) { int j; for (j = 0; j < 4; j++) glcd_write_data(chardataHan[code*4+j]); } // 全角一文字出力 void output_font2(char upper, char lower) { // 文字コードから文字データ配列のアドレスへと変換 int hosei = (upper- (upper >= 0xE0 ? 0xE0 : 0x81)) * 4 + (lower>0x7F ? 1 : 0) + (upper >= 0xE0 ? 0x7C : 0); int num = ((upper - (upper >= 0xE0 ? 0xE0 : 0x81))*0xC0 + lower-0x40 - hosei + (upper >= 0xE0 ? 0x1740 : 0))*8; printf("cc=%d, hosei=%d\n", num/8,hosei); int j; for (j = 0; j < 8; j++) // 全角 glcd_write_data(chardataZen[num+j]); } // 文字列出力 void output_text(char* text, int size) { int j; for (j = 0; j < size; j++) { char code = text[j]; if (code < 0x80 | (code >= 0xA0 & code < 0xE0)) { printf("code=%x\n",text[j]); output_font(text[j]); // 半角 } else { printf("code=%x %x\n",text[j], text[j+1]); output_font2(text[j], text[j+1]); // 全角 j++; } } } void utf2sjis(char utf8code[], char outbuf[]) { // ▼文字コード変換 int j; char inbuf[MAX_BUF+1] = { 0 }; char *in = inbuf; char *out = outbuf; size_t in_size = (size_t)MAX_BUF; size_t out_size = (size_t)MAX_BUF; iconv_t ic = iconv_open("SJIS", "UTF-8"); memcpy( in, utf8code, 64 ); iconv( ic, &in, &in_size, &out, &out_size ); iconv_close(ic); for (j = 0; j < 16; j++) printf("%x ", outbuf[j] ); } int fontOpen() { // ▼フォントファイルオープン FILE *fp; unsigned char buf[1024]; int size; fp = fopen( "misakiHan.dat", "rb" ); if( fp == NULL ) { printf( "misakiHan.dat が開けません\n" ); return -1; } size = fread( chardataHan, sizeof( unsigned char ), 1024, fp ); fclose(fp); // ▼フォントファイルオープン unsigned char buf2[70688]; int size2; fp = fopen( "misakiZen_gothic.dat", "rb" ); if( fp == NULL ) { printf( "misakiZen_gothic.dat が開けません\n" ); return -1; } size2 = fread( chardataZen, sizeof( unsigned char ), 70688, fp ); fclose(fp); } int main() { // ▼初期化 if (wiringPiSetup() == -1) { printf("wiringPiのセットアップに失敗しました。\n"); return 1; } int initv = wiringPiSPISetup(0, 1000000); printf("initv=%d\n", initv); if (initv < 0) { printf("wiringPiSPIのセットアップに失敗しました。\n"); return 1; } pinMode(LCD_A0, OUTPUT); glcd_init(); printf("init ok\n"); // ▼ここからメイン int fresult = fontOpen(); char outbuf[MAX_BUF+1] = { 0 }; glcd_set_axis(0,0); char* buff2 = " ==謹賀新年== "; utf2sjis(buff2, outbuf); output_text(outbuf, 64); glcd_set_axis(0,1); char* buff3 = "あけましておめでとうございます。"; utf2sjis(buff3, outbuf); output_text(outbuf, 64); glcd_set_axis(0,2); char* buff4 = " 今年もよろしくお願いします。 "; utf2sjis(buff4, outbuf); output_text(outbuf, 64); glcd_set_axis(0,3); char* buff5 = " 平成25年1月10日(木) "; utf2sjis(buff5, outbuf); output_text(outbuf, 64); glcd_set_axis(0,4); char* buff6 = " "; utf2sjis(buff6, outbuf); output_text(outbuf, 64); glcd_set_axis(0,5); char* buff7 = "X / _ / X <来週も見てくださいね!"; utf2sjis(buff7, outbuf); output_text(outbuf, 64); glcd_set_axis(0,6); char* buff8 = " "; utf2sjis(buff8, outbuf); output_text(outbuf, 64); glcd_set_axis(0,7); char* buff9 = "魑魅魍魎檸檬薔薇雲霧霜霰雹 凜 "; utf2sjis(buff9, outbuf); output_text(outbuf, 64); return 0; }
必要ファイル
フォントデータが無いと動きません。美咲フォントという素晴らしい漢字フォントがあるのでそれを使うことにしました。そのままでは使えないのであらかじめ変換しています。変換ソフトもそのうち公開予定です。
misaki_4x8_jisx0201.dat
misaki_gothic.dat
二つのファイルをプログラムファイルと同じディレクトリに入れるか、プログラムを変更してください。
あ、名前違いますね。misaki_4x8_jisx0201.datはmisakiHan.datに、misaki_gothic.datはmisakiZen_gothic.datにリネームしてください。
実行・出力例
sudo gcc lcd_test.c -o lcd_test -I/usr/local/include -L/usr/local/lib -lwiringPi sudo ./lcd_test
こんな感じ。もう13日ですけどね。