CH57x,CH582,CH592模拟I2C主机控制OLED屏幕

OLED驱动源码来自B站UP:江协科技

视频链接:https://www.bilibili.com/video/BV1th411z7sn?p=10&vd_source=d1b8b6d61c97078bb35a07cbc2e6608a

I2C通讯一般采用开漏输出的IO配置,可以降低总线上挂载的IIC从机设备的数据冲突风险。

而CH582等低功耗蓝牙芯片的GPIO不支持开漏输出模式,了解到开漏输出的特性为:IO输出高时为高阻态(由外部上拉或者下拉电阻决定最终电平),IO输出低时为低电平,因此可以模拟开漏:

1、当GPIO要输出高电平时,将GPIO配置为上拉输入模式,由芯片内部上拉电阻将总线拉至高电平;芯片内部上/下拉电阻阻值默认为50K ,如需加快电平转换速度,可外接阻值更小的上下拉电阻;

2、当GPIO要输出低电平时,将GPIO配置为输出模式,默认输出低电平。

具体配置为:

#define IIC_SCL_PIN     GPIO_Pin_5//PB5-SCL
#define IIC_SDA_PIN     GPIO_Pin_4//PB4-SDA

#define IIC_SCL_H()              R32_PB_DIR    &= ~IIC_SCL_PIN
#define IIC_SCL_L()              R32_PB_DIR    |=  IIC_SCL_PIN

#define IIC_SDA_H()              R32_PB_DIR    &= ~IIC_SDA_PIN
#define IIC_SDA_L()              R32_PB_DIR    |=  IIC_SDA_PIN
void IIC_Init()
{
    GPIOB_ModeCfg(IIC_SCL_PIN,GPIO_ModeIN_PU );//初始化为上拉输入
    GPIOB_ModeCfg(IIC_SDA_PIN,GPIO_ModeIN_PU );//初始化为上拉输入
    GPIOB_ResetBits(IIC_SCL_PIN|IIC_SDA_PIN);//配置默认输出低电平,保证在切换IO引脚为输出方向时能够及时输出低电平
    IIC_SCL_H();//SCL拉高
    IIC_SDA_H();//SDA拉高
}

 

void IIC_START()//开始信号:SCL为高电平时,SDA由高电平转变为低电平
{
    IIC_SDA_H();
    IIC_SCL_H();
    IIC_SDA_L();
    IIC_SCL_L();
}

 

void IIC_STOP()//结束信号:SCL为高电平时,SDA由低电平转变为高电平
{
    IIC_SDA_L(); 
    IIC_SCL_H();  
    IIC_SDA_H(); 
}

 

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的一个字节
  * @retval 无
  */
void OLED_IIC_SendByte(uint8_t Byte)
{
    uint8_t i;
    for(i = 0;i < 8;i++)
    {
        if(Byte & (0x80 >> i))
        {
            IIC_SDA_H();
        }
        else
        {
            IIC_SDA_L();
        }
        IIC_SCL_H();
        IIC_SCL_L();
    }
    IIC_SCL_H();
    IIC_SCL_L();
}

 

/**
  * @brief  OLED写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void OLED_WriteCommand(uint8_t Command)
{
    IIC_START();
    OLED_IIC_SendByte(0x78);
    OLED_IIC_SendByte(0x00);
    OLED_IIC_SendByte(Command);
    IIC_STOP();
}

 

/**
  * @brief  OLED写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void OLED_WriteData(uint8_t Data)
{
    IIC_START();
    OLED_IIC_SendByte(0x78);        //从机地址
    OLED_IIC_SendByte(0x40);        //写数据
    OLED_IIC_SendByte(Data);
    IIC_STOP();
}

 

void OLED_Init(void)//OLED屏幕按照手册进行初始化
{
    IIC_Init();            //端口初始化
    OLED_WriteCommand(0xAE);    //关闭显示
    OLED_WriteCommand(0xD5);    //设置显示时钟分频比/振荡器频率
    OLED_WriteCommand(0x80);
    OLED_WriteCommand(0xA8);    //设置多路复用率
    OLED_WriteCommand(0x3F);
    OLED_WriteCommand(0xD3);    //设置显示偏移
    OLED_WriteCommand(0x00);
    OLED_WriteCommand(0x40);    //设置显示开始行
    OLED_WriteCommand(0xA1);    //设置左右方向,0xA1正常 0xA0左右反置
    OLED_WriteCommand(0xC8);    //设置上下方向,0xC8正常 0xC0上下反置
    OLED_WriteCommand(0xDA);    //设置COM引脚硬件配置
    OLED_WriteCommand(0x12);
    OLED_WriteCommand(0x81);    //设置对比度控制
    OLED_WriteCommand(0xCF);
    OLED_WriteCommand(0xD9);    //设置预充电周期
    OLED_WriteCommand(0xF1);
    OLED_WriteCommand(0xDB);    //设置VCOMH取消选择级别
    OLED_WriteCommand(0x30);
    OLED_WriteCommand(0xA4);    //设置整个显示打开/关闭
    OLED_WriteCommand(0xA6);    //设置正常/倒转显示
    OLED_WriteCommand(0x8D);    //设置充电泵
    OLED_WriteCommand(0x14);
    OLED_WriteCommand(0xAF);    //开启显示
    OLED_Clear();               //OLED清屏
}

 应用到main.c中运行查看效果

int main()
{
    SetSysClock(CLK_SOURCE_PLL_60MHz);
    GPIOA_SetBits(GPIO_Pin_9);
    GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
    GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
    UART1_DefInit();

    OLED_Init();
    char Data = '!';
    for(uint8_t i=1;i<5;i++)
    {
        for(uint8_t j=1;j<17;j++)
        {
            OLED_ShowChar(i,j,Data);
            Data++;
        }
    }
    while(1);
}

显示效果如下:

工程链接(自取):

链接:https://pan.baidu.com/s/17BEm1VFW-zDocnlxwPNs1Q?pwd=q6wc
提取码:q6wc

posted on 2024-05-24 13:49  ZDeST  阅读(112)  评论(0编辑  收藏  举报