经验——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,一经查实,立即删除!

相关文章

PyTorch可以用来干嘛?

PyTorch 是一个广泛使用的开源机器学习库&#xff0c;由 Facebook AI Research&#xff08;FAIR&#xff09;开发。它主要用于计算机视觉和自然语言处理等深度学习领域&#xff0c;但也可以应用于许多其他类型的机器学习任务。PyTorch 提供了丰富的功能和灵活的设计&#xff0c…

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站音频和视频分开的原因吧

grub之loongarch架构调试

一 什么是grub GNU GRUB 是一个多重操作系统启动管理器。GNU GRUB是由GRUB&#xff08;GRandUnified Bootloader&#xff09;派生而来。 GRUB最初由Erich Stefan Boleyn 设计和应用&#xff1b; 主流发行版 Fedora、Redhat、Centos、Kylin 等基于RPM包的系统&#xff0c;在最新…

04 ES6中对象的简写

在 ES6 中&#xff0c;对象字面量的书写方式进行了一些简化&#xff0c;使得对象的创建更加简洁。以下是 ES6 中对象简写的几种形式&#xff1a; 属性值缩写&#xff1a; 当对象的属性名和属性值的变量名相同时&#xff0c;可以省略属性值&#xff0c;只写属性名。 // ES5 cons…

如何在Linux上安装配置RabbitMQ消息队列

RabbitMQ是一种开源的消息中间件&#xff0c;基于AMQP协议实现。它可以在分布式系统中传递消息&#xff0c;并提供了可靠的消息传递机制。RabbitMQ使用一种称为"消息队列"的方式来管理消息的发送和接收。它的主要特性包括&#xff1a; 可靠性&#xff1a;RabbitMQ使用…

Zabbix监控案例

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

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

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

面试官视角:Java高级面试中的考察与评判

1. 面试前的准备 1.1 明确岗位需求 在面试前&#xff0c;面试官需要对岗位需求有清晰的认识&#xff0c;明确需要考察的技术点和能力。 1.2 设计面试问题 设计针对性强、覆盖面广的面试问题&#xff0c;确保能够全面考察面试者的能力。 2. 考察技术能力 2.1 基础知识 考…

【数字范围按位与】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.两数之和思路 总结 今天是…

C++版OpenCV_03_图像增强

图像增强 3.1 直方图3.2 线性变换3.3 直方图归一化3.4 Gamma变换 3.1 直方图 概念&#xff1a;计算图像单个通道像素的分布。 步骤&#xff1a;把图像灰度级分为n个区间&#xff0c;计算每个区间像素的频数&#xff0c;把频数转化为频率&#xff0c;得到图像的直方图。如果图像…

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 调整图…