主控屏幕显示是main在函数中死循环执行的,主屏幕负责显示:设定温度、实际温度、PD诱骗电压。同时开机回显示自定义的开机画面,我会分享开机画面的定制过程。然后长按“设置键”即可进入设置页面,分为:休眠(自定义休眠时间)、电压(自定义诱骗电压)、校准(设定校准温度)、陀螺(显示三轴加速度)、显示(切换显示方向和反显)、版本(显示版本信息)。
开机logo定制
PCtoLCD界面进行取模,先将要显示的照片进行格式转化,并且转换成像素为128*64以内的大小,然后按图片设置取字模,生成一个16进制数组就可以直接显示。
unsigned char code BMP1[] =
{ 0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x18,0x80,0x81,0x01,0x18,0x80,0xC1,0x07,0x18,0x80,
0x81,0x0F,0x1C,0x80,0x01,0x1F,0x1C,0x80,0x0F,0x06,0x32,0x80,0x19,0x00,0x7B,0xC0,
0x31,0x80,0xED,0x80,0x67,0x70,0xEC,0x9F,0xCF,0x3C,0x7F,0xF0,0xDD,0xFE,0x7F,0xF8,
0x9D,0xFF,0xF8,0xF3,0x87,0x0F,0xFE,0xE1,0xC3,0x03,0xFC,0xC0,0xC1,0x01,0xF0,0xC1,
0xE1,0x00,0xC0,0xC3,0x61,0x00,0x80,0xE7,0x61,0x00,0x00,0xE7,0x6D,0x00,0xFC,0xFF,
0x7D,0x00,0xFF,0xFF,0xFF,0x87,0xF7,0xFE,0x1F,0xFC,0x7B,0xF8,0x1F,0xE0,0xF9,0xE0,
0x07,0xC0,0xFB,0xE0,0x03,0x00,0xFB,0xC0,0x07,0x60,0xFE,0xC0,0x03,0x80,0xF9,0x80,
0x03,0x00,0x3B,0x80,0x01,0x00,0x3E,0x80,0x01,0x00,0x3C,0x80,0x41,0x00,0x38,0x80,
0x81,0x01,0x30,0x80,0x01,0x03,0x30,0x80,0x03,0x0E,0x60,0x80,0x03,0x78,0x40,0x80,
0x03,0xF0,0x7F,0x80,0x03,0xE0,0x7E,0x80,0x03,0xC0,0xF9,0x80,0x03,0xDC,0xF9,0xC0,
0x07,0xFC,0xFB,0xC0,0x0F,0xF8,0xFB,0xE8,0x9F,0x3C,0x7E,0xFC,0x3F,0x7E,0xFC,0xFE,
0x3F,0x6E,0xFC,0xFF,0x6D,0xF8,0xFF,0xFF,0x6D,0xE0,0x3F,0xFF,0x61,0x00,0x00,0xE7,
0x61,0x00,0x80,0xC3,0x41,0x00,0xE0,0xC3,0xC1,0x00,0xF0,0xC3,0xC3,0x81,0xFF,0xC3,
0x8F,0x0F,0xFE,0xE3,0xBD,0x3F,0xFC,0xFC,0x3D,0xFC,0x78,0xF0,0x0F,0xE0,0x79,0xB0,
0x07,0x00,0xF3,0x80,0x01,0x00,0x76,0xC0,0x01,0x00,0x3C,0xC0,0x01,0x06,0x38,0x80,
0x81,0x1F,0x38,0x80,0xC1,0x0F,0x10,0x80,0xE1,0x03,0x10,0x80,0x81,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,
0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xFF,
};/*"C:\Users\CHY\Desktop\tlwvyfyd.bmp",0*/
0.87寸OLED屏幕显示
这段代码是用于控制 OLED 显示模块的一组函数集合。这段代码通过一个缓存数组OLED_GRAM[128][4]
来实现对 OLED 显示内容的管理。这个数组表示了一个128列、4页的显示区域,每个页包含了对应列的数据。在进行显示更新时,先将要显示的内容写入这个缓存数组中,然后通过 OLED_Refresh()
函数将缓存数组的内容传输到 OLED 显示屏上。这种方式的好处是可以在缓存中进行数据的修改和处理,而不必直接与显示屏进行频繁的通信,从而提高了效率和灵活性。
它包括了以下功能:
- 切换显示颜色模式(正常显示或反色显示)。
- 向 OLED 模块发送数据或命令。
- 刷新显示,将显存数据更新到 OLED 模块。
- 设置显示位置。
- 清空显示屏。
- 绘制像素点、直线、矩形等图形。
- 在 OLED 上显示单个字符、数字、字符串以及中文字符。
- 显示位图图片。
- 控制显示屏旋转角度。
- 初始化 OLED 显示模块。
#include "I2C.h"
#include "oled.h"
#include "oledfont.h"
///*************************外部变量声明******************************/
extern bit IIC_communication_busy;
/*******************************************************************/
//u8 x_offset;
static u8 xdata OLED_GRAM[128][4]; //申请一个二维数组作为显存,128列,4页,每页行。
/**************** I2C初始化函数 *****************/
//========================================================================
// 函数: void OLED_ColorTurn(u8 i)
// 描述: 反显函数
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_ColorTurn(u8 i)
{
if(i == 0)
{
OLED_WR_Byte(0xA6, OLED_CMD); //正常显示
}
if(i == 1)
{
OLED_WR_Byte(0xA7, OLED_CMD); //反色显示
}
}
//========================================================================
// 函数: void OLED_WR_Byte(u8 dat, u8 mode)
// 描述: 发送一个字节
// 参数: mode:数据/命令标志 0x00,表示命令; 0x40,表示数据;
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_WR_Byte(u8 dat, u8 mode)
{
if(IIC_communication_busy == 0)
{
IIC_communication_busy = 1; //IIC总线挂起标志位(忙碌)
Start();
SendData(0x78);
RecvACK();
if(mode)
{
SendData(0x40);
}
else
{
SendData(0x00);
}
RecvACK();
SendData(dat);
RecvACK();
Stop();
IIC_communication_busy = 0; //IIC总线解放标志位(未使用)
}
}
//========================================================================
// 函数: void OLED_Refresh(void)
// 描述: 向OLED传输显存数据,更新显存到OLED
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_Refresh(void)
{
u8 i, n;
for (i = 0; i < 4; i++)
{
OLED_WR_Byte(0xB0 + i, OLED_CMD); // 设置行起始地址
OLED_WR_Byte(0x00, OLED_CMD); // 设置低列起始地址
OLED_WR_Byte(0x10, OLED_CMD); // 设置高列起始地址
Start();
SendData(0x78);
RecvACK();
SendData(0x40);
RecvACK();
for (n = 0; n < 128; n++)
{
SendData(OLED_GRAM[n][i]);
RecvACK();
}
Stop();
}
}
//========================================================================
// 函数: void OLED_Set_Pos(u8 x, u8 y)
// 描述: 坐标设置
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_Set_Pos(u8 x, u8 y)
{
OLED_WR_Byte(0xb0 + y, OLED_CMD);
OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
OLED_WR_Byte((x & 0x0f), OLED_CMD);
}
//========================================================================
// void OLED_Clear(void)
// 描述: 清屏函数
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_Clear(void)
{
u8 i, n;
for(i = 0; i < 4; i++)
{
for(n=0;n<128;n++)
{
OLED_GRAM[n][i]=0;//清除所有数据
}
}
OLED_Refresh(); //更新显示
}
//========================================================================
// 函数: void OLED_DrawPoint(u8 x, u8 y, u8 dot)
// 描述: 在OLED上画点
// 参数: x X坐标,范围:0~127
// y Y坐标,范围:0~63
// dot 像素状态,1 表示填充,0 表示清空
// 返回: 无
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_DrawPoint(u8 x, u8 y,u8 t)
{
u8 i,m,n;
i=y/8;
m=y%8;
n=1<<m;
if(t){OLED_GRAM[x][i]|=n;}
else
{
OLED_GRAM[x][i]=~OLED_GRAM[x][i];
OLED_GRAM[x][i]|=n;
OLED_GRAM[x][i]=~OLED_GRAM[x][i];
}
}
//========================================================================
// 函数: void OLED_DrawLine(u8 x1, u8 y1, u8 x2, u8 y2, u8 mode)
// 描述: 画线函数
// 参数: x1, y1: 起点坐标
// x2, y2: 结束坐标
// mode : 1表示填充,0表示清空
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode)
{
u16 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_x;}
if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
else distance=delta_y;
for(t=0;t<distance+1;t++)
{
OLED_DrawPoint(uRow,uCol,mode); //画点
xerr+=delta_x;
yerr+=delta_y;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
//========================================================================
// 函数: void OLED_DrawRectangle(u8 x1, u8 y1, u8 x2, u8 y2, u8 mode)
// 描述: 在OLED上画矩形
// 参数: x1, y1 起点坐标,范围:x1(0~127), y1(0~63)
// x2, y2 结束坐标,范围:x2(0~127), y2(0~63)
// mode 模式,1 表示填充,0 表示清空
// 返回: 无
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_DrawSquar(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode)
{
if(mode==1)
{
OLED_DrawLine(x1,y1,x2,y1,1);
OLED_DrawLine(x1,y1,x1,y2,1);
OLED_DrawLine(x1,y2,x2,y2,1);
OLED_DrawLine(x2,y1,x2,y2,1);
}
else if(mode==0)
{
OLED_DrawLine(x1,y1,x2,y1,0);
OLED_DrawLine(x1,y1,x1,y2,0);
OLED_DrawLine(x1,y2,x2,y2,0);
OLED_DrawLine(x2,y1,x2,y2,0);
}
}
//========================================================================
// 函数: void OLED_ShowChar(u8 x, u8 y, u8 chr, u8 size1, u8 mode)
// 描述: 在OLED上显示单个字符
// 参数: x X坐标,范围:0~127
// y Y坐标,范围:0~63
// chr 要显示的字符
// size1 字体大小,支持 8 或 16
// mode 显示模式,1 表示填充,0 表示清空
// 返回: 无
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode)
{
u8 i,m,temp,size2,chr1;
u8 x0=x,y0=y;
if(size1==8)size2=6;
else size2=(size1/8+((size1%8)?1:0))*(size1/2); //得到字体一个字符对应点阵集所占的字节数
chr1=chr-' '; //计算偏移后的值
for(i=0;i<size2;i++)
{
if(size1==8)
{temp=asc2_0806[chr1][i];} //调用0806字体
else if(size1==16)
{temp=asc2_1608[chr1][i];} //调用1616字体
else return;
for(m=0;m<8;m++)
{
if(temp&0x01)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp>>=1;
y++;
}
x++;
if((size1!=8)&&((x-x0)==size1/2))
{x=x0;y0=y0+8;}
y=y0;
}
}
//========================================================================
// 函数: u32 oled_pow(u8 m, u8 n)
// 描述: 计算 m 的 n 次方
// 参数: m 底数
// n 指数
// 返回: m 的 n 次方
// 版本: V1.0, 2023-03-28
//========================================================================
u32 oled_pow(u8 m, u8 n)
{
u32 result = 1;
while(n--)result *= m;
return result;
}
//========================================================================
// void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len, u8 sizey)
// 描述: 显示数字
// 参数: x,y :起点坐标;num:要显示的数字;len :数字的位数;sizey:字体大小
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode)
{
u8 t,temp,m=0;
if(size1==8)m=2;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(temp==0)
{
OLED_ShowChar(x+(size1/2+m)*t,y,'0',size1,mode);
}
else
{
OLED_ShowChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);
}
}
}
//========================================================================
// void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len, u8 sizey)
// 描述: 显示一个字符号串
// 参数: x,y :起点坐标;*chr:要显示的字符串指针;sizey:字体大小
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode)
{
while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符!
{
OLED_ShowChar(x,y,*chr,size1,mode);
if(size1==8)x+=6;
else x+=size1/2;
chr++;
}
}
//========================================================================
// void OLED_ShowChinese(u8 x, u8 y, u8 no, u8 sizey)
// 描述: 显示汉字
// 参数: x,y :起点坐标;no:要显示的汉字;sizey:字体大小
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode)
{
u8 m,temp;
u8 x0=x,y0=y;
u16 i,size3=(size1/8+((size1%8)?1:0))*size1; //得到字体一个字符对应点阵集所占的字节数
for(i=0;i<size3;i++)
{
if(size1==12)
{temp=Hzk12[num][i];} //调用16*16字体
else if(size1==16)
{temp=Hzk16[num][i];} //调用12*12字体
else return;
for(m=0;m<8;m++)
{
if(temp&0x01)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp>>=1;
y++;
}
x++;
if((x-x0)==size1)
{x=x0;y0=y0+8;}
y=y0;
}
}
//========================================================================
// void OLED_DrawBMP(u8 x, u8 y, u8 sizex, u8 sizey, u8 BMP[])
// 描述: 显示图片
// 参数: x,y显示坐标;sizex,sizey,图片长宽
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_DrawBMP(u8 x, u8 y, u8 sizex, u8 sizey, u8 BMP[])
{
u16 j = 0;
u8 i, m;
sizey = sizey / 8 + ((sizey % 8) ? 1 : 0);
for(i = 0; i < sizey; i++)
{
OLED_Set_Pos(x, i + y);
for(m = 0; m < sizex; m++)
{
OLED_WR_Byte(BMP[j++], OLED_DATA);
}
}
}
#ifdef SSD1316
//========================================================================
// 函数: void OLED_DisplayTurn(u8 i)
// 描述: 屏幕旋转180度
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_DisplayTurn(u8 i)
{
if(i==0)
{
OLED_WR_Byte(0xC0,OLED_CMD);//正常显示
OLED_WR_Byte(0xA1,OLED_CMD);
}
if(i==1)
{
OLED_WR_Byte(0xC8,OLED_CMD);//反转显示
OLED_WR_Byte(0xA0,OLED_CMD);
}
}
//========================================================================
// void OLED_Init(void)
// 描述: OLED初始化
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_Init(void)
{
OLED_WR_Byte(0xAE,OLED_CMD); /*display off*/
OLED_WR_Byte(0x00,OLED_CMD); /*set lower column address*/
OLED_WR_Byte(0x10,OLED_CMD); /*set higher column address*/
OLED_WR_Byte(0x40,OLED_CMD); /*set display start line*/
OLED_WR_Byte(0xB0,OLED_CMD); /*set page address*/
OLED_WR_Byte(0x81,OLED_CMD); /*contract control*/
OLED_WR_Byte(0xc5,OLED_CMD); /*128*/
OLED_WR_Byte(0xA1,OLED_CMD); /*set segment remap 0XA0*/
OLED_WR_Byte(0xA6,OLED_CMD); /*normal / reverse*/
OLED_WR_Byte(0xA8,OLED_CMD); /*multiplex ratio*/
OLED_WR_Byte(0x1F,OLED_CMD); /*duty = 1/32*/
OLED_WR_Byte(0xC0,OLED_CMD); /*Com scan direction 0XC0 */
OLED_WR_Byte(0xD3,OLED_CMD); /*set display offset*/
OLED_WR_Byte(0x00,OLED_CMD); /* 0x20 */
OLED_WR_Byte(0xD5,OLED_CMD); /*set osc division*/
OLED_WR_Byte(0x80,OLED_CMD);
OLED_WR_Byte(0xD9,OLED_CMD); /*set pre-charge period*/
OLED_WR_Byte(0x22,OLED_CMD); /*0x22*/
OLED_WR_Byte(0xDA,OLED_CMD); /*set COM pins*/
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xdb,OLED_CMD); /*set vcomh*/
OLED_WR_Byte(0x20,OLED_CMD);
OLED_WR_Byte(0x8d,OLED_CMD); /*set vcomh*/
OLED_WR_Byte(0x15,OLED_CMD); /* Set_Charge_Pump 0x14:9v; 0x15 7.5v */
OLED_Clear();
OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
}
#else
//========================================================================
// 函数: void OLED_DisplayTurn(u8 i)
// 描述: 屏幕旋转180度
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_DisplayTurn(u8 i)
{
if(i==0)
{
OLED_WR_Byte(0xD3,OLED_CMD); /*set display offset*/
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
OLED_WR_Byte(0xA0,OLED_CMD);
}
if(i==1)
{
OLED_WR_Byte(0xD3,OLED_CMD); /*set display offset*/
OLED_WR_Byte(0x2e,OLED_CMD);
OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
OLED_WR_Byte(0xA1,OLED_CMD);
}
}
//========================================================================
// void OLED_Init(void)
// 描述: OLED初始化
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void OLED_Init(void)
{
OLED_WR_Byte(0xAE,OLED_CMD); /*display off*/
OLED_WR_Byte(0xA8,OLED_CMD); /*multiplex ratio*/
OLED_WR_Byte(0x1E,OLED_CMD); /*duty = 1/30*/
OLED_WR_Byte(0xad,OLED_CMD); /*External or Internal IREF Selection */
OLED_WR_Byte(0x40,OLED_CMD);
OLED_WR_Byte(0xD3,OLED_CMD); /*set display offset*/
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xA0,OLED_CMD); /*set segment remap*/
OLED_WR_Byte(0xC8,OLED_CMD); /*Com scan direction*/
OLED_WR_Byte(0xA6,OLED_CMD); /*normal / reverse*/
OLED_WR_Byte(0x40,OLED_CMD); /*set display start line*/
OLED_WR_Byte(0xA4,OLED_CMD);
OLED_WR_Byte(0x81,OLED_CMD); /*contract control*/
OLED_WR_Byte(0x30,OLED_CMD); /*128*/
OLED_WR_Byte(0xD9,OLED_CMD); /*set pre-charge period*/
OLED_WR_Byte(0x22,OLED_CMD);
OLED_WR_Byte(0xD5,OLED_CMD); /*set osc division*/
OLED_WR_Byte(0x41,OLED_CMD);
OLED_WR_Byte(0xDA,OLED_CMD); /*set COM pins*/
OLED_WR_Byte(0x10,OLED_CMD);
OLED_WR_Byte(0x20,OLED_CMD); /*Set Memory Addressing Mode */
OLED_WR_Byte(0x02,OLED_CMD); /*Page Addressing Mode*/
OLED_WR_Byte(0xdb,OLED_CMD); /*set vcomh*/
OLED_WR_Byte(0x30,OLED_CMD);
OLED_WR_Byte(0x8d,OLED_CMD); /*set charge pump enable*/
OLED_WR_Byte(0x52,OLED_CMD);
OLED_WR_Byte(0x08,OLED_CMD); /*set lower column address*/
OLED_WR_Byte(0x10,OLED_CMD); /*set higher column address*/
OLED_Clear();
OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
}
#endif
主控屏幕显示函数逻辑
show_Init(void)
:用于初始化显示界面,在 OLED 显示屏上显示一个初始的界面,并延时2秒后清空显示屏。
interface_show(void)
:是用于在 OLED 显示屏上显示操作主界面的函数。下面是对该函数的详细解释:
-
首先定义了两个静态变量
T12output_adc_past
和T12output_adc_now
用于记录上一次和当前的 ADC(模数转换器)采集值。这些值用于计算实际温度。 -
调用
T12output_adc_filter(12, 6)
函数获取当前温度传感器的 ADC 值,并通过温度拟合函数temp_fitting()
计算实际温度。 -
调用
power_test()
获取电源电压,并根据一定范围进行修正。 -
在 OLED 显示屏上依次显示设定温度、实际温度和实际电压的数值。调用了
OLED_ShowChinese()
和OLED_ShowNum()
函数进行显示。 -
检测按键操作,若按键被按下,则根据按键操作增加或减少设定温度。支持两种模式:点按模式和长按模式。根据不同的按键操作调整设定温度,并在 OLED 上显示。
-
若按键
key_set
被长按(持续1秒以上),则进入设置界面show_set()
,直到按键释放。在此期间,定时器ET0
被禁用。 -
在循环的最后,通过延时函数
delay_ms()
区分长按和短按。 -
如果系统进入睡眠模式(
sleep_time_min == 0
),则在 OLED 上显示 "OFF",并等待按键操作来恢复正常工作。同时,将定时器ET0
禁用。
这个函数实现了在 OLED 显示屏上显示主界面并进行用户操作的功能,通过按键操作可以实时调整设定温度,并显示实际温度和电压。
/*******************************************************************/
//========================================================================
// 函数: void show_Init(void)
// 描述: 初始loge显示界面
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void show_Init(void)
{
OLED_DrawBMP(0, 0, 128, 32, BMP1);
delay_s(2);
OLED_Clear();
}
//========================================================================
// 函数: void interface_show(void)
// 描述: 显示操作主界面
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-03-28
//========================================================================
void interface_show(void)
{
static int T12output_adc_past;
static int T12output_adc_now = 0;
u8 key0memory = 0;
u8 key1memory = 0;
T12output_adc_past = T12output_adc_now;
T12output_adc_now = T12output_adc_filter(12, 6);
if (T12output_adc_now != 0 && abs(T12output_adc_now - T12output_adc_past) <= 20)
actual_temp = temp_fitting(T12output_adc_now);
actual_v = power_test();
if (actual_v >= 3 && actual_v <= 6)
actual_v = 5;
else if (actual_v >= 8 && actual_v <= 10)
actual_v = 9;
else if (actual_v >= 11 && actual_v <= 12)
actual_v = 12;
else if (actual_v >= 14 && actual_v <= 16)
actual_v = 15;
else if (actual_v >= 19 && actual_v <= 21)
actual_v = 20;
OLED_ShowChinese(2, 2, 10, 12, 1); // 显示“设”
OLED_ShowChinese(16, 2, 11, 12, 1); // 显示“置”
OLED_ShowNum(5, 22, expect_temp, 3, 8, 1); // 显示设定温度
OLED_ShowChinese(70, 8, 0, 16, 1); // 显示℃
OLED_ShowNum(45, 8, actual_temp, 3, 16, 1); // 显示实际温度
OLED_ShowChinese(101, 2, 17, 12, 1); // 显示“电”
OLED_ShowChinese(115, 2, 18, 12, 1); // 显示“压”
OLED_ShowChar(116, 22, 'v', 8, 1); // 显示V
OLED_ShowNum(103, 22, actual_v, 2, 8, 1); // 显示实际电压
// OLED_ShowNum(53,22,NTC_temp,4,8,1); //显示实际电压
if (key0memory = keyscan(0)) // 调节温度,点按模式
{
switch (key0memory)
{
case keyadd_poss:
expect_temp++;
if (expect_temp >= 500)
expect_temp = 500;
eeprom_dat[2] = expect_temp / 10;
eeprom_dat[3] = expect_temp % 10;
Eeprom_updata(Start_addrs, &eeprom_dat, 6);
OLED_ShowNum(5, 22, expect_temp, 3, 8, 1);
break;
case keyless_poss:
expect_temp--;
if (expect_temp <= 50)
expect_temp = 50;
eeprom_dat[2] = expect_temp / 10;
eeprom_dat[3] = expect_temp % 10;
Eeprom_updata(Start_addrs, &eeprom_dat, 6);
OLED_ShowNum(5, 22, expect_temp, 3, 8, 1);
break;
default:
break;
}
}
else if (key1memory = keyscan(1)) // 调节温度,长按模式
{
switch (key1memory)
{
case keyadd_poss:
expect_temp += 10;
if (expect_temp >= 500)
expect_temp = 500;
eeprom_dat[2] = expect_temp / 10;
eeprom_dat[3] = expect_temp % 10;
Eeprom_updata(Start_addrs, &eeprom_dat, 6);
OLED_ShowNum(5, 22, expect_temp, 3, 8, 1);
break;
case keyless_poss:
expect_temp -= 10;
if (expect_temp <= 50)
expect_temp = 50;
eeprom_dat[2] = expect_temp / 10;
eeprom_dat[3] = expect_temp % 10;
Eeprom_updata(Start_addrs, &eeprom_dat, 6);
OLED_ShowNum(5, 22, expect_temp, 3, 8, 1);
break;
default:
break;
}
}
OLED_Refresh();
if (key_set == 0) // 进入设置界面,长按1s模式
{
delay_s(1);
if (key_set == 0)
{
OLED_Clear();
while (1)
{
show_set();
if (key_set == 0)
{
delay_s(1);
if (key_set == 0)
{
ET0 = 1;
break;
}
}
}
OLED_Clear();
}
}
delay_ms(50); // 区分长按和短按
if (sleep_time_min == 0)
{
OLED_Clear();
ET0 = 0;
P12 = 0;
while (1)
{
OLED_ShowString(50, 8, "OFF", 16, 1);
OLED_Refresh();
if (key_set == 0)
{
delay_s(1);
if (key_set == 0)
{
ET0 = 1;
sleep_time_min = sleep_time_min_menory;
break;
}
}
}
}
temp_protect();
}
设置切换函数
函数 show_set(void)
用于显示设置主界面,并根据按键操作进入相应的设置子界面。下面是对该函数的详细解释:
-
首先定义了一个局部变量
keymemory_s
用于存储按键扫描的结果,以及两个整型变量Linex
和Liney
用于记录当前光标的位置。 -
将定时器
ET0
禁用,并将引脚P12
置为低电平,以确保在设置界面时不会发生中断和输出。 -
在 OLED 显示屏上显示各个设置项的名称,包括睡眠设置、电源设置、校准设置、陀螺仪设置、显示设置和版本设置。
-
进入一个无限循环,在循环中不断扫描按键操作。如果按键被按下,则根据按键操作移动光标的位置,并在 OLED 上绘制光标。
-
如果按键
key_set
被按下,则根据当前光标位置进入相应的设置子界面,如睡眠设置、电源设置等,并跳出循环。 -
若在设置界面中按下了
key_set
键,则跳出循环,返回到主界面。
这个函数实现了显示设置主界面,并能够根据按键操作进入相应的设置子界面。
//========================================================================
// 函数: void show_set(void)
// 描述: 显示设置主界面
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-04-06
//========================================================================
void show_set(void)
{
u8 keymemory_s;
int Linex = -45;
int Liney = 1;
ET0 = 0;
P12 = 0;
// OLED_Clear();
OLED_ShowChinese(4, 2, 6, 12, 1); // 显示“睡”
OLED_ShowChinese(18, 2, 7, 12, 1); // 显示“眠”
OLED_ShowChinese(51, 2, 17, 12, 1); // 显示“电”
OLED_ShowChinese(65, 2, 18, 12, 1); // 显示“压”
OLED_ShowChinese(98, 2, 23, 12, 1); // 显示“校”
OLED_ShowChinese(112, 2, 24, 12, 1); // 显示“准”
OLED_ShowChinese(4, 17, 1, 12, 1); // 显示“陀”
OLED_ShowChinese(18, 17, 2, 12, 1); // 显示“螺”
OLED_ShowChinese(51, 17, 3, 12, 1); // 显示“显”
OLED_ShowChinese(65, 17, 4, 12, 1); // 显示“示”
OLED_ShowChinese(98, 17, 12, 12, 1); // 显示“版”
OLED_ShowChinese(112, 17, 13, 12, 1); // 显示“本”
OLED_Refresh();
while (1)
{
if (keymemory_s = keyscan(0)) // 调节温度,点按模式
{
switch (keymemory_s)
{
case keyadd_poss:
OLED_DrawSquar(Linex, Liney, Linex + 29, Liney + 14, 0);
if (Linex == 96 && Liney == 1)
{
Linex = 2;
Liney = 16;
}
else if (Linex == 96 && Liney == 16)
{
Linex = 96;
Liney = 16;
}
else
Linex += 47;
OLED_DrawSquar(Linex, Liney, Linex + 29, Liney + 14, 1);
break;
case keyless_poss:
OLED_DrawSquar(Linex, Liney, Linex + 29, Liney + 14, 0);
if (Linex == 2 && Liney == 16)
{
Linex = 96;
Liney = 1;
}
else if (Linex == 2 && Liney == 1)
{
Linex = 2;
Liney = 1;
}
else
Linex -= 47;
OLED_DrawSquar(Linex, Liney, Linex + 29, Liney + 14, 1);
break;
default:
break;
}
OLED_Refresh();
}
if (key_set == 0)
{
switch (Liney)
{
case 1:
switch (Linex)
{
case 2:
show_sleepset();
break;
case 49:
show_powerset();
break;
case 96:
show_calibraset();
break;
}
break;
case 16:
switch (Linex)
{
case 2:
show_gyroset();
break;
case 49:
show_displayset();
break;
case 96:
show_versionset();
break;
}
break;
}
break;
}
}
}
其他页面设置函数
-
show_powerset(void)
: 这个函数用于显示电压设置界面。首先,它定义了一个用于存储按键扫描结果的变量keymemory_p
,以及一个数组v
用于存储不同电压值。然后,在一个无限循环中,它不断显示当前的电压设置,并根据按键操作调整电压值。最后,如果按下确认键key_set
,则将当前电压值存储到EEPROM中,并根据设置的电压值执行相应的操作。 -
show_sleepset(void)
: 这个函数用于显示休眠设置界面。它也采用了类似的逻辑,不断显示当前的休眠时间,并根据按键操作调整时间值。最后,如果按下确认键key_set
,则将当前的休眠时间存储到EEPROM中。 -
show_calibraset(void)
: 这个函数用于显示校准设置界面。它同样采用了类似的逻辑,不断显示当前的校准温度,并根据按键操作调整温度值。最后,如果按下确认键key_set
,则将当前的校准温度存储到EEPROM中。 -
show_gyroset(void)
: 这个函数用于显示陀螺仪界面。它显示三个轴的加速度值,并且不响应任何按键操作。 -
show_displayset(void)
: 这个函数用于显示显示设置界面。它根据按键操作调整显示设置,并根据用户的选择执行相应的操作。最后,如果按下确认键key_set
,则将当前的显示设置存储到EEPROM中。 -
show_versionset(void)
: 这个函数用于显示版本信息。它显示当前版本号以及作者信息,并且不响应任何按键操作。 -
display_select(int displaymemory)
: 这个函数用于根据用户选择的显示设置执行相应的操作。根据传入的参数displaymemory
,它会调用OLED_ColorTurn()
和OLED_DisplayTurn()
函数来设置显示屏的颜色和显示方向
//========================================================================
// 函数: void show_powerset(void)
// 描述: 显示电压设置界面
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-08-29
//========================================================================
void show_powerset(void)
{
u8 keymemory_p, j, i;
u8 v[5] = {5, 9, 12, 15, 20};
for (i = 0; i < 5; i++)
{
if (v[i] == actual_v)
j = i;
}
OLED_Clear();
while (1)
{
OLED_ShowChinese(37, 2, 17, 12, 1); // 显示“电”
OLED_ShowChinese(51, 2, 18, 12, 1); // 显示“压”
OLED_ShowChinese(65, 2, 10, 12, 1); // 显示“设”
OLED_ShowChinese(79, 2, 11, 12, 1); // 显示“置”
OLED_ShowNum(53, 21, v[j], 2, 8, 1); // 显示目前实际电压
OLED_ShowChar(68, 21, 'v', 8, 1); // 显示min
OLED_Refresh();
delay_ms(200); // 防止误判
if (keymemory_p = keyscan(0)) // 调节温度,点按模式
{
switch (keymemory_p)
{
case keyadd_poss:
if (j == 4)
j = 4;
else
j++;
OLED_ShowNum(53, 21, v[j], 2, 8, 1); // 显示目前实际电压
OLED_Refresh();
break;
case keyless_poss:
if (j == 0)
j = 0;
else
j--;
OLED_ShowNum(53, 21, v[j], 2, 8, 1); // 显示目前实际电压
OLED_Refresh();
break;
default:
break;
}
}
if (key_set == 0)
{
set_power_select = v[j];
eeprom_dat[1] = set_power_select;
Eeprom_updata(Start_addrs, &eeprom_dat, 6); // 掉电记录设置的电源电压
power_select(set_power_select); // 冲突,会卡死在这一步,原因未知。
ET0 = 1;
OLED_Clear();
break;
}
}
}
//========================================================================
// 函数: void show_sleepset(void)
// 描述: 显示休眠设置界面
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-08-29
//========================================================================
void show_sleepset(void)
{
u8 keymemory_l;
// 位置有问题
OLED_Clear();
while (1)
{
OLED_ShowChinese(37, 2, 6, 12, 1); // 显示“休”
OLED_ShowChinese(51, 2, 7, 12, 1); // 显示“眠”
OLED_ShowChinese(65, 2, 8, 12, 1); // 显示“时”
OLED_ShowChinese(79, 2, 9, 12, 1); // 显示“间”
OLED_ShowNum(48, 21, sleep_time_min, 2, 8, 1); // 显示目前休眠时间
OLED_ShowString(63, 21, "min", 8, 1); // 显示min
OLED_Refresh();
delay_ms(200); // 防止误判
if (keymemory_l = keyscan(0)) // 点按模式
{
switch (keymemory_l)
{
case keyadd_poss:
if (sleep_time_min == 30)
sleep_time_min = 30;
else
sleep_time_min++;
OLED_ShowNum(48, 21, sleep_time_min, 2, 8, 1); // 显示目前休眠时间
OLED_Refresh();
break;
case keyless_poss:
if (sleep_time_min == 0)
sleep_time_min = 0;
else
sleep_time_min--;
OLED_ShowNum(48, 21, sleep_time_min, 2, 8, 1); // 显示目前休眠时间
OLED_Refresh();
break;
default:
break;
}
}
if (key_set == 0)
{
sleep_time_min_menory = sleep_time_min;
eeprom_dat[0] = sleep_time_min;
Eeprom_updata(Start_addrs, &eeprom_dat, 6); // 掉电记录设置的电源电压
ET0 = 1;
OLED_Clear();
break;
}
}
}
//========================================================================
// 函数: void show_calibraset(void)
// 描述: 显示校准设置界面
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-08-29
//========================================================================
void show_calibraset(void)
{
u8 keymemory_c;
OLED_Clear();
while (1)
{
OLED_ShowChinese(37, 2, 19, 12, 1); // 显示“温”
OLED_ShowChinese(51, 2, 20, 12, 1); // 显示“度”
OLED_ShowChinese(65, 2, 23, 12, 1); // 显示“校”
OLED_ShowChinese(79, 2, 24, 12, 1); // 显示“准”
if (calibra_temp >= 0)
OLED_ShowNum(52, 21, calibra_temp, 2, 8, 1); // 显示目前校准温度
else
{
OLED_ShowChar(44, 21, '-', 8, 1);
OLED_ShowNum(52, 21, -calibra_temp, 2, 8, 1); // 显示目前校准温度
}
OLED_ShowChinese(68, 19, 0, 12, 1); // 显示min
OLED_Refresh();
if (keymemory_c = keyscan(0)) // 调节温度,点按模式
{
switch (keymemory_c)
{
case keyadd_poss:
calibra_temp++;
if (calibra_temp >= 0)
OLED_ShowNum(52, 21, calibra_temp, 2, 8, 1); // 显示目前校准温度
else
{
OLED_ShowChar(44, 21, '-', 8, 1);
OLED_ShowNum(52, 21, -calibra_temp, 2, 8, 1); // 显示目前校准温度
}
OLED_Refresh();
break;
case keyless_poss:
calibra_temp--;
if (calibra_temp >= 0)
OLED_ShowNum(52, 21, calibra_temp, 2, 8, 1); // 显示目前校准温度
else
{
OLED_ShowChar(44, 21, '-', 8, 1);
OLED_ShowNum(52, 21, -calibra_temp, 2, 8, 1); // 显示目前校准温度
}
OLED_Refresh();
break;
default:
break;
}
}
delay_ms(200); // 防止误判
if (key_set == 0)
{
eeprom_dat[4] = calibra_temp;
Eeprom_updata(Start_addrs, &eeprom_dat, 6); // 掉电记录设置的电源电压
ET0 = 1;
OLED_Clear();
break;
}
}
}
//========================================================================
// 函数: void show_gyroset(void)
// 描述: 显示陀螺仪界面
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-09-10
//========================================================================
void show_gyroset(void)
{
u8 keymemory_g;
// xx=10;yy=-10;zz=1;
OLED_Clear();
while (1)
{
OLED_ShowChar(10, 2, 'X', 16, 1); // 显示“X”
OLED_ShowChar(56, 2, 'Y', 16, 1); // 显示“Y”
OLED_ShowChar(102, 2, 'Z', 16, 1); // 显示“Z”
if (xx >= 0)
OLED_ShowNum(10, 22, xx, 4, 8, 1); // 显示x轴加速度
else
{
OLED_ShowChar(0, 22, '-', 8, 1);
OLED_ShowNum(10, 22, -xx, 4, 8, 1);
}
if (yy >= 0)
OLED_ShowNum(56, 22, yy, 4, 8, 1); // 显示y轴加速度
else
{
OLED_ShowChar(46, 22, '-', 8, 1);
OLED_ShowNum(56, 22, -yy, 4, 8, 1);
}
if (zz >= 0)
OLED_ShowNum(102, 22, zz, 4, 8, 1); // 显示z轴加速度
else
{
OLED_ShowChar(92, 22, '-', 8, 1);
OLED_ShowNum(102, 22, -zz, 4, 8, 1);
}
OLED_Refresh();
delay_ms(200); // 防止误判
if (keymemory_g = keyscan(0)) // 点按模式
{
}
if (key_set == 0)
{
ET0 = 1;
OLED_Clear();
break;
}
}
}
//========================================================================
// 函数: void show_displayset(void)
// 描述: 显示电压设置界面
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-09-10
//========================================================================
void show_displayset(void)
{
u8 keymemory_d;
int Linex = -32;
int Liney = 1;
OLED_Clear();
OLED_ShowChinese(24, 2, 5, 12, 1); // 显示“正”
OLED_ShowChinese(38, 2, 14, 12, 1); // 显示“常”
OLED_ShowChinese(78, 2, 15, 12, 1); // 显示“反”
OLED_ShowChinese(92, 2, 16, 12, 1); // 显示“色”
OLED_ShowChinese(24, 17, 25, 12, 1); // 显示“翻”
OLED_ShowChinese(38, 17, 26, 12, 1); // 显示“转”
OLED_ShowChinese(78, 17, 15, 12, 1); // 显示“反”
OLED_ShowChinese(92, 17, 26, 12, 1); // 显示“转”
OLED_Refresh();
delay_ms(200);
while (1)
{ // 防止误判
if (keymemory_d = keyscan(0)) // 调节温度,点按模式
{
switch (keymemory_d)
{
case keyadd_poss:
OLED_DrawSquar(Linex, Liney, Linex + 29, Liney + 14, 0);
if (Linex == 76 && Liney == 1)
{
Linex = 22;
Liney = 16;
}
else if (Linex == 76 && Liney == 16)
{
Linex = 76;
Liney = 16;
}
else
Linex += 54;
OLED_DrawSquar(Linex, Liney, Linex + 29, Liney + 14, 1);
break;
case keyless_poss:
OLED_DrawSquar(Linex, Liney, Linex + 29, Liney + 14, 0);
if (Linex == 22 && Liney == 16)
{
Linex = 76;
Liney = 1;
}
else if (Linex == 22 && Liney == 1)
{
Linex = 22;
Liney = 1;
}
else
Linex -= 54;
OLED_DrawSquar(Linex, Liney, Linex + 29, Liney + 14, 1);
break;
default:
break;
}
OLED_Refresh();
}
if (key_set == 0)
{
switch (Liney)
{
case 1:
switch (Linex)
{
case 22:
display_memory = 1;
break;
case 76:
display_memory = 2;
break;
}
break;
case 16:
switch (Linex)
{
case 22:
display_memory = 3;
break;
case 76:
display_memory = 4;
break;
}
break;
}
eeprom_dat[5] = display_memory;
Eeprom_updata(Start_addrs, &eeprom_dat, 6); // 掉电记录设置的电源电压
display_select(display_memory);
ET0 = 1;
OLED_Clear();
break;
}
}
}
//========================================================================
// 函数: void show_versionset(void)
// 描述: 显示版本信息
// 参数: none.
// 返回: none.
// 版本: V1.0, 2023-09-10
//========================================================================
void show_versionset(void)
{
OLED_Clear();
while (1)
{
OLED_ShowChar(37, 2, 'V', 16, 1);
OLED_ShowChar(55, 2, '1', 16, 1);
OLED_ShowChar(65, 2, '.', 16, 1);
OLED_ShowChar(75, 2, '1', 16, 1);
OLED_DrawLine(50, 25, 62, 25, 1);
OLED_ShowString(65, 22, "by whxnchy", 8, 1);
OLED_Refresh();
delay_ms(200);
if (key_set == 0)
{
ET0 = 1;
OLED_Clear();
break;
}
}
}
void display_select(int displaymemory)
{
if (displaymemory == 1)
{
OLED_ColorTurn(0);
OLED_DisplayTurn(0);
}
else if (displaymemory == 2)
{
OLED_ColorTurn(1);
OLED_DisplayTurn(0);
}
else if (displaymemory == 3)
{
OLED_ColorTurn(0);
OLED_DisplayTurn(1);
}
else if (displaymemory == 4)
{
OLED_ColorTurn(1);
OLED_DisplayTurn(1);
}
}
所有T12电烙铁的资源链接
链接:https://pan.baidu.com/s/1ONAqpAOg6m1XDOnHmrwoTg?pwd=zazw
提取码:zazw