上期的《墨水屏电子书》过程篇2-字符显示:https://forum.eepw.com.cn/thread/384823/1展示了有关ASCII显示方法,同样基于该工程,实现中文字符显示,并通过“A”“B”“C”三个按键进行换行阅读。
首先来实现按键控制换行部分的功能,因此首当其冲就要分析按键部分的电路原理图。
根据上面电路原理图的设计,显然很容易得知,当按键“A”,“B”,“C”没有被按下时是悬空状态,为高电平。当按键“A”,“B”,“C”中某个按键按下时,则该管脚被拉低,为低电平输入。按键部分的代码实现如下:
#define PICO_SWA_PIN 12 #define PICO_SWB_PIN 13 #define PICO_SWC_PIN 14 void key_init(void){ gpio_init(PICO_SWA_PIN); gpio_init(PICO_SWB_PIN); gpio_init(PICO_SWC_PIN); gpio_set_dir(PICO_SWA_PIN, GPIO_IN); gpio_set_dir(PICO_SWB_PIN, GPIO_IN); gpio_set_dir(PICO_SWC_PIN, GPIO_IN); gpio_set_pulls(PICO_SWA_PIN,1, 0); gpio_set_pulls(PICO_SWB_PIN,1, 0); gpio_set_pulls(PICO_SWC_PIN,1, 0); } char get_key(void){ if(gpio_get(PICO_SWA_PIN)== 0){ return 1; } else if(gpio_get(PICO_SWB_PIN)== 0){ return 2; } else if(gpio_get(PICO_SWC_PIN)== 0){ return 3; } else{ return 0; } }
工程是基于MDK5.38版本上编辑的,由“axf2uf2.bat”文件可知工程中运用了“tool”文件夹下“elf2uf2.exe”工具,实现将编译好的.axf文件转换成.uf2文件。因此“elf2uf2.exe”文件显得尤为重要,如果开发者的电脑中安装了杀毒软件(如360安全卫士),必须在编译该工程前检查“tool”文件夹下“elf2uf2.exe”是否存在,并将杀毒软件强制退出,否则该文件会被杀毒软件误删。如以下脚本所示,编译完成后,如果检测到Pico处在盘符下载模式,则会“template.uf2”文件自动拷贝到Pico的盘符根目录下。
"..\..\tool\elf2uf2.exe" .\Objects\template.axf .\template.uf2 copy/B .\template.uf2 H:\
接下来就是中文字符显示部分的功能实现,部分代码展示如下:
#include "epd2.h" #include "epd.h" #include "key.h" #include "my_epd.h" #define EPD_W 128 #define EPD_H 296 #define GB2312_FONT_W 16 #define GB2312_FONT_H 16 uint8_t Image_BW2[EPD_W*EPD_H/8]; uint8_t drawfb[EPD_H][EPD_W]; extern const unsigned char acHZK16C[]; uint16_t EPD_WidthMemory; uint16_t EPD_HeightMemory; unsigned char *rj_dzs; void fb_init(){ int x,y; for(x = 0; x < EPD_H; x++){ for(y = 0; y < EPD_W; y++){ drawfb[x][y] = 0; } } EPD_HeightMemory = EPD_H; EPD_WidthMemory = EPD_W; if(EPD_WidthMemory % 8){ EPD_WidthMemory = EPD_W / 8 + 1; }else{ EPD_WidthMemory = EPD_W / 8 ; } } extern const unsigned char acHZK16C[]; 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); } } } } void draw_hanzi(int x, int y, char *data) { int i, dataLen = My_strlen(data); for (i = 0; i < dataLen;) { if (data[i] > 127) { if ((x + GB2312_FONT_H) > EPD_H) { x = 0; y += GB2312_FONT_W; } 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; } draw_fb_ASCII(x, y, data[i]); x += ASCII_FONT_H; i++; } } } int My_strlen(char *data) { int i = 0; while (data[i]) { i++; } return i; } uint8_t get_fb_to_epd(int x,int y){ uint8_t dat = 0xff; char i; for(i = 0; i < 8; i++){ if(drawfb[x][y*8+i]){ dat &= (~(0x80>>i)); } } return dat; } void fb_to_epddata(){ int x,y; int index = 0; for(x = 0; x < EPD_HeightMemory; x++){ index = x * EPD_WidthMemory; for(y = 0; y < EPD_WidthMemory; y++){ Image_BW2[index + y] = get_fb_to_epd( x, y); } } } void draw_fb_point(int x,int y){ drawfb[OLED_H - x - 1][y] = 1; } void epd_init(){ OLED_GPIOInit(); EPD_2IN9D_Init(); EPD_2IN9D_Clear(); fb_init(); } void updata_to_epd(char flag){ fb_to_epddata(); if(flag == DISPLAY_PART){ EPD_2IN9D_DisplayPart(Image_BW2); DEV_Delay_ms(600); }else{ EPD_2IN9D_Init(); EPD_2IN9D_Display(Image_BW2); DEV_Delay_ms(600); } } void clear_fb_point(int x, int y){ drawfb[OLED_H - x -1][y] = 0; }
main函数内容如下:
#define KEYA_MASK 1 #define KEYB_MASK 2 #define KEYC_MASK 3 int main(void) { volatile char key = 0x00; unsigned short offise= 0 ; system_init(); LED_init(); key_init(); epd_init(); while (true) { key = get_key(); switch(key){ case KEYA_MASK: LED_Toggle(); if(offise > 108){ offise -= 108; draw_hanzi(0, 0, rj_dzs+offise); } updata_to_epd(DISPLAY_PART); break; case KEYB_MASK: LED_Toggle(); offise = 0; draw_hanzi(0, 0, rj_dzs+offise); updata_to_epd(DISPLAY_PART); break; case KEYC_MASK: LED_Toggle(); if(offise < My_strlen(rj_dzs)){ offise += 108; draw_hanzi(0, 0, rj_dzs+offise); } updata_to_epd(DISPLAY_PART); break; default: break; } } }
编译完成后,等Pico自动重启后,则可通过按键换行阅读朱自清的《背影》了。阅读部分内容展示如下: 写到最后,小结一下:这是笔者初次通过Keil对Raspberry Pi Pico进行开发,虽然每次编译后下载到Pico开发板,都需要先按下boot按键再给Pico上电,使其进入盘符下载模式,因此感觉有点繁琐。之前基本上都是使用Thonny这类Python语言开发的IDE,这次活动也是让我受益匪浅。感谢EEPW与DigKey联合举办的DIY活动,实验的操作演示视频见B站,链接如下:
https://www.bilibili.com/video/BV1n91qYhEs8/