基于CH592x的硬件I2C驱动(AHT20)调试记录

前言:AHT20是一个I2C器件,恰好CH592芯片资源有硬件I2C我们可以尝试使用592的硬件I2C去驱动AHT20。

资料:I2C接口使用指南(可见EVT中I2C例程文件下),AHT20数据手册(可以在立创商城直接下载)

数据手册中对这个器件的驱动流程也有说明,

分别对几个步骤进行解读:

 1、根据手册提示开机后,要等待40ms才能够与AHT20通信。0x71地址实际上AHT20作为IIC从机的地址。按照AHT20手册,在启动传输后,随后传输的 I2C首字节包括 7位的 I2C设备地址0x38。因为IIC通信一般使用7位地址码,但是读写数据都是一个字节一个字节的读写。0x38的七位二进制为0111000。规定从机地址要左一位。多出来的第八位就是读写位。IIC协议规定,如果主机发起通信的目的是为了写从机,那么读写位是0,此时AHT20的地址是01110000,即0x70.如果主机发起通信的目的是为了读从机传入的数据,那么读写位就是1。此时AHT20的地址是0x71。

2、直接发送按照命令。按照(0xac,0x33,0x00)依次发送;

3、等待75ms后,读取6个字节数据,里面包含了状态信息,湿度信息,和温度信息。其中第0个字节是状态位,需获取bit[7]判断设备是否空闲。而后,湿度数据由20个bit位组成:第1个字节是湿度的高8位,第2个字节是湿度的次高8位.第3个字节的高4个bit位是湿度的低4位。温度数据也由20个bit位组成。第3个字节的低4个bit位是温度的高4位,第4个字节是温度的次高8位,第5个字节是温度的低8位。

4、根据手册的计算公式将获取的温度、湿度值计算出来。

接下来就可可以看代码实现部分:
AHT20.h

#ifndef DRIVER_CODE_AHT20_H_
#define DRIVER_CODE_AHT20_H_

#include "CH59x_common.h"
#include "app_i2c.h"

extern uint8_t send_data[4];

#define AHT20_Slave_Adress 0x38
#define AHT20_Init_REG_Adress   0x71

extern void AHT20_READ_Status(uint8_t slave_adress , uint8_t reg_adress , uint32_t *cb_data );

AHT20.c

#include "aht20.h"

uint8_t send_data[4]={0xac , 0x33, 0x00};
uint8_t receive_data[7];
uint8_t Inspection_data;

void AHT20_READ_Status(uint8_t slave_adress , uint8_t reg_adress ,uint32_t *cb_data)
{
    uint8_t i = 0;
    uint32_t humi_temp_data =0;

    I2C_Init(I2C_Mode_I2C, 400000, I2C_DutyCycle_16_9, I2C_Ack_Enable, I2C_AckAddr_7bit, 0x42);
    DelayMs(40);

    while(I2C_GetFlagStatus(I2C_FLAG_BUSY) != RESET);

    I2C_GenerateSTART(ENABLE);

    while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
    I2C_Send7bitAddress(slave_adress<<1, I2C_Direction_Transmitter);


    while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    while(i < 3)
                {
                    if(I2C_GetFlagStatus(I2C_FLAG_TXE) != RESET)
                    {
                        I2C_SendData(send_data[i]);
                        i++;
                    }
                }

    while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_GenerateSTART(ENABLE);                                          //重起始信号

    while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));               //判断BUSY, MSL and SB flags
    I2C_Send7bitAddress(reg_adress, I2C_Direction_Receiver);                  //发送地址+最低位1表示为“读”
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));    //判断BUSY, MSL and ADDR flags
    //I2C_GenerateSTOP(DISABLE);

    for(uint8_t j=0; j<7; j++)
        {
            if(j == 7-1)
            I2C_AcknowledgeConfig(DISABLE);         //清除ACK位               主设备为了能在收到最后一个字节后产生一个NACK脉冲,
                                                    //必须在读取倒数第二个字节之后(倒数第二个RxNE 事件之后)清除ACK位(ACK=0)
            while(!I2C_GetFlagStatus(I2C_FLAG_RXNE));                       //获取RxEN的状态,等待收到数据
            receive_data[j] = I2C_ReceiveData();
        }
    I2C_GenerateSTOP(ENABLE);            //停止信号
    humi_temp_data = 0;

    humi_temp_data =(humi_temp_data | receive_data[1])<<8;
    humi_temp_data =(humi_temp_data | receive_data[2])<<8;
    humi_temp_data =(humi_temp_data | receive_data[3]);
    humi_temp_data = humi_temp_data >>4;
    cb_data[0] = humi_temp_data;

    humi_temp_data = 0;
    humi_temp_data =(humi_temp_data | receive_data[3])<<8;
    humi_temp_data =(humi_temp_data | receive_data[4])<<8;
    humi_temp_data =(humi_temp_data | receive_data[5]);
    humi_temp_data = humi_temp_data&0xfffff;
    cb_data[1] = humi_temp_data;

    PRINT("湿度 %d\r\n",cb_data[0]*100/1048576);
    PRINT("温度 %d\r\n",(cb_data[1]*200/1048576)-50);
};

 仅是个人学习分享;如有任何错漏敬请留言指正。

 

posted @ 2024-03-07 11:10  小舟从此逝_1  阅读(234)  评论(0编辑  收藏  举报