打印
[活动专区]

【AT-START-F405测评】4.I2C应用实现温湿度表

[复制链接]
1654|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
首先来配置I2C,在AT32 Work Bench中开启I2C1,这里可以直接设置I2C的各项参数

自动分配的IO是PC0和PC1

生成代码后添加I2C读写方法,可以考i2c_application_library来实现

#include "yuyy_hard_iic.h"

#define AT32I2C_TIMEOUT 0xFFFF

void YUYY_HARDIIC_ResetCtrl2Register(i2c_type *iicx)
{
  iicx->ctrl2_bit.saddr     = 0;
  iicx->ctrl2_bit.readh10   = 0;
  iicx->ctrl2_bit.cnt       = 0;
  iicx->ctrl2_bit.rlden     = 0;
  iicx->ctrl2_bit.dir       = 0;
}

uint8_t YUYY_HARDIIC_WaitFlag(i2c_type *iicx,uint32_t flag,flag_status status)
{
    uint16_t timeout = AT32I2C_TIMEOUT;
    while(i2c_flag_get(iicx, flag) != status)
    {
        timeout -= 1;
        if(timeout == 0)
            return 1;
    }
    return 0;
}

uint8_t YUYY_HARDIIC_MasterSendStop(i2c_type *iicx)
{
    i2c_stop_generate(iicx);
    if(YUYY_HARDIIC_WaitFlag(iicx,I2C_STOPF_FLAG,SET))
        return 6;
    i2c_flag_clear(iicx, I2C_STOPF_FLAG);
    return 0;
}

uint8_t YUYY_HARDIIC_MasterSendStart(i2c_type *iicx,uint8_t devaddr,i2c_start_mode_type startmode,i2c_reload_stop_mode_type stopmode,uint8_t datalen)
{
    if(startmode != I2C_WITHOUT_START && YUYY_HARDIIC_WaitFlag(iicx,I2C_BUSYF_FLAG,RESET))
        return 1;
    i2c_transmit_set(iicx, devaddr<<1, datalen, stopmode, startmode);
    return 0;
}

uint8_t YUYY_HARDIIC_SendDatas(i2c_type *iicx,uint8_t *datas,uint8_t datalen)
{
    uint8_t i=0;
    while(i<datalen)
    {
        if(YUYY_HARDIIC_WaitFlag(iicx,I2C_TDIS_FLAG,SET))
        {
            if(i2c_flag_get(iicx, I2C_ACKFAIL_FLAG) != RESET)
            {
                i2c_flag_clear(iicx, I2C_ACKFAIL_FLAG);
                return 3;
            }
            YUYY_HARDIIC_MasterSendStop(iicx);
            return 2;
        }
        if(i2c_flag_get(iicx, I2C_ACKFAIL_FLAG) != RESET)
        {
            i2c_flag_clear(iicx, I2C_ACKFAIL_FLAG);
            return 3;
        }
        i2c_data_send(iicx, datas[i]);
        i += 1;
    }
    return 0;
}

uint8_t YUYY_HARDIIC_ReadDatas(i2c_type *iicx,uint8_t *datas,uint8_t datalen)
{
    uint8_t i=0;
    while(i<datalen)
    {
        if(YUYY_HARDIIC_WaitFlag(iicx,I2C_RDBF_FLAG,SET))
        {
            if(i2c_flag_get(iicx, I2C_ACKFAIL_FLAG) != RESET)
            {
                i2c_flag_clear(iicx, I2C_ACKFAIL_FLAG);
                return 3;
            }
            YUYY_HARDIIC_MasterSendStop(iicx);
            return 2;
        }
        datas[i] = i2c_data_receive(iicx);
        i += 1;
    }
    return 0;
}

