STM32 IIC驱动OLED

#ifndef OLED_CFG_H_
#define OLED_CFG_H_
//
#ifdef __cplusplus
extern "C" {
#endif
    //
    #include "complier_lib.h"
    #include "i2c_task.h"
    #include "delay_task.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
    //===定义大小
    #define OLED_PAGE_SIZE                            8
    #define OLED_MAX_COL                            128
    #define OLED_MAX_ROW                            64
    
    #define OLED_XLevelL                            0x02
    #define OLED_XLevelH                            0x10
    #define OLED_Brightness                            0xFF
    #define OLED_X_WIDTH                            128
    #define OLED_Y_WIDTH                            64
    
    //===结构体定义
    typedef struct _OLED_IIC_HandlerType            OLED_IIC_HandlerType;

    //===指针结构体定义
    typedef struct _OLED_IIC_HandlerType            *pOLED_IIC_HandlerType;

    //===OLED的数据结构体
    struct _OLED_IIC_HandlerType
    {
        GPIO_HandlerType    msgRST;                    //---复位端口
        I2C_HandlerType        msgI2C;                    //---使用的I2C
    };

    //===定义的任务函数
    #define OLED_TASK_ONE                            pOLEDI2CDevice0
    #define OLED_TASK_TWO                            0
    #define OLED_TASK_THREE                            0
    
    extern const UINT8_T SYN_LOGO[];

    //===外部调用接口
    extern OLED_IIC_HandlerType                        g_OLEDI2CDevice0;
    extern pOLED_IIC_HandlerType                    pOLEDI2CDevice0;

    //===函数定义
    UINT8_T OLED_I2C_Init(OLED_IIC_HandlerType *OLEDx, void(*pFuncDelayus)(UINT32_T delay), UINT8_T isHWI2C);
    UINT8_T OLED_I2C_WriteCmd(OLED_IIC_HandlerType *OLEDx, UINT8_T cmd);
    UINT8_T OLED_I2C_WriteData(OLED_IIC_HandlerType *OLEDx, UINT8_T cmd);
    void OLED_I2C_DisplayON(OLED_IIC_HandlerType *OLEDx);
    void OLED_I2C_DisplayOFF(OLED_IIC_HandlerType *OLEDx);
    void OLED_I2C_Fill(OLED_IIC_HandlerType *OLEDx, UINT8_T dat);
    void OLED_I2C_Clear(OLED_IIC_HandlerType *OLEDx);
    void OLED_I2C_SetPos(OLED_IIC_HandlerType *OLEDx, UINT8_T xPos, UINT8_T yPos);
    void OLED_I2C_HWInit(OLED_IIC_HandlerType *OLEDx);
    void OLED_I2C_DrawBMP(OLED_IIC_HandlerType *OLEDx, UINT8_T x0Pos, UINT8_T y0Pos, UINT8_T x1Pos, UINT8_T y1Pos, UINT8_T BMP[]);
    //
#ifdef __cplusplus
}
#endif
//
#endif /*OLED_CFG_H_ */

#include "oled_cfg.h"

//===全局变量
OLED_IIC_HandlerType        g_OLEDI2CDevice0;
pOLED_IIC_HandlerType        pOLEDI2CDevice0 = &g_OLEDI2CDevice0;

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
UINT8_T OLED_Device0_Init(OLED_IIC_HandlerType *OLEDx)
{
    //---如果为6针的IIC模式,RES端口必须接入端口控制,否者需要拉高处理
    //---RST端口的配置
    OLEDx->msgRST.msgGPIOBit = LL_GPIO_PIN_5;
    OLEDx->msgRST.msgGPIOPort = GPIOB;

    //---端口初始化
    if (OLEDx->msgRST.msgGPIOPort != NULL)
    {
        GPIOTask_Clock(OLEDx->msgRST.msgGPIOPort, 1);
    }

    //---GPIO的结构体
    LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 };
    GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;                        //---配置状态为输出模式
    GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;                //---GPIO的速度---低速设备
    GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;            //---输出模式---推挽输出
    GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;                            //---上拉
