在前一篇我们驱动了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之间的移植。
我要赚赏金
