打印
[活动]

【APM32F411V Tiny Board测评】4.I2C点亮OLED和读取温湿度传感器数据

[复制链接]
852|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
原本想用硬件驱动的,结果和评测407时一样总是搞不定,官方的bsp_i2c也是用的模拟I2C,官网搜I2C相关文档也只能搜到模拟I2C与EEPROM通讯的,最后放弃改用软件模拟I2C
选用PB6和PB7作为SCL和SDA,初始化为开漏输出模式
YUYY_SOFTIIC_DEV_Type siic;
void app_SoftI2cInit()
{
    GPIO_Config_T gpioConfigStruct;
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
    GPIO_ConfigStructInit(&gpioConfigStruct);
    gpioConfigStruct.mode = GPIO_MODE_OUT;
    gpioConfigStruct.speed = GPIO_SPEED_100MHz;
    gpioConfigStruct.pin = GPIO_PIN_6 | GPIO_PIN_7;
    gpioConfigStruct.otype = GPIO_OTYPE_OD;
    gpioConfigStruct.pupd = GPIO_PUPD_NOPULL;
    GPIO_Config(GPIOB, &gpioConfigStruct);
   
    siic.scl.gpio = GPIOB;
    siic.scl.pin = GPIO_PIN_6;
    siic.sda.gpio = GPIOB;
    siic.sda.pin = GPIO_PIN_7;
    YUYY_SOFTIIC_Init(&siic);
}
模拟I2C代码

#define YUYY_SOFT_IIC_ACK 0
#define YUYY_SOFT_IIC_NACK 1

#define YUYY_SOFT_IIC_PIN_SDA 0
#define YUYY_SOFT_IIC_PIN_SCL 1


void YUYY_SOFTIIC_GPIO_INOUT(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t pin,uint8_t inout)
{
    if(pin == YUYY_SOFT_IIC_PIN_SDA)
        iicx->gpio_inout_func(&(iicx->sda),inout);
    else if(pin == YUYY_SOFT_IIC_PIN_SCL)
        iicx->gpio_inout_func(&(iicx->scl),inout);
}

void YUYY_SOFTIIC_GPIO_SETLEV(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t pin,YUYY_GPIO_LEV_TYPE lev)
{
    if(pin == YUYY_SOFT_IIC_PIN_SDA)
        iicx->gpio_setlev_func(&(iicx->sda),lev);
    else if(pin == YUYY_SOFT_IIC_PIN_SCL)
        iicx->gpio_setlev_func(&(iicx->scl),lev);
}

YUYY_GPIO_LEV_TYPE YUYY_SOFTIIC_GPIO_GETLEV(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t pin)
{
    if(pin == YUYY_SOFT_IIC_PIN_SDA)
        return iicx->gpio_getlev_func(&(iicx->sda));
    else if(pin == YUYY_SOFT_IIC_PIN_SCL)
        return iicx->gpio_getlev_func(&(iicx->scl));
    return YUYY_GPIO_LEV0;
}

void YUYY_SOFTIIC_DELAYMS(YUYY_SOFTIIC_DEV_Type *iicx,uint32_t delay)
{
    iicx->iic_delayus_func(delay);
}

uint8_t YUYY_SOFTIIC_WaitScl_Timeout(YUYY_SOFTIIC_DEV_Type *iicx,YUYY_GPIO_LEV_TYPE lev)
{
    uint8_t i = 0;
    while(YUYY_SOFTIIC_GPIO_GETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL) != YUYY_GPIO_LEV1)
    {
        i += 1;
        if (i == 10)
        {
            return 1;
        }
        YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
    }
    return 0;
}


uint8_t YUYY_SOFTIIC_Start(YUYY_SOFTIIC_DEV_Type *iicx)
{
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
    if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
        return 1;

    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV0);
    YUYY_SOFTIIC_DELAYMS(iicx,5*iicx->iic_delay_time);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
    YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
    return YUYY_SOFTIIC_OK;
}

uint8_t YUYY_SOFTIIC_Stop(YUYY_SOFTIIC_DEV_Type *iicx)
{
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV0);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
    if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
        return 1;

    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
    return YUYY_SOFTIIC_OK;
}

