前言
这算是基础任务的最终实现环节了吧(不考虑传文本置板卡,板卡识别文本的前提下)。文本可以显示了,剩下的就是文本翻页逻辑的添加。
代码实现
功能定义
结合目前资源和基础任务要求,将按键定义如下:
功能实
现按键功能
基于之前已经实现的按键检测功能,此处仅仅需要实现按键对应功能入口的设置,即按KeyA,调用向上翻页入口,按KeyB时,调用向下翻页入口,按KeyC时,调用文本切换入口。具体实现如下:
main.c
int main(void) {
char key = 0x00, key_new;
unsigned char txtIndex = 0;
system_init();
LED_init();
key_init();
epd_init();
DEV_Delay_ms(2000);
// main_EPD_test();
while (true) {
key_new = get_key();
if (key == key_new) {
continue;
}
key = key_new;
if (key) {
LED_ON();
} else {
LED_OFF();
}
switch (key) {
case KEYA_MASK:
epd_show(txtIndex, 2);
break;
case KEYB_MASK:
epd_show(txtIndex, 1);
break;
case KEYC_MASK:
txtIndex = (txtIndex ? 0 : 1);
epd_show(txtIndex, 0);
break;
default:
break;
}
}
return 0;
}翻页和文本切换实现
文本翻页,说简单也简单,就是在上一版本文本显示的基础上,计算出新文本的偏移地址并显示即可。但实现并没有那么容易。其中遇到了不少问题,如:
1. 不确定是否可以动态内存申请,只能做实验验证后看是否可导入。
做实验验证后,发现有戏,直接写双向链表实现。
2. 有点奇葩的是,keil工程中,char类型的变量,居然范围是0~255,不是-128~127,导致一次性写好的代码逻辑和预想的不一致
编译环境问题,也没别的招,只能把char型数据按照unsigned char型数据计算了
3. GB2312字库和ASCII字库的高度不一致,导致计算显示数量时误差大
直接使用简化后的逻辑,GB2312字库,补8行空白,确保缩进一致。
4. 显示屏刷新速度过慢(显示内容刷新了,但后台还在执行收尾动作,且收尾动作耗时过长),导致不知道实际操作状态
保留前面点灯的按键按下亮灯,松开灭灯逻辑,让人有一定感知容忍度
由于之前过程贴已提供前期的实现部分,因此这里仅提供有修改的部分,以期减少文本量。具体代码如下:
my_epd.c
void draw_fb_GB2132(int x, int y, int bankCode, int posCode) {
const unsigned char *pData = NULL;
unsigned char idxX, idxY;
int lineData;
int pos;
pos = ((bankCode - 0xA1) * 94 + (posCode - 0xA1)) * (GB2312_FONT_H * GB2312_FONT_W / 8);
pData = acHZK16C + pos;
for (idxY = 0; idxY < GB2312_FONT_W; idxY++) {
lineData = pData[idxY * 2];
lineData = lineData << 8;
lineData = lineData | pData[idxY * 2 + 1];
for (idxX = 0; idxX < GB2312_FONT_H; idxX++) {
if (lineData & (0x01 << idxX)) {
draw_fb_point(x + GB2312_FONT_H - idxX, y + idxY);
} else {
clear_fb_point(x + GB2312_FONT_H - idxX, y + idxY);
}
}
}
for (idxY = GB2312_FONT_W; idxY < ASCII_FONT_W; idxY++) {
for (idxX = 0; idxX < GB2312_FONT_H; idxX++) {
clear_fb_point(x + GB2312_FONT_H - idxX, y + idxY);
}
}
}
int draw_fb(int x, int y, char *data) {
int j, k, i = 0, dataLen = My_strlen(data);
for (i = 0; i < dataLen;) {
if (data[i] > 127) {
// if (data[i] < 0) {
if ((x + GB2312_FONT_H) > EPD_H) {
x = 0;
y += ASCII_FONT_W;
if ((y + ASCII_FONT_W) > EPD_W) {
goto RET;
}
}
draw_fb_GB2132(x, y, data[i], data[i + 1]);
x += GB2312_FONT_H;
i += 2;
} else {
if ((x + ASCII_FONT_H) > EPD_H) {
x = 0;
y += ASCII_FONT_W;
if ((y + ASCII_FONT_W) > EPD_W) {
goto RET;
}
}
draw_fb_ASCII(x, y, data[i]);
x += ASCII_FONT_H;
i++;
}
}
// clear lase line screen
if (x) {
for (j = x; j < EPD_H; j++) {
for (k = y; k < (y + ASCII_FONT_W); k++) {
clear_fb_point(j, k);
}
}
y += ASCII_FONT_W;
}
RET:
// clear other line
for (j = 0; j < EPD_H; j++) {
for (k = y; k < EPD_W; k++) {
clear_fb_point(j, k);
}
}
return i;
}
int get_next_text(int x, int y, char *data) {
int i = 0, dataLen = My_strlen(data);
for (i = 0; i < dataLen;) {
if (data[i] > 127) {
if ((x + GB2312_FONT_H) > EPD_H) {
x = 0;
y += ASCII_FONT_W;
if ((y + ASCII_FONT_W) > EPD_W) {
goto RET;
}
}
x += GB2312_FONT_H;
i += 2;
} else {
if ((x + ASCII_FONT_H) > EPD_H) {
x = 0;
y += ASCII_FONT_W;
if ((y + ASCII_FONT_W) > EPD_W) {
goto RET;
}
}
x += ASCII_FONT_H;
i++;
}
}
RET:
return i;
}
struct epd_pos {
int pos;
struct epd_pos *next;
struct epd_pos *prev;
};
struct epd_pos *posTbl = NULL, *currentPos = NULL;
void posTbl_free(struct epd_pos *tbl) {
struct epd_pos *nextTbl;
if (tbl == NULL) {
return;
}
while (tbl->next) {
nextTbl = tbl->next;
free(tbl);
tbl = nextTbl;
}
free(tbl);
return;
}
void posTbl_link(struct epd_pos *tbl, struct epd_pos *new_node) {
while (tbl->next) {
tbl = tbl->next;
}
tbl->next = new_node;
new_node->prev = tbl;
return;
}
int epd_show(unsigned char txtIndex, char direction) {
char *pText;
static unsigned char lastIndex = 0xFF;
static unsigned int showCount = 0;
static int pos = 0;
int textLen;
struct epd_pos *new_node, *oldPos = currentPos;
if (txtIndex == 0) {
pText = rj_dzs; // doc1
} else {
pText = dx_dzs; // doc2
}
textLen = My_strlen(pText);
if (lastIndex != txtIndex) {
posTbl_free(posTbl);
posTbl = (struct epd_pos *)malloc(sizeof(struct epd_pos));
posTbl->prev = NULL;
posTbl->next = NULL;
posTbl->pos = 0;
currentPos = posTbl;
}
if (direction == 1) {
if (currentPos->next) {
// Saved pos, just goto next pos
currentPos = currentPos->next;
} else if (currentPos->pos < (textLen - 1)) {
// Find for new pos
pos = currentPos->pos + get_next_text(0, 0, pText + currentPos->pos);
if (pos <= (textLen - 1)) {
new_node = (struct epd_pos *)malloc(sizeof(struct epd_pos));
new_node->pos = pos;
new_node->next = NULL;
posTbl_link(currentPos, new_node);
currentPos = new_node;
}
}
} else if (direction == 2) {
// just jump to prev pos if exist
if (currentPos->prev) {
currentPos = currentPos->prev;
}
}
// update display
if ((oldPos != currentPos) || (lastIndex != txtIndex)) {
draw_fb(0, 0, pText + currentPos->pos);
showCount++;
if (showCount > 40) {
showCount = 0;
updata_to_epd(DISPLAY_ALL);
} else {
updata_to_epd(DISPLAY_PART);
}
}
// update flag
lastIndex = txtIndex;
return pos;
}my_epd.hint epd_show(unsigned char txtIndex, char direction);
最终显示效果
其实这位置使用动图或者视频看效果更好,但奈何无环境录制视频,因此直接贴图片。






最终代码
https://www.bilibili.com/video/BV1fHaXenEcz/
http://v.eepw.com.cn/video/play/id/16144
我要赚赏金
