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)
{/** 开始信号:时钟在高电平期间,数据线从高到低的变化*     --------* SCL         \*              --------*     ----* SDA     \*          --------* */   //确保SDA是输出状态 PF15输出SET_SDA_OUT;// 空闲状态SDA和SCL拉高 I2C_SCL_H;I2C_SDA_H;delay_us();//延时等待一段时间I2C_SDA_L;//数据线拉低delay_us();//延时等待一段时间I2C_SCL_L;//时钟线拉低,让总线处于占用状态
}/** 函数名:i2c_stop* 函数功能:模拟i2c停止信号的时序* 函数参数:无* 函数返回值:无* */void i2c_stop(void)
{/** 停止信号 : 时钟在高电平期间,数据线从低到高的变化 *             ----------* SCL        /*    --------*    ---         -------* SDA   X       /*    --- -------* *///确保SDA是输出状态 PF15输出SET_SDA_OUT;//时钟线拉低I2C_SCL_L;//为了修改数据线的电平delay_us();//延时等待一段时间I2C_SDA_L;//数据线拉低delay_us();//延时等待一段时间//时钟线拉高I2C_SCL_H;delay_us();//延时等待一段时间I2C_SDA_H;//数据线拉高}/** 函数名: i2c_write_byte* 函数功能:主机向i2c总线上的从设备写8bits数据* 函数参数:dat : 等待发送的字节数据* 函数返回值: 无* */void i2c_write_byte(unsigned char dat)
{  /** 数据信号:时钟在低电平期间,发送器向数据线上写入数据*          时钟在高电平期间,接收器从数据线上读取数据 *      ----          --------*  SCL     \        /        \*           --------          --------*      -------- ------------------ ---*  SDA         X                  X*      -------- ------------------ ---**      先发送高位在发送低位 * *///确保SDA是输出状态 PF15输出SET_SDA_OUT;unsigned int i;for(i=0;i<8;i++){//时钟线拉低I2C_SCL_L;delay_us();//延时//0X3A->0011 1010   0X80->10000000if(dat&0X80)//最高位为1{//发送1I2C_SDA_H;}else  //最高位为0{I2C_SDA_L;//发送0}delay_us();//延时//时钟线拉高,接收器接收I2C_SCL_H;delay_us();//延时,用于等待接收器接收数据delay_us();//延时//将数据左移一位,让原来第6位变为第7位dat = dat<<1;}}/** 函数名:i2c_read_byte* 函数功能: 主机从i2c总线上的从设备读8bits数据, *          主机发送一个应答或者非应答信号* 函数参数: 0 : 应答信号   1 : 非应答信号* 函数返回值:读到的有效数据** */
unsigned char i2c_read_byte(unsigned char ack)
{/** 数据信号:时钟在低电平期间,发送器向数据线上写入数据*          时钟在高电平期间,接收器从数据线上读取数据 *      ----          --------*  SCL     \        /        \*           --------          --------*      -------- ------------------ ---*  SDA         X                  X*      -------- ------------------ ---**      先接收高位, 在接收低位 * */unsigned int i;unsigned char dat;//保存接受的数据//将数据线设置为输入SET_SDA_IN;for(i=0;i<8;i++){//先把时钟线拉低,等一段时间,保证发送器发送完毕数据I2C_SCL_L;delay_us();delay_us();//保证发送器发送完数据//时钟线拉高,读取数据I2C_SCL_H;delay_us();dat=dat<<1;//数值左移 一定要先左移在赋值,不然数据会溢出if(I2C_SDA_READ)//pf15管脚得到了一个高电平输入{dat |=1; //0000 0110}else{dat &=(~0X1);}delay_us();}if(ack){i2c_nack();//发送非应答信号,不再接收下一次数据}else{i2c_ack();//发送应答信号 }return dat;//将读取到的数据返回
}
/** 函数名: i2c_wait_ack* 函数功能: 主机作为发送器时,等待接收器返回的应答信号* 函数参数:无* 函数返回值:*                  0:接收到的应答信号*                  1:接收到的非应答信号* */
unsigned char i2c_wait_ack(void)
{/** 主机发送一个字节之后,从机给主机返回一个应答信号**                   -----------* SCL              /   M:读    \*     -------------             --------*     --- ---- --------------------* SDA    X    X*     ---      --------------------*     主  释   从机    主机*     机  放   向数据  读数据线*         总   线写    上的数据*         线   数据* */   //时钟线拉低,接收器可以发送信号I2C_SCL_L;I2C_SDA_H;//先把数据线拉高,当接收器回应应答信号时,数据线会拉低delay_us();SET_SDA_IN;//设置数据线为输入delay_us();//等待从机响应delay_us();I2C_SCL_H;//用于读取数据线数据if(I2C_SDA_READ)//PF15得到一个高电平输入,收到非应答信号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;//数据线处于占用状态,发送器发送下一次数据
}

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 delay(int ms);
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 

si7006.c

#include"si7006.h"
//封装延时函数
void delay(int ms)
{int i,j;for(i=0;i<ms;i++){for(j=0;j<2000;j++){}}
}
void si7006_init()
{//发起起始信号i2c_start();//发送从机地址+写标志i2c_write_byte(0X40<<1|0);//等待从机应答i2c_wait_ack();//发送寄存器地址 0XE6i2c_write_byte(0XE6);//等待从机应答i2c_wait_ack();//传输要写入的数据0X3A、i2c_write_byte(0X3A);//等待从机应答i2c_wait_ack();//发送终止信号i2c_stop();
}short si7006_read_tem()
{short tem;char tem_h,tem_l;//发起起始信号i2c_start();//发送从机地址+写标志i2c_write_byte(0x40<<1|0);//等待从机应答i2c_wait_ack();//发送寄存器地址  0XE3i2c_write_byte(0xe3);//等待从机应答i2c_wait_ack();//重复起始信号i2c_start();//发送从机地址+读标志i2c_write_byte(0x40<<1|1);//等待从机应答i2c_wait_ack();delay(100);//等待从机测量数据//接收数据高八位//发送应答信号tem_h=i2c_read_byte(0);//接收数据低八位//发送非应答信号tem_l=i2c_read_byte(1);//将高八位和低八位合成一个数据   高八位<<8|低8位tem=tem_h<<8|tem_l;return  tem;
}unsigned short si7006_read_hum()
{unsigned short hum;unsigned char hum_h,hum_l;//发起起始信号i2c_start();//发送从机地址+写标志i2c_write_byte(0x40<<1|0);//等待从机应答i2c_wait_ack();//发送寄存器地址  0XE3i2c_write_byte(0xe5);//等待从机应答i2c_wait_ack();//重复起始信号i2c_start();//发送从机地址+读标志i2c_write_byte(0x40<<1|1);//等待从机应答i2c_wait_ack();delay(100);//等待从机测量数据//接收数据高八位//发送应答信号hum_h=i2c_read_byte(0);//接收数据低八位//发送非应答信号hum_l=i2c_read_byte(1);//将高八位和低八位合成一个数据   高八位<<8|低8位hum=hum_h<<8|hum_l;return  hum;
}

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();#endif

main.c

#include "si7006.h"int main(){//si7006初始化si7006_init();i2c_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);delay(1000);}return 0;}

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/626602.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CNN卷积神经网络:理论基础、核心架构与多元应用

CNN是一种深度学习模型&#xff0c;利用卷积层提取图像特征&#xff0c;池化层降维与增强不变性&#xff0c;全连接层实现分类/回归。核心理论包括局部感知、权值共享、多层抽象。广泛应用图像识别、目标检测、语义分割、生成任务等领域。 一、CNN理论基础 1、局部感知野&…

【迅为iMX6Q】开发板 Linux version 6.6.3 SD卡 启动

开发环境 win10 64位 VMware Workstation Pro 16 ubuntu 20.04 【迅为imx6q】开发板&#xff0c; 2G DDR RAM linux-imx 下载 使用 NXP 官方提供的 linux-imx&#xff0c;代码地址为&#xff1a; https://github.com/nxp-imx/linux-imx 使用 git 下载 linux-imx&#xff…

Dual-AMN论文阅读

Boosting the Speed of Entity Alignment 10: Dual Attention Matching Network with Normalized Hard Sample Mining 将实体对齐速度提高 10 倍&#xff1a;具有归一化硬样本挖掘的双重注意力匹配网络 ABSTRACT 寻找多源知识图谱(KG)中的等效实体是知识图谱集成的关键步骤&…

IoC与Spring

目录 IoC控制反转 现实案例 特点 目的 DI依赖注入 小总结 介绍Spring 狭义和广义上的Spring 传统编码方式的不足 需求引入 弊端分析 IoC控制反转 现实案例 1、买水果问老板各种水果的口感而不是自己去挨个尝试一遍。 2、买房子找中介而不是自己去花时间找房东。…

springcloud 整合swagger文档教程

我用的是nacos和gateway 我的模块 父依赖没什么太大关系如果出现版本冲突问题可用参考我的依赖版本 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org…

claude国内无法使用的解决办法

claude3国内如何使用, claude国内无法使用的解决办法来啦&#xff01; 近日&#xff0c;人工智能公司AnthropicAI推出了全新的大语言模型Claude 3系列&#xff0c;其中最强大的版本Claude 3 Opus据称在性能上全面超越了OpenAI的GPT-4模型。Claude 3系列包括三个版本&#xff1…

金融科技领航者 财源滚滚选股软件助力投资者智赢未来

在波澜壮阔的金融科技浪潮中&#xff0c;河北源达凭借深厚的行业积淀与前瞻的创新思维&#xff0c;逐渐崭露头角&#xff0c;成为业界瞩目的领航者。多年来&#xff0c;公司始终坚守初心&#xff0c;致力于为客户提供高效、的金融科技服务&#xff0c;助力投资者在资本市场中稳…

OpenCV与AI深度学习 | 实战 | 基于YOLOv9+SAM实现动态目标检测和分割(步骤 + 代码)

本文来源公众号“OpenCV与AI深度学习”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;实战 | 基于YOLOv9SAM实现动态目标检测和分割&#xff08;步骤 代码&#xff09; 0 导 读 本文主要介绍基于YOLOv9SAM实现动态目标检测和分…

每日两题 / 76. 最小覆盖子串 239. 滑动窗口最大值(LeetCode热题100)

76. 最小覆盖子串 - 力扣&#xff08;LeetCode&#xff09; 类似双指针&#xff08;滑动窗口&#xff09;&#xff0c;一开始l和r指向0下标&#xff0c;当区间[l, r)之间的字符串无法覆盖t串时&#xff0c;r。直到区间覆盖了t串 接着移动l指针&#xff0c;假设当前区间为[l …

毕设学习:联邦学习梯度聚合加密算法

原本的加密算法大致思路&#xff1a;各个客户端上传梯度时进行加密&#xff0c;服务端直接用有扰乱的梯度当成真梯度来计算&#xff0c;这样一来谁也不知道谁是真梯度 为了避免原本的算法的一些问题&#xff0c;本文提出了加密-解密结构&#xff0c;并证明了这种结构带来的误差…

光伏电站智能勘探:无人机优势及流程详解

随着科技和互联网技术的不断发展&#xff0c;无人机在各个领域的应用越来越广泛&#xff0c;其中之一就是光伏电站智能勘探。利用无人机高清摄像头和传感器等设备&#xff0c;可以对光伏电站周边环境、日照情况、房屋状态进行全方面的勘探和记录&#xff0c;搭配卫星勘探、实地…

掌上医院预约挂号系统源码,开发技术:C#+uni-app+.net+SqlServer

医院微信预约挂号系统是一种基于微信平台的医疗服务系统&#xff0c;它利用微信的广泛覆盖和便捷性&#xff0c;为患者提供线上预约挂号的服务。通过该系统&#xff0c;患者可以使用自己的微信账号登录&#xff0c;浏览医院的医生排班信息&#xff0c;选择合适的医生和就诊时间…