打印
[MM32软件]

【灵动微电子MM32F5330测评】5.I2C驱动OLED+读取温湿度

[复制链接]
713|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
I2C全称Inter-Integrated Circuit,直接翻译过来就是内部集成电路,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发明。 I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。I2C通信方式为半双工,只有一根SDA线,同一时间只可以单向通信。

MM32F5330内置 2 个 I2C 接口, 能够工作于多主模式或从模式, 支持标准(100 Kbps)、 快速模式(400 Kbps)和快速扩展模式(1 Mbps), 支持 7 位或 10 位寻址。 支持 SMBus。所有的 I2C 接口都可以使用 DMA 操作。
开发板上集成了一颗EEPROM,例程里有它的驱动代码,这里就不再重新驱动了,改用I2C来驱动OLED

初始化I2C
void APP_I2CInit(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    I2C_InitTypeDef  I2C_InitStruct;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);

    I2C_DeInit(I2C2);
    I2C_StructInit(&I2C_InitStruct);
    I2C_InitStruct.I2C_Mode       = I2C_MODE_MASTER;
    I2C_InitStruct.I2C_OwnAddress = I2C_OWN_ADDRESS;
    I2C_InitStruct.I2C_ClockSpeed = 100000;
    I2C_Init(I2C2, &I2C_InitStruct);

    GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_4);
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_4);

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOC, &GPIO_InitStruct);

    I2C_Cmd(I2C2, ENABLE);
}

I2C读写方法
#define MM32I2C_TIMEOUT 0xFFFF

uint8_t YUYY_HARDI2C_WaitFlag(I2C_TypeDef *i2cx,uint32_t flag,FlagStatus status)
{
    uint16_t timeout = MM32I2C_TIMEOUT;
    while(I2C_GetFlagStatus(i2cx, flag) != status)
    {
        timeout -= 1;
        if(timeout == 0)
            return 1;
    }
    return 0;
}

uint8_t YUYY_HARDI2C_SendDatas(I2C_TypeDef *i2cx,uint8_t *datas,uint8_t datalen)
{
    uint8_t i=0;
    while(i<datalen)
    {
        if(YUYY_HARDI2C_WaitFlag(i2cx,I2C_STATUS_FLAG_TFE,SET))
        {
            I2C_GenerateSTOP(i2cx, ENABLE);
            return 2;
        }
        I2C_SendData(i2cx, datas[i]);
        i += 1;
    }
    return 0;
}

uint8_t YUYY_HARDI2C_ReadDatas(I2C_TypeDef *i2cx,uint8_t *datas,uint8_t datalen)
{
    uint8_t i=0;
    while(i<datalen)
    {
        I2C_ReadCmd(i2cx);
        if(YUYY_HARDI2C_WaitFlag(i2cx,I2C_STATUS_FLAG_RFNE,SET))
        {
            I2C_GenerateSTOP(i2cx, ENABLE);
            return 2;
        }
        datas[i] = I2C_ReceiveData(i2cx);
        i += 1;
    }
    return 0;
}

uint8_t YUYY_HARDI2C_MasterSendDatasWithOption(I2C_TypeDef *i2cx,uint8_t devaddr,uint8_t option,uint8_t *datas,uint16_t datalen)
{
    uint8_t err = 0;
    if(!i2cx)
        return 1;
    I2C_TargetAddressConfig(i2cx,devaddr<<1);
    err = YUYY_HARDI2C_SendDatas(i2cx,datas,datalen);
    if(option & YUYY_I2C_SEND_STOP)
    {
        YUYY_HARDI2C_WaitFlag(i2cx,I2C_STATUS_FLAG_TFE,SET);
        I2C_GenerateSTOP(i2cx, ENABLE);
        YUYY_HARDI2C_WaitFlag(i2cx,I2C_STATUS_FLAG_TFE,SET);
    }
    return err;
}
uint8_t YUYY_HARDI2C_MasterReadDatasWithOption(I2C_TypeDef *i2cx,uint8_t devaddr,uint8_t option,uint8_t *datas,uint16_t datalen)
{
    uint8_t err = 0;
    if(!i2cx)
        return 1;
    I2C_TargetAddressConfig(i2cx,devaddr<<1);
    err = YUYY_HARDI2C_ReadDatas(i2cx,datas,datalen);
    if(option & YUYY_I2C_SEND_STOP)
    {
        I2C_GenerateSTOP(i2cx, ENABLE);
        YUYY_HARDI2C_WaitFlag(i2cx,I2C_STATUS_FLAG_TFE,SET);
    }
    return err;
}

