GD32F303移植ATH10温湿度模块

该文介绍了如何在GD32F303RCT6开发板上使用Keil5进行ATH10温湿度传感器的I2C驱动移植,包括前期准备、时钟频率调整、GPIO配置、I2C通信协议实现以及读取数据的步骤。文章提供了详细的代码示例,如`ATH10.c`、`ATH10.h`和`main.c`,并展示了成功读取温湿度数据后的效果图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前期准备

移植准备

开始移植

        ATH10.c

        ATH10.h

        main.c

效果图

总结


前期准备

开发硬件:GD32F303RCT6开发板

开发平台:Keil5

网盘资料:见文章底部

移植准备

        ATH10模块I2C驱动使用到us延时,因此需要调整时钟频率,调整方法详细请看GD32F303移植4针0.96寸OLED显示屏(I2C)时钟频率调整部分,这里就不过多讲解了。

开始移植

        ATH10.c

#include "gd32f30x.h"
#include "systick.h"
#include <stdio.h>
#include "ath10.h"

/*
	初始化ATH10 GPIO引脚
*/
void ath10_iic_gpio_init(void)
{
	//	使能GPIOB时钟
    rcu_periph_clock_enable(ATH10_ENABLE_GPIO);
	
	//	配置ATH10_SDA_PIN为输出
    gpio_init(ATH10_SDA_GPIO, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, ATH10_SDA_PIN);	
	
	//	配置ATH10_SCL_PIN为输出
    gpio_init(ATH10_SCL_GPIO, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, ATH10_SCL_PIN);	
	
	ATH10_SDA_H;
	ATH10_SCL_H;
}

/*
	SDA模式切换

	mode:	1:输出	
			0:输入
*/
void ath10_iic_sda_mode(uint8_t mode)
{
	//	使能GPIOB时钟
    rcu_periph_clock_enable(ATH10_ENABLE_GPIO);
	
	if (mode)
	{
		//	配置ATH10_SDA_PIN为输出
		gpio_init(ATH10_SDA_GPIO, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,ATH10_SDA_PIN);	
	}
	else
	{
		//	配置ATH10_SDA_PIN为上拉输入
		gpio_init(ATH10_SDA_GPIO, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ,ATH10_SDA_PIN);	
	}
}

/*
	读取SDA 输入模式下的引脚状态
*/
uint8_t read_sda_in_mode_data(void)
{
	return gpio_input_bit_get(ATH10_SDA_GPIO, ATH10_SDA_PIN);
}

/*
	主机发送开始信号
*/
void ath10_start(void)
{
	ATH10_SDA_OUT;	//	SDA为输出模式
	
	ATH10_SCL_H;	//	拉高SCL
	ATH10_SDA_H;	//	拉高SDA
	delay_us(5);
	
	ATH10_SDA_L;	//	先拉低SDA,持续5us
	delay_us(5);
	ATH10_SCL_L;	//	再拉低SCL
}

/*
	主机发送停止信号
*/
void ath10_stop(void)
{
	ATH10_SDA_OUT;	//	SDA为输出模式
	
	ATH10_SCL_L;	//	拉低SCL
	ATH10_SDA_L;	//	拉低SDA
	delay_us(5);
	
	ATH10_SCL_H;	//	先拉高SCL,持续5us
	delay_us(5);
	ATH10_SDA_H;	//	再拉高SDA
}

/*
	等待从机应答

	返回:	0:收到应答	
			1:未收到应答
*/
uint8_t	ath10_wait_ack(void)
{
	uint8_t	ErrTime = 0;
	
	ATH10_SDA_IN;
	
	ATH10_SDA_H;
	delay_us(1);
	ATH10_SCL_H;
	delay_us(1);
	
	//	循环读取SDA引脚状态
	while (read_sda_in_mode_data())
	{
		ErrTime++;
		
		if (ErrTime > 250)
		{
			ath10_stop();
			
			return 1;
		}
	}
	
	ATH10_SCL_L;
	delay_us(1);
	
	return 0;
}

/*
	主机是否发送应答	

	ack:	1:发送	
			0:不发送
*/
void ath10_send_ack(uint8_t ack)
{
	ATH10_SCL_L;
	
	ATH10_SDA_OUT;
	
	if (ack)	ATH10_SDA_L;
	else		ATH10_SDA_H;
	
	delay_us(2);
	
	ATH10_SCL_H;
	delay_us(2);
	ATH10_SCL_L;
}