uint8_t YUYY_HARDIIC_MasterSendDatasWithStartStop(i2c_type *iicx,uint8_t devaddr,uint8_t startstop,uint8_t *datas,uint16_t datalen)
{
    uint8_t err = 0;
    if(!iicx)
        return 1;
    i2c_start_mode_type startmode = I2C_WITHOUT_START;
    i2c_reload_stop_mode_type stopmode = I2C_RELOAD_MODE;
    if(startstop & YUYY_IIC_SEND_START)
        startmode = I2C_GEN_START_WRITE;
    if(startstop & YUYY_IIC_SEND_STOP)
        stopmode = I2C_SOFT_STOP_MODE;
    err = YUYY_HARDIIC_MasterSendStart(iicx,devaddr,startmode,stopmode,datalen);
    if(err == 0)
        err = YUYY_HARDIIC_SendDatas(iicx,datas,datalen);
    if(stopmode == I2C_SOFT_STOP_MODE)
    {
        if(err == 0)
            err = YUYY_HARDIIC_MasterSendStop(iicx);
        if(err != 0)
            YUYY_HARDIIC_ResetCtrl2Register(iicx);
    }
    return err;
}
uint8_t YUYY_HARDIIC_MasterReadDatasWithStartStop(i2c_type *iicx,uint8_t devaddr,uint8_t startstop,uint8_t *datas,uint16_t datalen)
{
    uint8_t err = 0;
    if(!iicx)
        return 1;
    i2c_start_mode_type startmode = I2C_WITHOUT_START;
    i2c_reload_stop_mode_type stopmode = I2C_RELOAD_MODE;
    if(startstop & YUYY_IIC_SEND_START)
        startmode = I2C_GEN_START_READ;
    if(startstop & YUYY_IIC_SEND_STOP)
        stopmode = I2C_SOFT_STOP_MODE;
    err = YUYY_HARDIIC_MasterSendStart(iicx,devaddr,startmode,stopmode,datalen);
    if(err == 0)
        err = YUYY_HARDIIC_ReadDatas(iicx,datas,datalen);
    if(stopmode == I2C_SOFT_STOP_MODE)
    {
        if(err == 0)
            err = YUYY_HARDIIC_MasterSendStop(iicx);
        if(err != 0)
            YUYY_HARDIIC_ResetCtrl2Register(iicx);
    }
    return err;
}

uint8_t YUYY_HARDIIC_MasterSendRegDatas(i2c_type *iicx,uint8_t devaddr,uint8_t *reg,uint8_t reglen,uint8_t *datas,uint16_t datalen)
{
    uint8_t err = 0;
    if(!iicx)
        return 1;
    err = YUYY_HARDIIC_MasterSendStart(iicx,devaddr,I2C_GEN_START_WRITE,I2C_SOFT_STOP_MODE,reglen+datalen);
    err = YUYY_HARDIIC_MasterSendDatasWithStartStop(iicx,devaddr,0,reg,reglen);
    if(err == 0)
        err = YUYY_HARDIIC_MasterSendDatasWithStartStop(iicx,devaddr,YUYY_IIC_SEND_STOP,datas,datalen);
    return err;
}
uint8_t YUYY_HARDIIC_MasterReadRegDatas(i2c_type *iicx,uint8_t devaddr,uint8_t *reg,uint8_t reglen,uint8_t *datas,uint16_t datalen)
{
    uint8_t err = 0;
    if(!iicx)
        return 1;
    if(reglen > 0)
    {
        err = YUYY_HARDIIC_MasterSendStart(iicx,devaddr,I2C_GEN_START_WRITE,I2C_SOFT_STOP_MODE,reglen);
        if(err == 0)
            err = YUYY_HARDIIC_SendDatas(iicx,reg,reglen);
        if(err == 0 && YUYY_HARDIIC_WaitFlag(iicx,I2C_TDC_FLAG,SET))
            err = 4;
    }
    if(err == 0)
        err = YUYY_HARDIIC_MasterReadDatasWithStartStop(iicx,devaddr,YUYY_IIC_SEND_STOP,datas,datalen);
    return err;
}

uint8_t YUYY_HARDIIC_MasterSendDatas(YUYY_IIC_TYPE iicx,uint8_t devaddr,uint8_t *datas,uint16_t datalen)
{
    return YUYY_HARDIIC_MasterSendDatasWithStartStop(iicx,devaddr,YUYY_IIC_SEND_START|YUYY_IIC_SEND_STOP,datas,datalen);
}

uint8_t YUYY_HARDIIC_MasterReadDatas(YUYY_IIC_TYPE iicx,uint8_t devaddr,uint8_t *datas,uint16_t datalen)
{
    return YUYY_HARDIIC_MasterReadDatasWithStartStop(iicx,devaddr,YUYY_IIC_SEND_START|YUYY_IIC_SEND_STOP,datas,datalen);
}

