iic实现采集温湿度传感器值

2023-05-16

iic.h

#ifndef __IIC_H__
#define __IIC_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"

/* 通过程序模拟实现I2C总线的时序和协议
 * GPIOF ---> AHB4
 * 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 I2C_SCL_H       do{GPIOF->BSRR |= (0x1 << 14);}while(0)
#define I2C_SCL_L       do{GPIOF->BRR |= (0x1 << 14);}while(0)

#define I2C_SDA_H       do{GPIOF->BSRR |= (0x1 << 15);}while(0)
#define I2C_SDA_L       do{GPIOF->BRR |= (0x1 << 15);}while(0)

#define I2C_SDA_READ    (GPIOF->IDR & (0x1 << 15))

void delay_us(void);
void i2c_init(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_write_byte(unsigned char  dat);
unsigned char i2c_read_byte(unsigned char ack);
unsigned char i2c_wait_ack(void);       
void i2c_ack(void);
void i2c_nack(void);

#endif 

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)
{
	/*
	 * 开始信号:时钟在高电平期间,数据线从高到低的变化
	 *     --------
	 * SCL         \
	 *              --------
	 *     ----
	 * SDA     \
	 *          --------
	 * */	
      
	//设置SDA为输出模式
	SET_SDA_OUT;
	//SCL拉高
	I2C_SCL_H;
	//延迟函数
	delay_us();
	//SDA拉高
	I2C_SDA_H;
	//延迟函数
	delay_us();
	//SDA拉低
	I2C_SDA_L;
	//SCL拉低
	I2C_SCL_L;
}

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

void i2c_stop(void)
{
	/*
	 * 停止信号 : 时钟在高电平期间,数据线从低到高的变化 
	 *             ----------
	 * SCL        /
	 *    --------
	 *    ---         -------
	 * SDA   X       /
	 *    --- -------
	 * */
	SET_SDA_OUT;//设置SDA为输出模式
     I2C_SCL_L;//将SCL拉低
	 delay_us();//延迟函数
	 I2C_SDA_L;//将SDA拉低
	 delay_us();//延迟函数
	 I2C_SCL_H;//将SCL拉高
	 delay_us();//延迟函数
	 I2C_SDA_H;//将SDA拉高
     delay_us();//延迟函数

}

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

void i2c_write_byte(unsigned char dat)
{
	/*
	 * 数据信号:时钟在低电平期间,发送器向数据线上写入数据
	 * 			时钟在高电平期间,接收器从数据线上读取数据 
	 *      ----          --------
	 * 	SCL     \        /        \
	 *           --------          --------
	 *      -------- ------------------ ---
	 * 	SDA         X                  X
	 *      -------- ------------------ ---
	 *
	 *      先发送高位在发送低位 
	 * */
	unsigned int i=0;
      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)
{
	/*
	 * 数据信号:时钟在低电平期间,发送器向数据线上写入数据
	 * 			时钟在高电平期间,接收器从数据线上读取数据 
	 *      ----          --------
	 * 	SCL     \        /        \
	 *           --------          --------
	 *      -------- ------------------ ---
	 * 	SDA         X                  X
	 *      -------- ------------------ ---
	 *
	 *      先接收高位, 在接收低位 
	 * */
	unsigned int i=0;
	unsigned char dat;
     SET_SDA_IN;//设置SDA为输入模式
    for(i=0;i<8;i++)
	{
		I2C_SCL_L;//等待从机向数据线上写入数据
		delay_us();
		delay_us();
		I2C_SCL_H;//将SCL拉高
		delay_us();
		dat <<= 1;
		if(I2C_SDA_READ)//向数据线上读取数据
		{
			dat |= 1;//向数据线上写高电平
		}
		else
		{
			dat |= 0;//向数据线上写低电平
		}
		delay_us();
	}
	if(!ack)//判断应答信号
	{
		i2c_ack();//主机给从机发送应答信号
	}
	else
	{
		i2c_nack();//主机给从机发送非应答信号
	}
	return dat;
	 

	 
}
/*
 * 函数名: i2c_wait_ack
 * 函数功能: 主机作为发送器时,等待接收器返回的应答信号
 * 函数参数:无
 * 函数返回值:
 *					0:接收到的应答信号
 *                  1:接收到的非应答信号
 * */
