Files
morse_code_trainer/f103c8t6_keil/MDK-ARM/MYDEIVERS/oled.c
T
2022-08-18 18:01:08 +08:00

493 lines
8.2 KiB
C

/*
* oled.c
*
* Created on: 2022年4月15日
* Author: wuwen
*/
#include "oled.h"
#include "fonts.h"
/*
通过IIC发送指令到OLED
*/
void OLED_WrCmd(unsigned char IIC_Command)
{
uint8_t *pData;
pData = &IIC_Command;
IIC_SAND_DATE(OLED_ADDRESS,0x00,pData,1);
}
/*
通过IIC发送数据到OLED
*/
void OLED_WrDat(unsigned char IIC_Data)
{
uint8_t *pData;
pData = &IIC_Data;
IIC_SAND_DATE(OLED_ADDRESS,0x40,pData,1);
}
/*
设置硬件内的光标
*/
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WrCmd( 0xb0 + 7-y );
OLED_WrCmd(((x&0xf0)>>4)|0x10);
OLED_WrCmd( (x&0x0f) |0x00);
}
/*
初始化硬件内存(显存)
*/
void OLED_Init_Display_Buffer(char a)
{
for(unsigned char y = 0;y < Y_WIDTH_;y++)
{
OLED_Set_Pos(0,y);
for(unsigned char x = 0;x < X_WIDTH;x++)
{
OLED_WrDat(a);
//HAL_Delay(1);
}
}
}
/*
设置屏幕亮度
*/
void OLED_Setting_luminance(unsigned char a)
{
OLED_WrCmd(0x81);
OLED_WrCmd(a*2.55);
}
/*
初始化OLED
硬件扫描方式
从左到右从上到下
纵向8点上高位
*/
void OLED_Init(void)
{
//HAL_Delay(200);
OLED_WrCmd(0xAE); //关闭显示
OLED_WrCmd(0xD5); //设置时钟分频因子,震荡频率
OLED_WrCmd( 80); //[3:0],分频因子;[7:4],震荡频率
OLED_WrCmd(0xA8); //设置驱动路数
OLED_WrCmd(0X3F); //默认0X3F(1/64)
OLED_WrCmd(0xD3); //设置显示偏移
OLED_WrCmd(0X00); //默认为0
OLED_WrCmd(0x40); //设置显示开始行 [5:0],行数.
OLED_WrCmd(0x8D); //电荷泵设置
OLED_WrCmd(0x14); //bit2,开启/关闭
OLED_WrCmd(0x20); //设置内存地址模式
OLED_WrCmd(0x02); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
OLED_WrCmd(0xA1); //段重定义设置,bit0:0,0->0;1,0->127;
OLED_WrCmd(0xC0); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
//OLED_WrCmd(0xDA); //设置COM硬件引脚配置
//OLED_WrCmd(0x12); //[5:4]配置
//显示方向设置
//OLED_WrCmd(0xc8);//OLED_WrCmd(0xa0);
//行扫描顺序:从上到下
//列扫描顺序:从左到右
OLED_WrCmd(0xD9); //设置预充电周期
OLED_WrCmd(0xf1); //[3:0],PHASE 1;[7:4],PHASE 2;
OLED_WrCmd(0xDB); //设置VCOMH 电压倍率
OLED_WrCmd(0x30); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
OLED_WrCmd(0xA4); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
OLED_WrCmd(0xA6);
//设置显示方式;bit0:1,反相显示;0,正常显示
OLED_WrCmd(0xAF); //开启显示
OLED_Init_Display_Buffer(0);
}
/*************************************************************************************************************************************************************************************/
/*硬件与软件之间的部分*/
/*
定义显存
*/
char OLED_buff[Y_WIDTH_][X_WIDTH];
/*
加速缓存
*/
char OLED_speedup[Y_WIDTH_][X_WIDTH];
/*
将显存发送到硬件
*/
void OLED_Cache_to_hardware()
{
char b=0;
for(uint8_t y=0;y<Y_WIDTH_;y++)
{
OLED_Set_Pos(0,y);
for(uint8_t x=0;x<X_WIDTH;x++)
{
if(OLED_buff[y][x]!=OLED_speedup[y][x])
{
if(b==0){b=1;OLED_Set_Pos(x,y);}
OLED_WrDat(OLED_buff[y][x]);
OLED_speedup[y][x]=OLED_buff[y][x];
}else
{b=0;}
OLED_buff[y][x]=0x00;
}
}
}
/*
打点函数
打点类型
dot_type=0 清除点
=1 打点
=2 取反点
*/
void OLED_set_dot(unsigned char x,unsigned char y,unsigned char dot_type)
{
if(x>=X_WIDTH||y>=Y_WIDTH)
{
return ;
}
uint8_t y1=y/8;
uint8_t y2=y%8;
uint8_t y3=(0x80>>y2);
char temp=OLED_buff[y1][x];
switch(dot_type)
{
case 0:
temp &= ~y3;
break;
case 1:
temp |= y3;
break;
case 2:
temp ^= y3;
break;
case 3:break;
}
OLED_buff[y1][x]=temp;
}
/*
绘图函数
数据格式 从左到右,从上到下,横向8点右高位
type=0 清空区域
=1 区域图层
=2 正片叠底
=3 正片清空
=4 负片
=5 正片负片
*/
void OLED_Pix(unsigned char x,unsigned char y,unsigned char w,unsigned char h,const char *p,unsigned char type)
{
unsigned char b=0;
unsigned int c=0;
for(uint8_t h1=0;h1<h;h1++)
{
for(uint8_t w1=0;w1<w;w1++)
{
if(p[c]&0x80>>b)
{
switch(type)
{
case 0:
OLED_set_dot(w1+x,h1+y,0);
break;
case 1:
OLED_set_dot(w1+x,h1+y,1);
break;
case 2:
OLED_set_dot(w1+x,h1+y,1);
break;
case 3:
OLED_set_dot(w1+x,h1+y,0);
break;
case 4:
OLED_set_dot(w1+x,h1+y,0);
break;
case 5:
OLED_set_dot(w1+x,h1+y,2);
break;
}
}else
{
switch(type)
{
case 0:
OLED_set_dot(w1+x,h1+y,0);
break;
case 1:
OLED_set_dot(w1+x,h1+y,0);
break;
case 2:
break;
case 4:
OLED_set_dot(w1+x,h1+y,1);
break;
}
}
b++;
if(b==8)
{
b=0;c++;
}
}
if(b!=0)
{
b=0;c++;
}
}
}
/*
显示字符
数据格式 从左到右,从上到下,横向8点左高位 (同一个函数实现的显示不知道为何这里要用左高位才能正常显示)
type=0 清空区域
=1 区域图层
=2 正片叠底
=3 正片清空
=4 负片
*/
void OLED_Ascii(unsigned char x,unsigned char y,unsigned char size,char *chr,unsigned char type)
{
if(*chr>=' '&&*chr<='~')
{
switch(size)
{
case 8:
OLED_Pix(x,y,5,8,asc2_0805[*chr-' '],type);
break;
case 12:
OLED_Pix(x,y,6,12,asc2_1206[*chr-' '],type);
break;
case 16:
OLED_Pix(x,y,8,16,asc2_1608[*chr-' '],type);
break;
}
}
}
void OLED_Ch(unsigned char x,unsigned char y,unsigned char size,char *chr,unsigned char type)
{
unsigned int a=0,b=0;
while(chfonst1616_index[a]!='\0')
{
if(chfonst1616_index[a]==chr[0]&&chfonst1616_index[a+1]==chr[1])
{
b=a/2;
break;
}
a+=2;
}
OLED_Pix(x,y,16,16,chfonst1616[b],type);
}
void OLED_Str(unsigned char x,unsigned char y,unsigned char size,char *str,unsigned char lenconst,unsigned char type)
{
unsigned char size2;
unsigned char tempx=x;
unsigned char templenstard=1;
switch(size)
{
case 8:
size2=6;
break;
case 12:
size2=7;
break;
case 16:
size2=8;
break;
}
while(*str!='\0')
{
if((x+size2>=X_WIDTH)||(*str=='\n'))
{
if(lenconst!=0)
{
if(templenstard>=lenconst)
{
return;
}
}
templenstard++;
y+=size;
if(y>=Y_WIDTH)
{
//y=0;
return;
}
x=tempx;
}else
{
if(*str<127)
{
OLED_Ascii(x,y,size,str,type);
x+=size2;
}else
{
OLED_Ch(x,y,size,str,type);
str++;
x+=16;
}
}
str++;
}
}
void OLED_Str_list(unsigned char x,unsigned char y,unsigned char size,char *str,unsigned char lenstard,unsigned char lenconst,unsigned char type)
{
unsigned char templenstard=0;
while(templenstard!=lenstard)//跳转到指定行
{
switch(*str)
{
case '\n': //如果是回车 行加加
templenstard++;
break;
case '\0': //如果字符串提前结束 报错 直接返回
return;
}
str++;
}
OLED_Str(x,y,size,str,lenconst,type);
}
/*
几何绘图
*/
/*画横线*/
void OLED_HL(unsigned char x,unsigned char y,unsigned char size,unsigned char dot_type)
{
}
/*画竖线*/
void OLED_VL(unsigned char x,unsigned char y,unsigned char size,unsigned char dot_type)
{
}
/*画任意线*/
void OLED_AL(int sx,int sy,int ex,int ey,unsigned char dot_type)
{
int dx,dy,absx,absy;
//计算差
dx=ex-sx;
dy=ey-sy;
//取绝对值 就是轴长
absx=dx<0?0-dx:dx;
absy=dy<0?0-dy:dy;
if(dx==0)
{
if(dy>0)
{
for(int y=ey;y>sy;y--)
{
OLED_set_dot(sx,y,dot_type);
}
}else
if(dy<0)
{
for(int y=ey;y<sy;y++)
{
OLED_set_dot(sx,y,dot_type);
}
}
return ;
}
if(dy==0)
{
if(dx>0)
{
for(int x=ex;x>sx;x--)
{
OLED_set_dot(x,sy,dot_type);
}
}else
if(dx<0)
{
for(int x=ex;x<sx;x++)
{
OLED_set_dot(x,sy,dot_type);
}
}
return ;
}
if(dx==0&&dy==0)
{
//OLED_set_dot(sx,sy,dot_type);
return ;
}
}
/*画方框*/
void OLED_square(int Start_x, int Start_y, int End_x, int End_y, char type)
{
if(Start_x > End_x){int i1 = Start_x; Start_x = End_x; End_x=i1;}
if(Start_y > End_y){int i1 = Start_y; Start_y = End_y; End_y=i1;}
for(; Start_x < End_x ; Start_x++)
{
for(int y2 = Start_y ; y2 < End_y ; y2++)
{
OLED_set_dot(Start_x, y2, type);
}
}
}