墨水屏(电子纸)的介绍与使用(附STM32程序~~~)

电子墨水屏又被称为电子纸显示技术。电子纸显示技术(简称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,要避免阳光长时间直射显示屏表面。

墨水屏(电子纸)的介绍与使用(附STM32程序~~~)

它有如下特性

● 内置驱动器IC,无需另配驱动器,仅需少量外围器件,即可通过MCU控制显示,节省资源。

● 超宽视角 将近180°

● 超低功耗(断电可以继续保持显示内容)

● 纯反射模式

● 防眩硬涂层前表面

● 低电流深度睡眠模式

● 采用COG封装, IC厚度300um

● 使用寿命(无故障刷新次数):100万次以上

开发者可以参考下面的电路原理图

墨水屏(电子纸)的介绍与使用(附STM32程序~~~)

其中主要引脚功能如下

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引脚电压典型值都远大于芯片电源引脚,因此对该引脚还需要进行一个升压的处理。

墨水屏(电子纸)的介绍与使用(附STM32程序~~~)

如原理图所示,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引脚负电压“升压”操作。

介绍完墨水屏的驱动电路,再和开发者们介绍一下墨水屏的使用方法。

墨水屏的操作流程整体也是比较简单的,大致流程如下。

墨水屏(电子纸)的介绍与使用(附STM32程序~~~)
墨水屏采用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);
					}		
				
			} 	

}

其中

  • xstart,ystart是起始坐标。
  • *datas是传入的显示数组数据。
  • PART_LINE可以认为是显示区域的长度,必须是8的整数倍(一个字节8位)
  • PART_COLUMN可以认为是显示区域的宽度
  • mode是模式,mode位POS , 正显;mode为NEG , 负显;mode为OFF , 清除;

数据写入之后,就是更新显示墨水屏

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();
}

另外再和开发者强调以下几点:

  • 墨水屏刷新频率建议开发刷新时间间隔至少180秒(支持局刷功能的产品除外)。
  • 墨水屏若有在低功耗场景中使用需求,如果显示画面不经常刷新,建议开发者将墨水屏设置为睡眠模式或者将墨水屏驱动供电部分通过模拟开关断开,这样操作既可以降低功耗,同时也可以延长墨水屏的使用寿命。
  • 使用场所要求:墨水屏显示屏建议在室内使用,若在户外使用,需要让墨水屏避免长时间阳光直射,同时做好紫外线防护措施。开发者在设计产品的时候,要首先考虑使用环境是否满足墨水屏正常工作的温湿度要求。

有疑问,大家底下留言评论哦

上一篇:thinkphp做定时任务


下一篇:字符串题目:设计 Goal 解析器