经验——OLED的使用

型号:HS96L01W 4S03

分辨率:120*64

通讯方式:4线SPI 模式00

MCU:MSPM0G3507(只影响SPI的配置)

        原本照着型号搜到了嘉立创的使用文档,但是实际上并不能正常使用,后来寻到了一篇博客教程【常用模块】OLED显示模块(原理讲解、STM32实例操作)_oled介绍-CSDN博客,博客里写的非常详细且通俗易懂。

        借鉴了上面的初始化函数才能正常完成初始化,初始化代码如下:

void OLED_Init(void)
{SPI_Init(3,0);//4分频,模式为0,0DL_GPIO_initDigitalOutput(GPIO_OLED_RES_IOMUX);DL_GPIO_initDigitalOutput(GPIO_OLED_DC_IOMUX);DL_GPIO_clearPins(GPIO_OLED_PORT, GPIO_OLED_DC_PIN);DL_GPIO_setPins(GPIO_OLED_PORT, GPIO_OLED_RES_PIN);DL_GPIO_enableOutput(GPIO_OLED_PORT, GPIO_OLED_RES_PIN | GPIO_OLED_DC_PIN);//OLED复位OLED_RES_Ctrl();//RES 置0delay_ms(200);//延时 200msOLED_RES_Set();//RES 置1//OLED初始化OLED_WR_Byte(0xAE, OLED_CMD);//关闭显示OLED_WR_Byte(0xD5, OLED_CMD);//设置时钟分频因子,震荡频率OLED_WR_Byte(80, OLED_CMD);  //[3:0],分频因子;[7:4],震荡频率OLED_WR_Byte(0xA8, OLED_CMD);//设置驱动路数OLED_WR_Byte(0X3F, OLED_CMD);//默认0X3F(1/64)OLED_WR_Byte(0xD3, OLED_CMD);//设置显示偏移OLED_WR_Byte(0X00, OLED_CMD);//默认为0OLED_WR_Byte(0x40, OLED_CMD);//设置显示开始行 [5:0],行数.OLED_WR_Byte(0x8D, OLED_CMD);//电荷泵设置OLED_WR_Byte(0x14, OLED_CMD);//bit2,开启/关闭OLED_WR_Byte(0x20, OLED_CMD);//设置内存地址模式OLED_WR_Byte(0x02, OLED_CMD);//[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;OLED_WR_Byte(0xA1, OLED_CMD);//段重定义设置,bit0:0,0->0;1,0->127;OLED_WR_Byte(0xC0, OLED_CMD);//设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数OLED_WR_Byte(0xDA, OLED_CMD);//设置COM硬件引脚配置OLED_WR_Byte(0x12, OLED_CMD);//[5:4]配置OLED_WR_Byte(0x81, OLED_CMD);//对比度设置OLED_WR_Byte(0xEF, OLED_CMD);//1~255;默认0X7F (亮度设置,越大越亮)OLED_WR_Byte(0xD9, OLED_CMD);//设置预充电周期OLED_WR_Byte(0xf1, OLED_CMD);//[3:0],PHASE 1;[7:4],PHASE 2;OLED_WR_Byte(0xDB, OLED_CMD);//设置VCOMH 电压倍率OLED_WR_Byte(0x30, OLED_CMD);//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;OLED_WR_Byte(0xA4, OLED_CMD);//全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)OLED_WR_Byte(0xA6, OLED_CMD);//设置显示方式;bit0:1,反相显示;0,正常显示OLED_WR_Byte(0xAF, OLED_CMD);//开启显示//这里不能加延迟,否则什么都不显示!!!!!!!!OLED_Clear();/**下面代码为嘉立创源码,但不能用*/
#if 0////    OLED_WR_Byte(0xAE, OLED_CMD);//–turn off oled panel////    OLED_WR_Byte(0x00, OLED_CMD);//–set low column address////    OLED_WR_Byte(0x10, OLED_CMD);//–set high column address////    OLED_WR_Byte(0x40, OLED_CMD);//–set start line address////    OLED_WR_Byte(0x81, OLED_CMD);//–set contrast control register////    OLED_WR_Byte(0xCF, OLED_CMD);//Set SEG Output Current Brightness////    OLED_WR_Byte(0xA1, OLED_CMD);//–Set SEG/Column Mapping 0xa0左右反置 0xa1正常////    OLED_WR_Byte(0xC8, OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置  0xc8正常////    OLED_WR_Byte(0xA6, OLED_CMD);//–set normal display////    OLED_WR_Byte(0xAB, OLED_CMD);//–set multiplex ratio(1 to 64)////    OLED_WR_Byte(0x3f, OLED_CMD);//–1/64 duty////    OLED_WR_Byte(0xD3, OLED_CMD);//–set display offset Shift Mapping RAM Counter (0x00~0x3F)////    OLED_WR_Byte(0x00, OLED_CMD);//–not offset////    OLED_WR_Byte(0xd5, OLED_CMD);//–set display dock divide ratio/oscillator frequency////    OLED_WR_Byte(0x80, OLED_CMD);//–set divide ratio, Set Clock as 100 Frames/Sec////    OLED_WR_Byte(0xD9, OLED_CMD);//–set pre-charge period////    OLED_WR_Byte(0xf1, OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1Clock////    OLED_WR_Byte(0xDA, OLED_CMD);//–set com pins hardware configuration////    OLED_WR_Byte(0x12, OLED_CMD);////    OLED_WR_Byte(0xDB, OLED_CMD);//–set vcomh////    OLED_WR_Byte(0x30, OLED_CMD);//Set VCOM Deselect Level////    OLED_WR_Byte(0x20, OLED_CMD);//–Set Page Addressing Mode (0x00/0x01/0x02)////    OLED_WR_Byte(0x02, OLED_CMD);//////    OLED_WR_Byte(0x8D, OLED_CMD);//–set Charge Pump enable/disable////    OLED_WR_Byte(0x14, OLED_CMD);//–set(0x10) disable////    OLED_Clear();////    OLED_WR_Byte(0xAF, OLED_CMD);
#endif
}

       

         完整代码如下,为了提高刷新的性能,下面绘画函数没有选择直接更新屏幕,而是只有当所有绘画完成后,再统一调用更新函数。不过关于字体函数的命名有些紊乱