unsigned char i2c_wait_ack(void)
{
	/*
	 * 主机发送一个字节之后,从机给主机返回一个应答信号
	 *
	 *                   -----------
	 * SCL              /   M:读    \
	 *     -------------             --------
	 *     --- ---- --------------------
	 * SDA    X    X
	 *     ---      --------------------
	 *     主  释   从机    主机
	 *     机  放   向数据  读数据线
	 *         总   线写    上的数据
	 *         线   数据
	 * */
	I2C_SCL_L;//将scl拉低
	delay_us();
	I2C_SDA_H;//主机释放总线
	delay_us();
	SET_SDA_IN;//变换总线方向
	delay_us();
	I2C_SCL_H;//将scl拉高
	delay_us();
	if(I2C_SDA_READ)//主机读取数据线的数据
	{
		return 1;//发送器从总线读取到非应答信号
	}
	I2C_SCL_L;//总线处于占线状态
    return 0;//发送器从总线读取到应答信号




} 
/*
 * 函数名: iic_ack
 * 函数功能: 主机作为接收器时,给发送器发送应答信号
 * 函数参数:无
 * 函数返回值:无
 * */
void i2c_ack(void)
{
	/*            --------
	 * SCL       /        \
	 *    -------          ------
	 *    ---
	 * SDA   X 
	 *    --- -------------
	 * */
	SET_SDA_OUT;//设置输出模式

    I2C_SCL_L;//将时钟线拉低
	delay_us();
    I2C_SDA_L;//将数据线拉低
	delay_us();
	I2C_SCL_H;//将时钟线拉高
	delay_us();
	delay_us();
	I2C_SCL_L;//将时钟线拉低





}
/*
 * 函数名: iic_nack
 * 函数功能: 主机作为接收器时,给发送器发送非应答信号
 * 函数参数:无
 * 函数返回值:无
 * */
void i2c_nack(void)
{
	/*            --------
	 * SCL       /        \
	 *    -------          ------
	 *    --- ---------------
	 * SDA   X 
	 *    --- 
	 * */
	SET_SDA_OUT;

    I2C_SCL_L;
	delay_us();
    I2C_SDA_H;
	delay_us();
	I2C_SCL_H;
	delay_us();
	delay_us();
	I2C_SCL_L;

}

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_data
 * 函数功能:读取SI7006的转换结果
 * 函数参数:
 *     slave_addr : 从机地址
 *     reg_addr : 寄存器地址
 * 函数返回值:无
*/
short si7006_read_data(unsigned char slave_addr, 
		unsigned char reg_addr)
{
	short dat;
	unsigned char dat_h,dat_l;
	i2c_start();
	i2c_write_byte(slave_addr << 1);
	i2c_wait_ack();
	i2c_write_byte(reg_addr);
	i2c_wait_ack();

	i2c_start();
	i2c_write_byte((slave_addr << 1) | 1);
	i2c_wait_ack();
	delay_ms(10);
	dat_h= i2c_read_byte(0);
	dat_l=i2c_read_byte(1);
	i2c_stop();
	dat = dat_h;
	dat <<= 8;
    dat |= dat_l;
	return dat;

}

si7006.h

#ifndef __SI7006_H__
#define __SI7006_H__

#include "iic.h"
#define        SI7006_SLAVE      0x40

void si7006_init(void);

short si7006_read_data(unsigned char slave_addr, unsigned char reg_addr);


#endif //__SI7006_H__

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()

