270 lines
8.6 KiB
C++
270 lines
8.6 KiB
C++
#include "../2025_include_user/Oled.hpp"
|
||
|
||
#define OLED_ADDR 0x3C // 7位地址(0x78 >> 1)
|
||
|
||
void OLED::WR_CMD(uint8_t cmd) {
|
||
uint8_t temp[2];
|
||
temp[0] = 0x00; // Control byte for command
|
||
temp[1] = cmd;
|
||
|
||
DL_I2C_fillControllerTXFIFO(I2C_0_INST, temp, 2);
|
||
while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));
|
||
|
||
DL_I2C_startControllerTransfer(I2C_0_INST, OLED_ADDR, DL_I2C_CONTROLLER_DIRECTION_TX, 2);
|
||
while (DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
|
||
while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));
|
||
|
||
DL_I2C_flushControllerTXFIFO(I2C_0_INST);
|
||
}
|
||
|
||
void OLED::WR_DATA(uint8_t data) {
|
||
uint8_t temp[2];
|
||
temp[0] = 0x40; // Control byte for data
|
||
temp[1] = data;
|
||
|
||
DL_I2C_fillControllerTXFIFO(I2C_0_INST, temp, 2);
|
||
while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));
|
||
|
||
DL_I2C_startControllerTransfer(I2C_0_INST, OLED_ADDR, DL_I2C_CONTROLLER_DIRECTION_TX, 2);
|
||
while (DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
|
||
while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE));
|
||
|
||
DL_I2C_flushControllerTXFIFO(I2C_0_INST);
|
||
}
|
||
|
||
|
||
void OLED::Init() {
|
||
uint8_t CMD_Data[] = {
|
||
0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40, 0xA1, 0xC8, 0xDA,
|
||
0x12, 0x81, 0xCF, 0xD9, 0xF1, 0xDB, 0x40, 0xA4, 0xA6, 0x8D, 0x14,
|
||
0xAF
|
||
};
|
||
|
||
for (uint8_t i = 0; i < 23; i++) {
|
||
WR_CMD(CMD_Data[i]);
|
||
}
|
||
}
|
||
|
||
void OLED::Clear() {
|
||
for (uint8_t i = 0; i < 8; i++) {
|
||
WR_CMD(0xb0 + i); // 设置页地址(0~7)
|
||
WR_CMD(0x00); // 设置显示位置—列低地址
|
||
WR_CMD(0x10); // 设置显示位置—列高地址
|
||
for (uint8_t n = 0; n < 128; n++) {
|
||
WR_DATA(0);
|
||
}
|
||
}
|
||
}
|
||
|
||
void OLED::Display_On() {
|
||
WR_CMD(0x8D); // SET DCDC命令
|
||
WR_CMD(0x14); // DCDC ON
|
||
WR_CMD(0xAF); // DISPLAY ON, 打开显示
|
||
}
|
||
|
||
void OLED::Display_Off() {
|
||
WR_CMD(0x8D); // SET DCDC命令
|
||
WR_CMD(0x10); // DCDC OFF
|
||
WR_CMD(0xAE); // DISPLAY OFF,关闭显示
|
||
}
|
||
|
||
void OLED::Set_Pos(uint8_t x, uint8_t y) {
|
||
WR_CMD(0xb0 + y); // 设置页地址(0~7)
|
||
WR_CMD(((x & 0xf0) >> 4) | 0x10); // 设置显示位置—列高地址
|
||
WR_CMD(x & 0x0f); // 设置显示位置—列低地址
|
||
}
|
||
|
||
unsigned int OLED::oled_pow(uint8_t m, uint8_t n) {
|
||
unsigned int result = 1;
|
||
while (n--) result *= m;
|
||
return result;
|
||
}
|
||
|
||
void OLED::ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t Char_Size, uint8_t Color_Turn) {
|
||
uint8_t c = chr - ' '; // 得到偏移后的值
|
||
if (x > 128 - 1) { x = 0; y = y + 2; }
|
||
if (Char_Size == 16) {
|
||
Set_Pos(x, y);
|
||
for (uint8_t i = 0; i < 8; i++) {
|
||
if (Color_Turn)
|
||
WR_DATA(~F8X16[c * 16 + i]);
|
||
else
|
||
WR_DATA(F8X16[c * 16 + i]);
|
||
}
|
||
Set_Pos(x, y + 1);
|
||
for (uint8_t i = 0; i < 8; i++) {
|
||
if (Color_Turn)
|
||
WR_DATA(~F8X16[c * 16 + i + 8]);
|
||
else
|
||
WR_DATA(F8X16[c * 16 + i + 8]);
|
||
}
|
||
} else {
|
||
Set_Pos(x, y);
|
||
for (uint8_t i = 0; i < 6; i++) {
|
||
if (Color_Turn)
|
||
WR_DATA(~F6x8[c][i]);
|
||
else
|
||
WR_DATA(F6x8[c][i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
void OLED::ShowString(uint8_t x, uint8_t y, char* chr, uint8_t Char_Size, uint8_t Color_Turn) {
|
||
uint8_t j = 0;
|
||
while (chr[j] != '\0') {
|
||
ShowChar(x, y, chr[j], Char_Size, Color_Turn);
|
||
if (Char_Size == 12) // 6X8的字体列加6,显示下一个字符
|
||
x += 6;
|
||
else // 8X16的字体列加8,显示下一个字符
|
||
x += 8;
|
||
|
||
if (x > 122 && Char_Size == 12) // TextSize6x8如果一行不够显示了,从下一行继续显示
|
||
{
|
||
x = 0;
|
||
y++;
|
||
}
|
||
if (x > 120 && Char_Size == 16) // TextSize8x16如果一行不够显示了,从下一行继续显示
|
||
{
|
||
x = 0;
|
||
y++;
|
||
}
|
||
j++;
|
||
}
|
||
}
|
||
|
||
void OLED::ShowNum(uint8_t x, uint8_t y, unsigned int num, uint8_t len, uint8_t size2, uint8_t Color_Turn) {
|
||
uint8_t t, temp;
|
||
uint8_t enshow = 0;
|
||
for (t = 0; t < len; t++) {
|
||
temp = (num / oled_pow(10, len - t - 1)) % 10;
|
||
if (enshow == 0 && t < (len - 1)) {
|
||
if (temp == 0) {
|
||
ShowChar(x + (size2 / 2) * t, y, ' ', size2, Color_Turn);
|
||
continue;
|
||
} else enshow = 1;
|
||
}
|
||
ShowChar(x + (size2 / 2) * t, y, temp + '0', size2, Color_Turn);
|
||
}
|
||
}
|
||
|
||
void OLED::ShowDecimal(uint8_t x, uint8_t y, float num, uint8_t z_len, uint8_t f_len, uint8_t size2, uint8_t Color_Turn) {
|
||
uint8_t t, temp, i = 0; // i为负数标志位
|
||
uint8_t enshow;
|
||
int z_temp, f_temp;
|
||
if (num < 0) {
|
||
z_len += 1;
|
||
i = 1;
|
||
num = -num;
|
||
}
|
||
z_temp = (int)num;
|
||
// 整数部分
|
||
for (t = 0; t < z_len; t++) {
|
||
temp = (z_temp / oled_pow(10, z_len - t - 1)) % 10;
|
||
if (enshow == 0 && t < (z_len - 1)) {
|
||
if (temp == 0) {
|
||
ShowChar(x + (size2 / 2) * t, y, ' ', size2, Color_Turn);
|
||
continue;
|
||
} else
|
||
enshow = 1;
|
||
}
|
||
ShowChar(x + (size2 / 2) * t, y, temp + '0', size2, Color_Turn);
|
||
}
|
||
// 小数点
|
||
ShowChar(x + (size2 / 2) * (z_len), y, '.', size2, Color_Turn);
|
||
|
||
f_temp = (int)((num - z_temp) * (oled_pow(10, f_len)));
|
||
// 小数部分
|
||
for (t = 0; t < f_len; t++) {
|
||
temp = (f_temp / oled_pow(10, f_len - t - 1)) % 10;
|
||
ShowChar(x + (size2 / 2) * (t + z_len) + 5, y, temp + '0', size2, Color_Turn);
|
||
}
|
||
if (i == 1) // 如果为负,就将最前的一位赋值‘-’
|
||
{
|
||
ShowChar(x, y, '-', size2, Color_Turn);
|
||
i = 0;
|
||
}
|
||
}
|
||
|
||
void OLED::ShowChinese(uint8_t x, uint8_t y, uint8_t no, uint8_t Color_Turn) {
|
||
uint8_t t = 0;
|
||
Set_Pos(x, y);
|
||
for (t = 0; t < 16; t++) {
|
||
if (Color_Turn)
|
||
WR_DATA(~Hzk[2 * no][t]); // 显示汉字的上半部分
|
||
else
|
||
WR_DATA(Hzk[2 * no][t]); // 显示汉字的上半部分
|
||
}
|
||
|
||
Set_Pos(x, y + 1);
|
||
for (t = 0; t < 16; t++) {
|
||
if (Color_Turn)
|
||
WR_DATA(~Hzk[2 * no + 1][t]); // 显示汉字的上半部分
|
||
else
|
||
WR_DATA(Hzk[2 * no + 1][t]); // 显示汉字的上半部分
|
||
}
|
||
}
|
||
|
||
void OLED::DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t* BMP, uint8_t Color_Turn) {
|
||
uint32_t j = 0;
|
||
uint8_t x = 0, y = 0;
|
||
|
||
if (y1 % 8 == 0)
|
||
y = y1 / 8;
|
||
else
|
||
y = y1 / 8 + 1;
|
||
for (y = y0; y < y1; y++) {
|
||
Set_Pos(x0, y);
|
||
for (x = x0; x < x1; x++) {
|
||
if (Color_Turn)
|
||
WR_DATA(~BMP[j++]); // 显示反相图片
|
||
else
|
||
WR_DATA(BMP[j++]); // 显示图片
|
||
}
|
||
}
|
||
}
|
||
|
||
void OLED::HorizontalShift(uint8_t direction) {
|
||
WR_CMD(0x2e); // 停止滚动
|
||
WR_CMD(direction); // 设置滚动方向
|
||
WR_CMD(0x00); // 虚拟字节设置,默认为0x00
|
||
WR_CMD(0x00); // 设置开始页地址
|
||
WR_CMD(0x07); // 设置每个滚动步骤之间的时间间隔的帧频
|
||
WR_CMD(0x07); // 设置结束页地址
|
||
WR_CMD(0x00); // 虚拟字节设置,默认为0x00
|
||
WR_CMD(0xff); // 虚拟字节设置,默认为0xff
|
||
WR_CMD(0x2f); // 开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
|
||
}
|
||
|
||
void OLED::Some_HorizontalShift(uint8_t direction, uint8_t start, uint8_t end) {
|
||
WR_CMD(0x2e); // 停止滚动
|
||
WR_CMD(direction); // 设置滚动方向
|
||
WR_CMD(0x00); // 虚拟字节设置,默认为0x00
|
||
WR_CMD(start); // 设置开始页地址
|
||
WR_CMD(0x07); // 设置每个滚动步骤之间的时间间隔的帧频
|
||
WR_CMD(end); // 设置结束页地址
|
||
WR_CMD(0x00); // 虚拟字节设置,默认为0x00
|
||
WR_CMD(0xff); // 虚拟字节设置,默认为0xff
|
||
WR_CMD(0x2f); // 开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
|
||
}
|
||
|
||
void OLED::VerticalAndHorizontalShift(uint8_t direction) {
|
||
WR_CMD(0x2e); // 停止滚动
|
||
WR_CMD(direction); // 设置滚动方向
|
||
WR_CMD(0x01); // 虚拟字节设置
|
||
WR_CMD(0x00); // 设置开始页地址
|
||
WR_CMD(0x07); // 设置每个滚动步骤之间的时间间隔的帧频
|
||
WR_CMD(0x07); // 设置结束页地址
|
||
WR_CMD(0x01); // 垂直滚动偏移量
|
||
WR_CMD(0x00); // 虚拟字节设置,默认为0x00
|
||
WR_CMD(0xff); // 虚拟字节设置,默认为0xff
|
||
WR_CMD(0x2f); // 开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
|
||
}
|
||
|
||
void OLED::DisplayMode(uint8_t mode) {
|
||
WR_CMD(mode);
|
||
}
|
||
|
||
void OLED::IntensityControl(uint8_t intensity) {
|
||
WR_CMD(0x81);
|
||
WR_CMD(intensity);
|
||
} |