IIC总线空气温湿度监测实验

空气温湿度监测实验

  • IIC特性
    • 代码实现
      • iic.c
      • si7006.c
    • main.c
    • 运行结果

IIC特性

1.I2C总线是PHLIPS公司在八十年代初推出的一种串行的半双工同步总线,主要用于连接整体电路。
1)同一个板子两个芯片之间的通信 stm32mp157a<—IIC—>SI7006
2)两个设备之间的通信 SOC<—UART—>Target
2.I2C总线为两线制,只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。
3.I2C硬件结构简单,接口连接方便,成本较低。因此在各个领域得到了广泛的应用。
4.IIC总线传输速率
低速 100k
中速 400k
全速 3.4M
5.IIC总线需要接两个上拉电阻,这两个上拉电阻作用在IIC总线为空闲状态时保持高电平。

代码实现

iic.c

#include "iic.h"

extern void printf(const char* fmt, ...);
/*
 * 函数名 : delay_us
 * 函数功能:延时函数
 * 函数参数:无
 * 函数返回值:无
 * */
void delay_us(void)
{
	unsigned int i = 2000;
	while(i--);
}
/*
 * 函数名 : i2c_init
 * 函数功能: i2C总线引脚的初始化, 通用输出,推挽输出,输出速度,
 * 函数参数:无
 * 函数返回值:无
 * */
void i2c_init(void)
{
 	// 使能GPIOF端口的时钟
	RCC->MP_AHB4ENSETR |= (0x1 << 5);
	// 设置PF14,PF15引脚为通用的输出功能
	GPIOF->MODER &= (~(0xF << 28));
	GPIOF->MODER |= (0x5 << 28);
	// 设置PF14, PF15引脚为推挽输出
	GPIOF->OTYPER &= (~(0x3 << 14));
	// 设置PF14, PF15引脚为高速输出
	GPIOF->OSPEEDR |= (0xF << 28);
	// 设置PF14, PF15引脚的禁止上拉和下拉
	GPIOF->PUPDR &= (~(0xF << 28));
	// 空闲状态SDA和SCL拉高 
	I2C_SCL_H;
	I2C_SDA_H;
}



/*
 * 函数名:i2c_start
 * 函数功能:模拟i2c开始信号的时序
 * 函数参数:无
 * 函数返回值:无
 * */
void i2c_start(void)
{
//设置数据线为输出模式
SET_SDA_OUT;
//时钟线拉高
I2C_SCL_H;
//数据线拉高
I2C_SDA_H;
//延时函数
delay_us();
//数据线拉低
I2C_SDA_L;
delay_us();
I2C_SCL_L;//保持总线处于占用状态

}

/*
 * 函数名:i2c_stop
 * 函数功能:模拟i2c停止信号的时序
 * 函数参数:无
 * 函数返回值:无
 * */

void i2c_stop(void)
{
    SET_SDA_OUT; 
 
    I2C_SCL_L; 
    delay_us(); 
 
    I2C_SDA_L; 
    delay_us(); 
 
    I2C_SCL_H; 
    delay_us(); 
 
    I2C_SDA_H; 
    delay_us(); 

}

/*
 * 函数名: i2c_write_byte
 * 函数功能:主机向i2c总线上的从设备写8bits数据
 * 函数参数:dat : 等待发送的字节数据
 * 函数返回值: 无
 * */

void i2c_write_byte(unsigned char dat)
{
    unsigned int i; 
    SET_SDA_OUT; 
    for(i=0;i<8;i++) 
    { 
        I2C_SCL_L; 
         
        delay_us(); 
         
        if(dat &0x80) 
        { 
            I2C_SDA_H; 
        } 
        else 
        { 
            I2C_SDA_L; 
        } 
        delay_us(); 
        I2C_SCL_H; 
        delay_us(); 
        delay_us(); 
        dat <<=1; 
 
    }
	

}

/*
 * 函数名:i2c_read_byte
 * 函数功能: 主机从i2c总线上的从设备读8bits数据, 
 *          主机发送一个应答或者非应答信号
 * 函数参数: 0 : 应答信号   1 : 非应答信号
 * 函数返回值:读到的有效数据
 *
 * */
unsigned char i2c_read_byte(unsigned char ack)
{
    unsigned int i; 
    unsigned char s; 
        SET_SDA_IN; 
    for(i=0;i<8;i++) 
    { 
        I2C_SCL_L; 
        delay_us(); 
        delay_us(); 
        I2C_SCL_H; 
        delay_us(); 
 
        s<<=1; 
        if(I2C_SDA_READ) 
        { 
            s|=0x1; 
        } 
        delay_us(); 
 
    } 
    if(!ack) 
        i2c_ack(); 
    else 
        i2c_nack(); 
    return s;

}
/*
 * 函数名: i2c_wait_ack
 * 函数功能: 主机作为发送器时,等待接收器返回的应答信号
 * 函数参数:无
 * 函数返回值:
 *					0:接收到的应答信号
 *                  1:接收到的非应答信号
 * */
