电子墨水屏又被称为电子纸显示技术。电子纸显示技术(简称EPD),由美国麻省理工大学教授约瑟夫.雅各布森及其研发团队,经历30余年研发成功。
墨水屏的原理很简单,电子墨水屏是由许多电子墨水组成,电子墨水可以看成一个个胶囊的样子。每一个胶囊里面有液体电荷,其中正电荷染白色,负电荷染黑色。当我们在一侧给予正负电压,带有电荷的液体就会被分别吸引和排斥。这样,每一个像素点就可以显示白色或者黑色了。
因为电子墨水的刷新是不连续的,每一次刷新完成就可以保持现在的图形,即使拔掉电池也依旧保存。可能有人会问,为何电池没电,墨水屏也会一直显示最后的画面,那是因为电子墨水具有双稳态磁滞效应,所以即便电池没电,小球也不会回复原状或者进入随机的混沌状态,而是保持最后画面的状态,此时耗电量为0。
本次使用墨水屏型号为QYEG0420BNS19A,外形尺寸为91.0 x77.0x 1.2mm,显示区域尺寸为84.8 x 63.6mm,分辨率为400 x 300,支持显示黑色和白色两种颜色,支持全屏刷新和局部刷新两种模式,刷新功耗为12.6mW。
这里给开发者介绍一下全刷和局部刷的区别
1)全刷:电子纸刷新需要画面闪烁多次后,最终显示所需要的画面,其中闪烁的目的是清除显示残影,以达到最佳的显示效果。
2)局刷:电子纸刷新无画面闪烁,局刷需要用户在使用的时候,刷新几次后,进行一次全刷操作,以清除显示残影。
另外,墨水屏正常使用的温度范围:0~50℃ ,湿度范围:35%~65%RH,要避免阳光长时间直射显示屏表面。
它有如下特性
● 内置驱动器IC,无需另配驱动器,仅需少量外围器件,即可通过MCU控制显示,节省资源。
● 超宽视角 将近180°
● 超低功耗(断电可以继续保持显示内容)
● 纯反射模式
● 防眩硬涂层前表面
● 低电流深度睡眠模式
● 采用COG封装, IC厚度300um
● 使用寿命(无故障刷新次数):100万次以上
开发者可以参考下面的电路原理图
其中主要引脚功能如下
Name | Description |
---|---|
GDR | N勾道场效应管的栅极驱动控制脚 |
RESE | 控制回路的电流检测输入脚 |
VSH2 | 正源极驱动电压 |
TSCL | I2C数字温度传感器的时钟信号接口 |
TSDA | I2C数字温度传感器的数据信号接口 |
BS1 | 总线接口选择引脚 |
BUSY | 繁忙状态输出引脚 |
RES# | 复位信号输入脚, 低电平有效 |
D/C# | 数据/命令控制引脚 |
CS# | 芯片片选引脚 |
SCL | SPI接口的时钟引脚 |
SDA | SPI接口的数据引脚 |
VDDIO | 逻辑接口的电源引脚, 应与VCI脚连接 |
VCI | 芯片电源引脚 |
VSS | 参考地 |
VDD | 核心逻辑电源引脚 |
VPP | 测试脚 , 保持开路 |
VSH1 | 正源极驱动电压 |
VGH | 正门极驱动电压和VSH1的电源引脚 |
VSL | 负源极驱动电压 |
VGL | 负门极驱动电压,VCOM和VSL的电源引脚 |
VCOM | VCOM驱动电压 |
翻阅数据手册如下,可知源极驱动电压VSH引脚和门极驱动电压VGH引脚电压典型值都远大于芯片电源引脚,因此对该引脚还需要进行一个升压的处理。
如原理图所示,3.3V输入源,电感L1,MOS管Q1,电容C1,二极管D3,电阻R2构成了一个最基本的boost升压电路,MOS管Q1的导通或截止状态,由E_GDR控制。
当MOS管Q1导通时,输入电压经过电感L1后直接通过限流电阻R2返回到GND,这导致通过电感L1的电流线性的增大,此时输出滤波电容C1向负载放电。
当MOS管Q1截止时,由于电感L1的电流不能在瞬间发生突变,因此在电感L1上产生反向电动势Vs以维持通过电流不变。此时二极管D3导通,3.3V和Vs两电压串联后,以超过3.3V大小的电压向负载供电,并对输出滤波电容C1充电,如此循环,由此实现对E_PREVGH引脚的升压操作。
同样的,对于E_PREVGL引脚,
当MOS管Q1截止时,电容C2充电,二极管D1导通,D2截止,电流经过D1流向GND,理想情况下电容C2两端的电压差为3.3V+Vs。
当MOS管Q1导通时,Q1的漏极接近0V,由于电容C2电压不能突变,可认为二极管D2的K极电势为-(3.3V+Vs),电容C2放电,二极管D1截止,D2导通,电流经过D2流向C2,由此实现对E_PREVGL引脚负电压“升压”操作。
介绍完墨水屏的驱动电路,再和开发者们介绍一下墨水屏的使用方法。
墨水屏的操作流程整体也是比较简单的,大致流程如下。
墨水屏采用SPI通讯,这部分程序大家自行完成,小编主要给大家介绍一下应用端的程序。
首先是初始化函数
初始化过程中涉及全屏刷新和局部刷新两种
全屏刷新:整个页面全部刷新一次,整个屏幕要闪几次。 优势是没有残影,缺点是要多刷几下屏。
局部刷新:每一次刷新显示内容时,不会整个屏幕都刷新,仅刷新那些有画面和字的地方。优势是屏幕不会闪烁,但会有残影。(残影问题多刷几次白屏就能清除掉或者执行一次全刷也可以清掉)
在实现墨水屏的全局刷新与局部刷新功能时, 从局刷转到全刷时休眠后一定要先进入初始化再刷新。
// refresh_mode = Full 全屏刷新 // refresh_mode = Partial 局部刷新 void EPD_HW_Init(const unsigned char refresh_mode) { EPD_W21_Init(); //hard reset Epaper_READBUSY(); Epaper_Write_Command(0x12); // soft reset Epaper_READBUSY(); Epaper_Write_Command(0x01); //Driver output control Epaper_Write_Data(0x2B); Epaper_Write_Data(0x01); Epaper_Write_Data(0x00); Epaper_Write_Command(0x11); //data entry mode Epaper_Write_Data(0x03); //Y increment, X increment Epaper_Write_Command(0x44); //set Ram-X address start/end position Epaper_Write_Data(0x00); //0x00-->0 Epaper_Write_Data(0x31); //0x31-->(49+1)*8=400 Epaper_Write_Command(0x45); //set Ram-Y address start/end position Epaper_Write_Data(0x00); Epaper_Write_Data(0x00); Epaper_Write_Data(0x2B); //0x012B-->(299+1)=300 Epaper_Write_Data(0x01); Epaper_Write_Command(0x3C); //BorderWavefrom Epaper_Write_Data(0x01); Epaper_Write_Command(0x18); //Temperature Sensor Selection Epaper_Write_Data(0x80); //Internal temperature sensor Epaper_Write_Command(0x22); if(refresh_mode==Full) Epaper_Write_Data(0xB1);//调用全刷LUT if(refresh_mode==Partial) Epaper_Write_Data(0xB9);//调用局刷LUT Epaper_Write_Command(0x20); Epaper_READBUSY(); 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(0x00); Epaper_Write_Data(0x00); Epaper_READBUSY(); }
EPD_W21_Init的功能就是对墨水屏的复位引脚拉低再拉高处理
可以参考如下
void EPD_W21_Init(void) { EPD_W21_RST_0; driver_delay_xms(100); EPD_W21_RST_1; //hard reset driver_delay_xms(100); }
程序中的Epaper_READBUSY函数可以如下定义
uint8_t Epaper_READBUSY(void) { uint8_t ret=1; uint16_t timeout=0xFFFF; LED2_SET; while(isEPD_W21_BUSY) { timeout--; if( 0 == timeout ) { ret = 0; break; } } LED2_RESET; return ret; }
接下来就是显示的例程,如下
void EPD_Dis_Part(unsigned int xstart,unsigned int ystart,const unsigned char * datas,unsigned int PART_LINE,unsigned int PART_COLUMN,unsigned char mode) { unsigned int i; int xend,ystart_H,ystart_L,yend,yend_H,yend_L; xstart=xstart/8;//转换为字节 xend=xstart+PART_LINE/8-1; ystart_H=ystart/256; ystart_L=ystart%256; yend=ystart+PART_COLUMN-1; yend_H=yend/256; yend_L=yend%256; Epaper_Write_Command(0x44); // set RAM x address start/end Epaper_Write_Data(xstart); // RAM x address start; Epaper_Write_Data(xend); // RAM x address end Epaper_Write_Command(0x45); // set RAM y address start/end Epaper_Write_Data(ystart_L); // RAM y address start Low Epaper_Write_Data(ystart_H); // RAM y address start High Epaper_Write_Data(yend_L); // RAM y address end Low Epaper_Write_Data(yend_H); // RAM y address end High Epaper_Write_Command(0x4E); // set RAM x address count Epaper_Write_Data(xstart); Epaper_Write_Command(0x4F); // set RAM y address count Epaper_Write_Data(ystart_L); Epaper_Write_Data(ystart_H); Epaper_Write_Command(0x24); //Write Black and White image to RAM for(i=0;i<PART_COLUMN*PART_LINE/8;i++) { if (mode==POS) { Epaper_Write_Data(*datas); datas++; } if (mode==NEG) { Epaper_Write_Data(~*datas); datas++; } if (mode==OFF) { Epaper_Write_Data(0xFF); } } }
其中
数据写入之后,就是更新显示墨水屏
void EPD_Part_Update(void) { Epaper_Write_Command(0x22); Epaper_Write_Data(0xCF); Epaper_Write_Command(0x20); Epaper_READBUSY(); }
这样就完成显示了,如果想降低功耗,可以再执行睡眠的函数
void EPD_DeepSleep(void) { Epaper_Write_Command(0x10); //enter deep sleep Epaper_Write_Data(0x01); driver_delay_xms(100); }
整体流程可以如下
void EPD(void) { EPD_HW_Init(Full); EPD_Dis_Part(0,0,gImage_num,8,8,NEG); EPD_Part_Update(); EPD_DeepSleep(); }
另外再和开发者强调以下几点:
有疑问,大家底下留言评论哦