Files
TXH1.0/User/OLED/oled.c
T
2026-04-27 16:55:02 +08:00

450 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "config.h"
#include "oledfont.h"
u8 OLED_GRAM[144][8];
//反显函数
void OLED_ColorTurn(u8 i)
{
if(i==0)
{
OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
}
if(i==1)
{
OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
}
}
//屏幕旋转180度
void OLED_DisplayTurn(u8 i)
{
if(i==0)
{
OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
OLED_WR_Byte(0xA1,OLED_CMD);
}
if(i==1)
{
OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
OLED_WR_Byte(0xA0,OLED_CMD);
}
}
/****************************************************
函数名:OLED_SPI2_SendByte
功能 :FM存储部分用到的SPI发送函数
参数 dt 要发送的数据
返回值:无
****************************************************/
u8 OLED_SPI2_SendByte(u8 dt)
{
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI2, dt);
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI2);
}
void OLED_WR_Byte(u8 dat,u8 cmd)
{
if(cmd)
OLED_DC_Set();
else
OLED_DC_Clr();
OLED_CS_Clr();
OLED_SPI2_SendByte(dat);
OLED_CS_Set();
OLED_DC_Set();
}
//开启OLED显示
void OLED_DisPlay_On(void)
{
OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
}
//关闭OLED显示
void OLED_DisPlay_Off(void)
{
OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕
}
//更新显存到OLED 1.8ms
void OLED_Refresh(void)
{
u8 i=0,n=0;
OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
OLED_WR_Byte(0x00,OLED_CMD); //设置低列起始地址
OLED_WR_Byte(0x10,OLED_CMD); //设置高列起始地址
for(i=0;i<8;i++)
{
for(n=0;n<128;n++)
OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
}
}
//清屏函数
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
for(n=0;n<128;n++)
{
OLED_GRAM[n][i]=0;//清除所有数据
}
}
//OLED_Refresh();//更新显示
}
//画点
//x:0~127
//y:0~63
//t:1 填充 0,清空
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];
}
}
//画线
//x1,y1:起点坐标
//x2,y2:结束坐标
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;
}
}
}
//x,y:圆心坐标
//r:圆的半径
void OLED_DrawCircle(u8 x,u8 y,u8 r)
{
int a, b,num;
a = 0;
b = r;
while(2 * b * b >= r * r)
{
OLED_DrawPoint(x + a, y - b,1);
OLED_DrawPoint(x - a, y - b,1);
OLED_DrawPoint(x - a, y + b,1);
OLED_DrawPoint(x + a, y + b,1);
OLED_DrawPoint(x + b, y + a,1);
OLED_DrawPoint(x + b, y - a,1);
OLED_DrawPoint(x - b, y - a,1);
OLED_DrawPoint(x - b, y + a,1);
a++;
num = (a * a + b * b) - r*r;//计算画的点离圆心的距离
if(num > 0)
{
b--;
a--;
}
}
}
void OLED_DrawArc(int rx,int ry,int r, int j)
{
float x, y,i = 0;
float angleInRadians = j * (3.1415926 / 180.0); // 将角度转换为弧度
float startAngle = -angleInRadians / 2.0; // 计算起始角度(弧度)
float endAngle = angleInRadians / 2.0; // 计算结束角度(弧度)
float increment = (endAngle - startAngle) / 20.0;
for (i = startAngle; i <= angleInRadians; i += increment) {
x = rx + (r * sin(i));
y = ry - (r * cos(i)); // 注意Y轴的方向可能需要根据你的显示设备调整
OLED_DrawPoint(x, y, 1); // 绘制点,假设WHITE是你要使用的颜色
}
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//size1:选择字体 6x8/6x12/8x16/12x24
//mode:0,反色显示;1,正常显示
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==12)
{temp=asc2_1206[chr1][i];} //调用1206字体
else if(size1==16)
{temp=asc2_1608[chr1][i];} //调用1608字体
else if(size1==24)
{temp=asc2_2412[chr1][i];} //调用2412字体
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;
}
}
//显示字符串
//x,y:起点坐标
//size1:字体大小
//*chr:字符串起始地址
//mode:0,反色显示;1,正常显示
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Maxlen,u8 size1,u8 mode)
{
while(Maxlen && (*chr>=' ') && (*chr<='~'))//判断是不是非法字符!
{
OLED_ShowChar(x,y,*chr,size1,mode);
if(size1==8)x+=6;
else x+=size1/2;
chr++;
Maxlen --;
}
}
//显示进度条
//x,y:起点坐标
//sizex:长
//sizex:宽
//Num进度
//mode:0,反色显示;1,正常显示
void OLED_ProgressBar(u8 x,u8 y,u8 sizex,u8 sizey,u8 num,u8 mode)
{
u8 Setp = sizex * num / 100;
u8 i = 0;
OLED_DrawLine(x,y,x+sizex,y,1);
OLED_DrawLine(x,y+sizey,x+sizex,y+sizey,1);
OLED_DrawLine(x,y,x,y+sizey,1);
OLED_DrawLine(x+sizex,y,x+sizex,y+sizey,1);
for(i = 0;i < sizey;i ++)
{
OLED_DrawLine(x,y+i,x+Setp,y+i,1);
}
}
//m^n
u32 OLED_Pow(u8 m,u8 n)
{
u32 result=1;
while(n--)
{
result*=m;
}
return result;
}
//显示数字
//x,y :起点坐标
//num :要显示的数字
//len :数字的位数,0表示自适应
//size:字体大小
//mode:0,反色显示;1,正常显示
//u8 OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode)
//{
// u8 t,temp,m=0;
// if(len == 0)
// len = (int)(log10(num) + 1);
// 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);
// }
// }
// return len;
//}
u8 OLED_ShowNum(u8 x, u8 y, u32 num, u8 len, u8 Dec, u8 size1, u8 mode)
{
u8 t, temp, m = 0,d = 0;
if(len == 0)
len = (int)(log10(num) + 1);
//if(Dec)len++;
if (size1 == 8)
m = 2;
if(len <= Dec && Dec > 0)
{
OLED_ShowChar(x, y, '0', size1, mode);
x += (size1 / 2 + m);
}
for(t = 0; t < len+d; t++)
{
if(t == len - Dec)
{ // 判断是否到了小数点位置
OLED_ShowChar(x + (size1 / 2 + m) * t, y, '.', size1, mode); // 显示小数点
d = 1;
continue;
}
// if(t >= len - Dec)
// d = 1;
// else
// d = 0;
temp = (num / OLED_Pow(10, len+d - t - 1)) % 10;
if(temp == 0)
{
OLED_ShowChar(d + x + (size1 / 2 + m) * t, y, '0', size1, mode);
}
else
{
OLED_ShowChar(d + x + (size1 / 2 + m) * t, y, temp + '0', size1, mode);
}
}
return len;
}
//x,y:起点坐标
//sizex,sizey,图片长宽
//BMP[]:要写入的图片数组
//mode:0,反色显示;1,正常显示
void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode)
{
u16 j=0;
u8 i,n,temp,m;
u8 x0=x,y0=y;
sizey=sizey/8+((sizey%8)?1:0);
for(n=0;n<sizey;n++)
{
for(i=0;i<sizex;i++)
{
temp=BMP[j];
j++;
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)==sizex)
{
x=x0;
y0=y0+8;
}
y=y0;
}
}
}
//OLED的初始化
void OLED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOB,ENABLE);//使能PORTA~E,PORTG时钟
//GPIO初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化
//GPIO初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
delay_ms(200);
OLED_RES_Clr();
delay_ms(200);
OLED_RES_Set();
delay_ms(200);
OLED_WR_Byte(0xFD,OLED_CMD);
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
OLED_WR_Byte(0xA0,OLED_CMD);
OLED_WR_Byte(0xA8,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(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
if(TXHData.HardwareVersion > 31)//24-31是大板,32-38是小板
{
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正常
}
else
{
OLED_WR_Byte(0xA0,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常
OLED_WR_Byte(0xC0,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常
}
OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
OLED_WR_Byte(0x7F,OLED_CMD);// Set SEG Output Current Brightness
OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
OLED_WR_Byte(0x82,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
OLED_WR_Byte(0x34,OLED_CMD);//Set VCOM Deselect Level
OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_WR_Byte(0x20,OLED_CMD);
OLED_WR_Byte(0x00,OLED_CMD);
OLED_Clear();
OLED_WR_Byte(0xAF,OLED_CMD);
//OLED_ShowPicture(0,0,128,64,BMP1,1);
OLED_Refresh();
}