OLED.h

//
// Created by 34753 on 2024/7/22.
//#ifndef ISB_TI_OLED_H
#define ISB_TI_OLED_H
#include "ZQ_Conf.h"#include "ti_init.h"
#include "SPI.h"/* Port definition for Pin Group GPIO_LCD */
#define GPIO_OLED_PORT (GPIOA)/* Defines for RS: GPIOA.12 with pinCMx 34 on package pin 5 */
#define GPIO_OLED_RES_PIN (DL_GPIO_PIN_12)
#define GPIO_OLED_RES_IOMUX (IOMUX_PINCM34)
/* Defines for RST: GPIOA.13 with pinCMx 35 on package pin 6 */
#define GPIO_OLED_DC_PIN (DL_GPIO_PIN_13)
#define GPIO_OLED_DC_IOMUX (IOMUX_PINCM35)#define OLED_RES_Ctrl()  DL_GPIO_clearPins(GPIO_OLED_PORT, GPIO_OLED_RES_PIN)
#define OLED_RES_Set()  DL_GPIO_setPins(GPIO_OLED_PORT, GPIO_OLED_RES_PIN)
#define OLED_DC_Ctrl()  DL_GPIO_clearPins(GPIO_OLED_PORT, GPIO_OLED_DC_PIN)
#define OLED_DC_Set()  DL_GPIO_setPins(GPIO_OLED_PORT, GPIO_OLED_DC_PIN)void OLED_Init(void);
void OLED_Clear();void OLED_Fill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t dot);
void OLED_Refresh_Gram(void);
void OLED_ShowChar_1608(uint16_t x, uint16_t y, uint8_t chr);
void OLED_ShowChar_1206(uint16_t x, uint16_t y, char chr);
void OLED_ShowString_1206(uint16_t x, uint16_t y, char *chr, uint16_t length);
void OLED_ShowCustomChar_1616_Fast(uint16_t x, uint16_t y, uint16_t chrNum);
void OLED_ShowCustomString_1616_Fast(uint16_t x, uint16_t y, uint16_t chrNum,uint16_t length);
void OLED_ShowCustomChar_1212_Fast(uint16_t x, uint16_t y, uint16_t chrNum);
void OLED_ShowCustomString_1212_Fast(uint16_t x, uint16_t y, uint16_t chrNum,uint16_t length);
void OLED_Point(uint16_t x, uint16_t y);//只用来画像素点,并不作为其他函数的子函数,若需则用OLED_DrawPointvoid OLED_Rectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t width);//显示矩形框
void OLED_Line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t width);//显示线条
void OLED_Circle(uint16_t x, uint16_t y, uint16_t r, uint16_t width);//显示圆#endif//ISB_TI_OLED_H

OLED.c

