基于昊芯DSC28034+四针OLED屏(保姆级教程)

/******************************************************************

编  译  器: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<len;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();
    }
}

//初始化OLED屏芯片,对OLED寄存器设置初始化

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

  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STM32四针OLED幕可以实现万年历功能。首先,我们需要连接STM32四针OLED幕到STM32微控制器。然后,我们可以使用STM32的编程工具,如Keil或STM32CubeIDE,编写相应的代码实现万年历功能。 在代码中,我们可以利用STM32的时钟模块来获取当前日期和时间。通过相应的算法,我们可以确定当前年份是否为闰年,以及每个月份的天数。然后,我们可以将这些信息与当前日期进行比较,并在OLED幕上显示出来。 我们可以使用OLED幕的绘图函数来绘制日期、星期和月份等信息。可以使用合适的字体和颜色,在幕上显示当前日期。我们可以使用矩形或其他形状表示当前选定的日期。还可以使用箭头或其他指示符号来标记当前日期所在的位置。 为了提供更多的功能,我们还可以在OLED幕上显示特殊的事件或提醒。我们可以在特定的日期下方添加文本说明,例如生日、纪念日或会议。我们还可以在幕上显示当前时间和温度等其他实用信息。 如果需要,我们还可以为万年历添加用户交互功能。通过加入按钮、旋钮或触摸等输入设备,我们可以实现用户选择日期、切换月份或进行其他设置的功能。 通过合理设计和编程,STM32四针OLED幕可以成为一个功能强大的万年历设备。无论是个人使用还是商业应用,它都能提供便利和实用性,帮助人们跟踪时间和日期,并且提醒重要事件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Utams

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值