LCD 12864的信号图如下,一共20个pin,GND为pin#1. 支持并行和串行读写方式。
为了节省pin数目,这里采用串行SPI方式(PSB 信号拉低)。LCD电路板上有一个小的旋钮电阻VR1,可以调节对比度(Vout和Vo为NC,不需要外接)。
BLA和BLK为背光,BLA为正极,可接5V或更低的电压,BLK为负极,接GND。
采用串行方式,并口数据线D7~D0为NC,E接SPI的SCK,R/W接SPI的数据MOSI(这里只写不读,采用固定延时方式避免LCD busy),RS接SPI的CS(chip select)。具体在Arduino端分别为P13/clk,P11/MOSI,P10/CS(or SS)。
在ST7920手册里描述了初始化的过程,写30H->30H->0CH->01H->06H
两个30H的写操作是为了区分 8/4为模式必须先设置,然后做其他的功能设定。
调试过程中遇到的两点问题
1,在提取低4bit操作是漏了括号,byteLow=(value&0x0f<<4),正确应为byteLow=((value&0x0f)<<4)。导致实际取得是高4位。上示波器测量信号才找出问题。
2,关于SPI的采样模式也花了些时间,看ST7920的时序图“认为”SCLK在闲时是低电平,上升沿准备数据,下降沿采样。最后测试下来发现不行。能工作的是Arduino 的SPI_MODE3,即下降沿置位,上升沿采用,SCK闲时为高。
(不知道是不是哪里理解错了,有使用不一样模式并工作ok的可以告知一下。)
最后分享一下自己的代码
[code]
#include
const int CS_PIN=10;
void setup() {
// put your setup code here, to run once:
pinMode(CS_PIN,OUTPUT);
digitalWrite(CS_PIN,LOW); //disable at first
SPI.begin();
SPI.setBitOrder(MSBFIRST); // LSBFIRST or MSBFIRST
SPI.setClockDivider(SPI_CLOCK_DIV64); //SPI_CLOCK_DIV2/4/8/16/32/64/128
//SPI_MODE0: sample@rising, set@falling, SCK=0@idle
//SPI_MODE1: sample@falling, set@rising, SCK=0@idle
//SPI_MODE2: sample@falling, set@rising, SCK=1@idle
//SPI_MODE3: sample@rising, set@falling, SCK=1@idle
SPI.setDataMode(SPI_MODE3); //
delay(50); //50ms
//to initialize the lcd
lcdWrite(0,0x30); //function set, 001 DL,X 0/RE X X => DL=1 8bit MPU interface, DL=0 4bit MPU interface, RE=0 basic set, RE=1 extensible set,
delayMicroseconds(200); //>100us
lcdWrite(0,0x30); //function set //DL and R/E can't be changed at same time, change DL at first, then R/E, so need twice 'function set' cmd
delayMicroseconds(50); //>37us
lcdWrite(0,0x0c); // display setting, 0000,1DCB, D(Display), C(Cursor), B(Background reverse)
delayMicroseconds(200); //>100us
lcdWrite(0,0x01); // clear
delay(30); //>10ms
lcdWrite(0,0x06); //entry mode set, 0000,01 I/D S => I/D=1 cursor right shift, =0 cursor left shift. S=>whole picture shift
delay(10);
//init done
}
void loop() {
// put your main code here, to run repeatedly:
//const char *p="Hello World!";
char c;
lcdWrite(0,0x80); //address of Row#1/Character#1
for(const char *p="Hello World!";c=*p;p++)
{
lcdWrite(1,c);
}
lcdWrite(0,0x90);
for(const char *p="Welcome to China";c=*p;p++)
{
lcdWrite(1,c);
}
lcdWrite(0,0x88);
for(const char *p="Shanghai";c=*p;p++)
{
lcdWrite(1,c);
}
lcdWrite(0,0x98);
for(const char *p="2020-04-17";c=*p;p++)
{
lcdWrite(1,c);
}
//delay(1000);
}
// type=0 for command, type=1 for data
void lcdWrite(byte type, byte value)
{
byte byteHigh=0,byteLow=0;
byteHigh=value&0xf0;byteLow=((value&0x0f)<<4);
digitalWrite(CS_PIN,HIGH); //active HIGH
delayMicroseconds(10);
if(type==0)
{
SPI.transfer(0xf8); //5*sync bits(11111) + RW+RS +0, RW=0 write, RW=1 read, RS=0 control, RS=1 data
}
else
{ //type=1
SPI.transfer(0xfa);
}
SPI.transfer(byteHigh);
SPI.transfer(byteLow);
delayMicroseconds(10);
digitalWrite(CS_PIN,LOW);
delay(2); //2ms delay
}
[/code]