2298 views|2 replies

6818

Posts

11

Resources
The OP
 

【AT-START-F425 Review】Thermohygrometer (Hardware I2C) AHT10 [Copy link]

 This post was last edited by lugl4313820 on 2022-3-29 14:08

I have driven the SPI screen before, and today I learned about the I2C hardware of AT32F425. After referring to the examples of netizens and working on it for a day, I finally got the I2C hardware to drive the thermometer and hygrometer. The report is as follows:

【Drive steps】

1. Create a new AHT driver file AHT10.c and header file AHT10.h in the drivers directory.

2. Select I2C1 IO as PB6-SCL, PB7-SDA. Check the data sheet for GPIO_MUX_1.

3. Define the I2C timeout, communication speed, AHT10 device address, CLK, GPIO port pins, multiplexing number, etc. in the macro:

#define I2C_TIMEOUT                      0xFFFFFFF
                                         
//#define I2Cx_CLKCTRL                   0x2170FAFA   //10K
//#define I2Cx_CLKCTRL                   0x80E06565   //50K
#define I2Cx_CLKCTRL                     0x80E03030   //100K
//#define I2Cx_CLKCTRL                   0x20E0355F   //200K

#define I2Cx_ADDRESS                     0xA0
#define AHT10_ADDRESS                    0x70	               

#define I2Cx_PORT                        I2C1
#define I2Cx_CLK                         CRM_I2C1_PERIPH_CLOCK
#define I2Cx_DMA                         DMA1
#define I2Cx_DMA_CLK                     CRM_DMA1_PERIPH_CLOCK
//SCL 引脚配置重定义     
#define I2Cx_SCL_GPIO_CLK                CRM_GPIOB_PERIPH_CLOCK
#define I2Cx_SCL_GPIO_PIN                GPIO_PINS_6
#define I2Cx_SCL_GPIO_PinsSource         GPIO_PINS_SOURCE6  
#define I2Cx_SCL_GPIO_PORT               GPIOB
#define I2Cx_SCL_GPIO_MUX                GPIO_MUX_1     
//SDA 引脚配置重定义                                 
#define I2Cx_SDA_GPIO_CLK                CRM_GPIOB_PERIPH_CLOCK
#define I2Cx_SDA_GPIO_PIN                GPIO_PINS_7   
#define I2Cx_SDA_GPIO_PinsSource         GPIO_PINS_SOURCE7      
#define I2Cx_SDA_GPIO_PORT               GPIOB
#define I2Cx_SDA_GPIO_MUX                GPIO_MUX_1 

3. Initialize the i2c device structure i2c_handle_type hi2cx;

4. Modify void i2c_lowlevel_init and copy a function in the i2c routine. There is no useful DMA and interrupt here, so you can remove the interrupt and DMA configuration functions:

/**
  * @brief  initializes peripherals used by the i2c.
  * @param  none
  * @retval none
  */
void i2c_lowlevel_init(i2c_handle_type* hi2c)
{
  gpio_init_type gpio_init_structure;
  if(hi2c->i2cx == I2Cx_PORT)
  {
    /* i2c 时钟使能 */
    crm_periph_clock_enable(I2Cx_CLK, TRUE);    
    crm_periph_clock_enable(I2Cx_SCL_GPIO_CLK, TRUE); 
    crm_periph_clock_enable(I2Cx_SDA_GPIO_CLK, TRUE);
    
    /* gpio 复用端口配置 */  
    gpio_pin_mux_config(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_GPIO_PinsSource, I2Cx_SCL_GPIO_MUX);
    gpio_pin_mux_config(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_GPIO_PinsSource, I2Cx_SDA_GPIO_MUX);
    
    /* 配置 i2c pins: scl */
    gpio_init_structure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_structure.gpio_mode           = GPIO_MODE_MUX;
    gpio_init_structure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_structure.gpio_pull           = GPIO_PULL_UP;  
                                            
    gpio_init_structure.gpio_pins           = I2Cx_SCL_GPIO_PIN;
    gpio_init(I2Cx_SCL_GPIO_PORT, &gpio_init_structure);

    /* 配置 i2c pins: sda */
    gpio_init_structure.gpio_pins           = I2Cx_SDA_GPIO_PIN;
    gpio_init(I2Cx_SDA_GPIO_PORT, &gpio_init_structure); 
    
    /* config i2c */ 
    i2c_init(hi2c->i2cx, 0, I2Cx_CLKCTRL);
    i2c_own_address1_set(hi2c->i2cx, I2C_ADDRESS_MODE_7BIT, AHT10_ADDRESS);
	i2c_enable(hi2c->i2cx,TRUE);
  }
}

5. AHT10 write register function:

void AHT_Reset_REG(uint8_t addr)
{
	uint8_t dat1[2]={0};
	uint8_t dat2[3]={0};
//	i2c_status_type i2c_status;
	rt_thread_mdelay(100);
	i2c_memory_write(&hi2cx,AHT10_ADDRESS,addr,dat1,2,0xffffff);
	rt_thread_mdelay(5);
	i2c_master_receive(&hi2cx,AHT10_ADDRESS,dat2,3,0xffffff);
	dat2[0]=0xb0|addr;
	i2c_master_transmit(&hi2cx,AHT10_ADDRESS,dat2,3,0xffffff);
}

6. AHT10 initialization function:

void InitAHT10(void)
{
	  unsigned char rest_dat[2]={0,0},dat1[2]={0x00,0x80};
	  hi2cx.i2cx = I2Cx_PORT;
	  i2c_config(&hi2cx);
		//unsigned char status;	
		rt_thread_mdelay(150);
		AHT_Reset_REG(0x1b);
		rt_thread_mdelay(50);
		AHT_Reset_REG(0x1c);
		rt_thread_mdelay(50);
		AHT_Reset_REG(0x1e);
		rt_thread_mdelay(200);
		i2c_memory_write(&hi2cx,AHT10_ADDRESS,0xa8,rest_dat,2,0xffffff);//0xA8进入NOR工作模式
		rt_thread_mdelay(5);
		i2c_memory_write(&hi2cx,AHT10_ADDRESS,0xe1,dat1,2,0xfffff);//0xBE初始化命令,AHT20的初始化命令是0xBE,   AHT10的初始化命令是0xE1
		rt_thread_mdelay(5);

}

7. Read temperature and data:


void AHT10_Read_CTdata(uint32_t *ct) //没有CRC校验,直接读取AHT10的温度和湿度数据
{
//	i2c_status_type i2c_status;
	unsigned char	dat1[3]={0xac,0x33,0x00},retuenDAT[6]={0},dat2[3]={0xbe,0x08,0x00};//dat1 AC读取命令,retuenDAT 缓存数组,dat2为校准命令
//	unsigned char status=0;

	//uint16_t cnt = 0;
	rt_thread_mdelay(50);
	i2c_master_transmit(&hi2cx,AHT10_ADDRESS,dat2,3,0xffffff);//向AHT20发送校准命令
	rt_thread_mdelay(50);	
	i2c_master_transmit(&hi2cx,AHT10_ADDRESS,dat1,3,0xffffff);//向AHT20发送AC命令
//	printf("i2c_read_status=%d\n\r",i2c_status);
	rt_thread_mdelay(50);
	i2c_master_receive(&hi2cx,AHT10_ADDRESS,retuenDAT,6,0xffffff);
//	printf("i2c_receive_status=%d\n\r",i2c_status);
	while((retuenDAT[0]&0x80)==0x80)
	{
		i2c_master_receive(&hi2cx,AHT10_ADDRESS,retuenDAT,6,0xffffff);
		rt_thread_mdelay(10);
		printf("busy =0x%x\n\r",retuenDAT[0]);

	}
	ct[0]=(((uint32_t)retuenDAT[1]<<12)+((uint32_t)retuenDAT[2]<<4)+((uint32_t)retuenDAT[3]>>4));
	ct[1]=((((uint32_t)retuenDAT[3]&0xf)<<16)+((uint32_t)retuenDAT[4]<<8)+((uint32_t)retuenDAT[5]));	
}

At this point, the AHT10 function has been written. Import AHT10.h into the main function and create a task to display the collected data on the LCD screen.

#define THREAD_PRIORITY         25
#define THREAD_STACK_SIZE       1024
#define THREAD_TIMESLICE        5

static rt_thread_t tid_AHT10 = RT_NULL;

static void tid_AHT10_entry(void *parameter)
{
	uint32_t temp[2]={0};
	volatile float t1;
	u8 humidity;
	while(1)
	{
		AHT10_Read_CTdata(temp);
		humidity=(int)(temp[0]*100.0/1024/1024+0.5);
		t1=((int)(temp[1]*2000.0/1024/1024+0.5))/10.0-50;
		
		LCD_ShowIntNum(90, 100, humidity, 2,  BLUE,WHITE, 32);
		LCD_ShowFloatNum1(80, 60, t1, 4, BLUE,WHITE, 32);
		rt_thread_mdelay(500);
	}
}

【Feelings】

After a day of study, I found that there are still a lot of learning resources for AT32F425, especially the evaluation activity of this development board by Arteli, which has published a lot of posts and articles about driving OLED screens with i2c. As long as you spend some time, driving i2c is still very easy. I spent some time reading the official source code this time and gained a lot.

But last night, when the driver was ready and I was about to finish work, the program suddenly got stuck. I searched for the reason for a long time until noon today. The reason was that the USB power supply must be stable and the current must be sufficient, otherwise it cannot find AHT10 and will keep waiting for a timeout. In fact, the middleware of this official driver is still blocking when processing timeout functions. Under RT-Thread OS, it will run away due to the blocking time. If you want to use it in a production environment, you still need to modify it to a non-blocking timeout wait.

There is still a lot of room for modification in this I2C program, such as the judgment of I2C returning an error when waiting for ACK, NACK, STOP, etc. Compared with software simulation, using hard I2C requires more consideration of extreme environment issues, otherwise there will be many unexpected results.


This post is from Domestic Chip Exchange

Latest reply

Thanks for sharing, looking forward to the follow-up   Details Published on 2022-3-29 17:14
 
 

6818

Posts

11

Resources
2
 

Upload the RT_Thread Studio project for discussion with friends in need.

AT32F425SP9306—AHT10.7z

1.37 MB, downloads: 1

This post is from Domestic Chip Exchange
 
 
 

7422

Posts

2

Resources
3
 

Thanks for sharing, looking forward to the follow-up

This post is from Domestic Chip Exchange
Personal signature

默认摸鱼,再摸鱼。2022、9、28

 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list