---
---
秋月電子から販売されているSPI 超小型グラフィックCLCDモジュール(AQM1248A) を接続しました。 AQM1248Aは、128x48ドットの表示エリアがあり、LCDに内蔵された表示データRAMにSPI通信で、グラフィックパターンを書き込めば、対応したLCDドットがON/OFFし、画面表示されます。PICから送信するタイミングは、アイドル時のクロックは、「Hi」、クロックのの立下でデータを変更する Mode II のSPIです。
画面ほぼ中央に「こんにちは!」と表示するだけのプログラムです。「こんにちは!」は、縦16bitの高さがあるため、上下2分割し、上半分は表示RAMのPage2に、下半分はPage3に、8bitのグラフィックパターンを送信しています。
グラフィック表示の大まかな手順は以下の通りです。
実用的なプログラム例は、ライブラリ "AQM1248A.h" を参照してください。このライブラリでは、文字を3倍に拡大して見やすく表示するためのプログラム関数も準備してあります。
<プログラム>
// **************************************************************
// File name: SPI グラフィックLCDに「こんにちは!」と表示
//
// RC4 SPI_RS 0:コマンド 1:データ
// RC5 SPI_CS 0:有効 1:無効
// RC7 SPISDO
// RB6 SPISCK idle時:Hi SCKの立下でデータ変更
// Language: MPLABX XC8
// Target: PIC18F14K50
// Copyright (c) 2014 iwamoto All Rights Reserved
// **************************************************************
#include <xc.h>
#define _XTAL_FREQ 16000000 // delay_ms(x) のための定義
#define SPI_RS LATCbits.LATC4
#define SPI_CS LATCbits.LATC5
//-------------- コンフィグレーション --------------------------------
#pragma config MCLRE = OFF
#pragma config PWRTEN = OFF, BOREN = OFF, BORV = 30
#pragma config WDTEN = OFF, WDTPS = 32768
#pragma config STVREN = ON
#pragma config FOSC = IRC // 内部クロック
#pragma config PLLEN = ON, CPUDIV = NOCLKDIV, USBDIV = OFF
#pragma config FCMEN = OFF, IESO = OFF, HFOFST = OFF
#pragma config LVP = OFF, XINST = OFF, BBSIZ = OFF
#pragma config CP0 = OFF, CP1 = OFF, CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF
// プロトタイプ ------------------------------------------------------
void LCD_int (void);
void LCD_cmd (char );
void LCD_ram (char );
void LCD_clr (void );
void LCD_posyx (char, unsigned char );
// 表示データ「こんにちは!」のビットパターン ------------------------
const char PatUp[]={
0x00,0x0C,0x1C,0x78,0x78,0x38,0x3C,0x1C,0x00,0x00, // "こ"上半分
0x00,0x00,0x80,0xF0,0xFE,0x3E,0x0C,0x00,0x00,0x00, // "ん"
0xE0,0xFE,0x1E,0x00,0x30,0x38,0x78,0x78,0x30,0x00, // "に"
0x30,0x70,0xF2,0xFF,0x3E,0xB0,0xB8,0x38,0x18,0x00, // "ち"
0xE0,0xFE,0x1E,0xC0,0xE0,0xE2,0xFE,0xFE,0x70,0x30, // "は"
0x00,0x00,0x00,0x00,0xE0,0xFE,0xFE,0x0E,0x00,0x00 // "!"
};
const char PatLo[]={
0x1C,0x3E,0x70,0x70,0x70,0x70,0x70,0x78,0x38,0x00, // "こ"下半分
0xF0,0xFE,0x1F,0x07,0x3F,0xFF,0xE0,0xF0,0x78,0x00, // "ん"
0x3F,0x7F,0x30,0x00,0x38,0x38,0x70,0x70,0x38,0x18, // "に"
0x00,0x1C,0x1F,0x9F,0xC7,0xC3,0x63,0x7F,0x3E,0x00, // "ち"
0x7F,0xFF,0x30,0x00,0x78,0xEC,0xFF,0x7F,0x38,0x70, // "は"
0x00,0x00,0x00,0x00,0x6F,0x6F,0x00,0x00,0x00,0x00 // "!"
};
void main(void){
char i;
OSCCON = 0b01110010; // 内部クロック16Mhz
SSPSTAT = 0b00000000; // SPI機能の設定
SSPCON1 = 0b00110000; // FOSC_4, MODE_11, SMPMID
ANSEL = 0b00000000; // I/O端子をすべてデジタル
ANSELH = 0b00000000;
LATC = 0; // PortCのすべてのビットを「0」
SPI_CS = 1; // SPI_CSを「1」にする
TRISCbits.TRISC4 = 0; // SPI_RSを出力に設定
TRISCbits.TRISC5 = 0; // SPI_CSを出力に設定
TRISCbits.TRISC7 = 0; // SPISDOを出力に設定
TRISBbits.TRISB6 = 0; // SPISCKを出力に設定
LCD_int (); // LCDを初期化
LCD_clr (); // データを全消去
LCD_cmd (0x40); // Start address を 0
// ------------------------------------------------------------
// 「こんにちは!」表示パターンを LCD 表示データRAMMに転送
// ------------------------------------------------------------
LCD_posyx (2, 30); // LCD 表示データRAMMのアドレス指定
for(i=0; i<60; i++) { // 表示データをLCD RAMに書き込む
LCD_ram (PatUp[i]);
}
LCD_posyx (3, 30); // LCD 表示データRAMMのアドレス指定
for(i=0; i<60; i++) { // 表示データをLCD RAMに書き込む
LCD_ram (PatLo[i]);
}
while(1);
}
// --------------------------------------------------------------
// G-LCDを初期化する
// --------------------------------------------------------------
void LCD_int (void){
LCD_cmd (0xAE); // Display = OFF
LCD_cmd (0xA0); // ADC = normal
LCD_cmd (0xC8); // Common output = revers
LCD_cmd (0xA3); // bias = 1/7
//--内部レギュレータを順番にONする
LCD_cmd (0x2C); // power control 1
__delay_ms(2); // 2mS遅延
LCD_cmd (0x2E); // power control 2
__delay_ms(2); // 2mS遅延
LCD_cmd (0x2F); // power control 3
//--コントラスト設定
LCD_cmd (0x23); // Vo voltage resistor ratio set
LCD_cmd (0x81); // Electronic volume mode set
LCD_cmd (0x1C); // Electronic volume value set
//--表示設定
LCD_cmd (0xA4); // display all point = normal(全点灯しない)
LCD_cmd (0x40); // display start line = 0
LCD_cmd (0xA6); // Display normal/revers = normal(白黒反転しない)
LCD_cmd (0xAF); // Display = ON
}
// --------------------------------------------------------------
// G-LCDにコマンドを一文字送信する
// --------------------------------------------------------------
void LCD_cmd (char cmd){
SPI_CS = 0;
SPI_RS = 0; // コマンドを指定
SSPBUF = cmd; // コマンドを送信
while(!SSPSTATbits.BF); // 送信完了を待つ
cmd = SSPBUF; // BFをリセットするため空読み
SPI_CS = 1;
}
// --------------------------------------------------------------
// G-LCDの表示データRAMMにデータを一バイト送信する
// --------------------------------------------------------------
void LCD_ram (char dat){
SPI_CS = 0;
SPI_RS = 1; // 表示RAMを指定
SSPBUF = dat; // データの送信を開始
while(!SSPSTATbits.BF); // 送信完了を待つ
dat = SSPBUF; // BFをリセットするため空読み
SPI_CS = 1;
}
// --------------------------------------------------------------
// G-LCDの表示データRAMMを全消去する
// --------------------------------------------------------------
void LCD_clr (void){
char i,j;
for(j=0; j<8; j++) { // RAMMのPage 0 - 7 を順に消去
LCD_posyx (j, 0); // LCD 表示データRAMMのアドレス指定
for(i=0; i<128; i++) {
LCD_ram (0); // 全カラムを消去
}
}
}
// --------------------------------------------------------------
// 表示データRAMアドレス指定
// --------------------------------------------------------------
void LCD_posyx(char ypos, unsigned char xpos){
LCD_cmd(0xB0 | ypos); //ページを指定
LCD_cmd(0x10 | (xpos >> 4)); //ページ内RAMアドレスを
LCD_cmd(xpos & 0xF); // 分割し指定
}