uint8_t YUYY_HARDIIC_MasterSendReg8Datas(YUYY_IIC_TYPE iicx,uint8_t devaddr,uint8_t reg,uint8_t *datas,uint16_t datalen)
{
    return YUYY_HARDIIC_MasterSendRegDatas(iicx,devaddr,®,1,datas,datalen);
}
uint8_t YUYY_HARDIIC_MasterReadReg8Datas(YUYY_IIC_TYPE iicx,uint8_t devaddr,uint8_t reg,uint8_t *datas,uint16_t datalen)
{
    return YUYY_HARDIIC_MasterReadRegDatas(iicx,devaddr,®,1,datas,datalen);
}
uint8_t YUYY_HARDIIC_MasterSendReg16SEDatas(YUYY_IIC_TYPE iicx,uint8_t devaddr,uint16_t reg,uint8_t *datas,uint16_t datalen)
{
    uint8_t regd[2];
    regd[0] = reg&0xFF;
    regd[1] = (reg>>8)&0xFF;
    return YUYY_HARDIIC_MasterSendRegDatas(iicx,devaddr,regd,2,datas,datalen);
}
uint8_t YUYY_HARDIIC_MasterReadReg16SEDatas(YUYY_IIC_TYPE iicx,uint8_t devaddr,uint16_t reg,uint8_t *datas,uint16_t datalen)
{
    uint8_t regd[2];
    regd[0] = reg&0xFF;
    regd[1] = (reg>>8)&0xFF;
    return YUYY_HARDIIC_MasterReadRegDatas(iicx,devaddr,regd,2,datas,datalen);
}
uint8_t YUYY_HARDIIC_MasterSendReg16BEDatas(YUYY_IIC_TYPE iicx,uint8_t devaddr,uint16_t reg,uint8_t *datas,uint16_t datalen)
{
    uint8_t regd[2];
    regd[1] = reg&0xFF;
    regd[0] = (reg>>8)&0xFF;
    return YUYY_HARDIIC_MasterSendRegDatas(iicx,devaddr,regd,2,datas,datalen);
}
uint8_t YUYY_HARDIIC_MasterReadReg16BEDatas(YUYY_IIC_TYPE iicx,uint8_t devaddr,uint16_t reg,uint8_t *datas,uint16_t datalen)
{
    uint8_t regd[2];
    regd[1] = reg&0xFF;
    regd[0] = (reg>>8)&0xFF;
    return YUYY_HARDIIC_MasterReadRegDatas(iicx,devaddr,regd,2,datas,datalen);
}
先来驱动这个OLED显示屏

这个屏幕之前评测423时介绍了驱动方法,代码可以直接拿过来用,帖子地址https://bbs.21ic.com/icview-3338910-1-1.html
使用的时候只要修改i2c的指针和写方法就好了
YUYY_OLED_SSD1315_DEV_Type oled_dev;
void oled_init()
{
    oled_dev.iicx = I2C1;
    oled_dev.iic_senddatas_func = (YUYY_OLED_SSD1315_IICSendDatasFunc_Type)YUYY_HARDIIC_MasterSendReg8Datas;
    YUYY_OLED_SSD1315_Init(&oled_dev);
    YUYY_OLED_SSD1315_ClearScreen(&oled_dev);
    YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,0,0," AT32F405 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读取DHTC12的温湿度数据,这个在之前评测423时也介绍过驱动方法,帖子地址https://bbs.21ic.com/icview-3338286-1-1.html
同样修改i2c的指针和写方法就好,和OLED用同一路I2C
YUYY_DHTC12_DEV_Type dhtc12_dev;
void detc12_init()
{
    dhtc12_dev.iicx = I2C1;
    dhtc12_dev.delayms_func = YUYY_DelayMs;
    dhtc12_dev.iic_readdatas_func = YUYY_HARDIIC_MasterReadDatas;
    dhtc12_dev.iic_readregdatas_func = YUYY_HARDIIC_MasterReadReg16BEDatas;
    dhtc12_dev.iic_sendregdatas_func = YUYY_HARDIIC_MasterSendReg16BEDatas;
    YUYY_DHTC12_Init(&dhtc12_dev);
}
在OLED屏幕上显示温湿度,在主循环中添加
YUYY_DelayMs(1000);
      if(!YUYY_DHTC12_ReadHT(&dhtc12_dev,&temp,&humi))
      {
          sprintf(out,"T:%03.1f  H:%03.1f%%",temp,humi/);
          YUYY_OLED_SSD1315_DisplayString8x16(&oled_dev,0,4,0,out);
      }
运行效果






使用特权

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

本版积分规则

149

主题

708

帖子

7

粉丝