在前一篇我们驱动了OLED,这一篇将重构显示buff、全屏更新OLED显存。并添加显示字符串功能。
1、拷贝一个字符文件到工程中:
2、新建一个结构体,用于显示与命令的存放:
static struct OLED_all_buff_t{ uint8_t cmd; uint8_t data[1024]; //显存 } OLED_all_buff;
3、修改向OLED写入整个显存的函数如下:
static void OLED_Display(struct DisplayDevice* ptDev) { OLED_all_buff.cmd = 0x40; //写数据 //以下为修改为页寻址模式 OLEDDrvWriteReg(0x20); OLEDDrvWriteReg(0x00); OLEDDrvWriteReg(0x21); OLEDDrvWriteReg(0x00); OLEDDrvWriteReg(127); OLEDDrvWriteReg(0x22); OLEDDrvWriteReg(0x00); OLEDDrvWriteReg(7); //向OLED写入整屏 R_SAU_I2C_Write(&g_sau_i2c_master_ctrl, &OLED_all_buff, 1025, true); //等待发送结束 I2C1WaitTxCplt(); }
4、修改画点的函数,将画点修改为向显示缓存修改数据:
static int OLEDDrvSetPixel(struct DisplayDevice* ptDev, unsigned short wX, unsigned short wY, unsigned short wColor) { if(NULL == ptDev->name) return -1; unsigned char *buf = ptDev->FBBase; int page; unsigned char *byte; int bit; if (wX >= ptDev->wXres || wY >= ptDev->wYres) return -1; if(wColor) { buf[(wY/8)*128+wX]|= (1<<(wY%8))&0xff; } else { buf[(wY/8)*128+wX]&= ~((1<<(wY%8))&0xff); } }
5、添加字符显示函数:
static void OLED_ShowChar(struct DisplayDevice* ptDev,uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size,uint8_t mode) { if(NULL == ptDev->name) return; unsigned char c=0,i=0,tmp,j=0; c=chr-' ';//转换为字库里的序号 if(x>ptDev->wXres-1){x=0;y=y+2;} if(Char_Size ==16) { for(i=0;i<16;i++) { if(mode) { tmp = F8X16[c*16+i]; } else { tmp = ~(F8X16[c*16+i]); } for(j=0;j<8;j++) { if(tmp&(0x80>>j)) { ptDev->SetPixel(ptDev,x+j, y+i,1); } else { ptDev->SetPixel(ptDev,x+j, y+i,0); } } } } else if(Char_Size==8) { for(i=0;i<8;i++) { if(mode) { tmp = F6x8[c][i]; } else { tmp = ~(F6x8[c][i]); } for(j=0;j<8;j++) { if(tmp&(0x80>>j)) { ptDev->SetPixel(ptDev,x+j, y+i,1); } else { ptDev->SetPixel(ptDev,x+j, y+i,0); } } } } else { return; } }
6、添加显示字符串的函数如下:
static void OLED_ShowString(struct DisplayDevice* ptDev,uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size,uint8_t mode) { unsigned char j=0,csize; if(Char_Size == 16) { csize = Char_Size/2; } else if(Char_Size == 8) { csize = Char_Size/2+2; } else { return; } while (chr[j]!='\0') { OLED_ShowChar(ptDev,x,y,chr[j],Char_Size,mode); x+=csize; if(x>120) { x=0; y+=Char_Size; } j++; } //OLED_Display(); }
7、将上面的函数更新到LCD驱动里面,
static DisplayDevice gOledDev = { .name = "OLED", .FBBase = OLED_all_buff.data, .wXres = 128, .wYres = 64, .wBpp = 1, .dwSize = 128*64*1/8, .Init = OLEDDrvinit, .DisplayON = OLEDDrvDispON, .DisplayOFF = OLEDDrvDispOFF, .SetDisplayWindow = OLEDDrvSetDispWindow, .SetPixel = OLEDDrvSetPixel, .GUI_DrawPoint = OLED_DrawPoint, //画点 .GUI_ShowChar = OLED_ShowChar, //画字符 .GUI_ShowString = OLED_ShowString, //显示字符串 .GUI_Display = OLED_Display, //更新显存 };
8、这样,我们在主函数里实例化OLED对象,就可以用他的方法来显示字符或者字符串了,在主函数中加入测试函数如下:
void led_blink(void) { uint32_t cnt; UartDevicesRegister(); DisplayDevice *ptDispDev = OLEDGetDevice(); if(ptDispDev == NULL) { printf("Failed to get OLED Display Device!\r\n"); return; } ptDispDev->Init(ptDispDev); while(1) { ptDispDev->GUI_Fill(ptDispDev,0); //清理显存 ptDispDev->GUI_ShowString(ptDispDev,0,0, (uint8_t *)"HELLO WORLD",16,1); //显示字符串 ptDispDev->GUI_ShowString(ptDispDev,10,16, (uint8_t *)"HELLO EEPW",16,1); ptDispDev->GUI_Display(ptDispDev); //刷新数据到OLED HAL_Delay(2); } }
【实现效果】
【总结】
对于面向象对象的编程,我们可以方便的实现模块化的编程。方便在不同的MCU之间的移植。