13 August 2012

PIC16F690でC言語(XC8)を使ってLCDに文字表示

中国のSure Electronicsから個人輸入したLCD(2002 LCD Module)に、PIC16F690を使って文字表示する。

日本国内の電子パーツ屋で購入すると500円~1000円ほどするLCDモジュールが、中国から個人輸入すれば送料込みで4米ドル(300円程度)と割安だ。ただし、説明書などは一切付いていないので、全て自力解決出来る自信が無ければ手を出さないのが吉。(そもそも、個人向け商品ではなく、工場などの生産現場へのパーツの卸売業)


■ 検証環境
・LCD : Sure Electronics 2002 LCD Module (20x2 Character)
・PIC16F690

・Microchip MPLAB X IDE ver 1.30
・Microchip MPLAB XC8 ver 1.01

20120813-lcd-breadboard.jpg
ブレッドボード上に作成したテスト回路

20120813-circuit.png
回路図

コントラスト調整用の半固定抵抗は、SD1602Hのデータシートによれば20kオームのものを用いているが、今回は10kオームしか手元に無かったのでそれを使っている。なお、Voは0.5V程度でちょうどよいコントラストになるようだ。

■ main関数部分

#include <stdio.h> #include <stdlib.h> #include<xc.h> #include "lcd_lib.h" __CONFIG(CP_OFF & CPD_OFF & BOREN_OFF & MCLRE_OFF & WDTE_OFF & PWRTE_ON & FOSC_INTRCIO); #ifndef _XTAL_FREQ /* 例:4MHzの場合、4000000 をセットする */ #define _XTAL_FREQ 4000000 #endif /* printf関数の出力先のスタブ関数を定義する */ void putch(unsigned char ch){ lcd_putch(ch); return; } int main(int argc, char** argv) { OSCCON = 0b01100000; /* 内部オシレーター 4MHz */ TRISA = 0b00001000; /* IOポートRA0...RA5を出力モードに(RA3は仕様により入力専用) */ TRISB = 0; /* IOポートRB4...RB7を出力モードに */ TRISC = 0; /* IOポートRC0...RC7を出力モードに */ INTCONbits.PEIE = 0; /* 割り込み機能をOFF */ PORTA = 0; /* RA0...RA5をV-low */ PORTB = 0; /* RB4...RA7をV-low */ PORTC = 0; /* RC0...RC7をV-low */ CM1CON0 = 0; /* コンパレーター1 無効化設定 */ CM2CON0 = 0; /* コンパレーター1 無効化設定 */ ANSEL = 0; /* 全てのA/Dコンバータを無効化 */ ANSELH = 0; /* 全てのA/Dコンバータを無効化 */ __delay_ms(1000); lcd_init(); lcd_goto(0); lcd_puts("Initialize LCD ..."); for(unsigned int i=0; i<1000; i++) { __delay_ms(1000); lcd_clear(); lcd_goto(0); printf("%03d : Test Count", i); lcd_goto(0x40); lcd_puts("PIC 16F690"); } return (EXIT_SUCCESS); }

■ LCD共通関数

lcd_lib.h
#ifndef LCD_LIB_H #define LCD_LIB_H #ifdef __cplusplus extern "C" { #endif void lcd_write(unsigned char c); void lcd_clear(void); void lcd_puts(const char * s); void lcd_putch(char c); void lcd_goto(unsigned char pos); void lcd_init(void); #ifdef __cplusplus } #endif #endif /* LCD_LIB_H */

 

lcd_lib.c
#include <stdio.h> #include <stdlib.h> #include <xc.h> #include "lcd_lib.h" #ifndef _XTAL_FREQ /* 例:4MHzの場合、4000000 をセットする */ #define _XTAL_FREQ 4000000 #endif /* LCD_RS : データ制御ポート */ #define LCD_RS RC4 /* LCD_R/W : Read/Write選択ポート */ #define LCD_RW RC5 /* LCD_E : Eneble信号(この信号をHiにしている間、RS,R/W,Dataの送受信が行われる) */ #define LCD_EN RC6 /* データポート: LCD_DB4=RC0, LCD_DB5=RC1, LCD_DB6=RC2, LCD_DB7=RC3 */ #define LCD_DATA PORTC /* ENピンの信号を一瞬プルアップしてデータ転送 */ #define LCD_STROBE() ((LCD_EN = 1),(LCD_EN = 0)) /* 4ビットモードでの8ビット分のデータ転送 */ void lcd_write(unsigned char c) { __delay_us(40); LCD_DATA = (LCD_DATA & 0xf0) | ((c >> 4) & 0x0f); LCD_STROBE(); LCD_DATA = (LCD_DATA & 0xf0) | (c & 0x0f); LCD_STROBE(); } /* 画面クリア */ void lcd_clear(void) { LCD_RS = 0; lcd_write(0x1); __delay_ms(2); } /* カーソル位置に文字列を出力 */ void lcd_puts(const char * s) { LCD_RS = 1; // write characters while(*s) lcd_write(*s++); } /* カーソル位置に1文字出力 */ void lcd_putch(char c) { LCD_RS = 1; // write characters lcd_write( c ); } /* カーソル位置の設定 */ void lcd_goto(unsigned char pos) { LCD_RS = 0; lcd_write(0x80+pos); } /* LCDを4ビットモードで初期化 */ void lcd_init() { LCD_RS = 0; LCD_EN = 0; LCD_RW = 0; __delay_ms(15); /* 15ミリ秒待つ */ LCD_DATA = 0b00000011; /* 一旦8bitモード設定(初期化) */ LCD_STROBE(); __delay_ms(5); LCD_STROBE(); __delay_us(200); LCD_STROBE(); __delay_us(200); LCD_DATA = 0b00000010; /* 4bitモード設定 */ LCD_STROBE(); lcd_write(0x28); /* 2行表示モードに設定 */ lcd_write(0x0C); /* 表示ON,カーソルOFF,カーソル点滅OFF */ lcd_clear(); lcd_write(0x6); /* エントリーモード:左から右へ、シフト無し */ }

■ 参考にしたWebページ
液晶ディスプレイを使う - まずは表示してみる(4ビット操作) -
PICで気圧計 by 18LF2550 先ずは C言語 で LCD表示!
Hitachi HD44780 LCD controller (LCD制御コマンドがわからない場合は、Wikipediaのこのページで)
液晶表示モジュールを4ビットモードで使ったときの空きピン処理