{

    short temp;

	unsigned short hum;

	si7006_init();

	while(1)

	{

		hum = si7006_read_data(SI7006_SLAVE,0xE5);

		temp =si7006_read_data(SI7006_SLAVE,0xE0);

		printf("hum = %d\n",125*hum/65536-6);

		printf("temp = %d\n",176*temp/65536-47);

	}

	return 0;

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iic实现采集温湿度传感器值 的相关文章

  • paddle的两阶段基础算法基础

    paddle的两阶段基础算法详解与实践 有三部分分别是 xff1a 1 xff0c 两阶段算法发展历程 2 xff0c Faster R CNN原理解析 3 xff0c Paddle Detection实战演练 一 xff1a 两阶段算法的
  • Faster R-CNN网络架构

    Faster R CNN网络架构原理解析 Anchor的第一个分支是一个分类分支负责判断途中有没有东西 xff0c 但是不会判断物品 第二个分支是回归分支表示Anchor和真实值有多远最终提取的候选框尽量向真实值靠拢 RPN层是如何提取候选
  • Faster R-CNN原理详解

    Faster R CNN原理详解 首先将RPN输出以及将anchor解码 xff0c 然后对预测框进行clip xff0c 然后对预测狂进行过滤 xff0c filter将面积太小的过滤掉 xff0c 然后将分数较低的去掉 xff0c NM
  • linux出现“INFO: task xxxxxx: 634 blocked for more than 120 seconds.”的3种解决方案

    1 问题描述 最近搭建的一个linux最小系统在运行到241秒时在控制台自动打印如下图信息 xff0c 并且以后每隔120秒打印一次 仔细阅读打印信息发现关键信息是 hung task timeout secs xff0c 第一次遇到这样的
  • vue中的计算属性和侦听器

    vue中的计算属性和侦听器 computed xff08 计算属性 xff09 在模板中放入太多的逻辑不但难以维护 xff0c 就连作者自身在看到代码的时候可能都难以理解 vue开发了计算属性 xff0c 计算属性是依赖于本身的响应式以来进
  • vue-列表的渲染

    vue 列表的渲染 vue的列表渲染指令是基于v for的 xff0c 官方文档中是这么说的 v for 指令需要使用 item in items 形式的特殊语法 xff0c 其中 items 是源数据数组 xff0c 而 item 则是被
  • vue-事件处理

    vue 事件处理 一般使用v on来进行事件监听 xff0c 在监听DOM事件时会触发一部分的js代码 使用v on xxx或 64 xxx绑定事件 xff0c xxx指 事件名 事件的回调要写在methods对象中 xff0c 最终会放在
  • R-CNN算法优化策略

    R CNN算法优化策略 1 xff0c 两阶段检测的进阶模型 首先进行数据处理 xff0c 然后输入backbone得到特征图 xff0c 然后进入RPN中提取候选区域roi xff0c 然后再ROI Align提取特争 xff0c 然后送
  • 一篇文章让你从入门到彻底学会Java

    一篇文章让你从入门到彻底学会Java 文章目录 一篇文章让你从入门到彻底学会Java第一个Java程序 43 基础知识详解Java的对象和类Java中的数据类型Java变量类型Java运算符Java中的循环Java 条件语句Java中的sw
  • vue-进入/离开&列表过渡

    vue 进入 离开 amp 列表过渡 在 CSS 过渡和动画中自动应用 class可以配合使用第三方 CSS 动画库 xff0c 如 Animate css在过渡钩子函数中使用 JavaScript 直接操作 DOM可以配合使用第三方 Ja
  • vue中的路由基础

    vue中的路由 在使用vue router之前 xff0c 首先需要安装该插件 首先在cmd中使用npm install vue router进行插件的安装 xff0c 如果要在工程项目中使用它必须通过Vue use 明确地安装路由功能 就
  • 前端面试的基础四十小问(前20问)

    文章目录 1 什么是HTML语义化 xff1f 2 标签title与alt属性的区别是什么 xff1f 3 iframe的优缺点 xff1f 4 介绍一下CSS的盒子模型 xff1f 5 垂直居中的几种方式 xff1f 6 rgba和opa
  • 前端面试题--react与vue的区别

    前端面试题 react与vue的区别 首先从架构层面来看 xff0c vue是MVVM架构 xff0c 是一个灵活易用的渐进式双向绑定 xff0c 而react并没有准确的架构模式 xff0c react准确的架构模式是调和器和渲染器 xf
  • 前端面试题--详解flex

    前端面试题 详解flex Flex是指弹性盒子布局的意思 Flex的主要作用是 xff1a 解决元素居中问题 xff0c 自动弹性伸缩 xff0c 自动适配不同大小的屏幕和移动端 Flex的术语解释 xff1a 二成员 xff1a 容器和项
  • Linux系统中sysctl命令详解 sysctl -p、sysctl -a、sysctl -w

    sysctl命令用于运行时配置内核参数 xff0c 这些参数位于 proc sys目录下 sysctl配置与显示在 proc sys目录中的内核参数 xff0e 可以用sysctl来设置或重新设置联网功能 xff0c 如IP转发 IP碎片去
  • 前端面试题--vue的父子组件通信

    前端面试题 vue的父子组件通信 比较常见的就是父组件为控制组件子组件为视图组件 父组件传递数据给子组件使用 xff0c 遇到业务逻辑操作时子组件触发父组件的自定义事件 子组件接受使用父组件的数据 xff0c 这里的数据包括属性和方法 xf
  • 前端面试题--了解并简单介绍一下typescript

    前端面试题 了解并简单介绍一下typescript TypeScript是JavaScript的超集 xff0c 具有可选的类型并可以编译为纯JavaScript 从技术上讲TypeScript就是具有静态类型的 JavaScript 向J
  • HashMap MAXIMUM_CAPACITY 为什么设置成1 << 30---Java源码

    为什么是1 lt lt 30因为2个因素造成的 正如上楼的 MrAmity 所说 xff0c HashMap在确定数组下标Index的时候 xff0c 采用的是 length 1 amp hash的方式 xff0c 只有当length为2的
  • MATLAB循环结构与嵌套循环

    循环结构又称为重复结构 xff0c 是利用计算机运算速度快以及能进行逻辑控制得我特点来重复执行默写操作 while循环 while语句多用于循环次数不确定的情况 xff0c 而对于循环次数确定的情况 xff0c 使用for语句更方便 针对不
  • 机械臂(4)–正向求解

    最近准备研究下机械臂的运动分析 xff0c 本文记录相关过程 关于运动求解 xff0c 鄙人才疏学浅 xff0c 很多内容没有深入理解 xff0c 只是简单知道这个是什么 xff0c 代表什么意思 xff0c 怎么用 xff0c 关于原理了

随机推荐

  • Gazebo/Rviz仿真打开URDF模型

    当我们通过Solidworks成功导出URDF模型之后 xff0c 我们当然很希望在ROS中观察到自己导入的模型 ROS中有两个非常好的插件 xff0c 一个是RViz另一个是Gazebo 其中RViz类似一个可视化平台 xff0c 而Ga
  • 线性二次型最优控制

    本文涉及的李雅普诺夫方法的内容可参见另一篇博文 xff1a 李雅普诺夫 xff08 第二方法 xff09 稳定性分析 目录 一 连续时间系统线性二次型最优控制1 1 问题的提出1 2 问题的分析1 3 问题求解1 4 MATLAB函数1 5
  • 深入理解Tomcat虚拟目录

    我们知道 xff0c Web网站中的内容 xff08 包括网页 xff0c 图片 xff0c 音频文件等 xff09 一般都存放在App的目录下 但随着网站内容的不断丰富 xff0c 用户需要把不同层次的内容组织成网站的子目录 我们通常的做
  • Spring Security 实现身份认证

    Spring Security可以运行在不同的身份认证环境中 xff0c 当我们推荐用户使用Spring Security进行身份认证但并不推荐集成到容器管理的身份认证中时 xff0c 但当你集成到自己的身份认证系统时 xff0c 它依然是
  • 基于ubuntu18.04 VNC开机自启动

    本博客内容实现了RK3399 NanoPi NEO4的VNC的开机自启动 xff0c 以及原版桌面的显示 系统 xff1a FriendlyDesktop 最新版本 xff0d 基于Ubuntu 18 04 64位系统构建 易于开发 xff
  • Spring Security身份认证之UserDetailsService

    zhiqian我们采用了配置文件的方式从数据库中读取用户进行登录 虽然该方式的灵活性相较于静态账号密码的方式灵活了许多 xff0c 但是将数据库的结构暴露在明显的位置上 xff0c 绝对不是一个明智的做法 本文通过Java代码实现UserD
  • 基于Apache OLTU的OAuth2.0授权解决方案

    Apache OLTU实现了OAuth 2 0的规范 xff0c 是一种可靠的Java授权解决方案 但是 xff0c 官方文档实在是太惨不忍睹了 本文参考了开涛的 OAuth 2 0集成Shiro文章 模拟了OAuth2 0的认证流程 技术
  • Couch的MapReduce查询

    1 MapReduce介绍 传统的关系型数据库中 xff0c 只要你的数据是结构化的 xff0c 你可以进行任何类型的查询 Apache Couch与此相反 xff0c 它使用MapReduce xff08 预定义的map和的reduce方
  • Java遍历读取文件目录结构

    Java读取计算机目录 xff0c 并打印 public class ReadDirectory 文件所在的层数 private int fileLevel 生成输出格式 64 param name 输出的文件名或目录名 64 param
  • Java实现数字水印

    数字水印有可见不可见之分 xff0c 可见的比如课件上印有学校校徽 xff0c 微博发图片会水印上上传者的信息及微博logo等 用java实现可见的数字水印 xff0c 草人主要是用到了java awt包中的AlphaComposite类
  • 程序员应该如何去设计需求

    刚出道的程序员 xff0c 在做需求分析的时候 xff0c 总是经常挨批 xff0c 客户说他们不能按照客户的要求去设计原型 xff0c 领导说他们不用心去与客户沟通交流 程序员总是感到自己很冤枉 xff0c 明明客户没有给出一点建设性建议
  • 小小程序员的一周日报

    工作依旧在有条不紊的进行着 xff0c 一周的时间很快就会过去 xff0c 正如今天李哥所说的 xff0c 这一周还没有感觉怎么过呢 xff0c 就结束了 是啊 xff0c 这就是我们的工作 xff0c 程序员的工作 xff0c 软件设计师
  • 项目空间都有啥

    项目空间是什么 xff0c Workplace 答案是 xff1a No 项目空间是由项目负责人提出的实施某项目方案的一种流程 项目空间是XX海油ERP管理系统下的一个业务 xff0c 项目负责人通过创建项目名称 项目负责人 使用资源 所属
  • 你不要瞧不起Ctrl+C

    曾经 xff0c 在我未参加工作之前 xff0c 我认为靠 Ctrl 43 C 来完成工作的人 xff0c 肯定是懒惰的程序员 xff0c 但是现在我发现我错了 xff0c 而且是彻底的错了 能够通过 Ctrl 43 C 来完成工作的人 x
  • 文档交接说明书(模板)

    因为同事的离职 xff0c 我的入职 xff0c 要从同事手中交接过来一些项目 公司里只有一些开发文档相关的模板 xff0c 并没有文档交接相关的模板 xff0c 所以交接文档的模板也就由我们自己来定 我结合自己在工作中的经验 xff0c
  • UDS网络层/TP层(ISO 15765-2)的解读

    本文是对 ISO 15765 2 2011 协议的一些解读 需要指出该协议的最新版为2016版 TP层存在意义 UDS网络层 xff0c 又称为TP层 xff08 Transport Protocol Layer xff09 其存在的目的是
  • std vector传递指针使用说明

    今天用WM COPYDATA传递一个Vector的指针 xff0c 传递过来始终失败 后面找到一篇文章 xff0c 说只要传递第一个元素的地址就行 xff0c 因为vector在内存是连续的 static std vector lt UIm
  • Leetcode之运算库函数自定义

    一 Leetcode50 pow 注意点 1 n的值可以为正 xff0c 负 xff0c 0 2 O n 会TLE xff0c 使用递归时 xff0c 一定要将中间步保存 3 有博文中提到 xff0c 若n lt 0 xff0c 可以令n
  • 树莓派无键盘安装步骤

    树莓派无键盘安装 下载系统烧录系统配置无线网络开机并连接树莓派更新源和系统安装xrdp xff08 远程访问 xff09 Windows连接远程桌面 下载系统 应该只有官方的Raspbian系统支持无键盘安装 xff0c 官网下载系统 xf
  • iic实现采集温湿度传感器值

    iic h ifndef IIC H define IIC H include 34 stm32mp1xx gpio h 34 include 34 stm32mp1xx rcc h 34 通过程序模拟实现I2C总线的时序和协议 GPIOF