This repository has been archived on 2024-05-05. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
ABS-Peripheral-Drive/硬件驱动/OLED显示屏/实现示例/STM32 HAL库/AbsDrive_OLED.c
2023-10-18 22:36:02 +08:00

563 lines
14 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.
/*文件AbsDrive_OLED.c
* 作者:你遇了我
* 联系321640253@qq.com
* 描述抽象硬件OLED屏幕只需要实现指定的抽象函数即可使用
* 使用1、根据配置区在抽象实现区按照要求实现对应函数
*/
#include "AbsDrive_OLED.h"
#include "AbsDriveOledFont.h"
/**************************抽象实现区(BEGIN)************************************/
/*抽象函数:写字节
*要求1实现一个写入多个字节的函数
*要求2返回一个AbsDriveOLED_STATE类型的状态
*参数1_data:写入的数据一个u8指针类型
*参数2_size写入多少个字节
*/
static AbsDriveOLED_STATE AbsOledWriteByte(u8 *_data,u8 _size){
/********************请实现抽象写字节函数********************/
if(HAL_SPI_Transmit(&hspi2,_data,_size,1000)==HAL_OK)return ABS_OLED_OK;else return ABS_OLED_ERROR;
/********************请实现抽象写字节函数********************/
return ABS_OLED_OK;
}
#ifdef Enable_ABS_OLED_RES
/*抽象函数:复位信号函数
*要求1根据电平值设置复位引脚电平
*参数1electrical_level:电平值1、高电平0、低电平
*/
static void AbsDriveOLED_RES(u8 electrical_level){
/********************请实现抽象复位信号函数********************/
if(electrical_level)HAL_GPIO_WritePin(oled_res_GPIO_Port,oled_res_Pin,GPIO_PIN_SET);
else HAL_GPIO_WritePin(oled_res_GPIO_Port,oled_res_Pin,GPIO_PIN_RESET);
/********************请实现抽象复位信号函数********************/
}
#endif
#ifdef Enable_ABS_OLED_Delay
/*抽象函数:延时函数
*要求1实现延时函数、
*参数1t:延时时间
*/
static void AbsOledDelay(u32 t){
/********************请实现抽象延时函数********************/
while(t--){} //默认循环while(t--){},可重写
/********************请实现抽象延时函数********************/
}
#endif
/**************************抽象实现区(END)**************************************/
/*----------------------------------------------分割线(以下内容非开发人员切勿改动)---------------------------------------------------------*/
u8 ABS_OLED_GRAM[ABS_OLED_WIDTH][ABS_OLED_PAGE_SIZE]; //定义显存
/*
*函数AbsOledWriteCMD
*功能写OLED命令
*参数ABScmd:命令
*返回值AbsDriveOLED_STATE状态
*/
AbsDriveOLED_STATE AbsOledWriteCMD(u8 ABScmd){
#ifdef ABSDrive_4SPI
HAL_GPIO_WritePin(oled_cs_GPIO_Port, oled_cs_Pin, GPIO_PIN_RESET);
if(AbsOledWriteByte(&ABScmd,1)==ABS_OLED_OK)return ABS_OLED_OK;
#endif
#ifdef ABSDrive_3SPI
#endif
return ABS_OLED_ERROR;
}
/*
*函数AbsOledWriteDATA
*功能写OLED数据
*参数ABScmd:OLED数据
*返回值AbsDriveOLED_STATE状态
*/
AbsDriveOLED_STATE AbsOledWriteDATA(u8 ABSdata){
#ifdef ABSDrive_4SPI
HAL_GPIO_WritePin(oled_cs_GPIO_Port, oled_cs_Pin, GPIO_PIN_SET);
if(AbsOledWriteByte(&ABSdata,1)==ABS_OLED_OK)return ABS_OLED_OK;
#endif
#ifdef ABSDrive_3SPI
#endif
return ABS_OLED_ERROR;
}
/*
*函数ABS_OLED_Refresh
*描述刷新OLED显存
*/
void ABS_OLED_Refresh(void)
{
u8 i,n;
for(i=0;i<ABS_OLED_PAGE_SIZE;i++)
{
AbsOledWriteCMD(0xB0+i);
AbsOledWriteCMD(0x00);
AbsOledWriteCMD(0x10);
for(n=0;n<ABS_OLED_WIDTH;n++)AbsOledWriteDATA(ABS_OLED_GRAM[n][i]);
}
}
void ABS_OLED_ColorTurn(u8 i)
{
if(i==0)
{
AbsOledWriteCMD(0xA6);
}
if(i==1)
{
AbsOledWriteCMD(0xA7);
}
}
void ABS_OLED_DisplayTurn(u8 i)
{
if(i==0)
{
AbsOledWriteCMD(0xC8);
AbsOledWriteCMD(0xA1);
}
if(i==1)
{
AbsOledWriteCMD(0xC0);
AbsOledWriteCMD(0xA0);
}
}
void ABS_OLED_DisPlay_On(void)
{
AbsOledWriteCMD(0x8D);
AbsOledWriteCMD(0x14);
AbsOledWriteCMD(0xAF);
}
void ABS_OLED_DisPlay_Off(void)
{
AbsOledWriteCMD(0x8D);
AbsOledWriteCMD(0x10);
AbsOledWriteCMD(0xAE);
}
/*函数ABS_OLED_Clear
**描述:清空屏幕显存并刷新屏幕
*/
void ABS_OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
for(n=0;n<128;n++)
{
ABS_OLED_GRAM[n][i]=0;
}
}
ABS_OLED_Refresh();
}
/*函数ABS_OLED_DrawPoint
**描述:按照坐标绘制一个点
**参数1xx坐标 取值返回小于ABS_OLED_WIDTH
**参数2yy坐标 取值返回小于ABS_OLED_HEIGHT
**参数3mode:绘制模式1填充0清空
*/
void ABS_OLED_DrawPoint(u8 x,u8 y,u8 mode)
{
u8 i,m,n;
i=y/8;
m=y%8;
n=1<<m;
if(mode){ABS_OLED_GRAM[x][i]|=n;}
else
{
ABS_OLED_GRAM[x][i]=~ABS_OLED_GRAM[x][i];
ABS_OLED_GRAM[x][i]|=n;
ABS_OLED_GRAM[x][i]=~ABS_OLED_GRAM[x][i];
}
}
/*函数ABS_OLED_DrawLine
**描述:按照起始坐标和结束坐标绘制直线
**参数1x1起始x坐标 取值返回小于ABS_OLED_WIDTH
**参数2y1起始y坐标 取值返回小于ABS_OLED_HEIGHT
**参数3x2结束x坐标 取值返回小于ABS_OLED_WIDTH
**参数4y2结束y坐标 取值返回小于ABS_OLED_HEIGHT
**参数5mode:绘制模式1填充0清空
*/
void ABS_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++)
{
ABS_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;
}
}
}
/*函数ABS_OLED_DrawCircle
**描述按照中心坐标绘制半径r的圆
**参数1x中心x坐标 取值返回小于ABS_OLED_WIDTH
**参数2y中心y坐标 取值返回小于ABS_OLED_HEIGHT
**参数3mode:绘制模式1填充0清空
*/
void ABS_OLED_DrawCircle(u8 x,u8 y,u8 r)
{
int a, b,num;
a = 0;
b = r;
while(2 * b * b >= r * r)
{
ABS_OLED_DrawPoint(x + a, y - b,1);
ABS_OLED_DrawPoint(x - a, y - b,1);
ABS_OLED_DrawPoint(x - a, y + b,1);
ABS_OLED_DrawPoint(x + a, y + b,1);
ABS_OLED_DrawPoint(x + b, y + a,1);
ABS_OLED_DrawPoint(x + b, y - a,1);
ABS_OLED_DrawPoint(x - b, y - a,1);
ABS_OLED_DrawPoint(x - b, y + a,1);
a++;
num = (a * a + b * b) - r*r;
if(num > 0)
{
b--;
a--;
}
}
}
/*函数ABS_OLED_ShowChar
**描述:在指定位置打印字符
**参数1x1起始x坐标 取值返回小于ABS_OLED_WIDTH
**参数2y1起始y坐标 取值返回小于ABS_OLED_HEIGHT
**参数3chr需要打印的字符
**参数4sizel打印字符的字体大小。字库有8*6、12*6、16*8、24*12
**参数5mode:打印模式1正常显示 0反向显示
*/
void ABS_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];}
else if(size1==12)
{temp=asc2_1206[chr1][i];} //12*06大小
else if(size1==16)
{temp=asc2_1608[chr1][i];} //16*08大小
else if(size1==24)
{temp=asc2_2412[chr1][i];} //24*12大小
else return;
for(m=0;m<8;m++)
{
if(temp&0x01)ABS_OLED_DrawPoint(x,y,mode);
else ABS_OLED_DrawPoint(x,y,!mode);
temp>>=1;
y++;
}
x++;
if((size1!=8)&&((x-x0)==size1/2))
{x=x0;y0=y0+8;}
y=y0;
}
}
/*函数ABS_OLED_ShowString
**描述:在指定位置打印字符串
**参数1x1起始x坐标 取值返回小于ABS_OLED_WIDTH
**参数2y1起始y坐标 取值返回小于ABS_OLED_HEIGHT
**参数3chr需要打印的字符
**参数4sizel打印字符的字体大小。字库有8*6、12*6、16*8、24*12
**参数5mode:打印模式1正常显示 0反向显示
*/
void ABS_OLED_ShowString(u8 x,u8 y,char *chr,u8 size1,u8 mode)
{
while((*chr>=' ')&&(*chr<='~'))
{
ABS_OLED_ShowChar(x,y,*chr,size1,mode);
if(size1==8)x+=6;
else x+=size1/2;
chr++;
}
}
/*函数ABS_OLED_Pow
**描述:内部函数,用于求次方
**参数1m底数
**参数2n指数
*/
static u32 ABS_OLED_Pow(u8 m,u8 n)
{
u32 result=1;
while(n--)
{
result*=m;
}
return result;
}
/*函数ABS_OLED_ShowNum
**描述:在指定位置打印数字
**参数1x1起始x坐标 取值返回小于ABS_OLED_WIDTH
**参数2y1起始y坐标 取值返回小于ABS_OLED_HEIGHT
**参数3num需要打印的数字
**参数3len数字长度几位数
**参数5sizel打印字符的字体大小。字库有8*6、12*6、16*8、24*12
**参数6mode:打印模式1正常显示 0反向显示
**/
void ABS_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/ABS_OLED_Pow(10,len-t-1))%10;
if(temp==0)
{
ABS_OLED_ShowChar(x+(size1/2+m)*t,y,'0',size1,mode);
}
else
{
ABS_OLED_ShowChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);
}
}
}
/*函数ABS_OLED_ShowChinese
**描述:在指定位置打印中文字符
**参数1x1起始x坐标 取值返回小于ABS_OLED_WIDTH
**参数2y1起始y坐标 取值返回小于ABS_OLED_HEIGHT
**参数3num在中文字库数组中的索引
**参数4sizel打印字符的字体大小。字库有16*16、32*32、64*64
**参数6mode:打印模式1正常显示 0反向显示
**/
void ABS_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==16)
{temp=Hzk1[num][i];}
else if(size1==24)
{temp=Hzk2[num][i];}
else if(size1==32)
{temp=Hzk3[num][i];}
else if(size1==64)
{temp=Hzk4[num][i];}
else return;
for(m=0;m<8;m++)
{
if(temp&0x01)ABS_OLED_DrawPoint(x,y,mode);
else ABS_OLED_DrawPoint(x,y,!mode);
temp>>=1;
y++;
}
x++;
if((x-x0)==size1)
{x=x0;y0=y0+8;}
y=y0;
}
}
/*函数ABS_OLED_ScrollDisplay
**描述:滚动显示中文字符
**参数1num显示汉字个数
**参数2space每遍显示的间隔
**参数3mode:打印模式1正常显示 0反向显示
**/
void ABS_OLED_ScrollDisplay(u8 num,u8 space,u8 mode)
{
u8 i,n,t=0,m=0,r;
while(1)
{
if(m==0)
{
ABS_OLED_ShowChinese(128,24,t,16,mode);
t++;
}
if(t==num)
{
for(r=0;r<16*space;r++)
{
for(i=1;i<144;i++)
{
for(n=0;n<8;n++)
{
ABS_OLED_GRAM[i-1][n]=ABS_OLED_GRAM[i][n];
}
}
ABS_OLED_Refresh();
}
t=0;
}
m++;
if(m==16){m=0;}
for(i=1;i<144;i++)
{
for(n=0;n<8;n++)
{
ABS_OLED_GRAM[i-1][n]=ABS_OLED_GRAM[i][n];
}
}
ABS_OLED_Refresh();
}
}
/*函数ABS_OLED_ShowPicture
**描述:显示图片
**参数1x1起始x坐标 取值返回小于ABS_OLED_WIDTH
**参数2y1起始y坐标 取值返回小于ABS_OLED_HEIGHT
**参数3sizex图片的长
**参数4sizey图片的高
**参数5BMP[]:要写入的图片数组
**参数6mode打印模式1正常显示 0反向显示
**/
void ABS_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)ABS_OLED_DrawPoint(x,y,mode);
else ABS_OLED_DrawPoint(x,y,!mode);
temp>>=1;
y++;
}
x++;
if((x-x0)==sizex)
{
x=x0;
y0=y0+8;
}
y=y0;
}
}
}
/*
*函数ABS_OLED_Init
*功能初始化OLED
*/
void ABS_OLED_Init(void)
{
#ifdef Enable_ABS_OLED_RES
AbsDriveOLED_RES(0); //复位
#endif
#ifdef Enable_ABS_OLED_Delay
AbsOledDelay(3); //延时
#endif
#ifdef Enable_ABS_OLED_RES
AbsDriveOLED_RES(1); //启用正常工作
#endif
AbsOledWriteCMD(CMD_OFF_OLED); //关闭OLED屏幕、单次命令
AbsOledWriteCMD(CMD_Memory_Addr_Mode_OLED); //设置内存寻址模式;连续命令
AbsOledWriteCMD(0x10); //00水平寻址模式;01、垂直寻址模式;10、页面寻址模式重置;11、无效
AbsOledWriteCMD(0xB0); //Set Page Start Address for Page Addressing Mode,0-7
AbsOledWriteCMD(0xC8); //Set COM Output Scan Direction
AbsOledWriteCMD(CMD_LColAddr_OLED); //---set low column address
AbsOledWriteCMD(CMD_HColAddr_OLED); //---set high column address
AbsOledWriteCMD(0x40); //--set start line address
AbsOledWriteCMD(CMD_Set_Contrast_Control_OLED); //--set contrast control register
AbsOledWriteCMD(0xFF);
AbsOledWriteCMD(0xA1); //--set segment re-map 0 to 127
AbsOledWriteCMD(CMD_Normal_display_OLED); //--set normal display
AbsOledWriteCMD(0xA8); //--set multiplex ratio(1 to 64)
AbsOledWriteCMD(0x3F); //
AbsOledWriteCMD(CMD_EntireDisplay_OLED); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
AbsOledWriteCMD(0xD3); //-set display offset
AbsOledWriteCMD(CMD_LColAddr_OLED); //-not offset
AbsOledWriteCMD(0xD5); //--set display clock divide ratio/oscillator frequency
AbsOledWriteCMD(0xF0); //--set divide ratio
AbsOledWriteCMD(0xD9); //--set pre-charge period
AbsOledWriteCMD(0x22); //
AbsOledWriteCMD(0xDA); //--set com pins hardware configuration
AbsOledWriteCMD(0x12);
AbsOledWriteCMD(0xDB); //--set vcomh
AbsOledWriteCMD(CMD_Memory_Addr_Mode_OLED); //0x20,0.77xVcc
AbsOledWriteCMD(0x8D); //--set DC-DC enable
AbsOledWriteCMD(0x14); //
AbsOledWriteCMD(CMD_ON_OLED); //--turn on SSD1306 panel
ABS_OLED_Clear();
}
ABS_OLED_Drive Create_OLED(void){
ABS_OLED_Drive drive;
drive.Clear = ABS_OLED_Clear;
drive.Refresh=ABS_OLED_Refresh;
drive.DrawPoint=ABS_OLED_DrawPoint;
drive.DrawLine=ABS_OLED_DrawLine;
drive.DrawCircle=ABS_OLED_DrawCircle;
drive.ShowString=ABS_OLED_ShowString;
drive.ShowChinese=ABS_OLED_ShowChinese;
drive.ShowNum=ABS_OLED_ShowNum;
drive.ShowImage=ABS_OLED_ShowPicture;
ABS_OLED_Init();
return drive;
}