[MCU] 【沁恒RISC-V内核 CH582】AHT10

lugl4313820   2022-2-27 20:46 楼主

AHT10传感器,带转接板4.7元,体积小,精度湿度±2%RH,温度精度±0.3℃。这个是国产温湿度传感器,性价比是比较高的,前面采购元件时顺便买了一个回来,今天介绍AHT10温湿度传感器的使用。

关于AHT10温湿度传感器的数据手册在官方网站上面可以下载到:AHT10温湿度传感器的数据手册

网上给的驱动基本上是STM32的,今天我把CH582的驱动移植如下:

myii2.h:

/*
 * myiic.h
 *
 *  Created on: 2022年2月27日
 *      Author: Administrator
 */

#ifndef SRC_MYIIC_H_
#define SRC_MYIIC_H_
#include "CH58x_common.h"
//IO方向设置
typedef unsigned char           u8;
#define I2C_Pin_SCL   GPIO_Pin_8
#define I2C_Pin_SDA   GPIO_Pin_9

#define SCL_H         GPIOB_SetBits( I2C_Pin_SCL )
#define SCL_L         GPIOB_ResetBits( I2C_Pin_SCL )
#define SDA_H         GPIOB_SetBits( I2C_Pin_SDA )
#define SDA_L         GPIOB_ResetBits( I2C_Pin_SDA )
#define SCL_read      GPIOB_ReadPortPin( I2C_Pin_SCL )
#define SDA_read      GPIOB_ReadPortPin( I2C_Pin_SDA )
#define SCL_out       GPIOB_ModeCfg(I2C_Pin_SCL, GPIO_ModeOut_PP_5mA)
#define SCL_in        GPIOB_ModeCfg(I2C_Pin_SCL, GPIO_ModeIN_PU)
#define SDA_out       GPIOB_ModeCfg(I2C_Pin_SDA, GPIO_ModeOut_PP_5mA)
#define SDA_in        GPIOB_ModeCfg(I2C_Pin_SDA, GPIO_ModeIN_PU)




//IIC所有操作函数
void IIC_Init(void);                //初始化IIC的IO口
void IIC_Start(void);       //发送IIC开始信号
void IIC_Stop(void);          //发送IIC停止信号
void IIC_Send_Byte(u8 txd);     //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void);        //IIC等待ACK信号
void IIC_Ack(void);         //IIC发送ACK信号
void IIC_NAck(void);        //IIC不发送ACK信号

void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);


#endif /* SRC_MYIIC_H_ */

myii2c.c

/*
 * myiic.c
 *
 *  Created on: 2022年2月27日
 *      Author: Administrator
 */


#include "myiic.h"
#include "CH58x_common.h"

