IIC实验(测温度湿度)

头文件 iic.h  si7006.h

#ifndef __IIC_H__
#define __IIC_H__
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
/*
     I2C1_SCL ---> PF14
     I2C1_SDA ---> PF15
 
*/
//发送数据模式
#define SET_SDA_OUT     do{GPIOF->MODER &= (~(0x3<<30)); \
						   GPIOF->MODER |= (0x1<<30);}while(0)
//接收数据模式
#define SET_SDA_IN      do{GPIOF->MODER &= (~(0x3<<30));}while(0)
//拉高拉低时钟线
#define SCL_H       do{GPIOF->BSRR |= (0x1<<14);}while(0)
#define SCL_L       do{GPIOF->BRR  |= (0x1<<14);}while(0)
//拉高拉低数据线
#define SDA_H       do{GPIOF->BSRR |= (0x1<<15);}while(0)
#define SDA_L       do{GPIOF->BRR  |= (0x1<<15);}while(0)
//读取当前数据线上的值
#define SDA_READ    (GPIOF->IDR & (0x1<<15))
//延时函数
void delay_us();
//IIC初始化
void iic_init();
//起始信号
void iic_start();
//结束信号
void iic_stop();
//发送一个字节
void iic_write_byte(char  data);
//接收一个字节
char iic_read_byte(char ack);
//等待应答信号
char iic_wait_ack();  
//应答信号
void iic_ack();
//非应答信号
void iic_nack();

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

//si7006初始化
void si7006_init();
//获取数据
short si7006_read_data(char slave_addr, char register_addr);

#endif

功能函数 iic.c  si7006.c

#include "iic.h"

//延时函数
void delay_us()
{
	int i = 2000;
	while (i--);
}
//IIC初始化
void iic_init()
{
	/*********RCC使能GPIOF组时钟*********/
	RCC->MP_AHB4ENSETR |= (0x1<<5);	
	/**********GPIO章节配置*************/
	//1.模式设置为输出模式  MODER[31:28]=0101
	GPIOF->MODER &= (~(0xf<<28));
	GPIOF->MODER |= (0x5<<28);
	//2.输出类型设置为推挽输出  OTYPER[15:14]=00
	GPIOF->OTYPER &= (~(0x3<<14));
	//3.输出速度设置为非常高速  OSPEEDR[31:28]=1111
	GPIOF->OSPEEDR |= (0xf<<28);
	//4.禁止上拉和下拉电阻  PUPDR[31:28]=0000
	GPIOF->PUPDR &= (~(0xf<<28));
	/***********IIC设置为空闲态*********/
	SCL_H;  //时钟线拉高
	SDA_H;  //数据线拉高
}
//起始信号
void iic_start()
{
	SET_SDA_OUT;//发送数据模式
	SCL_H; 		//SCL拉高
	SDA_H;  	//SDA拉高
	delay_us();
	SDA_L; 		//SDA拉低
	delay_us();
	SCL_L;  	//SCL拉低,保持占用状态
}
//停止信号
void iic_stop()
{
	SET_SDA_OUT;//设置SDA为输出
	SCL_L;      //SCL拉低
	delay_us();
	SDA_L;      //SDA拉低
	delay_us();
	SCL_H;      //SCL拉高
	delay_us();
	SDA_H;      //SDA拉高
	delay_us();
}
//发送一个字节
void iic_write_byte( char data)
{
	SET_SDA_OUT;   //发送数据模式
	int i;
	for (i = 0 ; i < 8; i++) {
		SCL_L;     //SCL拉低
		delay_us();
		if (data & 0x80)//判断最高位的值
		{
			SDA_H; //写入高电平
		}else
		{
			SDA_L; //写入低电平
		}
		delay_us();
		SCL_H;     //SCL拉高
		delay_us();
		delay_us();  
		data <<= 1; //左移1位
	}
}
//接收一个字节
char iic_read_byte( char ack)
{
	unsigned char data;
	unsigned int i;
	SET_SDA_IN;   //设置SDA为输入
	for (i = 0; i < 8; i++) {
		SCL_L;   //SCL拉低
		delay_us();
		delay_us();  //保证数据写完
		SCL_H;   //SCL拉高
		delay_us();
		data <<= 1;
		if (SDA_READ) 
			data |= 1;//读到1
		else 
			data |= 0;//读到0
		
		delay_us();
	}

	if (!ack) 
		iic_ack();   //发送应答信号
	else 
		iic_nack();  //发送非应答信号
	return data;
}
//等待应答信号
 char iic_wait_ack()
{
	int ack;
	SCL_L;   //SCL拉低
	delay_us();
	SDA_H;   //SDA拉高, 释放总线
	SET_SDA_IN; 
	delay_us();
	SCL_H;
	delay_us();  
	if (SDA_READ) 
	{
		ack = 1;  //非应答信号
	}else 
	{
		ack = 0;  //应答信号
	}
	delay_us();
	SCL_L;
	return ack;
}
//应答信号
void iic_ack()
{
	SET_SDA_OUT;   //发送数据模式
	SCL_L;     //SCL拉低
	delay_us();
	SDA_L;     //SDA拉低,应答信号
	delay_us();   
	SCL_H;     //SCL拉高
	delay_us();
	delay_us();    //等待从机接收应答信号
	SCL_L;     //SCL拉低
}
void iic_nack()
{
	SET_SDA_OUT;   //发送数据模式
	SCL_L;     //SCL拉低
	delay_us();
	SDA_H;     //SDA拉高,非应答信号
	delay_us();   
	SCL_H;     //SCL拉高
	delay_us();
	delay_us();    //等待从机接收应答信号
	SCL_L;     //SCL拉低
}
#include "iic.h"
#include "si7006.h"
extern void delay_ms(unsigned int ms);
//SI7006初始化
void si7006_init()
{
	//IIC初始化
	iic_init();
	//起始信号
	iic_start();
	//发送从机地址
	iic_write_byte(0x40<<1);
	iic_wait_ack();
	//发送寄存器地址
	iic_write_byte(0xe6);
	iic_wait_ack();
	//发送初始值
	iic_write_byte(0x3a);
	iic_wait_ack();
	//结束信号
	iic_stop();
}
//获取数据
 short si7006_read_data(char slave_addr, char register_addr)
{
	//接收的数据
	short data;
	//接收高8位,低8位
	char data_h, data_l;
	//起始信号
	iic_start();
	//发送从机地址+w
	iic_write_byte(slave_addr << 1);
	iic_wait_ack();
	//发送寄存器地址
	iic_write_byte(register_addr);
	iic_wait_ack();
	iic_start();
	//发送从机地址+r
	iic_write_byte((slave_addr << 1) | 0x1);
	iic_wait_ack();
	delay_ms(100);  // 等待转换结束之后在读取测量的结果
	data_h = iic_read_byte(0);//高8位
	data_l = iic_read_byte(1);//低8位
	//结束信号
	iic_stop();
	data = data_h;
	data <<= 8;
	data |= data_l;
	return data;
}

主函数  main.c

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

int main()
{
	short hum;
	short temp;
	si7006_init();
	while (1)
	{
		hum = si7006_read_data(0x40, 0xe5);
		temp = si7006_read_data(0x40, 0xe3);
		printf("temp = %d\thum = %d\n", temp*176/65536-47,hum*125/65536-6);
		delay_ms(1000);
	}
	return 0;
}

测试结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

傾语

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

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

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

打赏作者

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

抵扣说明:

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

余额充值