山本ワールド
PIC18F46K22でI2C液晶(AQM0802A-RN-GW)に文字を表示(C言語)
概要
PIC18F46K22のI2Cモジュール1にI2Cキャラクタ液晶モジュール(8桁*2行)AQM0802A-RN-GBWを接続し文字の表示とコントラストの調整を実施するサンプルである。
電源はUSBから供給するので5Vである。液晶モジュールは標準電圧が3.3Vなので他の3.3V系のI2Cデバイスも接続できるように3.3V電源回路とレベル変換回路を設けた。液晶モジュール自体の最大定格は5V以上あるため、5Vを直接接続できるのではないかと思うが、試していない。
コントラスト調整は、プログラム制御できる。
本サンプルではコントラスト20~40を自動的に変更するようにしている。
秋月電子 PIC18F46K22使用 マイコンボードをベースとし半田付けされている水晶20MHzをH8/3048ボードの16MHzと交換し64MHzで動作可能とした。このボードはICSP端子を備えておりPICKIT 3で書き込みができ、電源はミニUSBで供給可能である。またユニバーサル基板になっているので簡単に回路を追加することができる。
ちなみに水晶が20MHzの場合は、動作が遅くなるだけである。
回路は次のとおりである。
回路図(PDF) 回路図(DXF)
プログラムの説明
ソースファイル
以下のファイルで構成されているlcd1c.asm ・・・ メインプログラムとLCD制御の関数
ソースファイルのダウンロード lcd1c.zip
/*
* I2C接続液晶 AQUM0802A-RN-GBWの表示とコントラスト調整サンプル Version 1.00
* File: lcd1c.c
* Target: PIC18F46K22 64MHz
* コンパイラ: Microchip MPLAB XC8 C Compiler V1.20
* 書き込み: PICKit 3
* リリース: 2014/01/25 14:00
* 表示例(2行目の26は現在のコントラスト値を表す サンプルでは20~40まで周期的に変化する)
* AQUM0802A
* CONT 26
* 使用端子
* SCK1(RC3),SDA1(RC4)
*/
#include <stdio.h>
#include <stdlib.h>
#include <p18f46k22.h>
#include <plib\delays.h>
#include <plib\i2c.h>
#pragma config FOSC = HSHP,PRICLKEN=ON,PLLCFG=ON,WDTEN=OFF,LVP=OFF
#define LED0 PORTBbits.RB5
#define LCD_SADS 0x7c // 液晶のスレーブアドレス
#define LCD_RSDATA 0x40
#define LCD_RSCMD 0x0
#define LCD_C01 0x80
#define LCD_C00 0x80
#define lcd_putc(c) lcd_data(c) // LCDへ1文字出力
signed char i2c_write(unsigned char d); // i2cへ1byte送信
void lcd_cmd(unsigned char cmd); // LCDへコマンドを1byte送信
void lcd_clear(void); // LCDをクリア
void lcd_init(void); // LCD初期化
void lcd_cont(unsigned char c); // LCDコントラスト変更(0?63)
void lcd_data(unsigned char c); // LCDへデータを1byte送信
void lcd_ddram(unsigned char ads); // LCDの表示アドレスを設定
void lcd_puts(const char* buf); // LCDに文字列を表示
void main(void) {
char buf[4];
ANSELCbits.ANSC3=0;
ANSELCbits.ANSC4=0;
Delay10KTCYx( 64); // 40ms/(64MHz/4)= 640000
OpenI2C(MASTER,SLEW_ON); // マスター
SSPADD=39; // 400kHz
lcd_init();
lcd_puts("AQM0802A\nCont");
unsigned char c; // コントラスト
for(;;){
for(c=20;c<40;c++){
sprintf(buf,"%.2i",(int)c);
lcd_ddram(6);
lcd_puts(buf);
lcd_cont(c);
Delay10KTCYx( 255);
}
for(;20<=c;c--){
sprintf(buf,"%.2i",(int)c);
lcd_ddram(6);
lcd_puts(buf);
lcd_cont(c);
Delay10KTCYx( 255);
}
}
}
// i2cへ1byte送信
signed char i2c_write(unsigned char d){
signed char ret;
ret=WriteI2C(d);
IdleI2C();
return ret;
}
// LCDへコマンドを1byte送信
void lcd_cmd(unsigned char cmd){
SSPCON1bits.WCOL=0;
IdleI2C();
StartI2C();
while(SSPCON2bits.SEN);
i2c_write( LCD_SADS);
i2c_write( LCD_RSCMD | LCD_C01 );
i2c_write(cmd);
StopI2C();
while(SSPCON2bits.PEN);
}
// LCDをクリア
void lcd_clear(void){
lcd_cmd(0x01); // Clear Display
Delay1KTCYx( 17); // 1.06ms/(64MHz/4)= 17000
}
// LCD初期化
void lcd_init(void){
lcd_cmd(0x38); // Function Set
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
lcd_cmd(0x39); // Function Set
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
lcd_cmd(0x14); // Internal OSC frequency
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
lcd_cmd(0x73); // Contrast set
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
lcd_cmd(0x56); // Power/ICON/Contrast control
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
lcd_cmd(0x6c); // Follower control
Delay10KTCYx( 160); // 100ms/(64MHz/4)= 1600000
Delay10KTCYx( 160); // 100ms/(64MHz/4)= 1600000
lcd_cmd(0x38); // Function Set
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
lcd_cmd(0x0c); // Display On/Off
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
lcd_clear();
}
// LCDコントラスト変更(0?63)
void lcd_cont(unsigned char c){
lcd_cmd(0x39); // Function Set
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
lcd_cmd(0x70 | c); // Contrast set
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
lcd_cmd(0x54 | (c>>4)); // Power/ICON/Contrast control
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
}
// LCDへデータを1byte送信
void lcd_data(unsigned char c){
SSPCON1bits.WCOL=0;
IdleI2C();
StartI2C();
while(SSPCON2bits.SEN);
i2c_write(LCD_SADS);
i2c_write( LCD_RSDATA | (LCD_C01) );
i2c_write(c);
StopI2C();
while(SSPCON2bits.PEN);
}
// LCDの表示アドレスを設定
void lcd_ddram(unsigned char ads){
lcd_cmd(0xc0 | ads);
Delay10TCYx( 43); // 26.3μs/(64MHz/4)= 430
}
// LCDに文字列を表示
void lcd_puts(const char* buf){
char* p=buf;
while(*p){
if(*p=='\n')
lcd_ddram(0x40); //2行目
else{
lcd_data(*p);
Delay10TCYx( 43); // 26.3μs*(64MHz/4)= 430
}
++p;
}
}
Copyright (C) 2012 山本ワールド All Rights Reserved.