STM32实现软件IIC协议操作OLED显示屏(1)

时间记录:2024/1/25

一、IIC协议介绍

(1)协议介绍

IIC(又称I2C,Inter-Integrated Circuit),即集成电路总线,是一种两线式串行总线,由PHILIPS公司开发,用于连接微控制器及其外围设备。多用于主机和从机在数据量不大且传输距离短的场合下的主从通信。I2C总线由数据线SDA和时钟线SCL构成通信线路,既可用于发送数据,也可接收数据,是一种半双工通信协议。总线上的主设备与从设备之间以字节(8位)为单位进行双向的数据传输。

(2)传输模式

  • 标准模式:100K bit/s
  • 快速模式:400K bit/s
  • 高速模式:3.4M bit/s

(3)连接线路

(4)通信时序图分析

1.4.1 空闲状态:IIC总线的SCL和SDA线同时处于高电平

1.4.2 起始信号S:SCL和SDA都处于高电平空闲状态(时间大于4.7us)时,将SDA线从高电平拉到低电平(时间大于4us)产生起始信号

1.4.3 终止信号P:SCL处于高电平,SDA处于低电平(时间大于4us),将SDA线从低电平拉到高电平(时间大于4.7us)产生终止信号

1.4.4 应答信号:8位1字节数据传输完毕后,第九位为应答信号,此时SCL由低电平转变为高电平,4us内读取SDA的电平状态,0表示从机应答,1表示无应答,主机发送应答信号时时间应大于4us

1.4.5 数据发送:SCL为高电平,SDA需要数据稳定,高电平发送数据1,低电平发送数据0,SCL为低电平时,SDA变换状态,改变要发送的数据位,且一字节数据高位先发,低位后发

二、软件IIC实现

(1)初始化GPIO口

cpp 复制代码
void vIICInit(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//开漏输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_Init(GPIOB,&GPIO_InitStruct);
    
    GPIO_SetBits(GPIOB,GPIO_Pin_14);//默认处于空闲状态高电平
    GPIO_SetBits(GPIOB,GPIO_Pin_15);
    
    Delay_Init();
}

(2)SDA总线切换输入/输出模式

cpp 复制代码
static void vSdaOut(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//开漏输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_Init(GPIOB,&GPIO_InitStruct);
}

static void vSdaIn(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_Init(GPIOB,&GPIO_InitStruct);
}

(3)起始信号

cpp 复制代码
void vIICStart(void)
{
    vSdaOut();//切换SDA总线为输出模式
    SCL=1;
    SDA=1;
    Delay_Us(5);//拉高SCL和SDA,维持5us
    SDA=0;
    Delay_Us(5);//拉低SDA,维持5us
}

(4)终止信号

cpp 复制代码
void vIICStop(void)
{
    vSdaOut();
    SCL=1;
    SDA=0;
    Delay_Us(5);//SCL高电平,SDA低电平,维持5us
    SDA=1;
    Delay_Us(5);//SDA电平拉高,维持5us
}

(5)发送校验位

cpp 复制代码
void vIICSendAck(u8 ack)//做从机设备时需要
{
    vSdaOut();
    SCL=0;
    Delay_Us(2);//发送数据,SCL拉低,SDA信号变换
    if(ack==ACK)
        SDA=0;//变换SDA电平
    else
        SDA=1;//变换SDA电平
    Delay_Us(2);//发送数据,SCL拉低,SDA信号变换
    SCL=1;
    Delay_Us(5);//拉高SCL将SDA数据发送出去
    SCL=0;
}

(6)接收校验位

cpp 复制代码
u8 vIICCheckAck(void)
{
    u8 ack;
    vSdaIn();//切换SDA总线为输入模式
    SCL=0;
    Delay_Us(3);
    SCL=1;
    Delay_Us(3);//拉高后延时3us等待信号稳定
    if(SDA_STATE)//无应答
        ack=NACK;
    else//有应答
        ack=ACK;
    Delay_Us(3);
    SCL=0;
    return ack;
}

(7)发送1字节数据

cpp 复制代码
void vIICSendByte(u8 byte_data)
{
    u8 i;
    vSdaOut();
    for(i=0;i<8;i++){
        SCL=0;
        Delay_Us(5);//拉低SCL等待SDA数据变换
        if(byte_data&0x80)//最高位为1,高位先发
            SDA=1;
        else
            SDA=0;
        SCL=1;
        Delay_Us(5);//拉高SCL将SDA的一位数据发送出去
        byte_data<<=1;
    }
    SCL=0;
    Delay_Us(5);//拉低SCL等待SDA数据变换
}

(8)接收1字节数据

cpp 复制代码
u8 vIICGetByte(void)
{
    vSdaIn();
    u8 temp,i;
    for(i=0;i<8;i++){
        SCL=0;
        Delay_Us(5);//拉低SCL等待接收数据
        SCL=1;
        Delay_Us(2);
        temp<<=1;
        if(SDA_STATE)
            temp|=0x01;
        Delay_Us(2);
    }
    SCL=0;
    Delay_Us(5);
    return temp;
}
相关推荐
逼子格1 小时前
五种音频器件综合对比——《器件手册--音频器件》
嵌入式硬件·音视频·硬件工程师·硬件测试·电子器件·硬件笔试真题·音频器件
niuTaylor3 小时前
STM32平衡车开发实战教程:从零基础到项目精通
stm32·单片机·嵌入式硬件
可待电子单片机设计定制(论文)12 小时前
【STM32设计】基于STM32的智能门禁管理系统(指纹+密码+刷卡+蜂鸣器报警)(代码+资料+论文)
stm32·单片机·嵌入式硬件
不可思议迷宫13 小时前
Verilog编程实现一个分秒计数器
单片机·嵌入式硬件·fpga开发
life_yangzi15 小时前
关于单片机IAP升级的那点事儿|智能设置中断向量表
单片机·嵌入式硬件
了一li17 小时前
STM32实现一个简单电灯
stm32·单片机·嵌入式硬件
可待电子单片机设计定制(论文)20 小时前
【STM32设计】数控直流稳压电源的设计与实现(实物+资料+论文)
stm32·嵌入式硬件·mongodb
march_birds20 小时前
FreeRTOS 与 RT-Thread 事件组对比分析
c语言·单片机·算法·系统架构
小麦嵌入式21 小时前
Linux驱动开发实战(十一):GPIO子系统深度解析与RGB LED驱动实践
linux·c语言·驱动开发·stm32·嵌入式硬件·物联网·ubuntu
触角010100011 天前
STM32F103低功耗模式深度解析:从理论到应用实践(上) | 零基础入门STM32第九十二步
驱动开发·stm32·单片机·嵌入式硬件·物联网