基于stm32的4.2寸墨水屏使用记录

微雪官网中墨水屏介绍:包括了应用在几种常用主控的例程,还有文档资料可供下载

前言

基本的硬件驱动部分就不用多说了,而软件的驱动部分直接使用微雪给的驱动程序就可以了,我主要就是记录下应用开发过程中出现的问题和注意点,特别是全刷和局刷的混用。另外,原本我使用的主控是stm32f103c8t6,后来我换了主控为stm32f401rct6,后面会说明原因。最后得提一下,显示的步骤是:不管全刷还是局刷,先写显存,然后开启显示,最好每次都初始化一下相应的刷新方式。

遇到的几个问题

内存不够

这就是换主控的原因,stm32f103c8t6SRAM只有20K,对于2.9寸可能够用,但是对于4.2寸就不够用了。

可以看到这里会用malloc申请大小为15K堆内存,一般没有改过堆内存大小的话,编译就有问题,我这里就是直接改为数组的形式了。

UBYTE DisplayBuf[(EPD_4IN2_WIDTH / 8)*EPD_4IN2_HEIGHT]={0};

还有一个特别坑的地方就是微雪的例程中,全刷的显存和局刷的显存本质上不是同一个
在局刷函数EPD_4IN2_PartialDisplay内,有这一行代码
static UBYTE DATA[EPD_4IN2_WIDTH * EPD_4IN2_HEIGHT / 8] = {0x00};,又是一个高达15K的空间,绝了。然后我就把它们改成用同一个显存

UBYTE DisplayBuf[(EPD_4IN2_WIDTH / 8)*EPD_4IN2_HEIGHT]={0};
UBYTE *DATA=DisplayBuf;

那个DATA主要是因为局刷函数中原本是靠他往寄存器写旧数据,但这样会导致全刷和局刷混用时出现数据不一致的情况,导致刷新没有理想的效果。现在显存就一个了,就不用考虑这些了,不要忘记把有一行更新DATA的代码注释掉更好。

颜色逻辑相反

这个就感觉是写反了一样,不知道具体原因,比如下面这个例子:

void Paint_DrawNum(UWORD Xpoint, UWORD Ypoint, int32_t Nummber,
                   sFONT* Font, UWORD Color_Foreground, UWORD Color_Background){
    //...其他代码
    //可以看到函数倒数第二个参数是前景色,最后一个是背景色
    //然后下面就把背景色给了画英文字符串函数的前景色参数
    Paint_DrawString_EN(Xpoint, Ypoint, (const char*)pStr, Font, Color_Background, Color_Foreground);
 }

//下面就是Paint_DrawString_EN的函数定义
void Paint_DrawString_EN(UWORD Xstart, UWORD Ystart, const char * pString,
                         sFONT* Font, UWORD Color_Foreground, UWORD Color_Background){
    //...其他代码
    //下面前景背景又反了一下,负负得正了。。
    Paint_DrawChar(Xpoint, Ypoint, * pString, Font, Color_Background, Color_Foreground);
    }


然后继续深入递进查看画图的函数,到画点的上一层为止,无非是区分前景背景,然后根据字符数组的内容,选择是点黑还是点白,应该没人会前景和背景都一样的吧。到这里可以看到逻辑都是正常的,Paint_SetPixel也是正常的,所以如果遇到显示效果前景背景反了,不妨改一下吧。

if (FONT_BACKGROUND == Color_Background) { 
    if (*ptr & (0x80 >> (Column % 8)))
        Paint_SetPixel(Xpoint + Column, Ypoint + Page, Color_Foreground);
        
} else {
    if (*ptr & (0x80 >> (Column % 8))) {
        Paint_SetPixel(Xpoint + Column, Ypoint + Page, Color_Foreground);
        
    } else {
        Paint_SetPixel(Xpoint + Column, Ypoint + Page, Color_Background);
    }
}

防止遗忘的事

巧妙的代码

微雪给的程序,其中最让我感到巧妙的是字模的处理,不过我见过更巧妙的,是结构体形式的字库模式,但忘记格式了。

typedef struct  // 汉字字模数据结构
{
  unsigned char index[2]; //汉字内码索引,巧妙的利用文字的储存格式
  //通过遍历来不断的比较,对于字库规模太大就不适用了,不如偏移的方式
  const char matrix[MAX_HEIGHT_FONT*MAX_WIDTH_FONT/8];  // 点阵码数据
}CH_CN;

typedef struct
{    
  const CH_CN *table;//字库
  uint16_t size;//字库大小
  uint16_t ASCII_Width;//用于英文,对于中文无所谓
  uint16_t Width;//字模的宽
  uint16_t Height;//字模的高
  
}cFONT;

Paint_SetPixel代码中,是通过对显存中原来的数据进行处理,不同于我用过的LCD12864,还得读取寄存器。有一点,X/8这个地方,一开始觉得有问题,后来发现是因为像素格式是和字模数据格式一样,以8位为一组,满8进1(进入下一个数据)的概念,必须等待处理全部的8位像素点才会到下一个数据。

UDOUBLE Addr = X / 8 + Y * Paint.WidthByte;
UBYTE Rdata = Paint.Image[Addr];
if(Color == BLACK)
    Paint.Image[Addr] = Rdata & ~(0x80 >> (X % 8));
else
    Paint.Image[Addr] = Rdata | (0x80 >> (X % 8));

字库的生成

字模采样的设置,大小自己定,每行显示数据指的是单个字模的宽度

当一次性生成大的字库时(数组格式),需要对生成的格式进行批处理,我是用的VIM的宏操作来批处理的,值得注意的是这个软件生成的格式中会在注释的字符后面加上表示该字符是第几个被处理的字符的数字,所以还得分批进行批处理,个位一批、十位一批、百位一批,以此类推。

posted @ 2023-04-01 17:17  pie_thn  阅读(1460)  评论(1)    收藏  举报