uint8_t YUYY_SOFTIIC_ReadACK(YUYY_SOFTIIC_DEV_Type *iicx)
{
    uint8_t i=0,ack=YUYY_SOFT_IIC_ACK;
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODIN);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
    if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
        return 1;
   
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
    while(YUYY_SOFTIIC_GPIO_GETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA)!=YUYY_GPIO_LEV0 && i<10)
    {
        YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
        i += 1;
    }
    if(i>8)
        ack = YUYY_SOFT_IIC_NACK;
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
    YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
    return ack;
}

uint8_t YUYY_SOFTIIC_SendACK(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t ack)
{
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
    if(ack == YUYY_SOFT_IIC_ACK)
        YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV0);
    else
        YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
    if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
        return 1;
   
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
    YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
    return YUYY_SOFTIIC_OK;
}

uint8_t YUYY_SOFTIIC_SendByte(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t dat)
{
    uint8_t i = 0;
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
    while(i<8)
    {
        if(dat & 0x80)
            YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
        else
            YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV0);
        YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
        YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
        if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
            return 1;
        
        YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
        YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
        YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
        YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
        dat = dat << 1;
        i += 1;
    }
    return YUYY_SOFTIIC_OK;
}

uint8_t YUYY_SOFTIIC_ReadByte(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t *dat)
{
    uint8_t i = 0;
    *dat = 0;
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODIN);
    while(i<8)
    {
        YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
        YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODIN);
        if(YUYY_SOFTIIC_WaitScl_Timeout(iicx,YUYY_GPIO_LEV1))
            return 1;
        
        YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
        YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
        *dat = *dat << 1;
        if(YUYY_SOFTIIC_GPIO_GETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA) == YUYY_GPIO_LEV1)
            *dat |= 0x01;
        YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV0);
        YUYY_SOFTIIC_DELAYMS(iicx,iicx->iic_delay_time);
        i += 1;
    }
    return YUYY_SOFTIIC_OK;
}

void YUYY_SOFTIIC_Init(YUYY_SOFTIIC_DEV_Type *iicx)
{
    if(!iicx->iic_delayus_func)
    {
        iicx->iic_delayus_func = YUYY_DelayUs;
        iicx->iic_delay_time = 1;
    }
    if(!iicx->gpio_inout_func)
        iicx->gpio_inout_func = YUYY_GPIO_ODInOut;
    if(!iicx->gpio_setlev_func)
        iicx->gpio_setlev_func = YUYY_GPIO_SetLev;
    if(!iicx->gpio_getlev_func)
        iicx->gpio_getlev_func = YUYY_GPIO_GetLev;
    //SDA SCL需接上拉电阻,开漏输出
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_GPIO_INOUT(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_ODOUT);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SDA,YUYY_GPIO_LEV1);
    YUYY_SOFTIIC_GPIO_SETLEV(iicx,YUYY_SOFT_IIC_PIN_SCL,YUYY_GPIO_LEV1);
    //YUYY_SOFTIIC_Stop(iicx);
}
//此处设备地址已经过移位处理,最低位0写1读
uint8_t YUYY_SOFTIIC_MasterSendStart(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr)
{
    if(YUYY_SOFTIIC_Start(iicx) != YUYY_SOFTIIC_OK)
        return 1;

    if(YUYY_SOFTIIC_SendByte(iicx,devaddr) != YUYY_SOFTIIC_OK)
        return 2;
   
    if(YUYY_SOFTIIC_ReadACK(iicx) != YUYY_SOFT_IIC_ACK)
        return 3;
    return 0;
}

