#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); }