型号:HS96L01W 4S03
分辨率:120*64
通讯方式:4线SPI 模式00
MCU:MSPM0G3507(只影响SPI的配置)
原本照着型号搜到了嘉立创的使用文档,但是实际上并不能正常使用,后来寻到了一篇博客教程【常用模块】OLED显示模块(原理讲解、STM32实例操作)_oled介绍-CSDN博客,博客里写的非常详细且通俗易懂。
借鉴了上面的初始化函数才能正常完成初始化,初始化代码如下:
void OLED_Init(void)
{
SPI_Init(3,0);//4分频,模式为0,0
DL_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 置0
delay_ms(200);//延时 200ms
OLED_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);//默认为0
OLED_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_DrawPoint
void 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 data
uint8_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 0
uint8_t pos, bx, temp = 0;
if (x > 127 || y > 63)
return;//超出范围了.
pos = 7 - y>>3;// 7-y/8
bx = y % 8;
temp = 1 << (7 - bx);
if (t)
OLED_GRAM[x][pos] |= temp;
else
OLED_GRAM[x][pos] &= ~temp;
#endif
/**优化后*/
uint8_t pos = 7 - (y / 8);//计算页数
if (t)
OLED_GRAM[x][pos] |= lut[y % 8];
else
OLED_GRAM[x][pos] &= ~lut[y % 8];
}
static inline void OLED_DrawPointDefault_Inline(uint8_t x, uint8_t y)
{
#if 0
uint8_t pos, bx, temp = 0;
if (x > 127 || y > 63)
return;//超出范围了.
pos = 7 - y>>3;// 7-y/8
bx = y % 8;
temp = 1 << (7 - bx);
if (t)
OLED_GRAM[x][pos] |= temp;
else
OLED_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_Point
for (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 necessary
OLED_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,1
DL_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 置0
delay_ms(200);//延时 200ms
OLED_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);//默认为0
OLED_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 ON
OLED_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 OFF
OLED_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);
}
}