uint8_t YUYY_SOFTIIC_MasterSendDatasWithOption(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t option,uint8_t *datas,uint16_t datalen)
{
    uint8_t i = 0,err = YUYY_SOFTIIC_OK;
    if(!iicx)
        return 1;
    if(option & YUYY_IIC_SEND_START)
    {
        err = YUYY_SOFTIIC_MasterSendStart(iicx,(devaddr<<1)&0xFE);
        if(err != YUYY_SOFTIIC_OK)
            return err;
    }
    while (i < datalen)
    {
        YUYY_SOFTIIC_SendByte(iicx,datas[i]);
        if(YUYY_SOFTIIC_ReadACK(iicx) != YUYY_SOFT_IIC_ACK)
            return 4;
        i += 1;
    }
    if(option & YUYY_IIC_SEND_STOP)
        YUYY_SOFTIIC_Stop(iicx);
    return YUYY_SOFTIIC_OK;
}
uint8_t YUYY_SOFTIIC_MasterReadDatasWithOption(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t option,uint8_t *datas,uint16_t datalen)
{
    uint8_t i = 0,err = YUYY_SOFTIIC_OK,ack;
    if(!iicx)
        return 1;
    if(option & YUYY_IIC_SEND_START)
    {
        err = YUYY_SOFTIIC_MasterSendStart(iicx,(devaddr<<1)|0x01);
        if(err != YUYY_SOFTIIC_OK)
            return err;
    }
    while (i < datalen)
    {
        if(YUYY_SOFTIIC_ReadByte(iicx,&datas[i]) != YUYY_SOFTIIC_OK)
            return 4;
        if(i==datalen-1)
            ack = YUYY_SOFT_IIC_NACK;
        else
            ack = YUYY_SOFT_IIC_ACK;
        if(YUYY_SOFTIIC_SendACK(iicx,ack) != YUYY_SOFTIIC_OK)
            return 5;
        i += 1;
    }
    if(option & YUYY_IIC_SEND_STOP)
        YUYY_SOFTIIC_Stop(iicx);
    return YUYY_SOFTIIC_OK;
}
uint8_t testerr = 0;

uint8_t YUYY_SOFTIIC_MasterSendRegDatas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t *reg,uint8_t reglen,uint8_t *datas,uint16_t datalen)
{
        uint8_t i = 0,ack = YUYY_SOFT_IIC_ACK,err = YUYY_SOFTIIC_OK;
    if(!iicx)
        return 1;
    err = YUYY_SOFTIIC_MasterSendDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START,reg,reglen);
    testerr = err;
    if(err == YUYY_SOFTIIC_OK)
            err = YUYY_SOFTIIC_MasterSendDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_STOP,datas,datalen);
    testerr = err;
        return err;
}
uint8_t YUYY_SOFTIIC_MasterReadRegDatas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t *reg,uint8_t reglen,uint8_t *datas,uint16_t datalen)
{
        uint8_t i = 0,ack = YUYY_SOFT_IIC_ACK,err = YUYY_SOFTIIC_OK;
    if(!iicx)
        return 1;
        if(reglen > 0)
        {
        err = YUYY_SOFTIIC_MasterSendDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START,reg,reglen);
        }
        if(err == YUYY_SOFTIIC_OK)
        err = YUYY_SOFTIIC_MasterReadDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START|YUYY_IIC_SEND_STOP,datas,datalen);
        return err;
}

uint8_t YUYY_SOFTIIC_MasterSendDatas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t *datas,uint16_t datalen)
{
    return YUYY_SOFTIIC_MasterSendDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START|YUYY_IIC_SEND_STOP,datas,datalen);
}

uint8_t YUYY_SOFTIIC_MasterReadDatas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t *datas,uint16_t datalen)
{
    return YUYY_SOFTIIC_MasterReadDatasWithOption(iicx,devaddr,YUYY_IIC_SEND_START|YUYY_IIC_SEND_STOP,datas,datalen);
}

