IIC温湿度检测实验

iic.h

#ifndef __IIC_H__
#define __IIC_H__
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_i2c.h"
/*
 * CLK---->PF14
 * SDA---->PF15
*/
//初始化RCC、GPIO、IIC空闲态
void iic_init();

//IIC主机发送(SDA引脚为输入模式)
#define SET_WRITE do{GPIOF->MODER &= (~(0x3<<30));}while(0)
//IIC主机接收(SDA引脚为输出模式)
#define SET_READ do{GPIOF->MODER &= (~(0x3<<30));\
					GPIOF->MODER |= (0x1<<30);}while(0)
//CLK高电平
#define CLK_H do{GPIOF->BSRR |= (0x1<<14);}while(0)
//CLK低电平
#define CLK_L do{GPIOF->BRR |= (0x1<<14);}while(0)
//SDA高电平
#define SDA_H do{GPIOF->BSRR |= (0x1<<15);}while(0)
//SDA低电平
#define SDA_L do{GPIOF->BRR |= (0x1<<15);}while(0)
//获取SDA当前值
#define SDA_READ (GPIOF->IDR & (0x1<<15))
//延时函数
void delay_us();
//开始信号
void start();
//停止信号
void stop();
//发送数据
void write_byte(unsigned char data);
//读取数据
unsigned char read_byte(unsigned char reack);
//等待应答
unsigned char wait_ack();
//应答
void ack();
//非应答
void no_ack();
#endif

iic.c

#include "iic.h"

/*
 * CLK---->PF14
 * SDA---->PF15
*/

//初始化RCC、GPIO、IIC空闲态
void iic_init()
{
	//GPIOF组使能
	RCC->MP_AHB4ENSETR |= (0x1<<5);
	//设置输出模式
	GPIOF->MODER &= (~(0xf<<28));
	GPIOF->MODER |= (0x5<<28);
	//设置输出类型为推挽输出
	GPIOF->OTYPER &= (~(0x3<<14));
	//输出速度设置为高速输出
	GPIOF->OSPEEDR |= (0xf<<28);
	//禁止上下拉电阻
	GPIOF->PUPDR &= (~(0xf<<28));
	//设置IIC为空闲态
	CLK_H;
	SDA_H;
}

//延时函数
void delay_us()
{
	unsigned short i=2000;
	while(i--);
}
//开始信号
void start()
{
	//写入模式
	SET_WRITE;
	//拉高时钟线和数据线
	CLK_H;
	SDA_H;
	//延时
	delay_us();
	//拉低数据线
	SDA_L;
	delay_us();
	//保持总线被占用状态
	CLK_L;
}
//停止信号
void stop()
{
	//写入模式
	SET_WRITE;
	CLK_L;
	delay_us();
	//拉低数据线
	SDA_L;
	delay_us();
	//拉高时钟线
	CLK_H;
	delay_us();
	//拉高数据线
	SDA_H;
	delay_us();
}
//发送数据
void write_byte(unsigned char data)
{
	SET_WRITE;
	unsigned int i;
	for(i=0; i<8;i++)
	{
		//拉低时钟线,准备写入数据
		CLK_L;
		delay_us();
		if(data & 0x80)//取最高位
		{
			SDA_H;//高位为1写高电平
		}else
		{
			SDA_L;//高位为0写低电平
		}
		delay_us();
		CLK_H;
		delay_us();
		delay_us();
		data <<= 1;//数据左移一位准备发送下一位
	}
}
//读取数据
unsigned char read_byte(unsigned char reack)
{
	SET_READ;
	unsigned int i;
	unsigned char data;
	for(i=0; i<8; i++)
	{
		//保证数据写完整
		CLK_L;
		delay_us();
		delay_us();
		//拉高时钟线,准备读数据
		CLK_H;
		delay_us();
		data <<= 1;
		if(SDA_READ)
		{
			data |= 1;//读取到1
		}else
		{
			data |= 0;//读取到0
		}
		delay_us();
	}
	if(reack)
	{
		no_ack();//非应答
	}else
	{
		ack();//应答
	}
	return data;
}
//等待应答
unsigned char wait_ack()
{
	SET_WRITE;
	CLK_L;
	SDA_H;
	delay_us();

	SET_READ;
	CLK_H;
	delay_us();
	if(SDA_READ)
	{
		return 1;
	}
	CLK_L;
	return 0;
}
//应答
void ack()
{
	SET_WRITE;
	CLK_L;
	delay_us();

	SDA_L;//应答信号
	delay_us();
	CLK_H;
	delay_us();
	delay_us();
	CLK_L;
}
//非应答
void no_ack()
{
	SET_WRITE;
	CLK_L;
	delay_us();
	SDA_H;//非应答信号
	delay_us();
	CLK_H;
	delay_us();
	delay_us();
	CLK_L;
}

si7006.h

#ifndef __SI7006_H__
#define __SI7006_H__
#include "iic.h"

//初始化si7006
void si7006_init();
//获取数据
unsigned short read_data(unsigned char slave_addr, unsigned char reg_addr);

#endif

si7006.c

#include "si7006.h"
extern void delay_ms(int ms);
//初始化si7006
void si7006_init()
{
	iic_init();
	start();
	write_byte(0x40<<1);
	wait_ack();
	write_byte(0xE6);
	wait_ack();
	write_byte(0x3A);
	wait_ack();
	stop();
}
//获取数据
unsigned short read_data(unsigned char slave_addr, unsigned char reg_addr)
{
	unsigned short data;
	//高8位和低8位
	unsigned char data_h, data_l;
	start();
	write_byte(slave_addr<<1);
	wait_ack();
	write_byte(reg_addr);
	wait_ack();
	write_byte(slave_addr |= 1);
	wait_ack();
	//转换时间
	delay_ms(100);
	//读取高8位
	data_h = read_byte(0);
	//读取低8位
	data_l = read_byte(1);
	stop();
	//把高8位和低8位组合在一起
	data = data_h;
	data <<= 8;
	data |= data_l;
	return data;
}

main.c

#include "si7006.h"
extern void printf(const char *fmt, ...);
void delay_ms(int ms)
{
	int i,j;
	for(i = 0; i < ms;i++)
		for (j = 0; j < 1800; j++);
}

int main()
{
	unsigned short hum, tem;
	si7006_init();
	while(1)
	{
		hum = read_data(0x40, 0xE5);
		tem = read_data(0x40, 0xE3);
		printf("hum = %d\n", (hum*125)/65536-6);
		printf("tem = %d\n", (tem*176)/65536-47);
		delay_ms(1000);
	}
	return 0;
}

实验结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傾语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值