关于LCD12864我也走了很多坑ovo,也花了不少时间,看过不少文章,现在我也总结一下我的一些发现,求点赞求关注QWQ。

在嵌入式开发中,液晶显示屏(LCD)作为一种常见的显示设备,广泛应用于各种应用场景。今天,我将分享一些关于LCD 128x64显示屏的地址映射和数据写入方式的心得体会,并深入探讨它的工作原理。
我购买的主要是这一款产品SMR12864-15A

SMR12864-15A系列中文图形液晶模块的特性主要由其控制AIP31020决定。AIP31020同时作为控制器和驱动器,它可提供 33 路 com 输出和 64 路 seg 输出在驱动器 AIP31021的配合下,最多可以驱动256×32 点阵液晶。备注:AIP31020控制器的 128×64 点阵液晶其实原理上等同 256×32 点阵,

LCD 128x64 显示屏的地址映射

Y\X 第0列 第2列 第3列 第4列 ~ 第7列
第0行 16位像素数据 16位 16位 16位 16位 16位
第2行 16位像素数据 数据 数据 数据 数据 数据
第3行 16位像素数据 数据 数据 数据 数据 数据
~ 16位像素数据 数据 数据 数据 数据 数据
第31行 16位像素数据 数据 数据 数据 数据 数据
Y\X 第8列 第9列 第10列 第11列 ~ 第15列
第0行 16位像素数据 数据 数据 数据 数据 数据
~ 16位像素数据 数据 数据 数据 数据 数据
第31行 16位像素数据 数据 数据 数据 数据 数据

他其实更像是一块256X32 ,只不过另一半给搬到了屏幕下面。折合成128X64,所以在设定地址上要做出一点修改
如果要找第63行,其实应该是下半屏幕,那么63-32=31.对应的是31行,那么如何定位X轴,呢 ,如果我们需要定位的
比如说是第255位,实际上是第7列,255/16 =7 ;
如果是在下半屏幕的255,只需要在7+8;

提供 64×32 个字节的空间(由扩充指令设定绘图 RAM 地址),最多可以控制256×64 点阵的二维绘图缓冲空间,在更改绘图 RAM 是,由扩充指令设置 GDRAM地址先垂直地址后水平地址(连续 2 个字节的数据来定义垂直和水平地址),再2 个字节的数据给绘图 RAM(先高 8 位后低 8 位)。

设定 GDRAM 地址到地址计数器(AC),先设置垂直位置再设置水平位置(连续写入 2 字节数据来完成垂直与水平坐标的设置)。
垂直地址范围:AC6~AC0 (0~63)
水平地址范围:AC3~AC0 (0~15)
因为他的地址格式实际上是这样子的

水平地址 1 0 0 0 A3 A2 A1 A0
垂直地址 1 A6 A5 A4 A3 A2 A1 A0

在理解了这个映射关系后,你可以通过设置坐标来控制显示内容。通常我们会使用LCD_SetGDRAMAddress函数来设置像素点的坐标,代码示例如下:

/**
  * @brief  设置 GDRAM 地址
  * @param  x: X 方向起始地址
  * @param  y: Y 方向起始地址
  * @retval 无
  * @note   
  */
void LCD_SetGDRAMAddress(uint8_t x, uint8_t y)
{
    uint8_t verticalAddr, horizontalAddr;

    if (y >= 32) // 下半屏
    {
        verticalAddr = 0x80 | (y - 32);   // 处理下半屏,Y 坐标减去 32
        horizontalAddr = 0x88 | (x >> 4); // horizontalAddr = 0x80 | 0x08 | (x / 16):
    }
    else // 上半屏
    {
        verticalAddr = 0x80 | y;          // 上半屏,直接使用 Y 坐标
        horizontalAddr = 0x80 | (x >> 4); // x/16
    }

    LCD_WriteCommand(verticalAddr);   // 先写入垂直地址
	
    LCD_WriteCommand(horizontalAddr); // 再写入水平地址
}

通过这段代码,我们可以清晰地控制每个像素点的显示,确保无论是上半屏还是下半屏,都能够正确地映射到LCD的显示区域。

地址映射细节

实际上,LCD 128x64屏幕的地址映射更像是一块256x32的屏幕,只不过下半部分被映射到屏幕的下方。为了正确地访问每个像素,我们必须注意到下半屏的地址偏移。

例如,如果你需要定位第63行,你应该将其映射到下半屏的第31行(63 - 32 = 31)。此外,x轴的地址是按列分配的,每列对应16个像素,因此每次需要跳转16个位置(也就是每次写两个字节)。这就意味着,写入一个字节将影响8个像素,而每两个字节写入将覆盖16个像素。

清屏与绘图

在得到了正确的地址映射后,我们可以轻松地实现清屏和绘图等功能。以下是一个简单的清屏实现,它将所有像素点的显示数据设置为0,清空屏幕:

void LCD_Draw_Clear(void)
{
	uint8_t x, y; 
	
	for(y = 0; y < 32; y++) // 0~31	
	{   
		LCD_SetGDRAMAddress(0, y);	// 设置显示坐标
  		for(x = 0; x < 16; x++) // 0~15
  		{	
			/* 因为x轴一个地址对应16个像素点,可以连续发送两个字节数据 */
  		    LCD_WriteDisplayData(0x00);
  		    LCD_WriteDisplayData(0x00);
  		}	
	}
}

这段代码遍历每一行,并设置每个像素点为0,从而清除屏幕上的所有内容。

绘制图片

在处理完屏幕清除后,我们可以绘制图像。这就需要将图片的数据转化为适合LCD显示的格式,通常是一个字节数组,每个字节代表8个像素。通过以下代码,我们能够将图片数据绘制到LCD屏幕上:

void LCD_Draw_Pic(const unsigned char *data){
	uint8_t x, y;
	
	for(y = 0; y < 64; y++)
	{   
		LCD_SetGDRAMAddress(0, y);
  		for(x = 0; x < 8; x++)
  		{	
  		    LCD_WriteDisplayData(*data++);
			LCD_DelayUs(10);			
			
			LCD_WriteDisplayData(*data++);
  		}	
	}	
}

通过这种方式,我们能够在LCD屏幕上绘制出自定义图像。

绘制自定义尺寸的图片

void LCD_Draw_CustomPic(uint8_t startX, uint8_t startY, uint8_t width, uint8_t height, const unsigned char *data)
{
    uint8_t x, y;
    
    // 确保宽度和高度不超出显示屏的最大尺寸
    if (startX + width > 128) startX = 128 - width;   
    if (startY + height > 64) startY = 64 - height;
	
    for (y = 0; y < height; y++)
    {
        LCD_SetGDRAMAddress(startX, startY + y); // 设定起始地址

        for (x = 0; x < width ; x += 8)
        {	
            LCD_WriteDisplayData(*data++);
			
        }
    }
}

图片的取模方式

取模软件位:Pctolcd2002
取模参数调整为:

  • 高位在前(MSB First)
  • 横向取模(逐行扫描)
  • 其他参数保持不变
  • 可以修改输出格式
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