uint8_t YUYY_SOFTIIC_MasterSendReg8Datas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t reg,uint8_t *datas,uint16_t datalen)
{
    return YUYY_SOFTIIC_MasterSendRegDatas(iicx,devaddr,®,1,datas,datalen);
}
uint8_t YUYY_SOFTIIC_MasterReadReg8Datas(YUYY_SOFTIIC_DEV_Type *iicx,uint8_t devaddr,uint8_t reg,uint8_t *datas,uint16_t datalen)
{
    return YUYY_SOFTIIC_MasterReadRegDatas(iicx,devaddr,®,1,datas,datalen);
}
OLED驱动代码
#define YUYY_OLED_SSD1315_IIC_ADDR 0x3C
const uint8_t oled_ssd1315_init_cmd[25]=
{
       0xAE,//关闭显示
       0xD5,//设置时钟分频因子,震荡频率
       0x80,  //[3:0],分频因子;[7:4],震荡频率
       0xA8,//设置驱动路数
       0X3F,//默认0X3F(1/64)
       0xD3,//设置显示偏移
       0X00,//默认为0
       0x40,//设置显示开始行 [5:0],行数.                              
       0x8D,//电荷泵设置
       0x14,//bit2,开启/关闭
       0x20,//设置内存地址模式
       0x02,//[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
       0xA1,//段重定义设置,bit0:0,0->0;1,0->127;
       0xC8,//设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
       0xDA,//设置COM硬件引脚配置
       0x12,//[5:4]配置            
       0x81,//对比度设置
       0xEF,//1~255;默认0X7F (亮度设置,越大越亮)
       0xD9,//设置预充电周期
       0xF1,//[3:0],PHASE 1;[7:4],PHASE 2;
       0xDB,//设置VCOMH 电压倍率
       0x30,//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
       0xA4,//全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
       0xA6,//设置显示方式;bit0:1,反相显示;0,正常显示        
       0xAF,//开启显示     
};

uint8_t YUYY_OLED_SSD1315_IICSendDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t cmd,uint8_t *datas,uint8_t datalen)
{
    uint8_t err = 0;
    if(!oled_ssd1315_dev->iic_senddatas_func)
        return 1;
    err = oled_ssd1315_dev->iic_senddatas_func(oled_ssd1315_dev->iicx,YUYY_OLED_SSD1315_IIC_ADDR,cmd,datas,datalen);
    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_IICSendDatas(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_IICSendDatas(oled_ssd1315_dev,0x40,datas,datalen);
}

uint8_t YUYY_OLED_SSD1315_SetPageCol(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t page,uint8_t col)
{
    uint8_t cmds[3];
    if(page < 8 && col < 128)
    {
        cmds[0] = 0xB0+page;
        cmds[1] = 0x10|(col>>4);
        cmds[2] = 0x00|(col&0x0f);
        return YUYY_OLED_SSD1315_SendCmds(oled_ssd1315_dev,cmds,3);
    }
    return 1;
}

uint8_t YUYY_OLED_SSD1315_ClearScreen(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev)
{
    uint8_t i=0,datas[128]={0};
    while(i<8)
    {
        if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,i,0))
            return 1;
        if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,128))
            return 1;
        i += 1;
    }
    return 0;
}

uint8_t YUYY_OLED_SSD1315_TestScreen(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t d1,uint8_t d2)
{
    uint8_t i=0,datas[128]={0};
    while (i < 128)
    {
        datas[i] = d1;
        datas[i+1] = d2;
        i += 2;
    }
    i = 0;
    while(i<8)
    {
        if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,i,0))
            return 1;
        if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,128))
            return 1;
        i += 1;
    }
    return 0;
}

uint8_t YUYY_OLED_SSD1315_Init(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev)
{
    uint8_t err = 0;
    err = YUYY_OLED_SSD1315_SendCmds(oled_ssd1315_dev,(uint8_t *)oled_ssd1315_init_cmd,25);
    return err;
}

void YUYY_OLED_SSD1315_CopyDatas(uint8_t *dst,uint8_t *src,uint8_t len,uint8_t rev)
{
    uint8_t i = 0;
    while (i < len)
    {
        if(rev)
            dst[i] = ~src[i];
        else
            dst[i] = src[i];
        i += 1;
    }
}


