※arduino や raspberry pi、esp32などは使ってません。
ルネサスのRL78と直接16bitのパラレル接続で動作させています(SPIではない)。
ライブラリ化しやすいようコードを分けています。
興味があるところを読む
ILI9341+グラフィックLCD
2016/10/29 参考HP データシート
グラフィックLCDを使うとなれば、LCDコントローラーの出番です。
LCDを直接操作するわけじゃなくて、コントローラICのILI9341(ILI9340でも動くと思う)のいじり方をご紹介しています。
・RL78と9341は16bitのパラレルで接続。
・リセットはハード的に発生してます。
ってことで、あちこちググり回って見付けたのが上記の参考HP。
とても分かりやすく、更にソースも載せてくれてるんで至って簡単に完成した。有り難うございます。
パラレル接続時の変更点
ところでどのサイトでもCPUと9341をSPIで接続してるけど、今回は16bitパラレル接続(P7/8)なので、IO部分だけを修正すれば動くはずと目星を付けて作ったのがこれ。
要するにSPIで出力してるのをポート出力に変更しただけ。
・IM0~3を0001にセットすることで16bitバスになる(9341マニュアルより抜粋)。
・またレジスタへのアクセスは8bit幅だけど、GRAMは16bit幅でアクセスすることが読み取れる。
CMDを書くときはDCX=L、DATAを書くときはDCX=Hにしておいて、WRXで↑エッジを出してやる。
・GRAMに上位8bitゼロで書き込むと赤だけ表示されなかった(CPUボードは北斗電子製)。 ・この後で16bitで書き込んだら赤も表示されたから上位8bitが赤だ。
コード
コードはライブラリー化し易いように分けてます。
コピーしてCS+に貼り付け、LcdMain()をコールすれば動作するはず。
//
// lcd.c ILI9341+4DLCD-28QA 2016/10/15
// http://imagewriteriij.blogspot.jp/2014/01/raspberry-pi-9-lcd-1.html
// http://nopnop2002.webcrow.jp/TFT/ILI9340-1.html
//
#include "r_cg_macrodriver.h"
#include "iodefine.h"
#include "r_cg_userdefine.h"
// LCD Ports define
#define LCD_BKL P3_bit.no1 // BackLight
#define LCD_CSX P6_bit.no5 // CSX
#define LCD_DCX P6_bit.no4 // DCX
#define LCD_WRX P6_bit.no7 // WRX
#define LCD_RDX P6_bit.no6 // RDX
// Prototype
static void lcd_test(uint16_t r, uint16_t g, uint16_t b);
static void clear(uint16_t r, uint16_t g, uint16_t b);
static void colorbar(void);
static void write_dc(uint8_t dc, uint8_t c);
static void write_dc_w(uint16_t w);
static void write_dc_w16(uint16_t w);
static void lcd_init(void);
static void addset(uint16_t x, uint16_t y);
static uint16_t rgb565_conv(uint16_t r, uint16_t g, uint16_t b);
//================================================================================================
// LCD main
//================================================================================================
void LcdMain(void)
{
/* 手動でリセットするなら・・・
LCD_CSX = 0; // CS=L(これは要らないかも)
LCD_DCX = 1; // D/C = H
RESET = 0; // Reset = L
delay1ms(100); // delay 100ms
RESET = 1; // Reset = 1
delay1ms(100); // delay 100ms
*/
LCD_BKL = 1; // バックライトON
LCD_CSX = 0; // CS=L
lcd_init();
lcd_test(0, 255, 255);
lcd_test(255, 255, 0);
lcd_test(255, 0, 255);
LCD_CSX = 1; // CS=H
LCD_BKL = 0; // バックライトOFF
}
// デバッグ用のLCD表示
void lcd_test(uint16_t r, uint16_t g, uint16_t b)
{
clear(r, g, b);
colorbar();
}
// lcd initial
static void lcd_init(void)
{
LCD_WRX = 1;
LCD_RDX = 1;
delay1ms(25);
write_dc(0,0xC0); //Power control
write_dc(1,0x23);
write_dc(0,0xC1); //Power control
write_dc(1,0x10);
write_dc(0,0xC5); //VCM control
write_dc(1,0x3e);
write_dc(1,0x28);
write_dc(0,0xC7); //VCM control2
write_dc(1,0x86);
write_dc(0,0x36); // Memory Access Control
write_dc(1,0x48);
write_dc(0,0x3A);
write_dc(1,0x55);
write_dc(0,0xB1);
write_dc(1,0x00);
write_dc(1,0x18);
write_dc(0,0xB6); // Display Function Control
write_dc(1,0x08);
write_dc(1,0x82);
write_dc(1,0x27);
write_dc(0,0xF2); // 3Gamma Function Disable
write_dc(1,0x00);
write_dc(0,0x26); //Gamma curve selected
write_dc(1,0x01);
write_dc(0,0xE0); //Set Gamma
write_dc(1,0x0F);
write_dc(1,0x31);
write_dc(1,0x2B);
write_dc(1,0x0C);
write_dc(1,0x0E);
write_dc(1,0x08);
write_dc(1,0x4E);
write_dc(1,0xF1);
write_dc(1,0x37);
write_dc(1,0x07);
write_dc(1,0x10);
write_dc(1,0x03);
write_dc(1,0x0E);
write_dc(1,0x09);
write_dc(1,0x00);
write_dc(0,0XE1); //Set Gamma
write_dc(1,0x00);
write_dc(1,0x0E);
write_dc(1,0x14);
write_dc(1,0x03);
write_dc(1,0x11);
write_dc(1,0x07);
write_dc(1,0x31);
write_dc(1,0xC1);
write_dc(1,0x48);
write_dc(1,0x08);
write_dc(1,0x0F);
write_dc(1,0x0C);
write_dc(1,0x31);
write_dc(1,0x36);
write_dc(1,0x0F);
write_dc(0,0x11); //Exit Sleep
delay1ms(120);
write_dc(0,0x29); //Display on
write_dc(0,0x2c); //Memory Write
}
// clear
static void clear(uint16_t r, uint16_t g, uint16_t b)
{
int i,j;
for (i=0;i<240;i++) { // x = 0 to 239
for(j=0;j<320;j++) { // y = 0 to 319
addset(i,j);
write_dc_w16(rgb565_conv(r, g, b));
}
}
}
// write color bar
static void colorbar(void)
{
int i,j;
for(i=0;i<240;i++){ // x = 0 to 239
for(j=0;j<320;j++){ // y = 0 to 319
if(j<106) {
addset(i,j);
write_dc_w16(rgb565_conv(255,0,0)); //red
} else if(j<212) {
addset(i,j);
write_dc_w16(rgb565_conv(0,255,0)); //green
} else {
addset(i,j);
write_dc_w16(rgb565_conv(0,0,255)); //blue
}
}
}
}
// set address
static void addset(uint16_t x, uint16_t y)
{
write_dc(0,0x2A); // set column(x) address
write_dc_w(x);
write_dc_w(x);
write_dc(0,0x2B); // set Page(y) address
write_dc_w(y);
write_dc_w(y);
write_dc(0,0x2C); // Memory Write
}
// RGB565 conversion
// RGB565 is R(5)+G(6)+B(5)=16bit color format.
// Bit image "RRRRRGGGGGGBBBBB"
static uint16_t rgb565_conv(uint16_t r,uint16_t g,uint16_t b)
{
uint16_t RR,GG,BB;
RR = (r * 31 / 255) << 11;
GG = (g * 63 / 255) << 5;
BB = (b * 31 / 255);
return(RR | GG | BB);
}
// Write data/command
static void write_dc(uint8_t dc, uint8_t c)
{
LCD_DCX = dc; // 0=command, 1=data
P7 = c; // 下位8bitのみ(上位8bitはdont care)
LCD_WRX = 0; // WR out
NOP();
LCD_WRX = 1;
}
// Write data word
static void write_dc_w(uint16_t w)
{
uint8_t hi,lo;
hi = (uint8_t)(w >> 8);
lo = (uint8_t)(w & 0x00FF);
write_dc(1,hi);
write_dc(1,lo);
}
// Write data word by 16bit
static void write_dc_w16(uint16_t w)
{
uint8_t hi,lo;
hi = (uint8_t)(w >> 8);
lo = (uint8_t)(w & 0x00FF);
LCD_DCX = 1; // 1=data
P8 = hi; // 上位8bit
P7 = lo; // 下位8bit
LCD_WRX = 0; // WR out
NOP();
LCD_WRX = 1;
}
コメント