表示器 (Nokia 5110 SPI)

2013/05/06


◆ Nokia 5110

Nokia 製携帯電話のグラフィック液晶。 値段が安いのと手頃な大きさなので好きなモジュールです。 aitenndo で取り扱ってますが、数個買ったうち いくつか不良品がありました。 多分、接点だろうけど液晶と基板間が特殊な素材の接続方法なのでなすすべがありません。 まぁ、aitendo で購入する際にはこういうリスクも含めた価格だと割り切っています。

グラフィック液晶の SPI 制御といっても内部 RAM の読み出しはできないようなのでマスターからの送信のみとなります。

 shiftOut() 関数と制御ピンの出力のみでデータが転送できるので SPI ライブラリを使用する必要はありません。

ノキア液晶 5110
コントローラ PCD8544
解像度 48 x 84 dot
バックライト 青

  1.Vcc     → 2.7 - 3.3V
  2.GND     → GND
  3.SCE     → Enable
  4.RES     → Reset
  5.D/C     → Data / Command
  6.SDIN    → Serial Input
  7.SCLK    → Clock Input
  8.LED(A)  → 2.7 - 3.2 V

◆ 制御コマンド

データ送信方法がシリアルかパラレルかの違いで、コマンドの考え方は同じです。 表示領域は横 83ドットと縦 8ページとなります。データ送信前に SCE を LOW にし、データ送信後 SCE を HIGH にすることでデータ送信完了となります。

Instruction DC Command byte Description
7 6 5 4 3 2 1 0
Function set 0 0 0 1 0 0 PD V H  
Function set bit0(H) = 0
Display control 0 0 0 0 0 0 D 0 E  
Set Y address 0 0 1 0 0 0 Y2 ~ Y0 Y = 0 - 7
Set X address 0 1 X6 ~ X0 X = 0 - 63
Function set bit0(H) = 1 : extendes instruction set
Temperature control 0 0 0 0 0 0 1 TC1 TC0  
Bias system 0 0 0 0 1 0 BS2 BS1 BS0  
Set Vop 0 1 Vop6 ~ Vop0 Contrast = 0 - 63

 

Instruction Symbol 0 1
Function set PD Active Power down mode
V Horizontal addressing Vertical addressing
H basic instruction extended instruction
Display control D / E  00  basic blank
 10  normal mode
 01  all display segments on
 11 inverse video mode 
Temperature control TC1 / TC0  00  VLCD temperature coefficient 0
 01  VLCD temperature coefficient 1
 10  VLCD temperature coefficient 2
 11  VLCD temperature coefficient 3

◆ サンプル・スケッチ

いつものように、コマンド/データ転送関数と初期化関数の他にいくつかの関数を作成し、動作を確認する。

//
// Div 003-01 Nokia 5110(SPI) グラフィックディスプレイ
//

#include <Wire.h>

// Nokia 5110 配線状態
                    // 3.3V (1)
                    // GND (2)
#define pin_SCE 2   // SCE (3)
#define pin_RST 15  // Reset (4)
#define pin_DC 16   // D/C (5)
#define pin_SDIN 17 // SDIN (6)
#define pin_SCLK 11 // SCLK (7)
#define pin_LED 12  // LED A+(8)

// 5x8 フォントデータ
static const byte font[][5] = {
  {0x00, 0x00, 0x00, 0x00, 0x00} // 20
 ,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
 ,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
 ,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
};

void setup() {
  glcdInitialize();
  glcdCLS();
}

void loop() {
  char text[] = "ABC";
  glcdPRINT(text);

  while(1);
}

// コマンド書込み
void writeCommand(byte data) {
  digitalWrite(pin_DC, LOW);
  digitalWrite(pin_SCE, LOW);
  shiftOut(pin_SDIN, pin_SCLK, MSBFIRST, data);
  digitalWrite(pin_SCE, HIGH);
}

// データ書込み
void writeData(byte data) {
  digitalWrite(pin_DC, HIGH);
  digitalWrite(pin_SCE, LOW);
  shiftOut(pin_SDIN, pin_SCLK, MSBFIRST, data);
  digitalWrite(pin_SCE, HIGH);
}

// 初期化
void glcdInitialize(void) {
  pinMode(pin_SCE, OUTPUT);
  pinMode(pin_RST, OUTPUT);
  pinMode(pin_LED, OUTPUT);
  pinMode(pin_DC, OUTPUT);
  pinMode(pin_SDIN, OUTPUT);
  pinMode(pin_SCLK, OUTPUT);

  digitalWrite(pin_RST, LOW);
  digitalWrite(pin_RST, HIGH);

  writeCommand(0b00100001); // Extended Commands.
  writeCommand(0b10100000); //   Contrast.
  writeCommand(0b00000100); //   Set Temp coefficent.
  writeCommand(0b00010100); //   LCD bias mode 1:48.

  writeCommand(0b00100000); // Normal Commands.
  writeCommand(0b00001100); //   Normal mode
}

// 画面消去
void glcdCLS(void) {
  glcdSetXY(0, 0);
  for (int i=0; i<84*6; i++) writeData(0x00);
}

// 画面アドレス指定
void glcdSetXY(int x, int y) {
  writeCommand(0x80 | x); // Column
  writeCommand(0x40 | y); // Row
}

// 1文字出力
void putChar(char c) {
  writeData(0x00);
  for (int i=0; i<5; i++) writeData(font[c - 0x40][i]);
  writeData(0x00);
}

// 文字列表示
void glcdPRINT(char *c) {
  while (*c) putChar(*c++);
}

コントラストの値は値が大きいほど濃くなります、0x90 位では良く見えません。

temperature と bias mode を他の値で試してみたけど画面が表示されませんでした。

Function set の V は画面の向きを変えて使用する際に設定します。 ただし横1ページになるのでアドレス指定の計算が手間になります。

Display control の D/E は、all display segments on でドットの塗りつぶし、inverse video mode で反転表示となります。

5 x 8 ドットのフォントでも十分読める大きさの文字で、12 x 16 の漢字の視認性は大変良いです。

VRAM の読み出しができないのでマイコン側に VRAM イメージを作成しておき、全画面を転送する方法が良いのですが 504 バイトを一気に書き込まないといけないので DMA 転送ができないと厳しいかもしれません。