uint8_t YUYY_HARDI2C_MasterSendRegDatas(I2C_TypeDef *i2cx,uint8_t devaddr,uint8_t *reg,uint8_t reglen,uint8_t *datas,uint16_t datalen)
{
    uint8_t err = 0;
    if(!i2cx)
        return 1;
    err = YUYY_HARDI2C_MasterSendDatasWithOption(i2cx,devaddr,0,reg,reglen);
    if(err == 0)
        err = YUYY_HARDI2C_MasterSendDatasWithOption(i2cx,devaddr,YUYY_I2C_SEND_STOP,datas,datalen);
    return err;
}
uint8_t YUYY_HARDI2C_MasterReadRegDatas(I2C_TypeDef *i2cx,uint8_t devaddr,uint8_t *reg,uint8_t reglen,uint8_t *datas,uint16_t datalen)
{
    uint8_t err = 0;
    if(!i2cx)
        return 1;
    if(reglen > 0)
    {
        err = YUYY_HARDI2C_SendDatas(i2cx,reg,reglen);
        if(err == 0 && YUYY_HARDI2C_WaitFlag(i2cx,I2C_STATUS_FLAG_TFE,SET))
            err = 4;
    }
    if(err == 0)
        err = YUYY_HARDI2C_MasterReadDatasWithOption(i2cx,devaddr,YUYY_I2C_SEND_STOP,datas,datalen);
    return err;
}

这个OLED是SSD1315驱动的,网上可以搜到具体的驱动代码,或者可以看我过往发的帖子,这里就不放完整代码了,只放上初始化代码
YUYY_OLED_SSD1315_DEV_Type oled_dev;
void APP_OledInit()
{
    oled_dev.i2cx = I2C2;
    oled_dev.i2c_senddatas_func = (YUYY_OLED_SSD1315_I2CSendDatasFunc_Type)YUYY_HARDI2C_MasterSendReg8Datas;
    YUYY_OLED_SSD1315_Init(&oled_dev);
    YUYY_OLED_SSD1315_ClearScreen(&oled_dev);
    YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,0,0,"MM32F5330 TEST");
    YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,2,0,"    I2C OLED");
    YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,4,0,"  bbs.21ic.com");
    YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,6,0,"Code by yuyy1989");
}

运行效果

I2C总线上可以挂载多个从设备,接下来就再增加个温湿度传感器,用I2C读取温湿度传感器的数据,并显示在OLED屏幕上,这里用的是DHTC12温湿度传感器,性能如下图

DHTC12驱动代码在以往的帖子里有,这里就不放代码了,只放上初始化代码
YUYY_DHTC12_DEV_Type dhtc12_dev;
void APP_DHTC12Init(void)
{
    dhtc12_dev.i2cx = I2C2;
    dhtc12_dev.delayms_func = YUYY_DelayMs;
    dhtc12_dev.i2c_readregdatas_func = (YUYY_DHTC12_I2CReadRegDatasFunc_Type)YUYY_HARDI2C_MasterReadRegDatas;
    dhtc12_dev.i2c_sendregdatas_func = (YUYY_DHTC12_I2CSendRegDatasFunc_Type)YUYY_HARDI2C_MasterSendRegDatas;
    YUYY_DHTC12_Init(&dhtc12_dev);
}
int main(void)
{
    int16_t temp,humi;
    char out[20];
    uart_init();
    led_init();
    APP_I2CInit();
    APP_OledInit();
    APP_DHTC12Init();
    while (1)
    {
        YUYY_DelayMs(100);
        led_toggle(LED_NO_1);
        if(!YUYY_DHTC12_ReadHT(&dhtc12_dev,&temp,&humi))
        {
            sprintf(out,"T:%03.1f  H:%03.1f%%\n",temp/10.0,humi/10.0);
            YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,4,0,out);
        }
    }
}

运行效果


使用特权

评论回复
沙发
地瓜patch| | 2024-7-30 22:38 | 只看该作者
oled的字体很漂亮的呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

146

主题

698

帖子

6

粉丝