PIC16F877AにGPSをつなぐ前にデバッグのためにLCDをつないだ。
以前、PIC18F2550につないだのでそれを参考にしようと思ったけど、回路図も残してなかった。
ソースコードはあったのでそのソースコードをPIC16F877A向けに書き換えた。
PIC時計に使えるようにわざとポートAを使っています。
回路図
ソースコードは以下の3つ。
main.c
#include <pic.h> __CONFIG(XT & WDTDIS & PWRTEN & BOREN & LVPDIS & UNPROTECT); #include "lcdlib16.h" void main() { // ポートの設定 ADCON1 = 0x06; // ポートAをデジタルへ TRISA = 0x00; // 全部出力 TRISB = 0xFE; // 0 出力 RB0 = 0; // LCD初期化 lcd_init(); lcd_clear(); lcd_str("Hello World!"); for (char i = 0; i < 10; i++) { __delay_ms(100); } lcd_clear(); while (1) { RB0 = !RB0; if (RB0) { lcd_str("LED OFF"); } else { lcd_str("LED ON"); } for (char i = 0; i < 10; i++) { __delay_ms(100); } lcd_clear(); } }
lcdlib16.h
__delay_us, __delay_ms
関数のために_XTAL_FREQ
にクロック周波数を定義しました。
#include <pic.h> #define _XTAL_FREQ 4000000 // LCDポート設定 #define LCD_DATA PORTA // 4ビットデータの出力ポート #define LCD_RS RA0 // RS信号 #define LCD_E RA1 // E(STB)信号 // LCD関数プロトタイピング void lcd_out(char code, char flag); void lcd_data(char asci); void lcd_cmd(char cmd); void lcd_goto(unsigned char y, unsigned char x); void lcd_clear(void); void lcd_init(void); void lcd_str(const char *str);
lcdlib.c
#include "lcdlib16.h" // データ出力サブ関数 void lcd_out(char code, char flag) { // 上位4ビットを出力 // LCD_DATA = (LCD_DATA & 0x0F) | (code & 0xF0); LCD_DATA = (LCD_DATA & 0x03) | ((code & 0xF0) >> 2); // LCD_DATA = (LCD_DATA & 0xF0) | ((code & 0xF0) >> 4); if (flag == 0) { LCD_RS = 1; } else { LCD_RS = 0; // コマンドデータの場合 } __delay_us(1); // pulse width LCD_E = 1; // strobe out __delay_us(1); // pulse width LCD_E = 0; // reset strobe } // 1文字表示関数 void lcd_data(char asci) { lcd_out(asci, 0); // 上位4ビット出力 lcd_out(asci << 4, 0); // 下位4ビット出力 __delay_us(50); // 50μsec待ち } // コマンド出力関数 void lcd_cmd(char cmd) { lcd_out(cmd, 1); // 上位4ビット出力 lcd_out(cmd << 4, 1); // 下位4ビット出力 if ((cmd & 0x03) != 0) { __delay_ms(2); // 2msec待ち } else { __delay_us(50); // 50μsec待ち } } // 行移動関数 void lcd_goto(unsigned char y, unsigned char x) { char cmd; switch (y) { case 1: cmd = 0xC0; break; case 2: cmd = 0x94; break; case 3: cmd = 0xD4; break; default: cmd = 0x80; break; } lcd_cmd(cmd+x); } // 全消去関数 void lcd_clear(void) { lcd_cmd(0x01); // 初期化コマンド出力 __delay_ms(15); // 15msec待ち } // 文字列出力関数 void lcd_str(const char *str) { while (*str != 0x00) { lcd_data(*str); str++; } } // 初期化関数 void lcd_init(void) { __delay_ms(30); // 30msec待ち lcd_cmd(0x03); // 8bit mode set __delay_ms(5); lcd_cmd(0x03); // 8bit mode set __delay_ms(1); lcd_cmd(0x03); // 8bit mode set __delay_ms(1); lcd_cmd(0x02); // 4bit mode set __delay_ms(1); lcd_cmd(0x28); // DL=0 4bit mode, N=1 2lines, F=0 5x7 font // lcd_cmd(0x24); // DL=0 4bit mode, N=0 1line, F=1 5x10 font __delay_ms(1); lcd_cmd(0x08); // display off D=C=B=0 lcd_cmd(0x0C); // display on D=1 C=B=0 // lcd_cmd(0x0D); // display on D=C=1 B=0 // lcd_cmd(0x0F); // display on D=C=B=1 lcd_cmd(0x06); // entry I/D=1 S=0 lcd_cmd(0x02); // cursor home lcd_clear(); }