カラーOLED SSD1331
有機ELディスプレイ 0.95インチ 96×64ドット RGB0.95インチの有機ELディスプレーです。
型格からしてSD1306の姉妹品と思われます。
接続方法、操作方法共にSSD1306と共通しています。
OLED SSD1331のコマンドと送信手順
SSD01331のコマンドは以下の手順で送信するコマンド送信 | |
---|---|
SS(Slave Select) | LOWにする |
DC(Data/Command) | LOWにする |
コマンド送信 | |
SS(Slave Select) | HIGHにする |
データ送信 | |
---|---|
SS(Slave Select) | LOWにする |
DC(Data/Command) | HIGHにする |
データ送信 | |
SS(Slave Select) | HIGHにする |
初期化に必要なコマンドを抜粋:輝度設定は最低限の抜粋なので詳細はデータシート参照
命令コード | 命令長 | 命令内容 | |
---|---|---|---|
0xA4 | 1 | 表示モード:通常 | |
0xA7 | 1 | 表示モード:反転 | |
0xA0 | 0x00~0xBF | 2 | 表示方向と色数 |
[7:6] 00=256色 / 01 = 65K色(2Byte) / 10=65K色(3Byte) | |||
[4]垂直方向の描画順序:縦方向にミラー反転 | |||
[2]R(赤)とB(青)を入れ替える | |||
[3][1]横方向にミラー反転 | |||
[0]描画方向-縦/横 | |||
0xA1 | 0~63 | 2 | 表示開始行 |
0xA2 | 0x00 | 2 | 表示行オフセット |
0xB0 | 0x0B or 0x1A | 2 | POWER SAVE MODE 0x0B=Disable(無効) / 0x1A=Enable(有効) |
0x87 | 0x00~0x0F | 2 | LCDパネルの明るさ設定 |
0x81 | 0x00~0xFF | 2 | REDのコントラスト |
0x82 | 0x00~0xFF | 2 | GREENのコントラスト |
0x83 | 0x00~0xFF | 2 | BLUEのコントラスト |
0xAE | 1 | DISPLAY OFF | |
0xAF | 1 | DISPLAY ON |
描画コマンドを抜粋:他にも部分的に暗くするコマンドなどがあるので詳細はデータシート参照
命令コード | 命令長 | 命令内容 | |
---|---|---|---|
0x25 | Xs,Ys,Xe,Ye | 5 | 指定エリアをクリア |
0x26 | B000x000x | 2 | 塗りつぶし [0]0=Disable(無効) / 1=Enable(有効) |
反転コピー [4]0=Disable(無効) / 1=Enable(有効) | |||
0x21 | Xs,Ys,Xe,Ye,RED,GREEN,BLUE | 8 | LINEを描画 |
0x22 | Xs,Ys,Xe,Ye, LineRED,LineGREEN,LineBLUE, FillRED,FillGREN,FillBLUE |
11 | RECTを描画 |
0x23 | Xs,Ys,Xe,Ye,Xd,Yd | 7 | 領域複写 |
0x27 | HorizontalStep,HorizontalStartRow, HorizontalHight,VerticalStep,Interval |
6 | スクロール設定 |
0x2E | 1 | スクロール停止 | |
0x2F | 1 | スクロール開始 | |
0x15 | Start-Col,End-Col | 3 | Column アドレス設定 |
0x75 | Start-Row,End-Row | 3 | Row アドレス設定 |
SSD1331での描画例
SSD1331Sample.zip
※ <>を全角<>に置き換えています。コピペの際は注意してください。
#include <SPI.h>
#include "image.h"
// Declaration for SSD1331 display connected using software SPI (default case):
#define OLED_MOSI 11 // Master In Slave Out
#define OLED_CLK 13 // Serial Clock
#define OLED_CS 7 // Slave Select(Chip select)
#define OLED_DC 6 // SSD1306 Data/Command
#define OLED_RESET 5 // SSD1306 Reset
static const int16_t oledWidth = 96; // OLEDの幅(ピクセル数)
static const int16_t oledHeight = 64; // OLEDの高さ(ピクセル数)
uint8_t SPIBuf[256] ; // SPI転送用バッファ
// --- SSD1331 COMMADN ---
static uint8_t oledInitCommands[] = { // SSD1331の初期化コマンド群
0xAE, // DISPLAYOFF
0xA0 , 0x72, // SETREMAP 0x72 / 0x76 : RGB Color
// ▼ 設定を変更してみる場合の設定値
// 0xA0 , B00110010 , // ノーマル 256色
// 0xA0 , B01110010 , // ノーマル 64色 Format1
// 0xA0 , B10110010 , // ノーマル 64色 Format2
// 0xA0 , B01100010 , // 縦方向ミラー反転 64色 Format1
// 0xA0 , B01110000 , // 横方向ミラー反転 64色 Format1
// 0xA0 , B01100000 , // 上下反転 64色 Format1
// 0xA0 , B01100011 , // 左90度回転表示 64色 Format1
// 0xA0 , B01110001 , // 右90度回転表示 64色 Format1
0xA1 , 0x00 , // STARTLINE
0xA2 , 0x00 , // DISPLAYOFFSET
0xA4 , // NORMALDISPLAY
0xB0 , 0x0B , // POWERMODE
0x87 , 0x01 , // MASTERCURRENT : 0x06
0x81 , 0x91 , // CONTRAST RED : 0x91
0x82 , 0x50 , // CONTRAST GREEN: 0x50
0x83 , 0x7D , // CONTRAST BLUR : 0x7D
0xAF , // DISPLAYON
};
uint8_t drowComandClearWindow[] = {0x25 , 0 , 0 , 95, 63 }; // ClearWindow Command
uint8_t drowComandRect[] = {0x22 , 0, 0, 95, 63, 0x00, 0x3E, 0x00, 0x3E, 0x3E, 0x3E }; // DrowRect Command
uint8_t drowComandLineR1[] = {0x21 , 0, 8,95, 8, 0x3E, 0x00, 0x00 }; // DrowLine Command
uint8_t drowComandLineR2[] = {0x21 ,87, 0,95, 8, 0x3E, 0x00, 0x00 }; // DrowLine Command
uint8_t drowComandLineR3[] = {0x21 ,87,16,95, 8, 0x3E, 0x00, 0x00 }; // DrowLine Command
uint8_t drowComandLineG1[] = {0x21 , 8, 0, 8,63, 0x00, 0x3E, 0x3E }; // DrowLine Command
uint8_t drowComandLineG2[] = {0x21 , 0,55, 8,63, 0x00, 0x3E, 0x3E }; // DrowLine Command
uint8_t drowComandLineG3[] = {0x21 ,16,55, 8,63, 0x00, 0x3E, 0x3E }; // DrowLine Command
uint8_t drowComandScroolH[] = {0x27 , 1, 16, 31, 0, 0 }; // Scroll Command
uint8_t drowComandScroolV[] = {0x27 , 0, 32, 31, 1, 0 }; // Scroll Command
// OLEDに1バイトコマンドを送信
void oledSendCommand(uint8_t command) {
digitalWrite(OLED_CS, LOW); // SSD1306セレクト
digitalWrite(OLED_DC, LOW); // Command mode
SPI.transfer(command);
digitalWrite(OLED_CS, HIGH); // SSD1306解放
}
// OLEDに2バイトコマンドを送信
void oledSendCommand2(uint8_t command1, uint8_t command2) {
digitalWrite(OLED_CS, LOW); // SSD1306セレクト
digitalWrite(OLED_DC, LOW); // Command mode
SPI.transfer(command1);
SPI.transfer(command2);
digitalWrite(OLED_CS, HIGH); // SSD1306解放
}
// OLEDに3バイトコマンドを送信
void oledSendCommand3(uint8_t command1, uint8_t command2, uint8_t command3) {
digitalWrite(OLED_CS, LOW); // SSD1306セレクト
digitalWrite(OLED_DC, LOW); // Command mode
SPI.transfer(command1);
SPI.transfer(command2);
SPI.transfer(command3);
digitalWrite(OLED_CS, HIGH); // SSD1306解放
}
// OLEDに複数のコマンドを送信
void oledSendCommands(int commandLen, uint8_t commands[]) {
digitalWrite(OLED_CS, LOW); // SSD1306セレクト
digitalWrite(OLED_DC, LOW); // Command mode
SPI.transfer(commands, commandLen);
digitalWrite(OLED_CS, HIGH); // SSD1306解放
}
// BITマップを表示する::oledFillDataの可変データ型なので基本oledFillDataと同じ作り
void oledBitMap(int offsetX , int offsetY , int width, int hight, uint8_t bitMap[]) {
uint8_t endX = offsetX + width - 1;
uint8_t endY = offsetY + hight - 1;
oledSendCommand3(0x15, offsetX, endX) ;
oledSendCommand3(0x75, offsetY, endY) ;
delayMicroseconds(500);
int pos = 0 ;
digitalWrite(OLED_CS, LOW); // SSD1306セレクト
digitalWrite(OLED_DC, HIGH); // Data mode
for (int row = 0 ; row < hight ; row ++) {
// 表示データ転送
// Arduinoだとメモリが足りなくて1画面分を一気に転送する事ができない
// なので、1Lineずつ送信している
for (int col = 0 ; col < width * 2 ; col ++ ) {
SPIBuf[col] = pgm_read_byte(bitMap + pos);
// SPIBuf[col] = 0xF8 ;
pos ++ ;
}
SPI.transfer(SPIBuf, width * 2);
}
digitalWrite(OLED_DC, LOW); // Command mode
digitalWrite(OLED_CS, HIGH); // SSD1306解放
}
// BITマップを表示する::oledFillDataの可変データ型なので基本oledFillDataと同じ作り
void oledFillBit1(int offsetX , int offsetY , int width, int hight, uint8_t bitData) {
uint8_t endX = offsetX + width - 1;
uint8_t endY = offsetY + hight - 1;
oledSendCommand3(0x15, offsetX, endX) ;
oledSendCommand3(0x75, offsetY, endY) ;
delayMicroseconds(500);
int pos = 0 ;
digitalWrite(OLED_CS, LOW); // SSD1306セレクト
digitalWrite(OLED_DC, HIGH); // Data mode
for (int row = 0 ; row < hight ; row ++) {
// 表示データ転送
// Arduinoだとメモリが足りなくて1画面分を一気に転送する事ができない
// なので、1Lineずつ送信している
for (int col = 0 ; col < width ; col ++ ) {
SPIBuf[col] = bitData ;
pos ++ ;
}
SPI.transfer(SPIBuf, width);
}
digitalWrite(OLED_DC, LOW); // Command mode
digitalWrite(OLED_CS, HIGH); // SSD1306解放
}
void oledFillBit2(int offsetX , int offsetY , int width, int hight, uint8_t bitData1 , uint8_t bitData2) {
uint8_t endX = offsetX + width - 1;
uint8_t endY = offsetY + hight - 1;
oledSendCommand3(0x15, offsetX, endX) ;
oledSendCommand3(0x75, offsetY, endY) ;
delayMicroseconds(500);
int pos = 0 ;
digitalWrite(OLED_CS, LOW); // SSD1306セレクト
digitalWrite(OLED_DC, HIGH); // Data mode
for (int row = 0 ; row < hight ; row ++) {
// 表示データ転送
// Arduinoだとメモリが足りなくて1画面分を一気に転送する事ができない
// なので、1Lineずつ送信している
for (int col = 0 ; col < width*2 ; col ++ ) {
SPIBuf[col*2] = bitData1 ;
SPIBuf[col*2+1] = bitData2 ;
pos ++ ;
}
SPI.transfer(SPIBuf, width*2);
}
digitalWrite(OLED_DC, LOW); // Command mode
digitalWrite(OLED_CS, HIGH); // SSD1306解放
}
void oledFillBit3(int offsetX , int offsetY , int width, int hight, uint8_t bitData1 , uint8_t bitData2, uint8_t bitData3) {
uint8_t endX = offsetX + width - 1;
uint8_t endY = offsetY + hight - 1;
oledSendCommand3(0x15, offsetX, endX) ;
oledSendCommand3(0x75, offsetY, endY) ;
delayMicroseconds(500);
int pos = 0 ;
digitalWrite(OLED_CS, LOW); // SSD1306セレクト
digitalWrite(OLED_DC, HIGH); // Data mode
for (int row = 0 ; row < hight ; row ++) {
// 表示データ転送
// Arduinoだとメモリが足りなくて1画面分を一気に転送する事ができない
// なので、1Lineずつ送信している
for (int col = 0 ; col < width*3 ; col ++ ) {
SPIBuf[col*3] = bitData1 ;
SPIBuf[col*3+1] = bitData2 ;
SPIBuf[col*3+2] = bitData3 ;
pos ++ ;
}
SPI.transfer(SPIBuf, width*3);
}
digitalWrite(OLED_DC, LOW); // Command mode
digitalWrite(OLED_CS, HIGH); // SSD1306解放
}
SPISettings settings = SPISettings(8000000, MSBFIRST, SPI_MODE3);
void setup() {
SPI.begin();//SPIを初期化、SCK、MOSI、SSの各ピンの動作は出力、SCK、MOSIはLOW、SSはHIGH
SPI.beginTransaction(settings);
// --- SOFTWARE SPI ピン設定
pinMode(OLED_CS, OUTPUT); // Sleva Select
pinMode(OLED_DC, OUTPUT); // SSD1306 Set data/command pin as output
digitalWrite(OLED_CS, HIGH); // SSD1306解放
pinMode(OLED_MOSI, OUTPUT); // MOSI and SCLK outputs
pinMode(OLED_CLK, OUTPUT); // Serial Clock
digitalWrite(OLED_CLK, LOW); // Clock low
// --- Reset SSD1306
pinMode(OLED_RESET, OUTPUT);
digitalWrite(OLED_RESET, HIGH);
delay(1); // VDD goes high at start, pause for 1 ms
digitalWrite(OLED_RESET, LOW); // Bring reset low
delay(10); // Wait 10 ms
digitalWrite(OLED_RESET, HIGH); // Bring out of reset
// --- SSD1306 初期化
// OLED設定コマンド送信
memcpy(SPIBuf, oledInitCommands, sizeof(oledInitCommands)) ;
oledSendCommands(sizeof(oledInitCommands), SPIBuf) ; // 初期化
oledSendCommand(0xA4) ; // 描画ON
oledSendCommand(0xAF) ; // 画面表示
}
void loop() {
// ----- CLEAR WINDOW -----
memcpy(SPIBuf, drowComandClearWindow, sizeof(drowComandClearWindow)) ;
oledSendCommands(sizeof(drowComandClearWindow), SPIBuf) ; // ClearWindow Command
delayMicroseconds(500);
// ----- FILL -----
oledSendCommand2(0x26, 0x01) ; // 塗りつぶしON
delayMicroseconds(500);
// ----- RECT -----
memcpy(SPIBuf, drowComandRect, sizeof(drowComandRect)) ;
oledSendCommands(sizeof(drowComandRect), SPIBuf) ; // DrowLine Command
delayMicroseconds(500);
// ---- TEST COLOR MODE ---
// oledFillBit1( 0,32,16,16,B11100000) ;
// oledFillBit1(20,32,16,16,B00011100) ;
// oledFillBit1(40,32,16,16,B00000011) ;
oledFillBit2( 0,32,16,16,B11111000,B00000000) ;
oledFillBit2(20,32,16,16,B00000111,B11100000) ;
oledFillBit2(40,32,16,16,B00000000,B00011111) ;
// oledFillBit3( 0,32,16,16,B11111110,B00000000,B00000000) ;
// oledFillBit3(20,32,16,16,B00000000,B11111111,B00000000) ;
// oledFillBit3(40,32,16,16,B00000000,B00000000,B11111110) ;
delay(5000) ;
// ----- TEST -----
oledBitMap(0, 0, 64, 64, bitmapData) ;
delayMicroseconds(500);
memcpy(SPIBuf, drowComandLineR1, sizeof(drowComandLineR1)) ;
oledSendCommands(sizeof(drowComandLineR1), SPIBuf) ; // DrowLine Command
memcpy(SPIBuf, drowComandLineR2, sizeof(drowComandLineR2)) ;
oledSendCommands(sizeof(drowComandLineR2), SPIBuf) ; // DrowLine Command
memcpy(SPIBuf, drowComandLineR3, sizeof(drowComandLineR3)) ;
oledSendCommands(sizeof(drowComandLineR3), SPIBuf) ; // DrowLine Command
memcpy(SPIBuf, drowComandLineG1, sizeof(drowComandLineG1)) ;
oledSendCommands(sizeof(drowComandLineG1), SPIBuf) ; // DrowLine Command
memcpy(SPIBuf, drowComandLineG2, sizeof(drowComandLineG2)) ;
oledSendCommands(sizeof(drowComandLineG2), SPIBuf) ; // DrowLine Command
memcpy(SPIBuf, drowComandLineG3, sizeof(drowComandLineG3)) ;
oledSendCommands(sizeof(drowComandLineG3), SPIBuf) ; // DrowLine Command
delay(5000) ;
// ----- SCROLL -----
memcpy(SPIBuf, drowComandScroolH, sizeof(drowComandScroolH)) ;
oledSendCommands(sizeof(drowComandScroolH), SPIBuf) ; // CopyWindow Command
delayMicroseconds(500);
oledSendCommand(0x2F) ;
delay(5000) ;
oledSendCommand(0x2E) ;
delay(3000) ;
}
SSD1331のビットマップ
ドットの色は R(赤)5Bit、G(緑)6Bit、B(青)5Bitの16Bitで指定
ドットの並びはRemap & Color Depth settingコマンド(0xA0)で指定
Remap & Color Depth setting(0XA0)コマンドのパラメタと表示方向 | |
---|---|
設定値:Bxx100x00 A[5]=0, Disable COM Split Odd Even A[4]=0, Scan from COM 0 to COM [N –1] A[3]=0, Disable left-right swapping on COM A[1]=0, RAM Column 0 to 95 maps to Pin Seg A[0]=0, Horizontal address increment |
設定値:Bxx110x10 A[5]=1, Enable COM Split Odd Even A[4]=1, Scan from COM [N-1] to COM0. A[3]=0, Disable left-right swapping on COM A[1]=1, RAM Column 0 to 95 maps to Pin Seg A[0]=0, Horizontal address increment |
設定値:Bxx100x00 A[5]=0, Disable COM Split Odd Even A[4]=0, Scan from COM 0 to COM [N –1] A[3]=0, Disable left-right swapping on COM A[1]=0, RAM Column 0 to 95 maps to Pin Seg A[0]=0, Horizontal address increment |
設定値:Bxx110x01 A[5]=1, Enable COM Split Odd Even A[4]=1, Scan from COM [N-1] to COM0. A[3]=0, Disable left-right swapping on COM A[1]=0, RAM Column 0 to 95 maps to Pin Seg A[0]=1, Vertical address increment |
Remap & Color Depth setting(0XA0)コマンドのパラメタとドットデータのフォーマット |
---|
設定値:B00xxxxxx |
設定値:B01xxxxxx |
設定値:B10xxxxxx |
BITMAPデータの作成
Windows用の画像データをLCD用のBITMAP定義データに変換するツール LCD Image Converter を利用します。
96x64にリサイズしたImageファイルを読み込みます。 トリミングと拡大は読み込み後にも操作できます。 |
|
Optionsを開いて作成するイメージの BlockSizeを8Bitに設定 | |
コンバートを実行 | |
イメージデータの定義ファイルが出来るので スケッチに貼付けて使用できます。 |