前言
最近想自己做一款加热台,在加热台交互的屏幕上选择犯了难,0.96的oled太小,1.3寸的oled太高,TFT屏幕对于打算用廉价芯片的项目来说,刷新的压力太大了,个位数的帧数让人又爱又恨。
翻了一遍又一遍淘宝看到了这款1.29寸的oled屏幕,这块屏幕的驱动芯片封装再右边再合适不过我对屏幕尺寸要够窄的要求,唯一的缺点就是有点贵,10块包邮的价格怎么说都偏高一点,好在也能接受,毕竟对于一个好的产品来说,用户的交互体验至关重要。
买了之后发现这款显示芯片的驱动在网上并不多,好在移植比较简单,这里分享下我移植好的代码,有差不多一半是利用江科大老师的第二版的驱动代码,剩下的有的是我自己写的有的是我之前用其他屏幕的驱动,又看到好的写法移植过来的。
硬件
我购买的是裸屏,我发的资料中有模块的电路,也有裸屏官方推荐的周边电路,有需要可以自行查找,我自己是使用spi方案,可供参考,推荐去看官方文档的电路
软件
在代码文件方面,我喜欢分为三个大类:
1.驱动代码储存硬件驱动函数显示函数绘图函数
2.用户代码储存菜单动画开机动画等等实际项目的功能代码
3.字库代码储存不同大小的ascii码图像中文文字图像以及图片
需要的话可以自己复制或者下载资料,里面也有。
drivers_oled.c
#include "drivers_oled.h"
/***********************************************************************************************
* 变量名称:OLED_DisplayBuf
* 功能描述:OLED显存数组
* 注意事项:调用Update函数,才会将显存数组的数据发送到OLED硬件,进行显示
* 修改日期 版本号 修改人 修改内容
* --------------------------------------------------------------------------------------------
* 2021/06/03 V1.0 WangJoy 创建
**********************************************************************************************/
static uint8_t OLED_DisplayBuf[8][128];
/***********************************************************************************************
* 函数名称:OLED_IsInAngle
* 功能描述:判断指定点是否在指定角度内部
* 输入参数:X Y 指定点的坐标
* 输入参数:StartAngle EndAngle 起始角度和终止角度,范围:-180~180
* 输出参数:无
* 返 回 值:指定点是否在指定多边形内部,1:在内部,0:不在内部
* 注意事项:水平向右为0度,水平向左为180度或-180度,下方为正数,上方为负数,顺时针旋转
* 修改日期 版本号 修改人 修改内容
* --------------------------------------------------------------------------------------------
* 2021/06/03 V1.0 WangJoy 创建
**********************************************************************************************/
static uint8_t OLED_IsInAngle(int16_t X, int16_t Y, int16_t StartAngle, int16_t EndAngle)
{
int16_t PointAngle;
PointAngle = atan2(Y, X) / 3.14 * 180; // 计算指定点的弧度,并转换为角度表示
if (StartAngle < EndAngle) // 起始角度小于终止角度的情况
if (PointAngle >= StartAngle && PointAngle <= EndAngle) // 如果指定角度在起始终止角度之间,则判定指定点在指定角度
return 1;
else // 起始角度大于于终止角度的情况
if (PointAngle >= StartAngle || PointAngle <= EndAngle) // 如果指定角度大于起始角度或者小于终止角度,则判定指定点在指定角度
return 1;
return 0; // 不满足以上条件,则判断判定指定点不在指定角度
}
/***********************************************************************************************
* 函数名称:OLED_WriteByte
* 功能描述:OLED写字节
* 输入参数:Byte 要写入数据的起始地址, Count 要写入数据的数量
* 输出参数:总线数据
* 返 回 值:无
* 注意事项:移植不同通信方式修改这个函数
* 修改日期 版本号 修改人 修改内容
* --------------------------------------------------------------------------------------------
* 2021/08/29 V1.0 WangJoy 创建
**********************************************************************************************/
static void OLED_WriteByte(uint8_t *Data, uint8_t Count)
{
HAL_SPI_Transmit(&hspi1, Data, Count, Max_time); // HAL库硬件spi
}
/***********************************************************************************************
* 函数名称:OLED_WriteCommand
* 功能描述:OLED写命令
* 输入参数:Command 要写入的命令值,范围:0x00~0xFF
* 输出参数:总线数据
* 返 回 值:无
* 注意事项:保持D/C信号始终为高电平(数据),可以更快速的传输数据
* 修改日期 版本号 修改人 修改内容
* --------------------------------------------------------------------------------------------
* 2021/07/26 V1.0 WangJoy 创建
**********************************************************************************************/
static void OLED_WriteCommand(uint8_t Command)
{
HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_RESET); // 指令
OLED_WriteByte(&Command, 1);
HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_SET); // 数据
}
/***********************************************************************************************
* 函数名称:OLED_WriteData
* 功能描述:OLED写数据
* 输入参数:Data 要写入数据的起始地址, Count 要写入数据的数量
* 输出参数:总线数据
* 返 回 值:无
* 注意事项:D/C信号始终为高电平,提供数据速率
* 修改日期 版本号 修改人 修改内容
* --------------------------------------------------------------------------------------------
* 2021/07/26 V1.0 WangJoy 创建
**********************************************************************************************/
static void OLED_WriteData(uint8_t *Data, uint8_t Count)
{
OLED_WriteByte(Data, Count);
}
/***********************************************************************************************
* 函数名称:OLED_Init
* 功能描述:OLED初始化
* 输入参数:无
* 输出参数:总线信号
* 返 回 值:无
* 注意事项:无
* 修改日期 版本号 修改人 修改内容
* --------------------------------------------------------------------------------------------
* 2021/06/03 V1.0 王佳煜 创建
**********************************************************************************************/
void OLED_Init(void)
{
HAL_Delay(50); // 稳定一下,有的屏幕驱动芯片可不加
OLED_WriteCommand(0xAE); /* 关闭显示 */
OLED_WriteCommand(0x00); /* 设置底行地址 */
OLED_WriteCommand(0x10); /* 设置顶行地址 */
OLED_WriteCommand(0xB0); /* 设置页地址 */
OLED_WriteCommand(0x40); /* 设置显示起始行 */
OLED_WriteCommand(0x81); /* 设置对比度 */
OLED_WriteCommand(0x88); /* 0x00-0xFF */
OLED_WriteCommand(0x82); /* 设置参考电流限流电阻 */
OLED_WriteCommand(0x00); /* 外部电阻 */
OLED_WriteCommand(0xA1); /* 设置段重映射 */
OLED_WriteCommand(0xA2); /* 设置硬件布局 */
OLED_WriteCommand(0xA4); /* 关闭全屏点亮 */
OLED_WriteCommand(0xA6); /* A6正显,A7反显 */
OLED_WriteCommand(0xA8); /* 设置多路复用率 */
OLED_WriteCommand(0x3F); /* 64位 */
OLED_WriteCommand(0xC8); /* 设置垂直翻转C8-C0 */
OLED_WriteCommand(0xD3); /* 设置显示偏移量 */
OLED_WriteCommand(0x00); /* 不偏移 */
OLED_WriteCommand(0xD5); /* 设置时钟 */
OLED_WriteCommand(0xa0); /* 默认频率 */
OLED_WriteCommand(0xD9); /* 设置充放电周期 */
OLED_WriteCommand(0x22); /* 默认周期 */
OLED_WriteCommand(0xdb); /* 设置VCOM电压 */
OLED_WriteCommand(0x40); /* 外部来源 */
OLED_WriteCommand(0x31); /* 设置电荷泵输出电压为7.4v */
OLED_WriteCommand(0xad); /* 使能电荷泵 */
OLED_WriteCommand(0x8b); /* 开启升压 */
OLED_WriteCommand(0xAF); /* 开启显示 */
OLED_Clear(0, 0, 127, 63); /* 清空数组 */
OLED_Update(0, 0, 127, 63); /* 清屏 */
}
/***********************************************************************************************
* 函数名称:OLED_Update
* 功能描述:将OLED显存数组更新到OLED屏幕
* 输入参数:X 指定区域左上角的横坐标,范围:0~127, Y 指定区域左上角的纵坐标,范围:0~63
* 输入参数:Width 指定区域的宽度,范围:0~128, Height 指定区域的高度,范围:0~64
* 输出参数:总线信号
* 返 回 值:无
* 注意事项:所有显示函数,都只对显存读写
* 修改日期 版本号 修改人 修改内容
* --------------------------------------------------------------------------------------------
* 2021/06/03 V1.0 王佳煜 创建
**********************************************************************************************/
void OLED_Update(uint8_t X, uint8_t Y, uint8_t Width, uint8_t Height)
{
/* 参数检查,保证指定区域不会超出屏幕范围 */
if (X > 127 || Y > 63) {return;}
if (X + Width > 128) {Width = 128 - X;}
if (Y + Height > 64) {Height = 64 - Y;}
for (uint8_t i = Y / 8; i < (Y + Height - 1) / 8 + 1; i ++) // 遍历指定区域涉及的相关页
{
OLED_WriteCommand(0xB0 | i); // 设置页位置
OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4)); // 设置X位置高4位
OLED_WriteCommand(0x00 | (X & 0x0F)); // 设置X位置低4位
OLED_WriteData(&OLED_DisplayBuf[i][X], Width); // 将显存数组的数据写入到OLED
}
}
/***********************************************************************************************
* 函数名称:OLED_Clear
* 功能描述:将OLED显存数组清零
* 输入参数:X 指定区域左上角的横坐标,范围:0~127
* 输入参数:Y 指定区域左上角的纵坐标,范围:0~63
* 输入参数:Width 指定区域的宽度,范围:0~128
* 输入参数:Height 指定区域的高度,范围:0~64
* 输出参数:显存数据
* 返 回 值:无
* 注意事项:只对显存读写
* 修改日期 版本号 修改人 修改内容
* --------------------------------------------------------------------------------------------
* 2021/06/03 V1.0 王佳煜 创建
**********************************************************************************************/
void OLED_Clear(uint8_t X, uint8_t Y, uint8_t Width, uint8_t Height)
{
/* 参数检查,保证指定区域不会超出屏幕范围 */
if (X > 127 || Y > 63) {return;}
if (X + Width > 128) {Width = 128-X;}
if (Y + Height > 64) {Height = 64-Y;}
for(uint8_t j = Y; j < Y + Height; j ++) // 遍历指定页
for(uint8_t i = X; i < X + Width; i ++) // 遍历指定列
OLED_DisplayBuf[j / 8][i] &= ~(0x01 << (j % 8)); // 将显存数组指定数据清零
}
/***********************************************************************************************
* 函数名称:OLED_ShowChar
* 功能描述:OLED显示一个字符
* 输入参数:X 指定字符左上角的横坐标,范围:0~127, Y 指定字符左上角的纵坐标,范围:0~63
* 输入参数:Char 指定要显示的字符,范围:ASCII码可见字符, FontSize 指定字体大小
* 输出参数:显存数据
* 返 回 值:无
* 注意事项:OLED_16x32的字符只有数字, 所以寻址范围 "-16"
* 修改日期 版本号 修改人 修改内容
* --------------------------------------------------------------------------------------------
* 2021/07/26 V1.0 WangJoy 创建
**********************************************************************************************/
void OLED_ShowChar(uint8_t X, uint8_t Y, char Char, OLED_FontSize FontSize)
{
if (FontSize == OLED_8X16) OLED_ShowImage(X, Y, 8, 16, OLED_F8x16[Char - ' ']);
if (FontSize == OLED_6X8) OLED_ShowImage(X, Y, 6, 8, OLED_F6x8[Char - ' ']);
if (FontSize == OLED_16X32