根据规格书流程图和指令表编写您的电子纸驱动程序 (Arduino-IDE)
- 以Good Display的2.13英寸电子墨水屏GDEY0213B74为例
-
产品链接地址 (英文官网):https://www.good-display.com/product/391.html
-
IC SSD1680 手册:https://www.good-display.com/companyfile/101.html
-
使用的示例程序demo: https://www.good-display.com/companyfile/631.html
-
GDEY0213B74图片取模说明: https://www.good-display.com/companyfile/633.html
-
推荐使用的取模软件-Image2LCD: https://github.com/GoodDisplay/E-paper-Display-Library-of-GoodDisplay/tree/main/Image2LCD
-
推荐使用的在线取模工具:https://www.e-paper-display.com/project/English.html
电子墨水屏的工作原理?
电子墨水屏采用了E Ink掌握的电泳显示技术,通过改变施加的电压来驱动带电微胶囊粒子进行工作。 其中的每个像素点由单个电子墨水组成,也就是一个微胶囊单元。每一个胶囊里都有液体电荷,其中正电荷染白色,负电荷染黑色。当在一侧给予正负电压,带有电荷的液体就会被分别吸引和排斥从而能够显示黑色或白色的图像。
2.13英寸电子墨水屏GDEY0213B74的硬件参数
#参数符号含义
单接地 Vss
逻辑电源电压 Vci
逻辑高电平 Voh
逻辑低电平 Vol
典型功率 Ptyp
睡眠功率 Psleep
睡眠电流 Isleep
深度睡眠电流 Idsleep
VCOM引脚输出
规格书中的墨水屏驱动流程图
流程图配合代码说明
1.给屏幕进行供电,一般推荐3.3V的电源
2.初始化配置
2.1. 在这一步您需要对墨水屏同MCU之间的SPI通信进行配置,也即IO setting
有关SPI以及这款墨水屏的SPI通信配置,具体您可以参考规格书的6.3 Panel AC Characteristics
参考以下代码:
#include <SPI.h>
#include"Ap_29demo.h"
//IO settings
int BUSY_Pin = 4;
int RES_Pin = 5;
int DC_Pin = 6;
int CS_Pin = 7;
#define EPD_W21_CS_0 digitalWrite(CS_Pin,LOW)
#define EPD_W21_CS_1 digitalWrite(CS_Pin,HIGH)
#define EPD_W21_DC_0 digitalWrite(DC_Pin,LOW)
#define EPD_W21_DC_1 digitalWrite(DC_Pin,HIGH)
#define EPD_W21_RST_0 digitalWrite(RES_Pin,LOW)
#define EPD_W21_RST_1 digitalWrite(RES_Pin,HIGH)
#define isEPD_W21_BUSY digitalRead(BUSY_Pin)
void setup() {
pinMode(BUSY_Pin, INPUT);
pinMode(RES_Pin, OUTPUT);
pinMode(DC_Pin, OUTPUT);
pinMode(CS_Pin, OUTPUT);
//SPI
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
SPI.begin ();
}
2.2. 根据流程图,完成SPI通信配置后,您需要执行墨水屏的硬件初始化以及软件初始化:
/////////////////EPD settings Functions/////////////////////
void EPD_HW_Init(void)
{
EPD_W21_RST_0; // Module reset
delay(10);//At least 10ms delay
EPD_W21_RST_1;
delay(10); //At least 10ms delay
Epaper_READBUSY();
Epaper_Write_Command(0x12); //SWRESET
Epaper_READBUSY();
3.发送初始化代码
此部分涉及代码片段如下:
Epaper_Write_Command(0x01); //Driver output control
Epaper_Write_Data(0xF9);
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x00);
Epaper_Write_Command(0x11); //data entry mode
Epaper_Write_Data(0x01);
Epaper_Write_Command(0x44); //set Ram-X address start/end position
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x0F); //0x0F-->(15+1)*8=128
Epaper_Write_Command(0x45); //set Ram-Y address start/end position
Epaper_Write_Data(0xF9); //0xF9-->(249+1)=250
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x00);
Epaper_Write_Command(0x3C); //BorderWaveform
Epaper_Write_Data(0x05);
3.1. 驱动器输出控制(Driver Output Control)
这部分总共需要分别写3个字节的数据:
往A[8:0]写0xF9, 也即(249+1),开启共250个Gate
往B[2:0]写0x00,即从G0开始到G249,G0作为第一个输出的Gate; 扫描序列0,1,2,3...249; 扫描顺序从0到249
3.2. Data Entry Mode Setting
写入指令0x11,并往A[2:0]写0x01, 也即ID[1:0]=01, AM=0
根据下图和解释说明,我们设置成这种模式:
地址计数器会在X方向上进行更新;并且在数据每次被写入RAM后,Y地址计数器自动减少1,X地址计数器自动增加1
- 内部有一个地址计数器,自动地在某方向加减地址,通过AM设置方向;ID控制加减。
- ID[0]=“1”时,将数据写入RAM后,X地址计数器将自动增加1。
- ID[0]=“0”时,将数据写入RAM后,X地址计数器会自动减少1。
- ID[1]=“1”时,将数据写入RAM后,Y地址计数器将自动增加1。
- ID[1]=“0”时,将数据写入RAM后,Y地址计数器会自动减少1。
- AM=“0”时,地址计数器在X方向上更新。
- AM=“1”时,地址计数器在Y方向上更新。
- 当选择窗口地址后,数据将以ID[1:0]和AM位指定的方式写入由窗口地址指定的RAM区域。
3.3. 扫描像素点地址设置(Set RAM X&Y-Address Start/End Position)
Epaper_Write_Command(0x44); //set Ram-X address start/end position
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x0F); //0x0F-->(15+1)*8=128
Epaper_Write_Command(0x45); //set Ram-Y address start/end position
Epaper_Write_Data(0xF9); //0xF9-->(249+1)=250
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x00);
您现在需要使用0x44, 0x45指令
0x44:A[5:0]设置窗口的X方向起始地址 0x44:B[5:0]设置窗口的X方向终止地址
分别写入0x00和0x0F,确定X起始为0,终止为(15+1)*8=128
0x45:A[8:0]设置窗口的Y方向起始地址 0x45:B[8:0]设置窗口的Y方向终止地址
根据0x01中写入的0x01确定的模式,
则在249设置起始地址,并在0处设置终止地址。
3.3. 边框设置(Border Waveform Control)
Epaper_Write_Command(0x3C); //BorderWaveform
Epaper_Write_Data(0x05);
4. Load Waveform LUT
Epaper_Write_Command(0x18); //Read built-in temperature sensor
Epaper_Write_Data(0x80);
5. 墨水屏图像输出
0x4E、0x4F设置RAM地址计数器的初值
0x4E:A[5:0]设置当前RAM地址X方向计数器的值, X为0
0x4F:A[7:0]设置当前RAM地址Y方向计数器的值, Y为249
Epaper_Write_Command(0x4E); // set RAM x address count
Epaper_Write_Data(0x00);
Epaper_Write_Command(0x4F); // set RAM y address count
Epaper_Write_Data(0xF9);
Epaper_Write_Data(0x00);
接下来执行0x24指令,对于GDEY0213B74这款黑白墨水屏,黑色则写0,白色则写1,分别对应0x00和0xff。
//////////////////////Single display///////////////////////////////////
void EPD_WhiteScreen_Black(void)
{
unsigned int i;
Epaper_Write_Command(0x24); //write RAM for black(0)/white (1)
for(i=0;i<4000;i++)
{
Epaper_Write_Data(0x00);
}
EPD_Update();
}
void EPD_WhiteScreen_White(void)
{
unsigned int i;
Epaper_Write_Command(0x24); //write RAM for black(0)/white (1)
for(i=0;i<4000;i++)
{
Epaper_Write_Data(0xff);
}
EPD_Update();
}
*0x0C在调用外部波形时调用的指令,本demo中不涉及
/////////////////////////All screen update//////////////////////////////
void EPD_WhiteScreen_ALL(const unsigned char * datas)
{
unsigned int i;
Epaper_Write_Command(0x24); //write RAM for black(0)/white (1)
for(i=0;i<4000;i++)
{
Epaper_Write_Data(pgm_read_byte(&datas[i]));
}
EPD_Update();
}
void EPD_WhiteScreen_ALL_Fast(const unsigned char *datas)
{
unsigned int i;
Epaper_Write_Command(0x24); //write RAM for black(0)/white (1)
for(i=0;i<4000;i++)
{
Epaper_Write_Data(pgm_read_byte(&datas[i]));
}
EPD_Update_Fast();
}
/////////////////////////////////////////////////////////////////////////////////////////
void EPD_Update(void)
{
Epaper_Write_Command(0x22); //Display Update Control
Epaper_Write_Data(0xF7);
Epaper_Write_Command(0x20); //Activate Display Update Sequence
Epaper_READBUSY();
}
void EPD_Update_Fast(void)
{
Epaper_Write_Command(0x22); //Display Update Control
Epaper_Write_Data(0xC7);
Epaper_Write_Command(0x20); //Activate Display Update Sequence
Epaper_READBUSY();
}
void EPD_Part_Update(void)
{
Epaper_Write_Command(0x22);//Display Update Control
Epaper_Write_Data(0xFF);
Epaper_Write_Command(0x20); //Activate Display Update Sequence
Epaper_READBUSY();
}
void EPD_DeepSleep(void)
{
Epaper_Write_Command(0x10); //enter deep sleep
Epaper_Write_Data(0x01);
delay(100);
}
void Epaper_READBUSY(void)
{
while(1)
{ //=1 BUSY
if(isEPD_W21_BUSY==0) break;
}
}
5.1 Display Update Control
上述代码片段设计三种墨水屏的更新方式:
EPD_Update Epaper_Write_Data(0xF7);
EPD_Update_Fast Epaper_Write_Data(0xC7);
EPD_Part_Update Epaper_Write_Data(0xFF);
Epaper_Write_Command(0x21); // Display update control
Epaper_Write_Data(0x00);
Epaper_Write_Data(0x80);
写0x00则有:
A[7:4] 0000-Normal
A[3:0] 0000-Normal
B[7]写0x80对应1, S8toS167 (写0x00则对应 S0toS175)
如果把0x80改为0x00,实际效果相当于整幅画面上移8bit
其中
for(i=0;i<4000;i++)
来源于Ap_29demo.h
const unsigned char gImage_basemap[4000]
所以,您首先需要进行图片取模,图片的分辨率必须是250x122,然后按照图片取模说明文档的步骤进行操作(配合Image2LCD软件使用);您也可以直接使用Good Display的在线工具-ImageToArray,这样您只需要确保图片分辨率满足250x122,图片格式支持jpg, png。
如果您选择了垂直扫描的方式,那么得到的就是4000个字节;
如果您选择了水平扫描的方式,那么得到的就是3904个字节;相应地,for(i=0;i<3904;i++)
6. 墨水屏完成画面更新,进入睡眠
void EPD_DeepSleep(void)
{
Epaper_Write_Command(0x10); //enter deep sleep
Epaper_Write_Data(0x01);
扫二维码用手机看