/*
	主机发送一个字节
*/
void ath10_send_Byte(uint8_t data)
{
	uint8_t i;
	ATH10_SDA_OUT;
	
	ATH10_SCL_L;
	delay_us(2);
	
	for (i=0; i<8; i++)
	{
		if ((data<<i) & 0x80)	ATH10_SDA_H;
		else	ATH10_SDA_L;
		
		ATH10_SCL_H;
		delay_us(2);
		
		ATH10_SCL_L;
		delay_us(2);
	}
}

/*
	主机读取一个字节
*/
uint8_t ath10_read_Byte(void)
{
	uint8_t i, receive = 0;
	
	ATH10_SCL_L;
	ATH10_SDA_IN;
	delay_us(2);
	
	for (i=0; i<8; i++)
	{
		ATH10_SCL_H;
		delay_us(1);
		
		receive<<=1;
		
		if (read_sda_in_mode_data())	receive ++;
		
		ATH10_SCL_L;
		delay_us(1);
	}
	
	return receive;
}

/*
	检测ATH10是否响应	

	返回:	1:未响应	
			0:响应
*/
uint8_t ath10_check(void)
{
	uint8_t ack = 0;
	
	ath10_start();
	
	ath10_send_Byte(ATH10_ADDRESS);
	
	ack = ath10_wait_ack();
	
	ath10_stop();
	
	return ack;
}

/*
	初始化ATH10
*/
uint8_t ath10_init(void)
{
	ath10_iic_gpio_init();
	
	ath10_start();
	
	ath10_send_Byte(ATH10_ADDRESS); 	
	ath10_wait_ack();
	
	ath10_send_Byte(0xe1);				
	ath10_wait_ack();
	
	ath10_send_Byte(0x08); 				
	ath10_wait_ack();
	
	ath10_send_Byte(0x00); 
	ath10_wait_ack();
	
	ath10_stop();
	delay_1ms(40);	//	延时40ms,使传感器稳定
	
	return 1;
}

/*
	ATH10 软件复位
*/
void ath10_reset(void)
{
	ath10_start();
	
	ath10_send_Byte(ATH10_WRITE);
	ath10_wait_ack();

	ath10_send_Byte(0xba);
	ath10_wait_ack();
	
	ath10_stop();
}

/*
	读取ATH10 温湿度数据	

	返回:	0:获取成功		
			1:获取失败
*/
uint8_t ath10_read_data(uint16_t *temp, uint16_t *humi)
{
	//	状态(第1数据)
	uint8_t state = 0;
	
	//	数据2-6
	uint8_t	databuf[5];
	
	//	for循环次数
	uint8_t	i;
	
	//	温度、湿度缓冲区
	uint32_t temp_buf = 0, humi_buf = 0;
	
	/*----------------- 触发测量 -----------------------*/
	ath10_start();
	
	ath10_send_Byte(ATH10_WRITE);	
	ath10_wait_ack();
	
	ath10_send_Byte(0xac);			
	ath10_wait_ack();
	
	ath10_send_Byte(0x33);			
	ath10_wait_ack();
	
	ath10_send_Byte(0x00);			
	ath10_wait_ack();
	
	ath10_stop();
	delay_1ms(80);	//	手册中要求主机发出测量指令(0xAC)后,需延时75ms以上
	/*---------------------------------------------------*/
	
	ath10_start();
	
	ath10_send_Byte(ATH10_READ);	
	ath10_wait_ack();
	
	state = ath10_read_Byte();
	ath10_send_ack(1);
	
	//	首次读取为状态数据,判断Bit7位,0表示可正常读取,1表示传感器正忙
	if ((state&0x80) == 0)
	{
		for (i=0; i<5; i++)
		{
			databuf[i] = ath10_read_Byte();
			
			if (i == 4)	ath10_send_ack(0);
			else	ath10_send_ack(1);
		}
		
		ath10_stop();
		
		//	第2、3数据,第4数据高4位为湿度数据
		humi_buf = (databuf[0]<<12) + (databuf[1]<<4) + (databuf[2]>>4);
		
		//	第4数据低4位,第5、6数据为湿度数据
		temp_buf = ((databuf[2]&0x0f)<<16) + (databuf[3]<<8) + (databuf[4]);
		
		*humi = humi_buf*1000/1024/1024;
		*temp = temp_buf*2000/1024/1024-500;	
		
		printf("获取温湿度成功!\r\n");
		
		return 0;
	}
	
	printf("获取温湿度失败!\r\n");
	ath10_stop();
	
	return 1;
}

        ATH10.h