unsigned char i2c_wait_ack(void)
{
    I2C_SCL_L; 
    delay_us(); 
    I2C_SDA_H; 
    delay_us(); 
    SET_SDA_IN; 
 
    I2C_SCL_H; 
    if(I2C_SDA_READ) 
    { 
        return 1; 
    } 
    I2C_SCL_L; 
    return 0; 
    
	
} 
/*
 * 函数名: iic_ack
 * 函数功能: 主机作为接收器时,给发送器发送应答信号
 * 函数参数:无
 * 函数返回值:无
 * */
void i2c_ack(void)
{
    SET_SDA_OUT; 
    I2C_SCL_L; 
    delay_us(); 
    I2C_SDA_L; 
    delay_us(); 
    I2C_SCL_H; 
    delay_us(); 
    I2C_SCL_L; 
    delay_us();
}
/*
 * 函数名: iic_nack
 * 函数功能: 主机作为接收器时,给发送器发送非应答信号
 * 函数参数:无
 * 函数返回值:无
 * */
void i2c_nack(void)
{
 SET_SDA_OUT;
 I2C_SCL_L;
 delay_us();
 I2C_SDA_H;
 delay_us();
 I2C_SCL_H;
 delay_us();
 I2C_SCL_L;
 delay_us();
}


si7006.c

#include "iic.h"
#include "si7006.h"
extern void delay_ms(unsigned int ms);
/*
 * 函数名:si7006_init
 * 函数功能:SI7006芯片的初始化
 * 函数参数:无
 * 函数返回值:无
*/
void si7006_init(void)
{
	i2c_init();
	i2c_start();
	i2c_write_byte(SI7006_SLAVE << 1);
	i2c_wait_ack();
	i2c_write_byte(0xE6);
	i2c_wait_ack();
	i2c_write_byte(0x3A);
	i2c_wait_ack();
	i2c_stop();

}
/*
 * 函数名:si7006_read_hum_data
 * 函数功能:读取SI7006的湿度转换结果
 * 函数参数:
 *     slave_addr : 从机地址
 *     cmd_code : 命令码
 * 函数返回值:湿度测量的数字量
*/
unsigned short si7006_read_hum_data(unsigned char slave_addr, 
		unsigned char cmd_code)
{
	unsigned short dat;
	unsigned char dat_h, dat_l;
	i2c_start();
	i2c_write_byte(slave_addr << 1);
	i2c_wait_ack();
	i2c_write_byte(cmd_code);
	i2c_wait_ack();
	i2c_start();
	i2c_write_byte((slave_addr << 1) | 1);
	i2c_wait_ack();
	delay_ms(100);  // 等待转换结束之后在读取测量的结果
	dat_h = i2c_read_byte(0);
	dat_l = i2c_read_byte(1);
	i2c_stop();

	dat = dat_h;
	dat = (dat << 8) | dat_l;

	return dat;
}
/*
 * 函数名:si7006_read_temp_data
 * 函数功能:读取SI7006的温度转换结果
 * 函数参数:
 *     slave_addr : 从机地址
 *     cmd_code : 命令码
 * 函数返回值:温度测量的数字量
*/
unsigned short si7006_read_temp_data(unsigned char slave_addr, 
		unsigned char cmd_code)
{
	short dat;
	unsigned char dat_h, dat_l;
	i2c_start();
	i2c_write_byte(slave_addr << 1);
	i2c_wait_ack();
	i2c_write_byte(cmd_code);
	i2c_wait_ack();
	i2c_start();
	i2c_write_byte((slave_addr << 1) | 1);
	i2c_wait_ack();
	delay_ms(100);     // 等待转换结束之后在读取测量的结果
	dat_h = i2c_read_byte(0);
	dat_l = i2c_read_byte(1);
	i2c_stop();

	dat = dat_h;
	dat = (dat << 8) | dat_l;

	return dat;
}

main.c

#include "iic.h"
#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;
	unsigned short temp;
	si7006_init(); 
	while(1)
	{
		 hum = si7006_read_hum_data(SI7006_SLAVE, 0XE3);
		temp = si7006_read_temp_data(SI7006_SLAVE, 0xE5);
		hum = (125 * hum / 65536 - 6) * 10;
		temp = (175.72 * temp / 65536 - 46.85) * 10;

		printf("hum = %d.%d\n", hum / 10, hum % 10);
		printf("temp = %d.%d\n", temp / 10, temp % 10);
		delay_ms(1000); 
 
 
	}
 
	return 0;
 
}

运行结果

IIC总线空气温湿度监测实验_第1张图片

你可能感兴趣的:(单片机,stm32,嵌入式硬件)