//
// Created by 34753 on 2024/7/22.
//#include "OLED.h"
#include "DATA/FONT.h"
#include "Timer.h"
#include <stdlib.h>#define OLED_CMD 0 //write command
#define OLED_DATA 1//write datauint8_t OLED_GRAM[128][8];//缓冲区数组
static const uint8_t lut[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};//用于加速描点计算/**内联函数*///画点
//x:0~127
//y:0~63
//t:1 填充 0,清空
static inline void OLED_WR_Byte(uint8_t data, uint8_t cmd)
{if (cmd){OLED_DC_Set();}else{OLED_DC_Ctrl();}SPI_WriteByte(data);OLED_DC_Set();
}static inline void OLED_DrawPoint_Inline(uint16_t x, uint16_t y, uint8_t t)
{
#if 0uint8_t pos, bx, temp = 0;if (x > 127 || y > 63)return;//超出范围了.pos = 7 - y>>3;// 7-y/8bx = y % 8;temp = 1 << (7 - bx);if (t)OLED_GRAM[x][pos] |= temp;elseOLED_GRAM[x][pos] &= ~temp;
#endif/**优化后*/uint8_t pos = 7 - (y / 8);//计算页数if (t)OLED_GRAM[x][pos] |= lut[y % 8];elseOLED_GRAM[x][pos] &= ~lut[y % 8];
}static inline void OLED_DrawPointDefault_Inline(uint8_t x, uint8_t y)
{
#if 0uint8_t pos, bx, temp = 0;if (x > 127 || y > 63)return;//超出范围了.pos = 7 - y>>3;// 7-y/8bx = y % 8;temp = 1 << (7 - bx);if (t)OLED_GRAM[x][pos] |= temp;elseOLED_GRAM[x][pos] &= ~temp;
#endif/**优化后*/uint8_t pos = 7 - (y / 8);//计算页数OLED_GRAM[x][pos] |= lut[y % 8];
}//更新显存到LCD
static inline void OLED_Refresh_Gram_Inline(void)
{for (uint8_t i = 0; i < 8; i++){OLED_WR_Byte(0xb0 + i, OLED_CMD);//设置页地址(0~7)OLED_WR_Byte(0x00, OLED_CMD);    //设置显示位置—列低地址OLED_WR_Byte(0x10, OLED_CMD);    //设置显示位置—列高地址for (uint8_t n = 0; n < 128; n++)OLED_WR_Byte(OLED_GRAM[n][i], OLED_DATA);}
}
static inline void OLED_FillRect_Inline(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{// 遍历矩形的宽度和高度,逐行逐列调用OLED_Pointfor (uint16_t row = 0; row < h; row++){for (uint16_t col = 0; col < w; col++){// 调用OLED_Point在当前位置绘制一个点OLED_DrawPoint_Inline(x + col, y + row, 1);}}
}void OLED_Line_In(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t width)
{int deltaX = x2 - x1;int deltaY = y2 - y1;uint16_t signX = (deltaX > 0) ? 1 : ((deltaX < 0) ? -1 : 0);uint16_t signY = (deltaY > 0) ? 1 : ((deltaY < 0) ? -1 : 0);deltaX = abs(deltaX);deltaY = abs(deltaY);if (deltaX > deltaY){int fraction = deltaY * 2 - deltaX;for (; x1 != x2; x1 += signX){OLED_FillRect_Inline(x1, y1, width, width);// Draw a square instead of a point.if (fraction >= 0){y1 += signY;fraction -= deltaX * 2;}fraction += deltaY * 2;}}else{int fraction = deltaX * 2 - deltaY;for (; y1 != y2; y1 += signY){OLED_FillRect_Inline(x1, y1, width, width);// Draw a square instead of a point.if (fraction >= 0){x1 += signX;fraction -= deltaY * 2;}fraction += deltaX * 2;}}// Draw the last point or adjust if necessaryOLED_FillRect_Inline(x1, y1, width, width);
}void drawCircleHelper_In(uint16_t x_center, uint16_t y_center, int x0, int y0, uint16_t width)
{for (uint16_t i = 0; i < width; i++){for (uint16_t j = 0; j < width; j++){if ((i * i + j * j) <= (width * width)){OLED_DrawPointDefault_Inline(x_center + x0 + i, y_center + y0 + j);OLED_DrawPointDefault_Inline(x_center + x0 + i, y_center - (y0 + j));OLED_DrawPointDefault_Inline(x_center - (x0 + i), y_center + y0 + j);OLED_DrawPointDefault_Inline(x_center - (x0 + i), y_center - (y0 + j));OLED_DrawPointDefault_Inline(x_center + (y0 + j), y_center + x0 + i);OLED_DrawPointDefault_Inline(x_center + (y0 + j), y_center - (x0 + i));OLED_DrawPointDefault_Inline(x_center - (y0 + j), y_center + x0 + i);OLED_DrawPointDefault_Inline(x_center - (y0 + j), y_center - (x0 + i));}}}
}void OLED_Init(void)
{SPI_Init(3,0);//模式为1,1DL_GPIO_initDigitalOutput(GPIO_OLED_RES_IOMUX);DL_GPIO_initDigitalOutput(GPIO_OLED_DC_IOMUX);DL_GPIO_clearPins(GPIO_OLED_PORT, GPIO_OLED_DC_PIN);DL_GPIO_setPins(GPIO_OLED_PORT, GPIO_OLED_RES_PIN);DL_GPIO_enableOutput(GPIO_OLED_PORT, GPIO_OLED_RES_PIN | GPIO_OLED_DC_PIN);//OLED复位OLED_RES_Ctrl();//RES 置0delay_ms(200);//延时 200msOLED_RES_Set();//RES 置1//OLED初始化OLED_WR_Byte(0xAE, OLED_CMD);//关闭显示OLED_WR_Byte(0xD5, OLED_CMD);//设置时钟分频因子,震荡频率OLED_WR_Byte(80, OLED_CMD);  //[3:0],分频因子;[7:4],震荡频率OLED_WR_Byte(0xA8, OLED_CMD);//设置驱动路数OLED_WR_Byte(0X3F, OLED_CMD);//默认0X3F(1/64)OLED_WR_Byte(0xD3, OLED_CMD);//设置显示偏移OLED_WR_Byte(0X00, OLED_CMD);//默认为0OLED_WR_Byte(0x40, OLED_CMD);//设置显示开始行 [5:0],行数.OLED_WR_Byte(0x8D, OLED_CMD);//电荷泵设置OLED_WR_Byte(0x14, OLED_CMD);//bit2,开启/关闭OLED_WR_Byte(0x20, OLED_CMD);//设置内存地址模式OLED_WR_Byte(0x02, OLED_CMD);//[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;OLED_WR_Byte(0xA1, OLED_CMD);//段重定义设置,bit0:0,0->0;1,0->127;OLED_WR_Byte(0xC0, OLED_CMD);//设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数OLED_WR_Byte(0xDA, OLED_CMD);//设置COM硬件引脚配置OLED_WR_Byte(0x12, OLED_CMD);//[5:4]配置OLED_WR_Byte(0x81, OLED_CMD);//对比度设置OLED_WR_Byte(0xEF, OLED_CMD);//1~255;默认0X7F (亮度设置,越大越亮)OLED_WR_Byte(0xD9, OLED_CMD);//设置预充电周期OLED_WR_Byte(0xf1, OLED_CMD);//[3:0],PHASE 1;[7:4],PHASE 2;OLED_WR_Byte(0xDB, OLED_CMD);//设置VCOMH 电压倍率OLED_WR_Byte(0x30, OLED_CMD);//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;OLED_WR_Byte(0xA4, OLED_CMD);//全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)OLED_WR_Byte(0xA6, OLED_CMD);//设置显示方式;bit0:1,反相显示;0,正常显示OLED_WR_Byte(0xAF, OLED_CMD);//开启显示//这里不能加延迟,否则什么都不显示!!!!!!!!OLED_Clear();/**下面代码为嘉立创源码,但不能用*/
#if 0////    OLED_WR_Byte(0xAE, OLED_CMD);//–turn off oled panel////    OLED_WR_Byte(0x00, OLED_CMD);//–set low column address////    OLED_WR_Byte(0x10, OLED_CMD);//–set high column address////    OLED_WR_Byte(0x40, OLED_CMD);//–set start line address////    OLED_WR_Byte(0x81, OLED_CMD);//–set contrast control register////    OLED_WR_Byte(0xCF, OLED_CMD);//Set SEG Output Current Brightness////    OLED_WR_Byte(0xA1, OLED_CMD);//–Set SEG/Column Mapping 0xa0左右反置 0xa1正常////    OLED_WR_Byte(0xC8, OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置  0xc8正常////    OLED_WR_Byte(0xA6, OLED_CMD);//–set normal display////    OLED_WR_Byte(0xAB, OLED_CMD);//–set multiplex ratio(1 to 64)////    OLED_WR_Byte(0x3f, OLED_CMD);//–1/64 duty////    OLED_WR_Byte(0xD3, OLED_CMD);//–set display offset Shift Mapping RAM Counter (0x00~0x3F)////    OLED_WR_Byte(0x00, OLED_CMD);//–not offset////    OLED_WR_Byte(0xd5, OLED_CMD);//–set display dock divide ratio/oscillator frequency////    OLED_WR_Byte(0x80, OLED_CMD);//–set divide ratio, Set Clock as 100 Frames/Sec////    OLED_WR_Byte(0xD9, OLED_CMD);//–set pre-charge period////    OLED_WR_Byte(0xf1, OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1Clock////    OLED_WR_Byte(0xDA, OLED_CMD);//–set com pins hardware configuration////    OLED_WR_Byte(0x12, OLED_CMD);////    OLED_WR_Byte(0xDB, OLED_CMD);//–set vcomh////    OLED_WR_Byte(0x30, OLED_CMD);//Set VCOM Deselect Level////    OLED_WR_Byte(0x20, OLED_CMD);//–Set Page Addressing Mode (0x00/0x01/0x02)////    OLED_WR_Byte(0x02, OLED_CMD);//////    OLED_WR_Byte(0x8D, OLED_CMD);//–set Charge Pump enable/disable////    OLED_WR_Byte(0x14, OLED_CMD);//–set(0x10) disable////    OLED_Clear();////    OLED_WR_Byte(0xAF, OLED_CMD);
#endif
}void OLED_Clear()
{for (uint16_t i = 0; i < 8; i++){OLED_WR_Byte(0xb0 + i, OLED_CMD);//设置页地址(0~7)OLED_WR_Byte(0x00, OLED_CMD);    //设置显示位置—列低地址OLED_WR_Byte(0x10, OLED_CMD);    //设置显示位置—列高地址for (uint16_t n = 0; n < 128; n++)OLED_WR_Byte(0x00, OLED_DATA);}
}void OLED_Refresh_Gram(void)
{OLED_Refresh_Gram_Inline();
}//开启OLED显示
void OLED_Display_On(void)
{OLED_WR_Byte(0X8D, OLED_CMD);//SET DCDC命令OLED_WR_Byte(0X14, OLED_CMD);//DCDC ONOLED_WR_Byte(0XAF, OLED_CMD);//DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{OLED_WR_Byte(0X8D, OLED_CMD);//SET DCDC命令OLED_WR_Byte(0X10, OLED_CMD);//DCDC OFFOLED_WR_Byte(0XAE, OLED_CMD);//DISPLAY OFF
}//x1,y1,x2,y2 填充区域的对角坐标
//确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63
//dot:0,清空;1,填充
void OLED_Fill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t dot)
{for (uint16_t x = x1; x <= x2; x++){for (uint16_t y = y1; y <= y2; y++)OLED_DrawPoint_Inline(x, y, dot);}
}void OLED_Point(uint16_t x, uint16_t y)
{OLED_DrawPoint_Inline(x, y, 1);
}/*** @brief   使用自定义字库16*16* @param   x,y 横纵坐标* @param   chrNum 字符在自定义字库里的位置* @note    默认亮显,取模方式为逐列式,低位在前* */
void OLED_ShowChineseChar_Fast_In(uint16_t x, uint16_t y, uint16_t chrNum, uint8_t size)
{uint8_t temp;uint16_t y0 = y;uint8_t pos;chrNum <<= 1;//由于1616字体数组是16为一行,而字体又是16*16,所以每个字体在字体数组中需要两行for (uint8_t i = 0; i < 2; ++i){for (uint8_t t = 0; t < size; t++){switch (size){case 12:temp = Character_Custom_1212[chrNum + i][t];break;case 16:temp = Character_Custom_1616[chrNum + i][t];break;default:return;//报错}//对一个字节开始解码for (uint8_t t1 = 0; t1 < 8; t1++){pos = 7 - (y / 8);//计算页数if (temp & 0x1){OLED_GRAM[x][pos] |= lut[y % 8];}else{OLED_GRAM[x][pos] &= ~lut[y % 8];}temp >>= 1;y++;//从上到下,如果满16字高则换一列if ((y - y0) == 16){y = y0;x++;break;}}}}
}/*** @brief   使用自定义字库16*16* @param   x,y 横纵坐标* @param   chrNum 字符在自定义字库里的位置* @note    默认亮显,取模方式为逐列式,低位在前* */
void OLED_ShowChar_Fast_In(uint16_t x, uint16_t y, char chr, uint8_t size)
{uint8_t temp;uint16_t y0 = y;uint8_t pos;chr = chr - ' ';for (uint8_t i = 0; i < 2; ++i){for (uint8_t t = 0; t < size; t++){switch (size){case 12:temp = asc_1206[chr + i][t];break;case 16:temp = asc_1608[chr + i][t];break;default:return;//报错}//对一个字节开始解码for (uint8_t t1 = 0; t1 < 8; t1++){pos = 7 - (y / 8);//计算页数if (temp & 0x1){OLED_GRAM[x][pos] |= lut[y % 8];}else{OLED_GRAM[x][pos] &= ~lut[y % 8];}temp >>= 1;y++;//从上到下,如果满16字高则换一列if ((y - y0) == 16){y = y0;x++;break;}}}}
}
void OLED_ShowCustomChar_1616_Fast(uint16_t x, uint16_t y, uint16_t chrNum)
{OLED_ShowChineseChar_Fast_In(x, y, chrNum, 16);
}void OLED_ShowCustomString_1616_Fast(uint16_t x, uint16_t y, uint16_t chrNum, uint16_t length)
{for (uint16_t i = 0; i < length; i++){OLED_ShowChineseChar_Fast_In(x + i * 16, y, chrNum + i, 16);}
}void OLED_ShowCustomChar_1212_Fast(uint16_t x, uint16_t y, uint16_t chrNum)
{OLED_ShowChineseChar_Fast_In(x, y, chrNum, 12);
}
void OLED_ShowChar_1206(uint16_t x, uint16_t y, char chr)
{OLED_ShowChar_Fast_In(x, y, chr, 12);
}void OLED_ShowString_1206(uint16_t x, uint16_t y, char *chr, uint16_t length)
{for (uint16_t i = 0; i != '\0'; ++i){chr[i] = chr[i] - ' ';OLED_ShowChar_Fast_In(x + i * 6, y, chr[i],12);}
}void OLED_ShowCustomString_1212_Fast(uint16_t x, uint16_t y, uint16_t chrNum, uint16_t length)
{for (uint16_t i = 0; i < length; i++){OLED_ShowChineseChar_Fast_In(x + i * 12, y, chrNum + i, 12);}
}//下面为原代码备份,不要做任何改动!!!
#if 0
//void OLED_ShowCustomChar_1616_Fast(uint8_t x, uint8_t y, uint8_t chrNum)
//{
//    static const uint8_t lut[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
//
//    uint8_t temp;
//    uint8_t y0 = y;
//    chrNum <<= 1;//由于字体数组是16为一行,而字体又是16*16,所以每个字体在字体数组中需要两行
//    for (uint8_t i = 0; i < 2; ++i)
//    {
//        for (uint8_t t = 0; t < 16; t++)
//        {
//            temp = Character_Custom[chrNum + i][t];
//
//            //对一个字节开始解码
//            for (uint8_t t1 = 0; t1 < 8; t1++)
//            {
//                if (temp & 0x1)
//                {
//                    uint8_t pos = 7 - (y / 8);//计算页数
//                    OLED_GRAM[x][pos] |= lut[y % 8];
//                }
//                else
//                {
//                    uint8_t pos = 7 - (y / 8);//计算页数
//                    OLED_GRAM[x][pos] &= ~lut[y % 8];
//                }
//                temp >>= 1;
//                y++;
//                //从上到下,如果满16字高则换一列
//                if ((y - y0) == 16)
//                {
//                    y = y0;
//                    x++;
//                    break;
//                }
//            }
//        }
//    }
//    OLED_Refresh_Gram();//更新显示
//}
#endif
void OLED_ShowChar_1608(uint16_t x, uint16_t y, uint8_t chr)
{uint8_t temp, pos;uint16_t y0 = y;chr = chr - ' ';//得到偏移后的值for (uint8_t t = 0; t < 16; t++){temp = asc_1608[chr][t];//调用1608字体//对一个字节开始解码for (uint8_t t1 = 0; t1 < 8; t1++){pos = 7 - (y / 8);//计算页数if (temp & 0x1){OLED_GRAM[x][pos] |= lut[y % 8];}else{OLED_GRAM[x][pos] &= ~lut[y % 8];}temp >>= 1;y++;//从上到下,如果满16字高则换一列if ((y - y0) == 16){y = y0;x++;break;}}}
}//显示字符串
//x,y:起点坐标
//size:字体大小
//*p:字符串起始地址
void OLED_ShowString(uint8_t x, uint8_t y, const uint8_t *p, uint8_t size)
{while ((*p <= '~') && (*p >= ' '))//判断是不是非法字符!{if (x > (128 - (size / 2))){x = 0;y += size;}if (y > (64 - size)){y = x = 0;}// OLED_ShowChar(x, y, *p, size, 1);x += size / 2;p++;}
}
//显示矩形框
void OLED_Rectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t width)
{OLED_Line_In(x, y, x + w, y, width);OLED_Line_In(x + w, y, x + w, y + h, width);OLED_Line_In(x, y + h, x + w, y + h, width);OLED_Line_In(x, y, x, y + h, width);
}
//显示线条
//void OLED_Line_nowidth(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
//{
//    unsigned int t;
//    int xerr=0,yerr=0,delta_x,delta_y,distance;
//    int incx,incy,uRow,uCol;
//
//    delta_x=x2-x1; //计算坐标增量
//    delta_y=y2-y1;
//    uRow=x1;
//    uCol=y1;
//
//    if(delta_x>0)
//        incx=1; //设置单步方向
//    else if(delta_x==0)
//        incx=0;//垂直线
//    else
//    {
//        incx=-1;delta_x=-delta_x;
//    }
//    if(delta_y>0)
//        incy=1;
//    else if(delta_y==0)
//        incy=0;//水平线
//    else
//    {
//        incy=-1;delta_y=-delta_y;
//    }
//    if( delta_x>delta_y)
//        distance=delta_x; //选取基本增量坐标轴
//    else
//        distance=delta_y;
//    for(t=0;t<=distance+1;t++ )//画线输出
//    {
//        OLED_Point(uRow,uCol);//画点
//        xerr+=delta_x ;
//        yerr+=delta_y ;
//        if(xerr>distance)
//        {
//            xerr-=distance;
//            uRow+=incx;
//        }
//        if(yerr>distance)
//        {
//            yerr-=distance;
//            uCol+=incy;
//        }
//    }
//}void OLED_Line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t width)
{OLED_Line_In(x1, y1, x2, y2, width);
}
//显示圆
void OLED_Circle(uint16_t x, uint16_t y, uint16_t r, uint16_t width)
{int d = 3 - 2 * r;int x0 = 0;int y0 = r;// 绘制外圆drawCircleHelper_In(x, y, x0, y0, width);while (x0 <= y0){if (d < 0){d += 4 * x0 + 6;}else{d += 4 * (x0 - y0) + 10;y0--;}x0++;// 每次迭代都要画圆的所有八分之一drawCircleHelper_In(x, y, x0, y0, width);}
}

        

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/50007.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MFC与QT中禁用Esc、Alt+F4、关闭图标

在业务中&#xff0c;我们需要按指定的方式才能关闭当前对话框。如下图需输入密码点击确认后&#xff0c;界面才能关闭。 方法1&#xff1a;通过禁用界面的按钮以及键盘上对应关闭对话框的按键。 1.灰度化关闭按钮 在对话框初始化部分添加将关闭按钮禁用 //MFC CMenu *pSysMe…

主要的国产信创数据库有哪些

数据库生态分类 当前数据库生态可以大致分类三类: 一、传统商业数据库&#xff0c;以 Oracle 为代表&#xff0c;其在 40 余年时间里所创造的数据库帝国已拥有了极其完善的生态; 二、开源数据库&#xff0c;以 MYSQL、PostgreSQL为代表&#xff0c;遍布全球的社区组织形成了强…

大文件分片上传(前端TS实现)

大文件分片上传 内容 一般情况下&#xff0c;前端上传文件就是new FormData,然后把文件 append 进去&#xff0c;然后post发送给后端就完事了&#xff0c;但是文件越大&#xff0c;上传的文件也就越长&#xff0c;如果在上传过程中&#xff0c;突然网络故障&#xff0c;又或者…

AHK是让任何软件都支持 Shift + 鼠标滚轮 实现界面水平滚动

目录 基本介绍 详细特点 图解安装 下载失败&#xff1f;缓慢&#xff1f; 创建并运行脚本代码&#x1f603; 新建空 xxx.ahk文件 vscode/记事本等编辑工具打开 复制并粘贴简易脚本 运行 其他问题 问题一&#xff1a;弹出无法执行此脚本 关闭脚本 基本介绍 AutoHot…

【MetaGPT系列】【MetaGPT完全实践宝典——如何定义单一行为多行为Agent】

目录 前言一、智能体1-1、Agent概述1-2、Agent与ChatGPT的区别 二、多智能体框架MetaGPT2-1、安装&配置2-2、使用已有的Agent&#xff08;ProductManager&#xff09;2-3、拥有单一行为的Agent&#xff08;SimpleCoder&#xff09;2-3-1、定义写代码行为2-3-2、角色定义2-3…

B站音视频分开 大小问题

音频是33331 kb&#xff0c;视频是374661 kb 合并之后却是2561363 kb 这可能是B站音频和视频分开的原因吧

Zabbix监控案例

文章目录 一、监控linux TCP连接状态TCP端口的十一种连接状态自定义监控项监控示例二、监控模板监控tcp连接监控nginx 一、监控linux TCP连接状态 TCP&#xff0c;全称Transfer Control Protocol&#xff0c;中文名为传输控制协议&#xff0c;它工作在OSI的传输层&#xff0c;…

3.Fabric系统架构、网络拓扑图、交易流程

Hyperledger Fabric系统架构 Fabric网络拓扑图 Fabric交易流程 多通道

【数字范围按位与】python刷题记录

run到位运算。 顿悟&#xff1a; 只看第一个二进制位&#xff0c;只存在0,1两种情况&#xff0c;所以如果left<right&#xff0c;区间中必然存在left1,那么最低位&一下一定等于0了&#xff0c;然后不停的右移&#xff0c;一直移到两个相等为止&#xff0c;就这么简单 …

Qt自定义下拉列表-可为选项设置标题、可禁用选项

在Qt中,ComboBox&#xff08;组合框&#xff09;是一种常用的用户界面控件,它提供了一个下拉列表,允许用户从预定义的选项中选择一个。在项目开发中&#xff0c;如果简单的QComboBox无法满足需求&#xff0c;可以通过自定义QComboBox来实现更复杂的功能。本文介绍一个自定义的下…

二级医院LIS系统源码,医学检验系统,支持DB2,Oracle,MS SQLServer等主流数据库

系统概述&#xff1a; LIS系统即实验室信息管理系统。LIS系统能实现临床检验信息化&#xff0c;检验科信息管理自动化。其主要功能是将检验科的实验仪器传出的检验数据经数据分析后&#xff0c;自动生成打印报告&#xff0c;通过网络存储在数据库中&#xff0c;使医生能够通过医…

7.消息应答

消费者完成一个任务可能需要一段时间&#xff0c;如果其中一个消费者处理一个长时间的任务并且只完成了部分突然就挂掉了&#xff0c;会发生什么情况&#xff1f; RabbitMQ一旦向消费者传递了一条消息&#xff0c;便立即将该消息标记为删除。这种情况下&#xff0c;突然有个消…

代码随想录算法训练营day6 | 242.有效的字母异位词、349. 两个数组的交集、202. 快乐数、1.两数之和

文章目录 哈希表键值 哈希函数哈希冲突拉链法线性探测法 常见的三种哈希结构集合映射C实现std::unordered_setstd::map 小结242.有效的字母异位词思路复习 349. 两个数组的交集使用数组实现哈希表的情况思路使用set实现哈希表的情况 202. 快乐数思路 1.两数之和思路 总结 今天是…

OpenCV 遍历Mat,像素操作,使用TrackBar 调整图像的亮度和对比度 C++实现

文章目录 1.使用C遍历Mat,完成颜色反转1.1 常规遍历方式1.2 迭代器遍历方式1.3指针访问方式遍历&#xff08;最快&#xff09;1.4不同遍历方式的时间对比 2.图像像素操作&#xff0c;提高图像的亮度3.TrackBar 进度条操作3.1使用TrackBar 调整图像的亮度3.2使用TrackBar 调整图…

学术研讨 | 区块链网络体系结构研讨会顺利召开

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 近日&#xff0c;国家区块链技术创新中心组织了“区块链网络体系结构研讨会”&#xff0c;会议面向跨域交互多、计算规模大、数据管理复杂、性能与扩展性要求高等特征的区块链网络的体系结构展开交流研讨&…

docker相关内容学习

一、docker的四部分 二、镜像相关命令 三、容器相关命令

视频生成【文章汇总】SVD, Sora, Latte, VideoCrafter12, DiT...

视频生成【文章汇总】SVD, Sora, Latte, VideoCrafter12, DiT... 数据集指标 【arXiv 2024】MiraData: A Large-Scale Video Dataset with Long Durations and Structured Captions【CVPR 2024】VBench : Comprehensive Benchmark Suite for Video Generative Models【arxiv 20…

学习记录——day15 数据结构 链表

链表的引入 顺序表的优缺点 1、优点:能够直接通过下标进行定位元素&#xff0c;访问效率高&#xff0c;对元素进行查找和修改比较快 2、不足:插入和删除元素需要移动大量的元素&#xff0c;效率较低 3、缺点:存储数据元素有上限&#xff0c;当达到MAX后&#xff0c;就不能再…

[python]数字与字符串

目录 Python 数字类型转换 Python 数字运算 Python字符串操作 修改 查询 Python 数字数据类型用于存储数值。 数据类型是不允许改变的&#xff0c;这就意味着如果改变数字数据类型的值&#xff0c;将重新分配内存空间。 Python 支持三种不同的数值类型&#xff1a; 整型…

javafx的ListView代入项目的使用

目录 1. 创建一个可观察的列表&#xff0c;用于存储ListView中的数据,这里的User是包装了用户的相关信息。 2.通过本人id获取friendid&#xff0c;及好友的id&#xff0c;然后用集合接送&#xff0c;更方便直观一点。 3.用for遍历集合&#xff0c;逐个添加。 4.渲染器&…