[AIROC™ 蓝牙]【英飞凌CYW20829测评】5.I2C驱动OLED和读取温湿度

I2C总线是Philips公司在八十年代初推出的一种串行、半双工的总线,主要用于近距离、低速的芯片之间的通信;I2C总线有两根双向的信号线,一根数据线SDA用于收发数据,一根时钟线SCL用于通信双方时钟的同步。连接在 I2C总线上的器件分为主机和从机,主机有权发起和结束一次通信,从机只能被动呼叫,每个连接到I2C总线上的器件都有一个唯一的地址。
 


开发板上引出的I2C接口是这个
 


不过使用了BSP后我们可以不用关心具体是哪个IO,这些都在BSP里定义好了,接下来使用CYW20829作为I2C主机点亮OLED屏幕,初始化I2C代码,配置为主机模式速度100k,初始化代码如下
 

复制

cyhal_i2c_t i2c_obj;

void APP_I2CInit(void)

{

    cyhal_i2c_cfg_t cfg = {

            .address = 0,

            .is_slave = false,

            .frequencyhal_hz = 100000,

    };

    cyhal_i2c_init(&i2c_obj,CYBSP_I2C_SDA,CYBSP_I2C_SCL,NULL);

    cyhal_i2c_configure(&i2c_obj,&cfg);

}


可以看到用了官方的BSP后初始化外设十分的简便,接下来实现OLED驱动代码,这个OLED是SSD1315驱动的,网上可以搜到具体的驱动代码,或者可以看我过往发的帖子,这里就不放完整代码了,只放上I2C通讯部分

复制

#define YUYY_OLED_SSD1315_I2C_ADDR 0x3C



uint8_t YUYY_OLED_SSD1315_I2CSendDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t cmd,uint8_t *datas,uint8_t datalen)

{

    uint8_t err = 0;

    err = cyhal_i2c_master_mem_write(oled_ssd1315_dev->i2cx,YUYY_OLED_SSD1315_I2C_ADDR,cmd,1,datas,datalen,1000);

    return err;

}



uint8_t YUYY_OLED_SSD1315_SendCmds(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t *cmds,uint8_t cmdlen)

{

    return YUYY_OLED_SSD1315_I2CSendDatas(oled_ssd1315_dev,0x00,cmds,cmdlen);

}



uint8_t YUYY_OLED_SSD1315_SendDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t *datas,uint8_t datalen)

{

    return YUYY_OLED_SSD1315_I2CSendDatas(oled_ssd1315_dev,0x40,datas,datalen);

}


点亮OLED显示指定字符串

复制

YUYY_OLED_SSD1315_DEV_Type oled_dev;

void APP_OledInit(void)

{

    oled_dev.i2cx = &i2c_obj;

    YUYY_OLED_SSD1315_Init(&oled_dev);

    YUYY_OLED_SSD1315_ClearScreen(&oled_dev);

    YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,0,0," CYW20829 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驱动代码

复制

#define DHTC12_I2C_ADDR 0x44

typedef struct

{

    uint8_t inited;

    cyhal_i2c_t *i2cx;

}YUYY_DHTC12_DEV_Type;

static uint16_t HumA,HumB;



uint8_t YUYY_DHTC12_WriteCmd(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint16_t cmd)

{

    uint8_t regs[2];

    regs[0] = (cmd>>8)&0xFF;

    regs[1] = cmd&0xFF;

    return cyhal_i2c_master_write(dhtc12_dev->i2cx,DHTC12_I2C_ADDR,regs,2,1000,true);

}



uint8_t YUYY_DHTC12_ReadDatas(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint8_t *rdatas,uint8_t rlen)

{

    return cyhal_i2c_master_read(dhtc12_dev->i2cx,DHTC12_I2C_ADDR,rdatas,rlen,1000,true);

}



uint8_t YUYY_DHTC12_ReadCmd(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint16_t cmd,uint8_t *rdatas,uint8_t rlen)

{

    uint8_t regs[2];

    regs[0] = (cmd>>8)&0xFF;

    regs[1] = cmd&0xFF;

    cyhal_i2c_master_write(dhtc12_dev->i2cx,DHTC12_I2C_ADDR,regs,2,1000,false);

    return cyhal_i2c_master_read(dhtc12_dev->i2cx,DHTC12_I2C_ADDR,rdatas,rlen,1000,true);

}



//初始化,获取湿度运算系数

uint8_t YUYY_DHTC12_Init(YUYY_DHTC12_DEV_Type *dhtc12_dev)

{

    uint8_t x,err = 0,retry = 3;

    dhtc12_dev->inited = 0;

    //复位传感器

    err = YUYY_DHTC12_WriteCmd(dhtc12_dev,0x30A2);

    err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD208,&x,1);

    HumA = (x<<8)&0xFF00;

    err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD209,&x,1);

    HumA |= x;

    

    err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD20A,&x,1);

    HumB = (x<<8)&0xFF00;

    err = YUYY_DHTC12_ReadCmd(dhtc12_dev,0xD20B,&x,1);

    HumB |= x;

    //HumA=0x7168;  HumB=0x2D73;

    //ReadDatSH[6]={0xF3, 0xA9, 0xC0, 0x41, 0xB4, 0x87}

    //27.6 48.4%

    dhtc12_dev->inited = 1;

    return 0;

}



