带字库LCD12864(ST7920)使用记录(命令 数据 地址 绘图 反白)


【本文发布地址https://blog.csdn.net/Stack_/article/details/113833549,未经许可不得转载,转载须注明出处】


以前用LCD12864做显示直接用前人的程序,今年过年研究了一下这块屏。

关于这块屏的文章已经有很多了,这里主要记录一下已经解开的我的疑惑。



一、串行通讯下,每次写数据都需要发送至少3个字节

带字库LCD12864(ST7920)使用记录(命令 数据 地址 绘图 反白)_第1张图片

/**
 * 串行帧格式:byte0:11111+RW+RS+0		RW:1读 0写   RS:写数据类型,1显示数据 0控制指令
 *			  byte1:HHHH + 0000					  	  读数据类型,1数据 0状态
 *			  byte2:LLLL + 0000		HHHH | LLLL为一个完整字节数据
 */
#define WRITE_COMMAND     0xf8	// 11111 000
#define WRITE_DATA        0xfa	// 11111 010
#define READ_STATE        0xfc	// 11111 100
#define READ_DATA         0xfe	// 11111 110

/**
  * @brief  向LCD12864发一字节显示数据/指令
  * @note   
  * @param  None
  * @retval None
  * @author PWH
  * @date   2021/1
  * @ CSDN Tyrion.Mon
  */
void LCD12864_Write(uint8_t byte_type, uint8_t byte)
{
     CS_SET;
     LCD12864_CheckBusy();
     LCD12864_SendByte(byte_type);            	//先标明数据字节类型:数据/命令
     LCD12864_SendByte(0xf0 & byte);			//字节高四位
     LCD12864_SendByte(0xf0 & (byte << 4));		//字节低四位
     CS_RESET;
}


二、显示地址


1、字符 (基本指令集)

这个不算疑惑,网上一抓一大把,也好理解。

带字库LCD12864(ST7920)使用记录(命令 数据 地址 绘图 反白)_第2张图片


const uint8_t AC_TABLE[4][8]=
{
	0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,      //第一行汉字位置	ST7920芯片分辨率为256 x 64 , 一三为一行,二四为一行,所以指令反白必定两两关联
	0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,      //第二行汉字位置
	0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,      //第三行汉字位置
	0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,      //第四行汉字位置
};

/**
  * @brief  LC12864显示字符串
  * @note   中文字符16*16,8192个在CGROM
  *         英文、数字字符16*8,126个在HCGROM
  * @param  None
  * @retval None
  * @author PWH
  * @date   2021/1
  * @ CSDN Tyrion.Mon
  */
void LCD12864_ShowStr(uint8_t row, uint8_t col, uint8_t *puts)
{
	LCD12864_Write(WRITE_COMMAND, 0x30);      				//基本指令集合
	LCD12864_Write(WRITE_COMMAND, 0x0C);
	LCD12864_Write(WRITE_COMMAND, AC_TABLE[row][col]);      //起始位置
	delay(10, ms);
	while(*puts != '\0')   
	{
		if(col >= 8)            //判断换行
		{            			//若不判断,则自动从第一行到第三行
//			col = 0;
//			row++;
			return;
		}
		if(row >= 4) 
//			row = 0;      //一屏显示完,回到屏左上角
			return;
		LCD12864_Write(WRITE_COMMAND, AC_TABLE[row][col]);
		LCD12864_Write(WRITE_DATA, *puts);      
		puts++;
		LCD12864_Write(WRITE_DATA, *puts);
		puts++;
		col++;
	}
}


2、图片/点阵/打点(扩充指令集)
带字库LCD12864(ST7920)使用记录(命令 数据 地址 绘图 反白)_第3张图片

切换到绘图模式,写入的RAM就从字符显示RAM(DDRAM)切换到点阵显示RAM(GDRAM)了,所以地址和显示字符的地址不一样。


/** 
@ CSDN Tyrion.Mon
  * 				【绘图RAM GDRAM】
  *
  *	屏左上角       水平坐标(每坐标2字节) (8个列地址 * (2bytes * 8bits)) = 128
  *         ---------------------------------
  *			|	  00   01    ...         07	 |										
  * 	垂	| 00							 |
  *			| 01			上半屏			 |
  *			| ...							 |
  *		直	| 1F(31)						 |
  *			|	  08   09    ...         0F  |
  *			| 00							 |
  *		坐	| 01							 |
  *			| ...			下半屏			 |
  *			| 1F(31)						 |
  *     标  |--------------------------------|
  *			(32行地址 + 32行地址 = 64)

  *     总共分为上下两个屏幕,其中第0->31行和第32->63行的行地址相同

		所有地址需要 | 0x80

        (上 0->31)上半屏的地址 (0x80,0x80) -> ... -> (0x80,0x87)
                                     ....
                              (0x9F,0x80) -> ... -> (0x9F,0x87)
        (下 32->63)下半屏的地址(0x80,0x88) -> ... -> (0x80,0x8F)
                                    ...
                              (0x9F,0x88) -> ... -> (0x9F,0x8F)
 */
