/******************************************************************
编 译 器:Haawking IDE V0.1.2
D S P:dsc28034湖人板
电 脑 配 置:Windows10 专业版; 64 位操作系统
仿 真 器:HX100v2
使 用 库:无
作 用:在OLED屏上显示文字及数字
说 明:无
版 本:V0.0.1
******************************************************************/
OLED屏资料:
链接:https://pan.baidu.com/s/1sQlrV6J09XKWtcQlFHXdXQ
提取码:8034
四针的OLED屏用IIC来写,原理在资料中 ,再结合以下例程,定能够轻松上手:
IIC_OLED.c、
//GPIO配置
void I2C_GPIO_Config_OLED(void)
{
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO14 = 0;
GpioCtrlRegs.GPAPUD.bit.GPIO15 = 0;
GpioCtrlRegs.GPAQSEL1.bit.GPIO14 = 3;
GpioCtrlRegs.GPAQSEL1.bit.GPIO15 = 3;
GpioCtrlRegs.GPADIR.bit.GPIO14 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO15 = 1;
GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 0;
GpioCtrlRegs.GPAMUX1.bit.GPIO15 = 0;
GpioDataRegs.GPASET.bit.GPIO14 = 1;
GpioDataRegs.GPASET.bit.GPIO15 = 1;
EDIS;
}
//得到输入数字的长度
int Data_len(int data)
{
int n=0;
if(data==0)
return ++n;
while(data!=0)
{
n++;
data/=10;
}
return n;
}
//延时
void I2C_OLED_delay(void) //延时函数
{
int i =50;
while(i)
{
i--;
}
}
//延时
void I2C_OLED_delay_more(void)
{
int i =200;
while(i)
{
i--;
}
}
//以GPIO14为SCL,GPIO15为SDA向OLED模块传送起始位
bool I2C_OLED_start(void)//IIC起始位
{
SDA1_H;
SCL1_H;
I2C_OLED_delay();
if(!SDA1_read)//SDA线为低电平,总线忙,退出
{
return 0;
}
SDA1_L;
I2C_OLED_delay();
if(SDA1_read)//SDA线为高电平则总线出错,退出
{
return 0;
}
SDA1_L;
I2C_OLED_delay();
return 1;
}
//以GPIO14为SCL,GPIO15为SDA向OLED模块传送停止位
void I2C_OLED_stop(void)
{
SCL1_L;
I2C_OLED_delay();
SDA1_L;
I2C_OLED_delay();
SCL1_H;
I2C_OLED_delay();
SDA1_H;
}
//以GPIO14为SCL,GPIO15为SDA向OLED模块传送响应位
void I2C_OLED_ack(void)
{
SCL1_L;
I2C_OLED_delay();
SDA1_L;
I2C_OLED_delay();
SCL1_H;
I2C_OLED_delay();
SCL1_L;
I2C_OLED_delay();
}
//以GPIO14为SCL,GPIO15为SDA向OLED模块传送不响应位
void I2C_OLED_noack(void)//不响应位
{
SCL1_L;
I2C_OLED_delay();
SDA1_H;
I2C_OLED_delay();
SCL1_H;
I2C_OLED_delay();
SCL1_L;
I2C_OLED_delay();
}
//接受ACK,有返回1,无返回0
bool I2C_OLED_WaitAck(void)//0无ACK,1有ACK
{
EALLOW;
GpioCtrlRegs.GPADIR.bit.GPIO15 = 0; //配置GPIO15(SDA)为输入模式
SCL1_L;
I2C_OLED_delay();
SDA1_H;
I2C_OLED_delay();
SCL1_H;
I2C_OLED_delay();
if(SDA1_read)
{
SCL1_L;
I2C_OLED_delay();
return 0;
}
SCL1_L;
I2C_OLED_delay();
GpioCtrlRegs.GPADIR.bit.GPIO15 = 1; //配置GPIO15为输出模式
EDIS;
return 1;
}
//判断是否有ACK,有返回1,无返回0
bool Juge_ACK_OLED(void)//判断有无ACK
{
if(!I2C_OLED_WaitAck())
{
I2C_OLED_stop();
return 0;
}
return 1;
}
//用IIC协议写数据SendByte
void I2C_OLED_SendByte(uint8 SendByte) //写入
{
uint8 i=8;
while(i--)
{
SCL1_L;
I2C_OLED_delay();
if(SendByte&0x80)
SDA1_H;
else
SDA1_L;
SendByte=SendByte<<1;
I2C_OLED_delay();
SCL1_H;
I2C_OLED_delay();
}
SCL1_L;
}
//向OLED模块传送写命令的要求,0x00,写命令IIC_Command(OLED模块的写时序)
bool Write_IIC_OLED_Command(uint8 IIC_Command)//写命令
{
if(!I2C_OLED_start())
{
return 0;//总线忙或出错
}
I2C_OLED_SendByte(OLED_addr); //Slave address,SA0=0
if(!Juge_ACK_OLED())
return 0;
I2C_OLED_SendByte(0x00); //write command
if(!Juge_ACK_OLED())
return 0;
I2C_OLED_SendByte(IIC_Command);
if(!Juge_ACK_OLED())
return 0;
I2C_OLED_stop();
return 1;
}
//向OLED模块传送写数据的要求,0x40,写数据IIC_Data(OLED模块的写时序)
bool Write_IIC_OLED_Data(uint8 IIC_Data)//写数据
{
if(!I2C_OLED_start())
{
return 0;//总线忙或出错
}
I2C_OLED_SendByte(OLED_addr); //D/C#=0; R/W#=0
if(!Juge_ACK_OLED())
return 0;
I2C_OLED_SendByte(0x40); //write data
if(!Juge_ACK_OLED())
return 0;
I2C_OLED_SendByte(IIC_Data);
if(!Juge_ACK_OLED())
return 0;
I2C_OLED_stop();
return 1;
}
//选择是写数据还是写命令,cmd==1则写数据,否则写命令
void OLED_WR_Byte(uint8 dat,int cmd)//写数据或命令
{
if(cmd)
{
Write_IIC_OLED_Data(dat);
}
else
{
Write_IIC_OLED_Command(dat);
}
}
//写入fill_Data整个OLED屏幕
void fill_picture(uint8 fill_Data)
{
uint8 m,n;
for(m=0;m<8;m++)
{
OLED_WR_Byte(page_address+m,0);
OLED_WR_Byte(low_column_address,0);
OLED_WR_Byte(high_column_address,0);
for(n=0;n<128;n++)
{
OLED_WR_Byte(fill_Data,1);
}
}
}
//坐标设置,y为页地址设置,x为列地址设置
void OLED_Set_Pos(int x,int y)//y>=0,y<=7,x>=0,x<=127
{
OLED_WR_Byte(page_address+y,OLED_CMD);//页地址
OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);//列高地址
OLED_WR_Byte((x&0x0f),OLED_CMD); //列低地址
}
//开启OLED显示
void OLED_Display_On(void)
{
OLED_WR_Byte(SET_DCDC,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON
OLED_WR_Byte(display_on,OLED_CMD); //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{
OLED_WR_Byte(SET_DCDC,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF
OLED_WR_Byte(display_off,OLED_CMD); //DISPLAY OFF
}
//清屏
void OLED_Clear(void)
{
uint8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (page_address+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (low_column_address,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (high_column_address,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)
{
OLED_WR_Byte(0,OLED_DATA);
I2C_OLED_delay_more();
}
}
}
//全亮,将屏幕全变亮
void OLED_On(void)
{
uint8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (page_address+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (low_column_address,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (high_column_address,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)
{
OLED_WR_Byte(0xff,OLED_DATA);
I2C_OLED_delay_more();
}
}
}
//在指定位置显示一个字符
void OLED_ShowChar(int x,int y,uint8 chr,int Char_Size)
{
unsigned char c=0,i=0;
c=chr;
if(x>Max_Column-1)
{
x=0;
y=y+2;
}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
{
OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
I2C_OLED_delay_more();
}
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
{
OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
I2C_OLED_delay_more();
}
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
}
//指数函数,m^n
uint32 oled_pow(int m,int n)
{
uint32 result=1;
while(n--)
result*=m;
return result;
}
//在指定位置(x,y)显示一串数字
void OLED_ShowNum(int x,int y,uint32 num,int len,int size2)
{
int t,temp;
int enshow=0;
for(t=0;t;t++)<>
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,0,size2);
I2C_OLED_delay_more();
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp,size2);
I2C_OLED_delay_more();
}
}
//在指定位置(x,y)显示汉字
void OLED_ShowCHinese(int x,int y,uint8 no)
{
uint8 t;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
I2C_OLED_delay_more();
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
I2C_OLED_delay_more();
}
}
void OLED_Init(void)
{
OLED_WR_Byte(display_off,OLED_CMD);//--display off
OLED_WR_Byte(low_column_address,OLED_CMD);//---set low column address
OLED_WR_Byte(high_column_address,OLED_CMD);//---set high column address
OLED_WR_Byte(start_line,OLED_CMD);//--set start line address
OLED_WR_Byte(page_address,OLED_CMD);//--set page address
OLED_WR_Byte(contract_control,OLED_CMD); // contract control
OLED_WR_Byte(0xFF,OLED_CMD);//--128
OLED_WR_Byte(segment_remap,OLED_CMD);//--set segment remap
OLED_WR_Byte(normal_dispaly,OLED_CMD);//--normal / reverse
OLED_WR_Byte(multiplex_ratio,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
OLED_WR_Byte(scan_direction,OLED_CMD);//Com scan direction
OLED_WR_Byte(display_offset,OLED_CMD);//-set display offset
OLED_WR_Byte(0x00,OLED_CMD);//复位
OLED_WR_Byte(clock_division,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(Pre_Charge_Period,OLED_CMD);//Set Pre-Charge Period
OLED_WR_Byte(0xF1,OLED_CMD);//
OLED_WR_Byte(pin_configuartion,OLED_CMD);//set com pin configuartion
OLED_WR_Byte(0x12,OLED_CMD);//复位
OLED_WR_Byte(0x20,OLED_CMD);
OLED_WR_Byte(0x02,OLED_CMD);
OLED_WR_Byte(Vcomh,OLED_CMD);//set Vcomh
OLED_WR_Byte(0x30,OLED_CMD);//复位
OLED_WR_Byte(SET_DCDC,OLED_CMD);//set charge pump enable
OLED_WR_Byte(0x14,OLED_CMD);//DCDC ON
OLED_WR_Byte(display_on,OLED_CMD);//--turn on oled panel
}
IIC_OLED.h
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
#define OLED_addr 0x78
#define display_off 0xAE//关显示
#define low_column_address 0x00//列低地址
#define high_column_address 0x10 //设置列高地址
#define start_line 0x40 //设置起始行
#define page_address 0xB0 //起始页
#define contract_control 0x81 //对比度设置
#define segment_remap 0xA1
#define normal_dispaly 0xA6 //普通显示
#define multiplex_ratio 0xA8
#define scan_direction 0xC8 //扫描
#define display_offset 0xD3
#define clock_division 0xD5
#define Pre_Charge_Period 0xD9
#define pin_configuartion 0xDA
#define Vcomh 0xDB
#define display_on 0xAF
#define SET_DCDC 0X8D
#define SCL1_H GpioDataRegs.GPASET.bit.GPIO14=1
#define SCL1_L GpioDataRegs.GPACLEAR.bit.GPIO14=1
#define SDA1_H GpioDataRegs.GPASET.bit.GPIO15=1
#define SDA1_L GpioDataRegs.GPACLEAR.bit.GPIO15=1
#define SCL1_read GpioDataRegs.GPADAT.bit.GPIO14
#define SDA1_read GpioDataRegs.GPADAT.bit.GPIO15
#define SIZE 16
#define Max_Column 128
#define Max_Row 64
void I2C_GPIO_Config_OLED(void);
int Data_len(int data);
void I2C_OLED_delay(void);
void I2C_OLED_delay_more(void);
bool I2C_OLED_start(void);
void I2C_OLED_stop(void);
void I2C_OLED_ack(void);
void I2C_OLED_noack(void);
bool I2C_OLED_WaitAck(void);
bool Juge_ACK_OLED(void);
void I2C_OLED_SendByte(uint8 SendByte);
bool Write_IIC_OLED_Command(uint8 IIC_Command);
bool Write_IIC_OLED_Data(uint8 IIC_Data);
void OLED_WR_Byte(uint8 dat,int cmd);
void fill_picture(uint8 fill_Data);
void OLED_Set_Pos(int x,int y);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Clear(void);
void OLED_On(void);
void OLED_ShowChar(int x,int y,uint8 chr,int Char_Size);
uint32 oled_pow(int m,int n);
void OLED_ShowNum(int x,int y,uint32 num,int len,int size2);
void OLED_ShowCHinese(int x,int y,uint8 no);
void OLED_Init(void);
main.c
int main(void)
{
int data;
EALLOW;
P_SysCtrlRegs->INTOSC1TRIM.bit.COARSETRIM = 0;
P_SysCtrlRegs->INTOSC2TRIM.bit.COARSETRIM= 0;
EDIS;
InitSysCtrl();
DINT;
InitPieCtrl();
IER_DISABLE(0xffff);
IFR_DISABLE(0xffff);
InitPieVectTable();
I2C_GPIO_Config_OLED();
OLED_Init();
EINT;
OLED_Clear();
OLED_ShowCHinese(28,0,0);
OLED_ShowCHinese(44,0,1);
OLED_ShowCHinese(60,0,2);
OLED_ShowCHinese(76,0,3);
OLED_ShowChar(16,4,16,16);
OLED_ShowChar(24,4,17,16);
OLED_ShowChar(32,4,16,16);
OLED_ShowChar(40,4,13,16);
OLED_ShowChar(48,4,22,16);
OLED_ShowChar(56,4,17,16);
OLED_ShowChar(64,4,25,16);
OLED_ShowChar(72,4,19,16);
OLED_ShowChar(80,4,20,16);
OLED_ShowChar(88,4,21,16);
OLED_ShowChar(96,4,22,16);
OLED_ShowChar(104,4,17,16);
while(1){}
return 0;
}
接线以及显示效果:
详细例程请参考
链接:https://pan.baidu.com/s/1C8I7OSgjKifGP8UX-U6Tmg
提取码:8034
————————————————
特别鸣谢 原创作者 博主「晟逸轩」
评论
查看更多