const uint16_t POLYNOMIAL = 0x131; //P(x)=x^8+x^5+x^4+1 = 100110001



uint8_t YUYY_DHTC12_CheckCrc(uint8_t Data[], uint8_t nbrOfBytes)

{

    uint8_t crc = 0xff; //0

    uint8_t byteCtr,Bit;

    //calculates 8-Bit checksum with given polynomial

    for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)

    {

        crc ^= (Data[byteCtr]);

        for (Bit = 8; Bit > 0; --Bit)

        {

            if (crc & 0x80)

                crc = (crc << 1) ^ POLYNOMIAL;

            else

                crc = (crc << 1);

        }

    }

    if (crc != Data[nbrOfBytes])

    {

        Data[nbrOfBytes] = crc;

        return 0x01;

    }

    else

        return 0;

}



//单次触发温湿度测量

uint8_t YUYY_DHTC12_ReadHT(YUYY_DHTC12_DEV_Type *dhtc12_dev,int16_t *tem,int16_t *hum)

{

    uint8_t i=0,errRe,ReadDatSH[6],CalCRC[3],errorflag=0;

    int16_t TemBuf;

    uint16_t CapBuf;

    errRe = YUYY_DHTC12_WriteCmd(dhtc12_dev,0x2C10);

    if(errRe)

        errRe = YUYY_DHTC12_WriteCmd(dhtc12_dev,0x2C10);

    if(errRe)

    {

        return 0x10|errRe; //发送命令失败

    }

    

    Cy_SysLib_Delay(100);

    errRe = YUYY_DHTC12_ReadDatas(dhtc12_dev,ReadDatSH,6);



    if(errRe)

    {

        return 0x20|errRe; //接收数据失败

    }

    CalCRC[0] = ReadDatSH[0];

    CalCRC[1] = ReadDatSH[1];

    CalCRC[2] = ReadDatSH[2];

    errorflag = YUYY_DHTC12_CheckCrc(CalCRC,2);

    if(errorflag==0)

    {

        TemBuf = (int16_t)(((ReadDatSH[0]<<8)&0xFF00)|ReadDatSH[1]);

        *tem = TemBuf*10/256 + 400;

    }

    CalCRC[0] = ReadDatSH[3];

    CalCRC[1] = ReadDatSH[4];

    CalCRC[2] = ReadDatSH[5];

    errorflag <<= 1;

    errorflag |= YUYY_DHTC12_CheckCrc(CalCRC,2);

    if(errorflag==0)

    {

        CapBuf = (uint16_t)(((ReadDatSH[3]<<8)&0xFF00)|ReadDatSH[4]);

        *hum = (CapBuf-HumB)*600/(HumA-HumB)+300;

        //20℃为5个湿度点  即1℃为0.25个湿度点  0.1℃为0.025

        *hum = *hum+ 2.5*(*tem-250);

        if(*hum>1000)

            *hum = 999;

        else if(*hum<0)

            *hum = 0;

    }

    return errorflag;    

}


初始化,读取温湿度并显示在OLED上

复制

YUYY_DHTC12_DEV_Type dhtc12_dev;

void APP_DHTC12Init(void)

{

    dhtc12_dev.i2cx = &i2c_obj;

    YUYY_DHTC12_Init(&dhtc12_dev);

}

int main(void)

{

    cy_rslt_t result;

    uint8_t printf_count = 0;

    int16_t temp,humi;

    char out[20];

    result = cybsp_init();

    if (result != CY_RSLT_SUCCESS)

    {

        CY_ASSERT(0);

    }

    app_uart_init();

    APP_I2CInit();

    printf("APP Start\n");

    /* Enable global interrupts */

    __enable_irq();



    for (;;)

    {

        Cy_SysLib_Delay(1000);

        printf_count += 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);

        }

    }

}


运行效果
 


除了以上的设备之外,还有很多其他的设备(例如气压传感器、EEPROM、LED驱动器等)可以使用I2C通讯控制,有兴趣的伙伴可以自行尝试。
---------------------
作者:yuyy1989
链接:https://bbs.21ic.com/icview-3385940-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值