#ifndef USE_MCU_STM32F1
    GPIO_InitStruct.Alternate = LL_GPIO_AF_0;                        //---端口复用模式
#endif

//---RST端口的初始化
    GPIO_InitStruct.Pin = OLEDx->msgRST.msgGPIOBit;
    if (OLEDx->msgRST.msgGPIOPort != NULL)
    {
        LL_GPIO_Init(OLEDx->msgRST.msgGPIOPort, &GPIO_InitStruct);
        GPIO_OUT_1(OLEDx->msgRST.msgGPIOPort, OLEDx->msgRST.msgGPIOBit);
    }

    //---I2C的配置
    OLEDx->msgI2C.msgI2Cx = NULL;
    OLEDx->msgI2C.msgSCL.msgGPIOPort = GPIOB;
    OLEDx->msgI2C.msgSCL.msgGPIOBit = LL_GPIO_PIN_6;
    OLEDx->msgI2C.msgSDA.msgGPIOPort = GPIOB;
    OLEDx->msgI2C.msgSDA.msgGPIOBit = LL_GPIO_PIN_7;
    OLEDx->msgI2C.msgModelIsHW = 0;
    OLEDx->msgI2C.msgPluseWidth = 1;
    OLEDx->msgI2C.msgFuncDelayus = NULL;

    //---通过调整0R电阻,屏可以0x78和0x7A两个地址 -- 默认0x78
    OLEDx->msgI2C.msgAddr = 0x78;
    OLEDx->msgI2C.msgClockSpeed = 0;
    return OK_0;
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
UINT8_T OLED_Device1_Init(OLED_IIC_HandlerType *OLEDx)
{
    return OK_0;
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
UINT8_T OLED_Device2_Init(OLED_IIC_HandlerType *OLEDx)
{
    return OK_0;
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
UINT8_T OLED_I2C_Init(OLED_IIC_HandlerType *OLEDx, void(*pFuncDelayus)(UINT32_T delay), UINT8_T isHWI2C)
{
    UINT8_T _return = OK_0;

    //---指定设备的初始化
    if ((OLEDx != NULL) && (OLEDx == OLED_TASK_ONE))
    {
        OLED_Device0_Init(OLEDx);
    }
    else if ((OLEDx != NULL) && (OLEDx == OLED_TASK_TWO))
    {
        OLED_Device1_Init(OLEDx);
    }
    else if ((OLEDx != NULL) && (OLEDx == OLED_TASK_THREE))
    {
        OLED_Device2_Init(OLEDx);
    }
    else
    {
        return ERROR_1;
    }

    //---判断是硬件I2C还是软件I2C
    if (isHWI2C)
    {
        //---初始化硬件I2C
        _return = I2CTask_MHW_Init(&(OLEDx->msgI2C));
        OLEDx->msgI2C.msgModelIsHW = 1;
    }
    else
    {
        //---初始化软件模拟I2C
        _return = I2CTask_MSW_Init(&(OLEDx->msgI2C), pFuncDelayus);
        OLEDx->msgI2C.msgModelIsHW = 0;
    }

    //---硬件初始化
    OLED_I2C_HWInit(OLEDx);
    return _return;
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
UINT8_T OLED_SWI2C_WriteByte(OLED_IIC_HandlerType *OLEDx, UINT8_T adddr, UINT8_T dat)
{
    UINT8_T _return = OK_0;

    //---启动并发送地址
    _return = I2CTask_MSW_START(&(OLEDx->msgI2C), 1);

    //if (_return != OK_0)
    //{
    //    //---启动写数据失败
    //    _return = ERROR_2;
    //    goto GoToExit;
    //}
    //---发送寄存器地址
    I2CTask_MSW_SendByte(&(OLEDx->msgI2C), adddr);

    //---读取ACK
    _return = I2CTask_MSW_ReadACK(&(OLEDx->msgI2C));

    //if (_return != OK_0)
    //{
    //    //---发送数据失败
    //    _return = ERROR_3;
    //    goto GoToExit;
    //}
    //---发送寄存器地址
    I2CTask_MSW_SendByte(&(OLEDx->msgI2C), dat);

    //---读取ACK
    _return = I2CTask_MSW_ReadACK(&(OLEDx->msgI2C));

    //GoToExit:

    //---发送停止信号
    I2CTask_MSW_STOP(&(OLEDx->msgI2C));
    return _return;
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
UINT8_T OLED_HWI2C_WriteByte(OLED_IIC_HandlerType *OLEDx, UINT8_T adddr, UINT8_T dat)
{
    return OK_0;
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
UINT8_T OLED_I2C_WriteByte(OLED_IIC_HandlerType *OLEDx, UINT8_T adddr, UINT8_T dat)
{
    if (OLEDx->msgI2C.msgModelIsHW == 0)
    {
        return OLED_SWI2C_WriteByte(OLEDx, adddr, dat);
    }
    else
    {
        return OLED_HWI2C_WriteByte(OLEDx, adddr, dat);
    }
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
UINT8_T OLED_I2C_WriteCmd(OLED_IIC_HandlerType *OLEDx, UINT8_T cmd)
{
    return OLED_I2C_WriteByte(OLEDx, 0x00, cmd);
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
UINT8_T OLED_I2C_WriteData(OLED_IIC_HandlerType *OLEDx, UINT8_T cmd)
{
    return OLED_I2C_WriteByte(OLEDx, 0x40, cmd);
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:开启OLED显示
//
void OLED_I2C_DisplayON(OLED_IIC_HandlerType *OLEDx)
{
    //---设置电荷泵
    OLED_I2C_WriteCmd(OLEDx, 0x8D);

    //---开启电荷泵
    OLED_I2C_WriteCmd(OLEDx, 0x14);

    //---OLED唤醒
    OLED_I2C_WriteCmd(OLEDx, 0xAF);
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:关闭OLED显示
//
void OLED_I2C_DisplayOFF(OLED_IIC_HandlerType *OLEDx)
{
    //---设置电荷泵
    OLED_I2C_WriteCmd(OLEDx, 0x8D);

    //---关闭电荷泵
    OLED_I2C_WriteCmd(OLEDx, 0x10);

    //---OLED休眠
    OLED_I2C_WriteCmd(OLEDx, 0xAE);
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:全屏填充
//
void OLED_I2C_Fill(OLED_IIC_HandlerType *OLEDx, UINT8_T dat)
{
    UINT8_T i = 0;
    UINT8_T n = 0;
    for (i = 0; i < OLED_PAGE_SIZE; i++)
    {
        //---设置页地址(0~7)
        OLED_I2C_WriteCmd(OLEDx, (0xB0 + i));

        //---设置显示位置—列低地址
        OLED_I2C_WriteCmd(OLEDx, 0x00);

        //---设置显示位置—列高地址
        OLED_I2C_WriteCmd(OLEDx, 0x10);
        for (n = 0; n < OLED_MAX_COL; n++)
        {
            //---更新显示
            OLED_I2C_WriteData(OLEDx, dat);
        }
    }
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:
//
void OLED_I2C_Clear(OLED_IIC_HandlerType *OLEDx)
{
    OLED_I2C_Fill(OLEDx, 0x00);
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:设置起始点坐标
//
void OLED_I2C_SetPos(OLED_IIC_HandlerType *OLEDx, UINT8_T xPos, UINT8_T yPos)
{
    OLED_I2C_WriteCmd(OLEDx, (0xB0 + yPos));
    OLED_I2C_WriteCmd(OLEDx, ((xPos & 0xf0) >> 4) | 0x10);
    OLED_I2C_WriteCmd(OLEDx, (xPos & 0x0f) | 0x01);
}

///
//函        数:
//功        能:
//输入参数:
//输出参数:
//说        明:OLED的硬件的初始化
//
void OLED_I2C_HWInit(OLED_IIC_HandlerType *OLEDx)
{
    if (OLEDx->msgRST.msgGPIOPort != NULL)
    {
        GPIO_OUT_1(OLEDx->msgRST.msgGPIOPort, OLEDx->msgRST.msgGPIOBit);
        DelayTask_ms(100);
        GPIO_OUT_0(OLEDx->msgRST.msgGPIOPort, OLEDx->msgRST.msgGPIOBit);
        DelayTask_ms(100);
        GPIO_OUT_1(OLEDx->msgRST.msgGPIOPort, OLEDx->msgRST.msgGPIOBit);
    }

    OLED_I2C_WriteCmd(OLEDx, 0xAE); //--display off
    OLED_I2C_WriteCmd(OLEDx, 0x00); //---set low column address
    OLED_I2C_WriteCmd(OLEDx, 0x10); //---set high column address
    OLED_I2C_WriteCmd(OLEDx, 0x40); //--set start line address
    OLED_I2C_WriteCmd(OLEDx, 0xB0); //--set page address
    OLED_I2C_WriteCmd(OLEDx, 0x81); // contract control
    OLED_I2C_WriteCmd(OLEDx, 0xFF); //--128
    OLED_I2C_WriteCmd(OLEDx, 0xA1); //set segment remap
    OLED_I2C_WriteCmd(OLEDx, 0xA6); //--normal / reverse
    OLED_I2C_WriteCmd(OLEDx, 0xA8); //--set multiplex ratio(1 to 64)
    OLED_I2C_WriteCmd(OLEDx, 0x3F); //--1/32 duty
    OLED_I2C_WriteCmd(OLEDx, 0xC8); //Com scan direction
    OLED_I2C_WriteCmd(OLEDx, 0xD3); //-set display offset
    OLED_I2C_WriteCmd(OLEDx, 0x00); //

    OLED_I2C_WriteCmd(OLEDx, 0xD5); //set osc division
    OLED_I2C_WriteCmd(OLEDx, 0x80); //set divide ratio

    OLED_I2C_WriteCmd(OLEDx, 0xD8); //set area color mode off
    OLED_I2C_WriteCmd(OLEDx, 0x05); //

    OLED_I2C_WriteCmd(OLEDx, 0xD9); //Set Pre-Charge Period
    OLED_I2C_WriteCmd(OLEDx, 0xF1); //

    OLED_I2C_WriteCmd(OLEDx, 0xDA); //set com pin configuartion
    OLED_I2C_WriteCmd(OLEDx, 0x12); //

    OLED_I2C_WriteCmd(OLEDx, 0xDB); //set Vcomh
    OLED_I2C_WriteCmd(OLEDx, 0x30); //0x20,0.77xVcc

    OLED_I2C_WriteCmd(OLEDx, 0x8D); //set charge pump enable
    OLED_I2C_WriteCmd(OLEDx, 0x14); //

    OLED_I2C_WriteCmd(OLEDx, 0xAF); //--turn on oled panel
}

///
//函        数:
//功        能:
//输入参数: x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8)
//输出参数:
//说        明:功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7
//
void OLED_I2C_DrawBMP(OLED_IIC_HandlerType *OLEDx, UINT8_T x0Pos, UINT8_T y0Pos, UINT8_T x1Pos, UINT8_T y1Pos, UINT8_T BMP[])
{
    UINT16_T j = 0;
    UINT8_T  x = 0;
    UINT8_T  y = 0;

    //---判断地址是否超界限
    if (x0Pos > (OLED_MAX_COL - 1))
    {
        x0Pos = (OLED_MAX_COL - 1);
    }

    if (y0Pos > (OLED_MAX_ROW - 1))
    {
        y0Pos = (OLED_MAX_ROW - 1);
    }

    if (x1Pos > (OLED_MAX_COL - 1))
    {
        x1Pos = (OLED_MAX_COL - 1);
    }

    if (y1Pos > (OLED_MAX_ROW - 1))
    {
        y1Pos = (OLED_MAX_ROW - 1);
    }

    //---判断数据位置
    if (y1Pos % 8 == 0)
    {
        y = y1Pos / 8;
    }
    else
    {
        y = y1Pos / 8 + 1;
    }

    for (y = y0Pos; y < y1Pos; y++)
    {
        //---设置坐标
        OLED_I2C_SetPos(OLEDx, x0Pos, y);
        for (x = x0Pos; x < x1Pos; x++)
        {
            //---设置数据
            OLED_I2C_WriteData(OLEDx, BMP[j++]);
        }
    }
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值