#ifndef ATH10_H
#define ATH10_H

/*-------------------------------- GPIO ------------------------------------------*/

#define	ATH10_ENABLE_GPIO	RCU_GPIOB

#define	ATH10_SDA_GPIO	GPIOB
#define	ATH10_SCL_GPIO	GPIOB

#define ATH10_SDA_PIN	GPIO_PIN_1
#define ATH10_SCL_PIN	GPIO_PIN_2

#define ATH10_SDA_H	gpio_bit_write(ATH10_SDA_GPIO, ATH10_SDA_PIN, SET)
#define ATH10_SDA_L	gpio_bit_write(ATH10_SDA_GPIO, ATH10_SDA_PIN, RESET)

#define ATH10_SCL_H	gpio_bit_write(ATH10_SCL_GPIO, ATH10_SCL_PIN, SET)
#define ATH10_SCL_L	gpio_bit_write(ATH10_SCL_GPIO, ATH10_SCL_PIN, RESET)

#define OUT_MODE	1
#define IN_MODE		0

#define ATH10_SDA_OUT	ath10_iic_sda_mode(OUT_MODE)
#define ATH10_SDA_IN	ath10_iic_sda_mode(IN_MODE)

/*-------------------------------- ADDRESS ------------------------------------------*/

#define	ATH10_ADDRESS	0x70
#define ATH10_WRITE	0x70
#define ATH10_READ	0x71

/*-------------------------------- Func Dec ------------------------------------------*/

void ath10_iic_gpio_init(void);
void ath10_iic_sda_mode(uint8_t mode);
uint8_t read_sda_in_mode_data(void);

void ath10_start(void);
void ath10_stop(void);
uint8_t	ath10_wait_ack(void);
void ath10_send_ack(uint8_t ack);
void ath10_send_Byte(uint8_t data);
uint8_t ath10_read_Byte(void);
uint8_t ath10_check(void);

uint8_t ath10_init(void);
void ath10_reset(void);
uint8_t ath10_read_data(uint16_t *temp, uint16_t *humi);
/*-------------------------------- End ------------------------------------------*/

#endif

        main.c

#include "gd32f30x.h"
#include "systick.h"
#include <stdio.h>
#include <string.h>
#include "ath10.h"

uint16_t	temp = 0;
uint16_t	humi = 0;

char temp_string[32];
char humi_string[32];

int main(void)
{
	uint8_t flag = 0;

	//	设置主频120MHZ -- 分频器选择
	rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV1);
	
	//	配置系统时钟	--	1us
	systick_config();
	
	//	使能AF时钟 -- 开启GPIO复用功能
	rcu_periph_clock_enable(RCU_AF); 
	
	//	延时1s
	delay_1ms(1000);
	
	//	将SWJ和NRST引脚重新映射到其他可用的引脚上,以确保它们不会与其他外设引脚功能发生冲突。
	//	即可当作普通IO引脚使用
	gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE);

	flag = ath10_init();
	
	if (flag == 0)
	{
		printf("Init Error!\r\n");
		
		return 0;
	}


	while (1)
	{
		if ( ath10_read_data(&temp, &humi) == 0)
		{
			sprintf(temp_string,"Temp:%d%d.%d C", temp/100, (temp/10)%10, temp%10);
			sprintf(humi_string,"Humi:%d%d.%d RH", humi/100, (humi/10)%10, humi%10);
			
			printf("%s -- %s\r\n", temp_string, humi_string);
		}

		delay_1ms(100);
	}
}

        串口打印部分的代码根据自身的情况进行添加,这里作者就不加上了。

效果图

总结

        写的比较简洁,如有遗漏之处还请各位大佬指正,我是陈师傅,我们下章再见!

ATH10icon-default.png?t=N3I4https://pan.baidu.com/s/12tqMsbFS1bO-oHjrjvC4kQ?pwd=3p8b

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值