/**
- @file oled.c
- @Software IAR 8.3 or MDK 5.28
- @Target CW32F030C8T6
- @author
- @date 2023-0617 */
#include "oled_iic.h" #include "oled_font.h"
//OLED的显存 //存放格式如下. //[0]0 1 2 3 ... 127 //[1]0 1 2 3 ... 127 //[2]0 1 2 3 ... 127 //[3]0 1 2 3 ... 127 //[4]0 1 2 3 ... 127 //[5]0 1 2 3 ... 127 //[6]0 1 2 3 ... 127 //[7]0 1 2 3 ... 127
/引脚初始化/ void OLED_I2C_Init(void) { __RCC_GPIOB_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.IT = GPIO_IT_NONE;
GPIO_InitStructure.Pins = OLED_SCL_PIN;
GPIO_Init(OLED_SCL_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pins = OLED_SDA_PIN;
GPIO_Init(OLED_SDA_PORT, &GPIO_InitStructure);
}
/********************************************** //IIC Start **********************************************/ void OLED_IIC_Start() { OLED_SCL_HIGH(); OLED_SDA_HIGH(); OLED_SDA_LOW(); OLED_SCL_LOW(); }
/********************************************** //IIC Stop **********************************************/ void OLED_IIC_Stop() { OLED_SCL_HIGH() ; // OLED_SCL_LOW(); OLED_SDA_LOW(); OLED_SDA_HIGH(); }
/********************************************** //OLED_IIC_WaitAck **********************************************/ void OLED_IIC_WaitAck() {
//GPIOB->CRH &= 0XFFF0FFFF; //设置PB12为上拉输入模式
//GPIOB->CRH |= 0x00080000;
// OLED_SDA = 1; // delay_us(1); //OLED_SCL = 1; //delay_us(50000); /* while(1) { if(!OLED_SDA) //判断是否接收到OLED 应答信号 { //GPIOB->CRH &= 0XFFF0FFFF; //设置PB12为通用推免输出模式 //GPIOB->CRH |= 0x00030000; return; } } / OLED_SCL_HIGH() ; OLED_SCL_LOW(); } /********************************************* // IIC Write byte / void OLED_IIC_WriteByte(uint8_t IIC_Byte) { uint8_t i; uint8_t m,da; da=IIC_Byte; OLED_SCL_LOW(); for(i=0;i<8;i++) { m=da; m=m&0x80; if(m==0x80) OLED_SDA_HIGH(); else OLED_SDA_LOW(); da=da<<1; OLED_SCL_HIGH(); OLED_SCL_LOW(); } } / // IIC Write Command / void OLED_IIC_WriteCommand(uint8_t IIC_Command) { OLED_IIC_Start(); OLED_IIC_WriteByte(0x78); //Slave address,SA0=0 地址位 OLED_IIC_WaitAck(); OLED_IIC_WriteByte(0x00); //write command OLED_IIC_WaitAck(); OLED_IIC_WriteByte(IIC_Command); OLED_IIC_WaitAck(); OLED_IIC_Stop(); } / // IIC Write Data / void OLED_IIC_WriteData(uint8_t IIC_Data) { OLED_IIC_Start(); OLED_IIC_WriteByte(0x78); //D/C#=0; R/W#=0 地址位 OLED_IIC_WaitAck(); OLED_IIC_WriteByte(0x40); //write data OLED_IIC_WaitAck(); OLED_IIC_WriteByte(IIC_Data); OLED_IIC_WaitAck(); OLED_IIC_Stop(); } /// //// OLED_WR_Byte //**********************************************/ void OLED_WR_Byte(unsigned dat,unsigned cmd) { OLED_IIC_Start(); OLED_IIC_WriteByte(0x78); //D/C#=0; R/W#=0 OLED_IIC_WaitAck(); OLED_IIC_WriteByte(cmd); OLED_IIC_WaitAck(); OLED_IIC_WriteByte(dat); OLED_IIC_WaitAck(); OLED_IIC_Stop(); }
/******************************************** // OLED_FillPicture ********************************************/ void OLED_FillPicture(uint8_t fill_Data) { uint8_t m,n; for(m=0;m<8;m++) { OLED_WR_Byte(0xb0+m,OLED_CMD); //page0-page1 OLED_WR_Byte(0x00,OLED_CMD); //low column start address OLED_WR_Byte(0x10,OLED_CMD); //high column start address for(n=0;n<128;n++) { OLED_WR_Byte(fill_Data,OLED_DATA); } } }
/*********************** 坐标设置 ***********************/
void OLED_SetPos(uint8_t x, uint8_t 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)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
} //更新显示
}
//开启OLED显示
void OLED_DisplayOn(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON
OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON
}
//关闭OLED显示
void OLED_DisplayOff(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF
OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF
}
//
void OLED_On(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA);
} //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 16/8
void OLED_ShowChar(uint8_t x,uint8_t y, const uint8_t chr,uint8_t size)
{
uint8_t i=0;
if(x>Max_Column-1){x=0;y=y+2;}
if(size == SIZE_8X16)
{
OLED_SetPos(x,y);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[chr-' '][i],OLED_DATA);
OLED_SetPos(x,y+1);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[chr-' '][i+8],OLED_DATA);
}
if(size == SIZE_6X8)
{
OLED_SetPos(x,y);
for(i=0;i<6;i++)
OLED_WR_Byte(F6X8[chr-' '][i],OLED_DATA);
}
}
//m^n函数
uint32_t OLED_Pow(uint8_t m,uint8_t n)
{
uint32_t result=1;
while(n--)result*=m;
return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式 0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/OLED_Pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size/2)*t,y,' ',size);
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size/2)*t,y,temp+'0',size);
}
}
//显示一个字符号串
void OLED_ShowString(uint8_t x,uint8_t y,const uint8_t *str,uint8_t size)
{
uint8_t j=0;
while (str[j]!='\0')
{
OLED_ShowChar(x,y,str[j],size);
x+=8;
if(x>120) {x=0;y+=2;}
j++;
}
}
//显示汉字
void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t *chin, uint8_t size)
{
uint8_t i = 0;
if(size == SIZE_GB16)
{
while (chin[i]!='\0')
{
OLED_ShowGB16(x,y,chin+i);
x+=16;
if(x>120) {x=0; y+=2;}
i += 2;
}
}
if(size == SIZE_GB24)
{
while (chin[i]!='\0')
{
OLED_ShowGB24(x,y,chin+i);
x+=24;
if(x>120) {x=0; y+=3;}
i += 2;
}
}
}
void OLED_ShowGB16(uint8_t x, uint8_t y,uint8_t *chin) { uint8_t i,j;
for(i=0; i<GB_16_NUM; i++)
{
if((FGB16[i].Index[0]==*chin)&&(FGB16[i].Index[1]==*(chin+1)))
{
OLED_SetPos(x, y);
for(j=0; j<16; j++)
{
OLED_WR_Byte(FGB16[i].Msk[j],OLED_DATA);
}
OLED_SetPos(x, y+1);
for(j=0; j<16; j++)
{
OLED_WR_Byte(FGB16[i].Msk[16+j],OLED_DATA);
}
break;
}
}
}
void OLED_ShowGB24(uint8_t x, uint8_t y,uint8_t *chin) { uint8_t i,j;
for(i=0; i<GB_24_NUM; i++)
{
if((FGB24[i].Index[0]==*chin)&&(FGB24[i].Index[1]==*(chin+1)))
{
OLED_SetPos(x, y);
for(j=0; j<24; j++)
{
OLED_WR_Byte(FGB24[i].Msk[j],OLED_DATA);
}
OLED_SetPos(x, y+1);
for(j=0; j<24; j++)
{
OLED_WR_Byte(FGB24[i].Msk[24+j],OLED_DATA);
}
OLED_SetPos(x, y+2);
for(j=0; j<24; j++)
{
OLED_WR_Byte(FGB24[i].Msk[48+j],OLED_DATA);
}
break;
}
}
}
/功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7******/ void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint8_t BMP[]) { unsigned int j=0; uint8_t x,y;
if(y1%8==0) y = y1 / 8;
else y = y1/8 + 1;
for(y=y0;y<y1;y++)
{
OLED_SetPos(x0,y);
for(x=x0;x<x1;x++)
{
OLED_WR_Byte(BMP[j++],OLED_DATA);
}
}
}
//初始化SSD1306
void OLED_Init(void)
{
OLED_I2C_Init();
delay_ms(800);
OLED_WR_Byte(0xAE,OLED_CMD);//--display off
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address
OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
OLED_WR_Byte(0x81,OLED_CMD); // contract control
OLED_WR_Byte(0xFF,OLED_CMD);//--128
OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
OLED_WR_Byte(0x00,OLED_CMD);//
OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
OLED_WR_Byte(0x80,OLED_CMD);//
OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
OLED_WR_Byte(0x05,OLED_CMD);//
OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
OLED_WR_Byte(0xF1,OLED_CMD);//
OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
OLED_WR_Byte(0x12,OLED_CMD);//
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(0x14,OLED_CMD);//
OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
OLED_Clear();
}