void YUYY_OLED_SSD1315_DisplayDatas(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t option,uint8_t page,uint8_t column,uint8_t *dp,uint8_t width,uint8_t height)
{
    uint8_t rev,i=0,j=0,k=0,hp=height/8;
    uint8_t datas[128] = {0};
    rev = option&YUYY_FONT_DATAS_REVERSE;
    if((option&YUYY_FONT_DATAS_COL_COL) == 0)
    {
        while (i<hp)
        {
            if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page+i,column))
                return;
            YUYY_OLED_SSD1315_CopyDatas(datas,dp,width,rev);
            if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,width))
                return;
            i+=1;
        }
    }
    else
    {
        while (i<hp)
        {
            if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page+i,column))
                return;
            k=i;
            j=0;
            while (j<width)
            {
                if(rev == 0)
                    datas[j] == dp[k];
                else
                    datas[j] == ~dp[k];
                j+=1;
                k+=hp;
            }
            if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,width))
                return;
            i+=1;
        }
    }
}

void YUYY_OLED_SSD1315_DisplayString8x16(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t option,uint8_t page,uint8_t column,char *text)
{
    uint8_t i=0,j = 0,rev = option&YUYY_FONT_DATAS_REVERSE;
    uint8_t datas1[128] = {0},datas2[128] = {0};
   
    while(text[i]>0x00 && j < 128)
    {
        if((text[i] > 0x1F)&&(text[i] < 0x7F))
        {
            YUYY_OLED_SSD1315_CopyDatas(&datas1[j],(uint8_t *)&YUYY_FONT_ASCII_TABLE_8x16[text[i]-0x20][0],8,rev);
            YUYY_OLED_SSD1315_CopyDatas(&datas2[j],(uint8_t *)&YUYY_FONT_ASCII_TABLE_8x16[text[i]-0x20][8],8,rev);
        }
        j += 8;
        i += 1;
    }
    if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page,column))
        return;
    if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas1,j))
        return;
    if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page+1,column))
        return;
    if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas2,j))
        return;
}

void YUYY_OLED_SSD1315_DisplayString6x8(YUYY_OLED_SSD1315_DEV_Type *oled_ssd1315_dev,uint8_t option,uint8_t page,uint8_t column,char *text)
{
    uint8_t i=0,j = 0,rev = option&YUYY_FONT_DATAS_REVERSE;
    uint8_t datas[128] = {0};
    while(text[i]>0x00 && j < 128)
    {
        if((text[i] > 0x1F)&&(text[i] < 0x7F))
        {
            if(j < 126)
                YUYY_OLED_SSD1315_CopyDatas(&datas[j],(uint8_t *)YUYY_FONT_ASCII_TABLE_6x8[text[i]-0x20],6,rev);
            else
                YUYY_OLED_SSD1315_CopyDatas(&datas[j],(uint8_t *)YUYY_FONT_ASCII_TABLE_6x8[text[i]-0x20],2,rev);
        }
        j += 6;
        i += 1;
    }
    if(j > 128)
        j = 128;
    if(YUYY_OLED_SSD1315_SetPageCol(oled_ssd1315_dev,page,column))
        return;
    if(YUYY_OLED_SSD1315_SendDatas(oled_ssd1315_dev,datas,j))
        return;
}
初始化OLED
void oled_init()
{
//    oled_dev.iicx = I2C1;
//    oled_dev.iic_senddatas_func = (YUYY_OLED_SSD1315_IICSendDatasFunc_Type)YUYY_HARDIIC_MasterSendReg8Datas;
    oled_dev.iicx = &siic;
    oled_dev.iic_senddatas_func = (YUYY_OLED_SSD1315_IICSendDatasFunc_Type)YUYY_SOFTIIC_MasterSendReg8Datas;
    YUYY_OLED_SSD1315_Init(&oled_dev);
    YUYY_OLED_SSD1315_ClearScreen(&oled_dev);
    YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,0,0," APM32F411 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");
}
运行效果

接下来读取DHTC12的温湿度数据并在OLED上显示出来
DHTC12驱动代码

#define DHTC12_I2C_ADDR 0x44

static uint16_t HumA,HumB;

uint8_t YUYY_DHTC12_WriteCmd(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint16_t cmd)
{
        return dhtc12_dev->iic_sendregdatas_func(dhtc12_dev->iicx,DHTC12_I2C_ADDR,cmd,NULL,0);
}

