Arduino驱动LCD12864

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]

你可能感兴趣的:(Arduino驱动LCD12864)