这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【墨水屏电子书】Let'sDo第2期任务+成果帖+滚动显示文字

共4条 1/1 1 跳转至

【墨水屏电子书】Let'sDo第2期任务+成果帖+滚动显示文字

专家
2024-08-11 14:42:35     打赏

依旧是在例程的基础上进行增改,处理的是对诗词的分析、显示。遇到标点符号,进行换行处理。例程中,实际上把文字转换为了点阵图的图形来显示的。但我没有对例程进行仔细分析,所以走了一条弯路。基本思路是,分析需要显示的汉字、符号,总字库中找到对应的点阵数据,然后根据显示特点,再设置与画面点对点对应的图片上。这个图片定义的宽度与墨水屏的现实宽度一致,高度是墨水屏高的4倍,主要是为了方便实现滚动显示。在转换过程中,因为诗词容量通常不大,所以一次性把所有文字的点阵数据全部保存在图像变量中。这样在处理滚动的时候,只需要控制显示范围的起始、结束行号就行,相当于拿一个框子在图片上上下移动,这样显示起来不用加入过多的计算。

程序主要使用两个函数,一个是把诗词内容的点阵数据转化到图片变量中。一个是根据当前滚动点,把图片数据反映到墨水屏上。


// 将诗词文字转换为背景图像,方便上下移动显示
// 遇到标点符号,自动追加换行符,将文字表示为一行一行的内容
// 墨水屏的分辨率为296*128,对16点阵字符为每行18.5个文字,可显示8行
// 作为示例,下面的诗词每行最多8个文字,因此不用考虑一行显示不下,需要换行的问题
void loadTextToBmp(unsigned char *shici) {
    unsigned int screen_x=0, screen_y=0;    // 屏幕上点的坐标
    unsigned int chridx=0;                  // 字符在字符串中的索引
    uint32_t i=0, j=0;
    uint32_t idx=0;
    
    unsigned char chr[3]={'\0','\0', '\0'}; 
    const unsigned char *pData = NULL;  
    unsigned long lineData;  
    unsigned long pos;  
    unsigned char tmpstr[32] = {'\0'};
    
    clearScreen();
    
    // 初始化bmp数组
    for (j = 0; j < 512; j++) {
        for (i = 0; i < 296; i++) {
            bmp[i][j] = 0;
        }
    }
    
    // 定位到bmp的左上角位置,坐标0,0
    screen_x =0;  // 汉字位置坐标x ,对应在汉字字符串中的水平方向位置,每个汉字占横向占两个字节
    screen_y = 0; // 汉字位置坐标y ,对应在汉字字符串中的垂直方向位置,每个汉字占纵向16行
    idx = 0;
    
    // 分析文字,取得对应的汉字点阵,放入bmp中
    // 每次取出两个字节,一个汉字两个字节
    for (chridx=0; chridx<strlen(shici); chridx+=2) {
        chr[0] = shici[chridx];
        chr[1] = shici[chridx+1];
        
        byteImage[idx++] = chr[0];
        byteImage[idx++] = chr[1];
        
        // 计算汉字在字库中的位置:偏移量
        pos = ((chr[0] - 0xA1) * 94 + (chr[1] - 0xA1)) * (GB2312_FONT_H * GB2312_FONT_W / 8);  
        // 获得该汉字所在地址
        pData = acHZK16C + pos;
        
        // 该汉字所在位置开始,(GB2312_FONT_W/8) * GB2312_FONT_H 个字节为该汉字占用的点阵数据
        for (i=0; i<16; i++) {
            for (j=0; j<8; j++) {
                bmp[screen_x + j][screen_y+i] = (pData[i*2] & (1<<(7-j)))?1:0;    
                bmp[screen_x + j+8][screen_y+i] = (pData[i*2+1] & (1<<(7-j)))?1:0;
            }
        }
        
        // 横向坐标向右移动16个像素点,设置下一个汉字的显示位置
        screen_x = screen_x + GB2312_FONT_W;
        // 遇到,和。要换行
        if ((chr[0] == 0xA3 && chr[1] == 0xAC ) || (chr[0] == 0xA1 && chr[1] == 0xA3 ) || screen_x>= 296 || (chr[0] == 13 && chr[1] == 10 )) {
            // 从头开始显示
            screen_x = 0;
            // 纵坐标向下移动16个像素点
            screen_y += GB2312_FONT_H + 5;  
        }
    }
}
// 一行可以容纳 18.5 个 16*16点阵的汉字
// 显示bmp映射的图像
void loadBmp(uint16_t rowno) {
    uint32_t x=0, y = 0;
    uint32_t idx = 0;
    
    uint16_t screen_x=0, screen_y=0;    // 屏幕上点的坐标(0,0) - (295,127)
    if (rowno >=256) {
        //clearScreen();
        EPD_2IN9D_Clear();
        return;
    } else {
        for (y=rowno; y<128+rowno; y++) {
            for (x=0; x<296; x++ ) {
                if (y>=272) {
                    clear_fb_point(x, y-rowno);  
                } else {
                    if (bmp[x][y]) {  
                        draw_fb_point(x, y-rowno);  
                    } else {  
                        clear_fb_point(x, y-rowno);  
                    }              
                }
            }
        }
    }
    
    updata_to_epd(DISPLAY_PART);  
}

显示效果如下:

整个电路,没有其他多余的电路。按照发货过来时的情况,两个模块直接对接就行。我这里为了方便调试,做了个简单的板子,相当于使用面包板中心进行连接。电路上因为没有附加其它的东西,所以很简单。

原理图.png

墨水屏使用SPI模式通讯,通过接口直接接入PicoSPI外设。这样控制起来就相对简单了。以滚动方式显示文字内容,相对于通过按钮,替换屏幕文字的一个优势是:显示的内容是以图像平移方式显示,看起来顺滑一些,但比较消耗内存。如果是以按钮方式改变显示内容的话,通常是整行替换文字,对内存的要求不高,控制起来也相对容易一些。总之,各有优缺点吧。

参加这次活动的木器,是学习墨水屏的驱动方式。作为显示器件,虽然在构造和显示风格上存在不同的地方,但在外部驱动上,与其它TFT屏,区别还真不是很大。一样采用SPI接口。墨水屏和其它LCDTFT最大的不同在于:断电后,墨水屏依然可以保持住断电前的显示状态,这一点对于某些场景(比如超市价签、电子工牌)非常实用。




菜鸟
2024-08-16 11:13:08     打赏
2楼

谢谢分享


高工
2024-08-20 10:30:18     打赏
3楼

看到你的成果,为你骄傲


助工
2024-08-20 22:45:53     打赏
4楼

谢谢分享


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]