完成温湿度传感器数据采集实验。
【思路:1.通过IIC通信原理,理解其通信过程,通过调用封装的IIC函数达成主机和从机之间:起始信号、终止信号、读、写数据的操作; 2.了解温湿度传感器控制芯片SI7006的工作原理,通过对其寄存器的相应操作,完成SI7006的初始化、启动温度测量并读取数值、启动湿度测量并读取数值】
【本次实验效果:当读取到的测量温度大于等于28°时,启动电风扇,小于则关闭风扇;当读取到的测量湿度大于等于60时,启动震动马达,小于则关闭】
代码如下<不含icc.c/.h>:
头文件si7006.h:
// 先写防止头文件的重复包含的机制
#ifndef __SI7006_H__
#define __SI7006_H__
#include"iic.h"
void delay_ms(int ms);
void si7006_init();
unsigned short si7006_read_hum();
short si7006_read_tem();
extern void printf(const char *fmt, ...);
void Motor_init();
void FAN1_init();
#endif
封装函数:si7006.c:
#include "si7006.h"
//封装延时函数
void delay_ms(int ms)
{
int i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<2000;j++)
{
}
}
}
//温湿度传感器初始化
void si7006_init()
{
//1.发起起始信号
i2c_start();
//2.发送7bit从机地址和写标志位 0X80
i2c_write_byte(0x80);
//3.等待从机应答
if(i2c_wait_ack())
{
printf("no ack\n");
}
//4.发送寄存器地址 0XE6
i2c_write_byte(0xe6);
//5.等待从机应答
if(i2c_wait_ack())
{
printf("no ack\n");
}
//6.向从机发送数据 0X3A
i2c_write_byte(0x3a);
//7.等待从机应答
if(i2c_wait_ack())
{
printf("no ack\n");
}
//8.发送终止信号
i2c_stop();
}
unsigned short si7006_read_hum()
{
unsigned char hum_l,hum_h;
unsigned short hum;
// 1.主机发起起始信号
i2c_start();
// 2.主机发送7bit从机地址+1bit写标志
i2c_write_byte(0x80);
// 3.等待从机应答
if(i2c_wait_ack())
{
printf("no ack\n");
}
// 4.主机发送8bit寄存器地址
i2c_write_byte(0xe5);
// 5.等待从机应答
if(i2c_wait_ack())
{
printf("no ack\n");
}
// 6.主机发起重复起始信号
i2c_start();
// 7.主机发送7bit从机地址+1bit 读 0X81
i2c_write_byte(0x81);
// 8.等待从机应答
if(i2c_wait_ack())
{
printf("no ack\n");
}
// 9.延时等待从机测量数据
delay_ms(100);
// 10.读取湿度的高8bit数据 hum_h
hum_h = i2c_read_byte(0);
hum_l = i2c_read_byte(1);
// 11.发送应答信号
// 12.读取湿度的低8位数据 hum_l
// 13.发送非应答信号
// 14.发起终止信号
i2c_stop();
// 15.将读取到的数据的低8位和高8bit合成一个完整的数据
hum=hum_h<<8|hum_l ;
return hum;
}
short si7006_read_tem()
{
char tem_l,tem_h;
short tem;
// 1.主机发起起始信号
i2c_start();
// 2.主机发送7bit从机地址+1bit写标志
i2c_write_byte(0x80);
// 3.等待从机应答
if(i2c_wait_ack())
{
printf("no ack\n");
}
// 4.主机发送8bit寄存器地址
i2c_write_byte(0xe3);
// 5.等待从机应答
if(i2c_wait_ack())
{
printf("no ack\n");
}
// 6.主机发起重复起始信号
i2c_start();
// 7.主机发送7bit从机地址+1bit 读 0X81
i2c_write_byte(0x81);
// 8.等待从机应答
if(i2c_wait_ack())
{
printf("no ack\n");
}
// 9.延时等待从机测量数据
delay_ms(100);
// 10.读取温度的高8bit数据 tem_h
tem_h = i2c_read_byte(0);
tem_l = i2c_read_byte(1);
// 11.发送应答信号
// 12.读取温度的低8位数据 tem_l
// 13.发送非应答信号
// 14.发起终止信号
i2c_stop();
// 15.将读取到的数据的低8位和高8bit合成一个完整的数据
tem=tem_h<<8|tem_l;
return tem;
}
//马达初始化 TIM16 /GPIOF6
void Motor_init()
{
//iic.c中已经使能GPIOF时钟
//使能TIM16 时钟
RCC->MP_APB2ENSETR |= (0X1<<3);
// 设置PF6引脚为通用的输出功能
GPIOF->MODER &= (~(0x3 << 12));
GPIOF->MODER |= (0x1 << 12);
//初始化设置为低电平(关闭状态)
GPIOF->ODR &= (~(0X1<<6));
}
//风扇初始化 TIM1 / GPIOE9
void FAN1_init()
{
//使能TIM1时钟
RCC->MP_APB2ENSETR |= (0X1);
//使能GPIOE时钟
RCC->MP_AHB4ENSETR |= (0x1 << 4);
// 设置PE9引脚为通用的输出功能
GPIOE->MODER &= (~(0x3 << 18));
GPIOE->MODER |= (0x1 << 18);
//默认关闭状态
GPIOE->ODR &= (~(0X1<<9));
}
主程序main.c:
#include "si7006.h"
int main()
{
//si7006初始化
si7006_init();
i2c_init();
Motor_init();
FAN1_init();
unsigned short hum;
short tem;
while (1)
{
hum = si7006_read_hum();
tem = si7006_read_tem();
hum = hum*125/65536 -6;
tem=tem*175.72/65536-46.85;
printf("hum:%d\n",hum);
printf("tem:%d\n",tem);
if(tem >= 28)
{
//如果温度超出30 打开风扇
GPIOE->ODR |= (0X1<<9);
}else
{
//关闭风扇
GPIOE->ODR &= (~(0X1<<9));
}
if(hum>=60 )
{
//如果湿度大于60打开震动马达
GPIOF->ODR |= (0X1<<6);
}else
{
//关闭震动马达
GPIOF->ODR &= (~(0X1<<6));
}
delay_ms(1000);
}
return 0;
}