//初始化IIC
void IIC_Init(void)
{
  SCL_out;
  SDA_out;
}
//产生IIC起始信号
void IIC_Start(void)
{
  SDA_out;     //sda线输出
  SDA_H;
  SCL_H;
  mDelayuS(4);
  SDA_L;//START:when CLK is high,DATA change form high to low
  mDelayuS(4);
  SCL_L;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
  SDA_out;//sda线输出
  SCL_L;
  SDA_L;//STOP:when CLK is high DATA change form low to high
  mDelayuS(4);
  SCL_H;
  SDA_H;//发送I2C总线结束信号
  mDelayuS(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
  u8 ucErrTime=0;
  SDA_in;      //SDA设置为输入
  SDA_H;mDelayuS(1);
  SCL_H;mDelayuS(1);
  while(SDA_read)
  {
    ucErrTime++;
    if(ucErrTime>250)
    {
      IIC_Stop();
      return 1;
    }
  }
  SCL_L;//时钟输出0
  return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
  SCL_L;
  SDA_out;
  SDA_L;
  mDelayuS(2);
  SCL_H;
  mDelayuS(2);
  SCL_L;
}
//不产生ACK应答
void IIC_NAck(void)
{
  SCL_L;
  SDA_out;
  SDA_H;
  mDelayuS(2);
  SCL_H;
  mDelayuS(2);
  SCL_L;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
    u8 t;
  SDA_out;
    SCL_L;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {
    if((txd&0x80)>>7)
      SDA_H;
    else
      SDA_L;
    txd<<=1;
    mDelayuS(2);
    SCL_H;
    mDelayuS(2);
    SCL_L;
    mDelayuS(2);
    }
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
  unsigned char i,receive=0;
  SDA_in;//SDA设置为输入
    for(i=0;i<8;i++ )
  {
        SCL_L;
        mDelayuS(2);
    SCL_H;
        receive<<=1;
        if(SDA_read)receive++;
    mDelayuS(1);
    }
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK
    return receive;
}

aht10.h

/*
 * AHT10.h
 *
 *  Created on: 2022年2月27日
 *      Author: Administrator
 */
#include "CH58x_common.h"
#include "myiic.h"
#ifndef SRC_AHT10_H_
#define SRC_AHT10_H_

#define AHT10_ADDRESS 0x70
#define AHT10_WRITE 0x70
#define AHT10_READ 0x71

/*****************函数声明******************/
extern void AHT10Init(void);
extern uint8_t AHT10Check(void);
extern void AHT10Reset(void);
extern uint8_t AHT10ReadData(float *temperature,uint8_t *humidity);


#endif /* SRC_AHT10_H_ */

aht10.c

/*
 * AHT10.c
 *
 *  Created on: 2022年2月27日
 *      Author: Administrator
 */


#include "CH58x_common.h"
#include "lcd.h"
#include "aht10.h"
#include "myiic.h"


/**
brief AHT10初始化函数
param NONE
return NONE
*/
void AHT10Init()
{
  IIC_Init();


  IIC_Start();
  IIC_Send_Byte(AHT10_ADDRESS);
  IIC_Send_Byte(0xe1);
  IIC_Send_Byte(0x08);
  IIC_Send_Byte(0x00);
  IIC_Stop();
  mDelaymS(40);//延时20ms让传感器稳定
}

/**
brief 检查AHT10是否存在
param NONE
return 0存在  1不存在
*/
u8 AHT10Check(void)
{
  u8 ack=0;
  IIC_Start();
  IIC_Send_Byte(AHT10_ADDRESS);
  ack=IIC_Wait_Ack();
  IIC_Stop();
  return ack;
}

/**
brief AHT10软复位
param NONE
return NONE
*/
void AHT10Reset(void)
{
  IIC_Start();
  IIC_Send_Byte(AHT10_WRITE);
  IIC_Wait_Ack();
  IIC_Send_Byte(0xba);
  IIC_Wait_Ack();
  IIC_Stop();
}

/**
brief 检查AHT10读温湿度数据
param *temperature:需要读出的温度数据,float指针类型,精度范围+-0.3C
param *humidity:需要读出的湿度数据,u8指针类型,精度范围+-2RH
return 0 读数据正常 1读数据失败
*/
u8 AHT10ReadData(float *temperature,u8 *humidity)
{
  u8 ack;
  uint32_t SRH=0,ST=0;
  u8 databuff[6];
  IIC_Start();
  IIC_Send_Byte(AHT10_WRITE);
  IIC_Wait_Ack();
  IIC_Send_Byte(0xac);
  IIC_Wait_Ack();
  IIC_Send_Byte(0x33);
  IIC_Wait_Ack();
  IIC_Send_Byte(0x00);
  IIC_Wait_Ack();
  IIC_Stop();
  mDelaymS(80);//延时一会等待数据读出
  IIC_Start();
  IIC_Send_Byte(AHT10_READ);
  IIC_Wait_Ack();
  ack=IIC_Read_Byte(1);
  if((ack&0x40)==0)
  {
    databuff[0]=IIC_Read_Byte(1);
    databuff[1]=IIC_Read_Byte(1);
    databuff[2]=IIC_Read_Byte(1);
    databuff[3]=IIC_Read_Byte(1);
    databuff[4]=IIC_Read_Byte(0);
    IIC_Stop();
    SRH=(databuff[0]<<12)+(databuff[1]<<4)+(databuff[2]>>4);
    ST=((databuff[2]&0X0f)<<16)+(databuff[3]<<8)+(databuff[4]);
    *humidity=(int)(SRH*100.0/1024/1024+0.5);
    LCD_ShowIntNum(30, 100, *humidity, 2,  BLUE,WHITE, 32);
    *temperature=((int)(ST*2000.0/1024/1024+0.5))/10.0-50;
    LCD_ShowFloatNum1(10, 50, *temperature, 4, BLUE,WHITE, 32);
    return 0;
  }
  IIC_Stop();
  return 1;
}

main.c

/********************************** (C) COPYRIGHT *******************************
 * File Name          : Main.c
 * Author             : 刘建华
 * Version            : V1.0
 * Date               : 2022/02/27
 * Description        : 演示ST7735 硬件SPI驱动 i2c 驱动AHT10,显示
 *******************************************************************************/

#include "CH58x_common.h"
#include "lcd_init.h"
#include "lcd.h"
#include "aht10.h"

UINT16 abcBuff[40];
uint32_t temp_value;
volatile UINT8 adclen;
void DebugInit( void )
{
  GPIOA_SetBits( GPIO_Pin_9 );
  GPIOA_ModeCfg( GPIO_Pin_8, GPIO_ModeIN_PU );
  GPIOA_ModeCfg( GPIO_Pin_9, GPIO_ModeOut_PP_5mA );
  UART1_DefInit();
}

int main()
{
  UINT8 i;
  char show_shr[30];
  float *temperate;
  uint8_t *humidity;
  int  C25;
  int cal;
  C25 = (*((PUINT32)ROM_CFG_TMP_25C));
  signed short RoughCalib_Value = 0;    // ADC粗调偏差值
  SetSysClock( CLK_SOURCE_PLL_60MHz );

  /* 配置串口调试 */
  DebugInit();
  AHT10Init();
  LCD_Init();
  LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
  LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
  LCD_ShowString(10,0,"CH582M",BLUE,WHITE,32,0);

  i = AHT10Check();
  LCD_ShowChinese(36,30,"温度",BLACK,WHITE,24,0);
  LCD_ShowChinese(96,56,"℃",BLACK,WHITE,24,0);
  LCD_ShowChinese(36,80,"湿度",BLACK,WHITE,24,0);
  LCD_ShowString(70, 100, "%", BLUE,WHITE, 32, 0);

  while( 1 )
  {

    if (i==0) {
      AHT10ReadData(temperate,humidity);
      //LCD_ShowFloatNum1(10, 80, *temperate, 4, BLUE,WHITE, 32);
      //LCD_ShowIntNum(10, 120, *humidity, 2,  BLUE,WHITE, 32);
    }
    else {
      LCD_ShowString(10,80,"NO AHT10!",RED,WHITE,16,0);
    }

    mDelaymS(1000);
  }

}


吹气后可以看到温度、湿度的变化。

回复评论 (1)

吹气结果看温湿度的显示还是比较灵敏的

点赞  2022-2-28 23:29
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复