2024-06-22 06:29:51 +00:00
|
|
|
#include "oled.h"
|
|
|
|
#include "oled_font.h"
|
2024-06-23 10:03:57 +00:00
|
|
|
#include "oled_font_chuc.h"
|
2024-06-24 14:58:18 +00:00
|
|
|
#include "../../inc/font/lvgl_font.h"
|
2024-06-22 06:29:51 +00:00
|
|
|
|
2024-06-22 11:13:18 +00:00
|
|
|
#define BUFPOINT(x, y) (*(dev->buf + x + (y * dev->width)))
|
2024-06-23 10:03:57 +00:00
|
|
|
#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit)
|
2024-06-22 06:29:51 +00:00
|
|
|
|
2024-06-23 05:03:24 +00:00
|
|
|
const uint8_t initCmd[] = {
|
|
|
|
0xAE, // 关闭显示
|
|
|
|
0xD5, 0x80, // 设置显示时钟分频比/振荡器频率
|
|
|
|
0xA8, 0x3F, // 设置多路复用比率
|
|
|
|
0xD3, 0x00, // 设置显示偏移
|
|
|
|
0x40, 0x00, // 设置显示起始行
|
|
|
|
0x8D, 0x14, // 电荷泵设置
|
|
|
|
0x20, 0x00, // 设置内存寻址模式
|
|
|
|
0xA0, // 设置段重映射
|
|
|
|
0xC0, // 设置COM输出扫描方向
|
|
|
|
0xDA, 0x12, // 设置COM引脚硬件配置
|
|
|
|
0x81, 0xCF, // 设置对比度控制
|
|
|
|
0xD9, 0xF1, // 设置预充电周期
|
|
|
|
0xDB, 0x20, // 设置VCOMH取消电平
|
|
|
|
0xA4, 0xA6, // 整个显示打开
|
|
|
|
0xAF // 打开显示
|
|
|
|
};
|
|
|
|
|
2024-06-22 06:29:51 +00:00
|
|
|
void OLED_Init(OLED_T *dev) {
|
|
|
|
uint8_t *cmdIndex = (uint8_t *) initCmd;
|
2024-06-22 11:13:18 +00:00
|
|
|
// uint8_t count, temp;
|
|
|
|
// while (*cmdIndex) {
|
|
|
|
// temp = *cmdIndex++;
|
|
|
|
// count = temp & 0x7F;
|
|
|
|
//
|
|
|
|
// dev->cmd(cmdIndex, count);
|
|
|
|
// cmdIndex += count;
|
|
|
|
// }
|
|
|
|
dev->cmd(cmdIndex, sizeof(initCmd));
|
2024-06-22 06:29:51 +00:00
|
|
|
dev->state = IDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_ON(OLED_T *dev) {
|
|
|
|
uint8_t cmd[3] = {0x8D, 0x14, 0xAF};
|
|
|
|
if (dev->state == IDLE) {
|
|
|
|
dev->state = WRITE;
|
|
|
|
dev->cmd(cmd, 3);
|
|
|
|
dev->state = IDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_OFF(OLED_T *dev) {
|
|
|
|
uint8_t cmd[3] = {0x8D, 0x10, 0xAE};
|
|
|
|
if (dev->state == IDLE) {
|
|
|
|
dev->state = WRITE;
|
|
|
|
dev->cmd(cmd, 3);
|
|
|
|
dev->state = IDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_Turn(OLED_T *dev, bool e) {
|
|
|
|
uint8_t cmd = 0xA6 + e;
|
|
|
|
if (dev->state == IDLE) {
|
|
|
|
dev->state = WRITE;
|
|
|
|
dev->cmd(&cmd, 1);
|
|
|
|
dev->state = IDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_Refresh(OLED_T *dev) {
|
2024-06-22 06:45:07 +00:00
|
|
|
#if REFRESH_CALL_ENABLE
|
2024-06-22 07:21:15 +00:00
|
|
|
dev->call(dev);
|
2024-06-22 06:45:07 +00:00
|
|
|
#else
|
2024-06-22 07:21:15 +00:00
|
|
|
uint8_t i, cmd[3] = {0xb0, 0x00, 0x10};
|
2024-06-22 06:29:51 +00:00
|
|
|
if (dev->state == IDLE) {
|
|
|
|
dev->state = REFRESH;
|
|
|
|
for (i = 0; i < (dev->height >> 3); i++) {
|
|
|
|
cmd[0] = 0xb0 + i;
|
|
|
|
dev->cmd(cmd, 3);
|
|
|
|
dev->data(dev->buf + (i * dev->width), dev->width);
|
|
|
|
}
|
2024-06-22 08:41:48 +00:00
|
|
|
dev->state = IDLE;
|
2024-06-22 06:29:51 +00:00
|
|
|
}
|
2024-06-22 06:45:07 +00:00
|
|
|
#endif
|
2024-06-22 06:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_DisplayTurn(OLED_T *dev, bool e) {
|
|
|
|
uint8_t cmd[2];
|
|
|
|
if (e) {
|
|
|
|
cmd[0] = 0xC8;
|
|
|
|
cmd[1] = 0xA1;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
cmd[0] = 0xC0;
|
|
|
|
cmd[1] = 0xA0;
|
|
|
|
}
|
|
|
|
if (dev->state == IDLE) {
|
|
|
|
dev->state = WRITE;
|
|
|
|
dev->cmd(cmd, 1);
|
|
|
|
dev->state = IDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_Set(OLED_T *dev, uint8_t x, uint8_t y) {
|
|
|
|
uint8_t i, m, n;
|
|
|
|
i = y / 8;
|
|
|
|
m = y % 8;
|
|
|
|
n = 1 << m;
|
|
|
|
BUFPOINT(x, i) |= n;
|
|
|
|
}
|
|
|
|
|
2024-06-23 10:03:57 +00:00
|
|
|
void OLED_BSet(OLED_T *dev, uint8_t x, uint8_t y, uint8_t data) {
|
|
|
|
uint8_t i, ys = y;
|
|
|
|
for (i = 0; i < 8; i++) //写入数据
|
|
|
|
{
|
|
|
|
if (GET_BIT(data, i))OLED_Set(dev, x, ys);
|
|
|
|
else OLED_RSet(dev, x, ys);
|
|
|
|
ys++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-22 06:29:51 +00:00
|
|
|
void OLED_RSet(OLED_T *dev, uint8_t x, uint8_t y) {
|
|
|
|
uint8_t i, m, n;
|
|
|
|
i = y / 8;
|
|
|
|
m = y % 8;
|
|
|
|
n = 1 << m;
|
|
|
|
BUFPOINT(x, i) = ~BUFPOINT(x, i);
|
|
|
|
BUFPOINT(x, i) |= n;
|
|
|
|
BUFPOINT(x, i) = ~BUFPOINT(x, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_DrawLine(OLED_T *dev, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
|
|
|
|
uint8_t i, k, k1, k2;
|
|
|
|
if ((x1 < 0) || (x2 > dev->width) || (y1 < 0) || (y2 > dev->height) || (x1 > x2) || (y1 > y2))return;
|
|
|
|
if (x1 == x2) //画竖线
|
|
|
|
{
|
|
|
|
for (i = 0; i < (y2 - y1); i++) {
|
|
|
|
OLED_Set(dev, x1, y1 + i);
|
|
|
|
}
|
|
|
|
} else if (y1 == y2) //画横线
|
|
|
|
{
|
|
|
|
for (i = 0; i < (x2 - x1); i++) {
|
|
|
|
OLED_Set(dev, x1 + i, y1);
|
|
|
|
}
|
|
|
|
} else //画斜线
|
|
|
|
{
|
|
|
|
k1 = y2 - y1;
|
|
|
|
k2 = x2 - x1;
|
|
|
|
k = k1 * 10 / k2;
|
|
|
|
for (i = 0; i < (x2 - x1); i++) {
|
|
|
|
OLED_Set(dev, x1 + i, y1 + i * k / 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-22 11:13:18 +00:00
|
|
|
void OLED_DrawRect(OLED_T *dev, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
|
|
|
|
OLED_DrawLine(dev, x1, y1, x2, y1); // Top side
|
|
|
|
OLED_DrawLine(dev, x1, y1, x1, y2); // Left side
|
|
|
|
OLED_DrawLine(dev, x2, y1, x2, y2); // Right side
|
|
|
|
OLED_DrawLine(dev, x1, y2, x2, y2); // Bottom side
|
|
|
|
}
|
|
|
|
|
2024-06-22 06:29:51 +00:00
|
|
|
void OLED_DrawCircle(OLED_T *dev, uint8_t x, uint8_t y, uint8_t r) {
|
|
|
|
int a, b, num;
|
|
|
|
a = 0;
|
|
|
|
b = r;
|
|
|
|
while (2 * b * b >= r * r) {
|
|
|
|
OLED_Set(dev, x + a, y - b);
|
|
|
|
OLED_Set(dev, x - a, y - b);
|
|
|
|
OLED_Set(dev, x - a, y + b);
|
|
|
|
OLED_Set(dev, x + a, y + b);
|
|
|
|
|
|
|
|
OLED_Set(dev, x + b, y + a);
|
|
|
|
OLED_Set(dev, x + b, y - a);
|
|
|
|
OLED_Set(dev, x - b, y - a);
|
|
|
|
OLED_Set(dev, x - b, y + a);
|
|
|
|
|
|
|
|
a++;
|
|
|
|
num = (a * a + b * b) - r * r;//计算画的点离圆心的距离
|
|
|
|
if (num > 0) {
|
|
|
|
b--;
|
|
|
|
a--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_ShowChar(OLED_T *dev, uint8_t x, uint8_t y, uint8_t chr, uint8_t size1) {
|
|
|
|
uint8_t i, m, temp, size2, chr1;
|
2024-06-23 10:03:57 +00:00
|
|
|
uint8_t ys = y;
|
2024-06-22 06:29:51 +00:00
|
|
|
size2 = (size1 / 8 + ((size1 % 8) ? 1 : 0)) * (size1 / 2); //得到字体一个字符对应点阵集所占的字节数
|
|
|
|
chr1 = chr - ' '; //计算偏移后的值
|
|
|
|
for (i = 0; i < size2; i++) {
|
|
|
|
if (size1 == 12) { temp = asc2_1206[chr1][i]; } //调用1206字体
|
|
|
|
else if (size1 == 16) { temp = asc2_1608[chr1][i]; } //调用1608字体
|
|
|
|
else if (size1 == 24) { temp = asc2_2412[chr1][i]; } //调用2412字体
|
|
|
|
else return;
|
|
|
|
for (m = 0; m < 8; m++) //写入数据
|
|
|
|
{
|
2024-06-23 10:03:57 +00:00
|
|
|
if (temp & 0x80)OLED_Set(dev, x, ys);
|
|
|
|
else OLED_RSet(dev, x, ys);
|
2024-06-22 06:29:51 +00:00
|
|
|
temp <<= 1;
|
2024-06-23 10:03:57 +00:00
|
|
|
ys++;
|
|
|
|
if ((ys - y) == size1) {
|
|
|
|
ys = y;
|
2024-06-22 06:29:51 +00:00
|
|
|
x++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_ShowString(OLED_T *dev, uint8_t x, uint8_t y, uint8_t *chr, uint8_t size1) {
|
|
|
|
while ((*chr >= ' ') && (*chr <= '~'))//判断是不是非法字符!
|
|
|
|
{
|
|
|
|
OLED_ShowChar(dev, x, y, *chr, size1);
|
|
|
|
x += size1 / 2;
|
|
|
|
if (x > dev->width - size1) //换行
|
|
|
|
{
|
|
|
|
x = 0;
|
|
|
|
y += 2;
|
|
|
|
}
|
|
|
|
chr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-24 14:58:18 +00:00
|
|
|
void OLED_ShowCHString(OLED_T *dev, uint8_t x, uint8_t y, uint8_t *str) {
|
|
|
|
uint8_t i, temp, size2, ys = y, xs = x, c = x;
|
2024-06-23 10:03:57 +00:00
|
|
|
uint16_t index;
|
2024-06-24 14:58:18 +00:00
|
|
|
size2 = Hzk_size * Hzk_size / 8; //得到字体一个字符对应点阵集所占的字节数
|
2024-06-23 10:03:57 +00:00
|
|
|
while (*str) {
|
2024-06-24 14:58:18 +00:00
|
|
|
for (index = 0; index < sizeof(Hzk) / sizeof(Chinese_t); index++) {
|
|
|
|
if (Hzk[index].unicode[0] == str[0] && Hzk[index].unicode[1] == str[1])//对比汉字区码位码
|
2024-06-23 10:03:57 +00:00
|
|
|
{
|
|
|
|
for (i = 0; i < size2; i++) {
|
|
|
|
temp = Hzk[index].data[i];
|
2024-06-24 14:58:18 +00:00
|
|
|
OLED_BSet(dev, xs, ys, temp);
|
|
|
|
xs++;
|
|
|
|
if (xs - c == Hzk_size) {
|
|
|
|
ys += 8;
|
|
|
|
xs = c;
|
|
|
|
c += Hzk_size;
|
|
|
|
}
|
2024-06-23 10:03:57 +00:00
|
|
|
}
|
|
|
|
ys = y;
|
|
|
|
str++;
|
|
|
|
str++;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-06-24 14:58:18 +00:00
|
|
|
//
|
|
|
|
//void OLED_DisplayString(OLED_T *dev, const lv_font_t *font, uint8_t *s, uint16_t x, uint16_t y) {
|
|
|
|
// uint32_t unicode_letter;
|
|
|
|
// while (*s) {
|
|
|
|
// if (font) {
|
|
|
|
// s += utf8_to_unicode(s, &unicode_letter);
|
|
|
|
// x += lv_draw_letter(font, unicode_letter, x, y);
|
|
|
|
// x += 2; //字间距
|
|
|
|
// } else {
|
|
|
|
// OLED_ShowChar(dev, x, y, *s, 6);
|
|
|
|
// x += 6;
|
|
|
|
// s++;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//}
|
2024-06-23 10:03:57 +00:00
|
|
|
|
2024-06-23 05:03:24 +00:00
|
|
|
uint32_t OLED_Pow(uint8_t m, uint8_t n) {
|
|
|
|
uint32_t result = 1;
|
|
|
|
while (n--) {
|
|
|
|
result *= m;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_ShowNum(OLED_T *dev, uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1) {
|
|
|
|
uint8_t t, temp;
|
|
|
|
for (t = 0; t < len; t++) {
|
|
|
|
temp = (num / OLED_Pow(10, len - t - 1)) % 10;
|
|
|
|
if (temp == 0) {
|
|
|
|
OLED_ShowChar(dev, x + (size1 / 2) * t, y, '0', size1);
|
|
|
|
} else {
|
|
|
|
OLED_ShowChar(dev, x + (size1 / 2) * t, y, temp + '0', size1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_ShowPic(OLED_T *dev, uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t *bmp) {
|
|
|
|
uint8_t y = 0;
|
|
|
|
if (y % 8 == 0)y = 0;
|
|
|
|
else y += 1;
|
|
|
|
for (y = y0; y < y1; y++) {
|
|
|
|
OLED_SPos(dev, x0, y);
|
|
|
|
dev->data(bmp + y * (x1 - x0), x1 - x0);
|
|
|
|
}
|
|
|
|
}
|
2024-06-23 10:03:57 +00:00
|
|
|
|
2024-06-22 06:45:07 +00:00
|
|
|
void OLED_Fill(OLED_T *dev, uint8_t data) {
|
|
|
|
uint8_t x, y;
|
|
|
|
for (y = 0; y < (dev->height >> 3); y++) {
|
|
|
|
for (x = 0; x < dev->width; x++) {
|
|
|
|
BUFPOINT(x, y) = data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OLED_CLS(OLED_T *dev) {
|
|
|
|
OLED_Fill(dev, 0x00);
|
|
|
|
}
|
|
|
|
|
2024-06-22 06:29:51 +00:00
|
|
|
void OLED_SPos(OLED_T *dev, uint8_t x, uint8_t y) {
|
|
|
|
uint8_t cmd[3];
|
2024-06-22 06:45:07 +00:00
|
|
|
cmd[0] = 0xb0 + y;
|
2024-06-22 06:29:51 +00:00
|
|
|
cmd[1] = ((x & 0xf0) >> 4) | 0x10;
|
|
|
|
cmd[2] = (x & 0x0f) | 0x01;
|
|
|
|
if (dev->state == IDLE) {
|
|
|
|
dev->state = WRITE;
|
|
|
|
dev->cmd(cmd, 3);
|
|
|
|
dev->state = IDLE;
|
|
|
|
}
|
|
|
|
}
|