/**
  * @brief  LC12864显示一张128*64像素的图片
  * @note   
  * @param  None
  * @retval None
  * @author PWH
  * @date   2021/1
  * @ CSDN Tyrion.Mon
  */
void LCD12864_ShowFullImage(uint8_t *puts)
{
	uint16_t x = 0;
	uint8_t  row = 0;
	uint8_t  col = 0;
//	LCD12864_Write(WRITE_COMMAND, 0x34);	//切换到扩展功能,不开绘图显示   (开关会导致闪屏)
	LCD12864_Write(WRITE_COMMAND, 0x36);	//切换到扩展功能,开绘图显示	
	for(row = 0; row < 64; row++)       	//逐行写入     
	{
		/* 设定行地址 , 上半屏0x80 - 0x9F ,下半屏0x80 - 0x9F */
		LCD12864_Write(WRITE_COMMAND, 0x80 + ((row / 32) ? (row - 32) : row));      
		/* 设定列地址起始地址,列地址只需给定一次,因其会自动增加 */
		/* 上半屏首列地址0x80,下半屏首列地址0x88 */
		LCD12864_Write(WRITE_COMMAND, (row / 32) ? 0x88 : 0x80);    
		/* 每行8个列地址,每个地址2字节数据 */						
		for(col = 0; col < 16; col++)      				
		{           
			LCD12864_Write(WRITE_DATA, puts[x++]);
		} 
	}
//	LCD12864_Write(WRITE_COMMAND, 0x36);	//开绘图显示    
//	LCD12864_Write(WRITE_COMMAND, 0x30);	//切换到基本指令
}

/**
  * @brief  LC12864描点
  * @note  
  * @param  None
  * @retval None
  * @author PWH
  * @date   2021/1
  * @ CSDN Tyrion.Mon
  */
void LCD12864_DrawDots(uint8_t row, uint8_t col, uint8_t DotByteH, uint8_t DotByteL)
{
	LCD12864_Write(WRITE_COMMAND, 0x36);	//切换到扩展功能,开绘图显示      
	LCD12864_Write(WRITE_COMMAND, 0x80 + ((row / 32) ? (row - 32) : row));      //设定行地址 , 上半屏0x80 - 0x9F ,下半屏0x80 - 0x9F
	LCD12864_Write(WRITE_COMMAND, (row / 32) ? (0x88 + col) : (0x80 + col));      		//设定列地址起始地址,列地址只需给定一次,因会自动增加
																		//上半屏首列地址0x80,下半屏首列地址0x88
	LCD12864_Write(WRITE_DATA, DotByteH);   
	LCD12864_Write(WRITE_DATA, DotByteL);   	
}



三、反白显示

因为硬件设计问题,一三行会同时反白,二四行也同时反白,只能自行实现任意点反白。

因为最终的显示是DDRAM和GDRAM异或的结果,因此调用LCD12864_DrawDots函数将特定位置填充0xFF后,再调用LCD12864_ShowStr函数在此位置写入字符即可达到反白效果。(如下图“周二”)

或者取字模,在调用LCD12864_DrawDots写入时将点阵数据按位取反。如下图的大数字

带字库LCD12864(ST7920)使用记录(命令 数据 地址 绘图 反白)_第4张图片



四、指令


/*  初始化  */
//功能设定   0x30: DL=1 , 8BitMCU
LCD12864_Write(WRITE_COMMAND, 0x30);   
//功能设定   0x30: RE=0 , 基本指令集合 DL和RE虽在同一组里,但不能同时设,须发两次   				
LCD12864_Write(WRITE_COMMAND, 0x30);      		
//清除显示   0x01: 清屏,AC归0		
LCD12864_Write(WRITE_COMMAND, 0x01);      		
//显示状态   0x0C: 整体显示ON,游标OFF,游标反白OFF		
LCD12864_Write(WRITE_COMMAND, 0x0C);		


/*  写入字符前  */
//切换到基本指令集合
LCD12864_Write(WRITE_COMMAND, 0x30);   
//显示状态   0x0C: 整体显示ON,游标OFF,游标反白OFF   				
LCD12864_Write(WRITE_COMMAND, 0x0C);	


/*  描点前  */
//切换到扩展功能,不开绘图显示(开关会导致闪屏,不关闭也能正常写入、显示)
//	LCD12864_Write(WRITE_COMMAND, 0x34);	
//切换到扩展功能,开绘图显示	
LCD12864_Write(WRITE_COMMAND, 0x36);	

/*  进入点设定  */
未搞懂
/*  游标或显示移位控制  */
未搞懂



主要参考文章
1
2
3
4
5

你可能感兴趣的:(MCU,笔记,单片机)