uint8_t YUYY_DHTC12_ReadDatas(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint8_t *rdatas,uint8_t rlen)
{
        return dhtc12_dev->iic_readdatas_func(dhtc12_dev->iicx,DHTC12_I2C_ADDR,rdatas,rlen);
}

uint8_t YUYY_DHTC12_ReadCmd(YUYY_DHTC12_DEV_Type *dhtc12_dev,uint16_t cmd,uint8_t *rdatas,uint8_t rlen)
{
        return dhtc12_dev->iic_readregdatas_func(dhtc12_dev->iicx,DHTC12_I2C_ADDR,cmd,rdatas,rlen);
}

//初始化,获取湿度运算系数
uint8_t YUYY_DHTC12_Init(YUYY_DHTC12_DEV_Type *dhtc12_dev)
{
    uint8_t x,err = 0,retry = 3;
    dhtc12_dev->inited = 0;
    if(!dhtc12_dev->delayms_func)
        dhtc12_dev->delayms_func = YUYY_DelayMs;
    //复位传感器
    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; //发送命令失败
    }
   
    dhtc12_dev->delayms_func(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;       
}
DHTC12初始化
YUYY_DHTC12_DEV_Type dhtc12_dev;
void dhtc12_init()
{
//    dhtc12_dev.iicx = I2C1;
    dhtc12_dev.iicx = &siic;
    dhtc12_dev.delayms_func = YUYY_DelayMs;
//    dhtc12_dev.iic_readdatas_func = (YUYY_DHTC12_IICReadDatasFunc_Type)YUYY_HARDIIC_MasterReadDatas;
//    dhtc12_dev.iic_readregdatas_func = (YUYY_DHTC12_IICReadReg16BEDatasFunc_Type)YUYY_HARDIIC_MasterReadReg16BEDatas;
//    dhtc12_dev.iic_sendregdatas_func = (YUYY_DHTC12_IICSendReg16BEDatasFunc_Type)YUYY_HARDIIC_MasterSendReg16BEDatas;
    dhtc12_dev.iic_readdatas_func = (YUYY_DHTC12_IICReadDatasFunc_Type)YUYY_SOFTIIC_MasterReadDatas;
    dhtc12_dev.iic_readregdatas_func = (YUYY_DHTC12_IICReadReg16BEDatasFunc_Type)YUYY_SOFTIIC_MasterReadReg16BEDatas;
    dhtc12_dev.iic_sendregdatas_func = (YUYY_DHTC12_IICSendReg16BEDatasFunc_Type)YUYY_SOFTIIC_MasterSendReg16BEDatas;
    YUYY_DHTC12_Init(&dhtc12_dev);
}
在main函数中调用
int main(void)
{
    uint8_t i = 0;
    int16_t temp,humi;
    char out[20];
    ConfigSysClock();
    yuyy_LedInit();
    tim9_init();
//    pwm_init();
    uart_init();
//    core_main();
//    app_I2CInit();
    //YUYY_HARDIIC_SetInitFunc(app_I2CInit);
    app_SoftI2cInit();
    oled_init();
    dhtc12_init();
    while (1)
    {
        i += 1;
//        printf("极海APM32F411串口Printf测试 by yuyy1989 当前数字是:%d\n",i);
        YUYY_DelayMs(1000);
        yuyy_LedToggle(YUYY_LED2);
        YUYY_DelayMs(1000);
        yuyy_LedToggle(YUYY_LED3);
        YUYY_DelayMs(1000);
        yuyy_LedToggle(YUYY_LED2|YUYY_LED3);
        if(!YUYY_DHTC12_ReadHT(&dhtc12_dev,&temp,&humi))
        {
            sprintf(out,"T:%03.1f  H:%03.1f%%",temp/10.0,humi/10.0);
            YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,4,0,out);
        }
    }
}
运行效果


使用特权

评论回复
沙发
丙丁先生| | 2024-7-1 17:32 | 只看该作者
移植不清楚,需要代码

使用特权

评论回复
板凳
caigang13| | 2024-7-2 08:27 | 只看该作者
这种小尺寸的OLED用IIC控制还好,屏幕再大点,通信速率上不去了。

使用特权

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

本版积分规则

146

主题

698

帖子

6

粉丝