事接上一集,没看过的直接点击——>优快云
目录
OLED显示
OLED画一个点
void OLED_DrawPoint(uint8_t X, uint8_t Y)
{
/*参数检查,保证指定位置不会超出屏幕范围*/
if (X > 127) {return;}
if (Y > 63) {return;}
/*将显存数组指定位置的一个Bit数据置1*/
OLED_DisplayBuf[Y / 8][X] |= 0x01 << (Y % 8);
}
两个if函数将我们的输入位置确定在屏幕内,这个昨天才说过。
而我们的OLED缓冲序列在门拉出来好好讲讲!
Y / 8
计算了Y
坐标对应的显存数组的行号。因为每一行代表8个像素,所以我们用Y
除以8来得到正确的行号。X
是显存数组的列号,直接表示了点的水平位置。Y % 8
计算了Y
坐标在该行中的具体位位置(0到7)。因为我们要在一个字节中设置特定位,所以我们需要知道要设置的是哪一位。0x01 << (Y % 8)
是一个位操作。它将数字1(在二进制中表示为0000 0001
)左移(Y % 8)
位。这样,我们就得到了一个只有一位是1的字节,其他位都是0。就是选定我们需要的点进行置一!!!|=
是位或赋值运算符。它将左边的表达式的结果与右边的表达式进行位或操作,并将结果存回左边的变量。在这里,它将OLED_DisplayBuf[Y / 8][X]
的当前值与0x01 << (Y % 8)
进行位或操作,以确保OLED_DisplayBuf[Y / 8][X]
中对应的位置被设置为1(如果它之前已经是1,则保持不变)。
总的来说,这个函数允许你在OLED屏幕上绘制一个点,通过修改显存数组中的相应位置的值来实现。在实际应用中,还需要一个函数来将显存数组的内容刷新到实际的OLED屏幕上。
获取OLED点的位置
uint8_t OLED_GetPoint(uint8_t X, uint8_t Y)
{
/*参数检查,保证指定位置不会超出屏幕范围*/
if (X > 127) {return 0;}
if (Y > 63) {return 0;}
/*判断指定位置的数据*/
if (OLED_DisplayBuf[Y / 8][X] & 0x01 << (Y % 8))
{
return 1; //为1,返回1
}
return 0; //否则,返回0
}
好了,举一反三,如果检测到我们需要的点已经置一则返回1否则返回零!
OLED由点——>画图
void OLED_ShowImage(uint8_t X, uint8_t Y, uint8_t Width, uint8_t Height, const uint8_t *Image)
{
uint8_t i, j;
/*参数检查,保证指定图像不会超出屏幕范围*/
if (X > 127) {return;}
if (Y > 63) {return;}
/*将图像所在区域清空*/
OLED_ClearArea(X, Y, Width, Height);
/*遍历指定图像涉及的相关页*/
/*(Height - 1) / 8 + 1的目的是Height / 8并向上取整*/
for (j = 0; j < (Height - 1) / 8 + 1; j ++)
{
/*遍历指定图像涉及的相关列*/
for (i = 0; i < Width; i ++)
{
/*超出边界,则跳过显示*/
if (X + i > 127) {break;}
if (Y / 8 + j > 7) {return;}
/*显示图像在当前页的内容*/
OLED_DisplayBuf[Y / 8 + j][X + i] |= Image[j * Width + i] << (Y % 8);
/*超出边界,则跳过显示*/
/*使用continue的目的是,下一页超出边界时,上一页的后续内容还需要继续显示*/
if (Y / 8 + j + 1 > 7) {continue;}
/*显示图像在下一页的内容*/
OLED_DisplayBuf[Y / 8 + j + 1][X + i] |= Image[j * Width + i] >> (8 - Y % 8);
}
}
}
参数中我们需要知道,const uint8_t *Image是一个指针哦!
这里面所有的if都是用来保证我们的图像不会超出屏幕。
我们来说说,这个操控缓冲序列的函数。
- 对于当前页,函数将图像数据中对应位置的值(
Image[j * Width + i]
)左移(Y % 8)
位,然后使用位或赋值运算符|=
将其与显存中对应位置的值合并。这确保了图像数据的正确位被设置到显存中。 - 如果图像的一个像素跨越了两个页(即该像素在 OLED 显示屏上的 Y 坐标是 8 的倍数加某个值),则需要将该像素的数据也设置到下一页。这通过右移
(8 - Y % 8)
位并将结果合并到下一页的显存中来实现。但是,注意这个操作是在内部循环之后进行的(使用continue
跳过),以确保在当前页没有超出屏幕高度时才进行。
点堆成了图——>变成了有序符号
void OLED_ShowChar(uint8_t X, uint8_t Y, char Char, uint8_t FontSize)
{
if (FontSize == OLED_8X16) //字体为宽8像素,高16像素
{
/*将ASCII字模库OLED_F8x16的指定数据以8*16的图像格式显示*/
OLED_ShowImage(X, Y, 8, 16, OLED_F8x16[Char - ' ']);
}
else if(FontSize == OLED_6X8) //字体为宽6像素,高8像素
{
/*将ASCII字模库OLED_F6x8的指定数据以6*8的图像格式显示*/
OLED_ShowImage(X, Y, 6, 8, OLED_F6x8[Char - ' ']);
}
}
-
大概讲述
Char
:要显示的字符,通常是一个 ASCII 字符。FontSize
:指定字符的字体大小。从代码中可以看出,支持两种字体大小:OLED_8X16
(宽度为 8 像素,高度为 16 像素)和OLED_6X8
(宽度为 6 像素,高度为 8 像素)。函数首先检查FontSize
参数的值来确定要使用的字体大小。如果FontSize
等于OLED_8X16
,则函数将从OLED_F8x16
字模库中选择相应的字符数据,如果FontSize
等于OLED_6X8
,则函数将从OLED_F6x8
字模库中选择相应的字符数据。
-
字符数据获取:
- 字符数据在字模库中的索引是通过
Char - ' '
得到的。这是因为字模库通常是从空格字符(ASCII 值 32)开始存储的,所以通过减去空格字符的 ASCII 值,可以得到字符在字模库中的相对位置。(超级重要)让我来引申一下我们的固有字模库!每一位其实都对应一个点。点与点的组合才构成了我的字符。const uint8_t OLED_F8x16[][16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0 0x00,0x00,0x00,
- 字符数据在字模库中的索引是通过