C语言 Cortex-A7核 IIC实验

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     \*          --------       数据线* */	SET_SDA_OUT;  //1.设置数据线为输出模式I2C_SCL_H;    //2.SCL为高电平delay_us();I2C_SDA_H;    //3.SDA为高电平delay_us();I2C_SDA_L;    //4.SDA为低电平I2C_SCL_L;    //5.起始信号产生之后,总线处于占用状态
}/** 函数名:i2c_stop* 函数功能:模拟i2c停止信号的时序* 函数参数:无* 函数返回值:无* */void i2c_stop(void)
{/** 停止信号 : 时钟在高电平期间,数据线从低到高的变化 *             ----------* SCL        /              时钟线*    --------*    ---         -------* SDA   X       /           数据线*    --- -------* */SET_SDA_OUT;  //1.设置数据线为输出模式I2C_SCL_L;    //2.SCL为低电平,改变数据线上数据delay_us();I2C_SDA_L;    //3.SDA为低电平delay_us();I2C_SCL_H;    //4.SCL为高电平delay_us();I2C_SDA_H;    //5.SDA为高电平,停止信号产生之后,总线处于空闲状态delay_us();
}/** 函数名: i2c_write_byte* 函数功能:主机向i2c总线上的从设备写8bits数据* 函数参数:dat : 等待发送的字节数据* 函数返回值: 无* */void i2c_write_byte(unsigned char dat)
{/** 数据信号:时钟在低电平期间,发送器向数据线上写入数据* 			时钟在高电平期间,接收器从数据线上读取数据 *      ----          --------* 	SCL     \        /        \*           --------          --------*      -------- ------------------ ---* 	SDA         X                  X*      -------- ------------------ ---**      先发送高位在发送低位 * */unsigned int i;SET_SDA_OUT; //1.设置数据为输出模式//2.for循环 条件 实现for(i=0;i<8;i++){I2C_SCL_L;  //3.SCL为低电平期间,发送器向数据线上写入数据 时钟线拉低才能写入数据delay_us();//4. 先发送高位再发送低位if(dat & 0x80)I2C_SDA_H; //向数据线上写入高电平elseI2C_SDA_L; //向数据线上写入低电平delay_us();I2C_SCL_H;  //SCL拉高,等待从机从数据线上读取数据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;unsigned char dat;SET_SDA_IN; //0.设置数据线为输入模式for(i=0;i<8;i++){I2C_SCL_L;  //1.SCL拉低,保证主机向数据线上,写入数据完成delay_us();delay_us();I2C_SCL_H;; //2.SCL拉高,数据线上数据保持稳定,从数据线上读取数据delay_us();dat <<= 1;   //3.移位,放到if前面if(I2C_SDA_READ)dat |= 1; //4.从总线上读取数据为1elsedat |= 0; //5.从总线上读取数据为0delay_us();}if(!ack)i2c_ack();  //6.主机产生应答信号elsei2c_nack(); //7.主机产生非应答信号return dat;     //8.读取到数据	
}
/** 函数名: i2c_wait_ack* 函数功能: 主机作为发送器时,等待接收器返回的应答信号* 函数参数:无* 函数返回值:*					0:接收到的应答信号*                  1:接收到的非应答信号* */
unsigned char i2c_wait_ack(void)
{/** 主机发送一个字节之后,从机给主机返回一个应答信号**                   -----------* SCL              /   M:读    \*     -------------             --------*     --- ---- --------------------* SDA    X    X*     ---      --------------------*     主  释   从机    主机*     机  放   向数据  读数据线*         总   线写    上的数据*         线   数据* */	I2C_SCL_L; //1.SCL为低电平期间,总线上数据允许发生变化delay_us();I2C_SDA_H; //2.SDA为高电平,将数据线释放(空闲)delay_us();SET_SDA_IN; //3.设置SDA为输入模式delay_us();I2C_SCL_H; //4.SCL为高电平,从总线上读取数据delay_us();//5.判断读取数据为0/1,   0 : 应答信号   1 : 非应答信号if(I2C_SDA_READ)return 1; //非应答信号//6.总线处于占用状态I2C_SCL_L;return 0; //应答信号} 
/** 函数名: iic_ack* 函数功能: 主机作为接收器时,给发送器发送应答信号* 函数参数:无* 函数返回值:无* */
void i2c_ack(void)
{/*            --------* SCL       /        \*    -------          ------*    ---* SDA   X *    --- -------------* */SET_SDA_OUT; //1.设置数据线为输出模式I2C_SCL_L;   //2.在SCL为低电平期间,改变数据线上数据delay_us();I2C_SDA_L;   //3.数据线为低电平,应答信号delay_us();I2C_SCL_H;   //4.在SCL为高电平期间,从数据线读取数据delay_us();delay_us();I2C_SCL_L;   //5.总线处于占用状态
}
/** 函数名: iic_nack* 函数功能: 主机作为接收器时,给发送器发送非应答信号* 函数参数:无* 函数返回值:无* */
void i2c_nack(void)
{/*            --------* SCL       /        \*    -------          ------*    --- ---------------* SDA   X *    --- * */SET_SDA_OUT; //1.设置数据线为输出模式I2C_SCL_L;   //2.在SCL为低电平期间,改变数据线上数据delay_us();I2C_SDA_H;   //3.数据线为低电平,非应答信号delay_us();I2C_SCL_H;   //4.在SCL为高电平期间,从数据线读取数据delay_us();delay_us();I2C_SCL_L;   //5.总线处于占用状态
}

si7006.h

#ifndef __SI7006_H__
#define __SI7006_H__#include "iic.h"
#define        SI7006_SLAVE      0x40void si7006_init(void);//参数1:从机地址  参数2:湿度命令码
unsigned short si7006_read_hum_data(unsigned char slave_addr,unsigned char reg_addr);//参数1:从机地址  参数2:温度命令码
short si7006_read_temp_data(unsigned char slave_addr, unsigned char reg_addr);#endif //__SI7006_H__

si7006.c

#include "iic.h"
#include "si7006.h"
extern void delay_ms(unsigned int ms);
/** 函数名:si7006_init* 函数功能:SI7006芯片的初始化* 函数参数:无* 函数返回值:无* 地址:0xE6 初始化值:0x3A
*/
void si7006_init(void)
{i2c_init();i2c_start(); //起始信号i2c_write_byte(SI7006_SLAVE << 1 | 0); //寻址 寻找从机 0x40 + 写(0) = 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 : 寄存器地址* 函数返回值:无
*///参数1:从机地址  参数2:湿度命令码
unsigned short si7006_read_hum_data(unsigned char slave_addr,unsigned char reg_addr)
{unsigned short dat;unsigned char dat_h; //高8位值unsigned char dat_l; //低8位值i2c_start(); //起始信号i2c_write_byte(slave_addr << 1 | 0); //寻址 从机地址 + 写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(1000); //延时函数dat_h = i2c_read_byte(0); //读取高8位数据dat_l = i2c_read_byte(1); //读取低8位数据i2c_stop(); //停止信号// 将高8位和低8位进行拼接dat = dat_h;dat <<= 8;dat |= dat_l;return dat;	
}//参数1:从机地址  参数2:温度命令码
short si7006_read_temp_data(unsigned char slave_addr, unsigned char reg_addr)
{short dat;                                                     unsigned char dat_h; //高8位值                                 unsigned char dat_l; //低8位值                                 i2c_start(); //起始信号                                        i2c_write_byte(slave_addr << 1 | 0); //寻址 从机地址 + 写      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(1000);//延时函数                                      dat_h = i2c_read_byte(0); //读取高8位数据                      dat_l = i2c_read_byte(1); //读取低8位数据                      i2c_stop(); //停止信号                                         // 将高8位和低8位进行拼接                                      dat = dat_h;                                                   dat <<= 8;                                                     dat |= 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(){short temp;unsigned short hum;si7006_init(); //si7006初始化while(1){hum = si7006_read_hum_data(SI7006_SLAVE,0xE5);temp = si7006_read_temp_data(SI7006_SLAVE,0xE3);printf("hum = % d\n",125*hum/65536-6);printf("temp = %d\n",176*temp/65536-47);;}return 0;
}

效果呈现

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

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

相关文章

C# Onnx Yolov8 Detect 手势识别

效果 Lable five four one three two 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing;…

SpringCloud Alibaba - Sentinel 微服务保护解决雪崩问题、Hystrix 区别、安装及使用

目录 一、Sentinel 1.1、背景&#xff1a;雪崩问题 1.2、雪崩问题的解决办法 1.2.1、超时处理 缺陷&#xff1a;为什么这里只是 “缓解” 雪崩问题&#xff0c;而不是百分之百解决了雪问题呢&#xff1f; 1.2.2、舱壁模式 缺陷&#xff1a;资源浪费 1.2.3、熔断降级 1.…

GPT系列论文解读:GPT-1

GPT系列 GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一系列基于Transformer架构的预训练语言模型&#xff0c;由OpenAI开发。以下是GPT系列的主要模型&#xff1a; GPT&#xff1a;GPT-1是于2018年发布的第一个版本&#xff0c;它使用了12个Transformer…

数据分析:人工智能篇

文章目录 第三章 数据可视化库matplotlib3.1 matplotlib基本绘图操作3.2 plot的线条和颜色3.3 条形图分析3.4 箱型图分析3.5 直方图分析3.6 散点图分析3.7 图表的美化 第四章 数据预测库Sklearn4.1 sklearn预测未来4.2 回归数据的预测4.2.1 回归数据的切分4.2.2 线性回归数据模…

SpringBoot整合RocketMQ笔记

SpringBoot版本为2.3.12.Release RocketMQ对比kafka 学习链接 https://zhuanlan.zhihu.com/p/335216381 代码实战 https://www.cnblogs.com/RedOrange/p/17401238.html Centos安装rocketmq https://blog.csdn.net/chuige2013/article/details/123783612 RocketMQ详细配置与…

怎么将本地代码文件夹通过Git 命令上传到启智平台仓库

在本地创建一个与启智平台仓库同样名字的文件夹 然后在本地文件夹右键–>选择Git Bash Here,就会打开Git命令窗口 初始化本地仓库 git init将项目文件添加到Git git add .提交更改&#xff1a; 使用以下命令提交您的更改&#xff0c;并为提交添加一条描述性的消息&#…

大数据Flink(九十六):DML:Deduplication

文章目录 DML:Deduplication DML:Deduplication Deduplication 定义(支持 Batch\Streaming):Deduplication 其实就是去重,也即上文介绍到的 TopN 中 row_number = 1 的场景,但是这里有一点不一样在于其排序字段一定是时间属性列,不能是其他非时间属性的普通列。在 ro…

嵌入式Linux应用开发-驱动大全-同步与互斥②

嵌入式Linux应用开发-驱动大全-同步与互斥② 第一章 同步与互斥②1.3 原子操作的实现原理与使用1.3.1 原子变量的内核操作函数1.3.2 原子变量的内核实现1.3.2.1 ATOMIC_OP在 UP系统中的实现1.3.2.2 ATOMIC_OP在 SMP系统中的实现 1.3.3 原子变量使用案例1.3.4 原子位介绍1.3.4.1…

《Vue.js+Spring Boot全栈开发实战》简介

大家好&#xff0c;我是老卫。 恰逢中秋国庆双节&#xff0c;不想出门看人山&#xff0c;惟愿宅家阅书海&#xff01; 今天开箱的这本书是《Vue.jsSpring Boot全栈开发实战》。 外观 从书名故名思议&#xff0c;就是基于Vue.jsSpring Boot来实现企业级应用全栈开发。 该书由…

【单片机】16-LCD1602和12864显示器

1.LCD显示器相关背景 1.LCD简介 &#xff08;1&#xff09;显示器&#xff0c;常见显示器&#xff1a;电视&#xff0c;电脑 &#xff08;2&#xff09;LCD&#xff08;Liquid Crystal Display&#xff09;&#xff0c;液晶显示器&#xff0c;原理介绍 &#xff08;3&#xff…

设计模式11、享元模式Flyweight

解释说明&#xff1a;享元模式&#xff08;Flyweight Pattern&#xff09;运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象&#xff0c;而这些对象都很相似&#xff0c;状态变化很小&#xff0c;可以实现对象的多次复用。 抽象享元类&#xff08;Flyweight&…

Spring MVC:数据绑定

Spring MVC 数据绑定数据类型转换数据格式化数据校验 附 数据绑定 数据绑定&#xff0c;指 Web 页面上请求和响应的数据与 Controller 中对应处理方法上的对象绑定&#xff08;即是将用户提交的表单数据绑定到 Java 对象中&#xff09;。 过程如下&#xff1a; ServletRequest…

python和java类的编写(属性私有化,方法公开化)

初始化类的属性的2种写法&#xff1a; 如下要注意python对文件名称、类、方法名的命名 方式一&#xff1a;原始的定义 class User1: # 初始化账号和密码 def __init__(self):# 账号和密码self.__username Noneself.__password Nonedef getnsername(self):return self.__us…

服务网关Gateway_入门案例

创建cloud-gateway-gateway9527工程 pom文件引入依赖 <dependencies><!-- 引入网关Gateway依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></depe…

用向量数据库Milvus Cloud搭建检索知识库机器人

检索知识库 Milvus 中已经存储了文本块向量,现在可以进行向量查询了。 以下函数创建了 1 个查询 pipeline。注意,这是本教程中最为关键的一个步骤! ops.ann_search.osschat_milvus(host=MILVUS_HOST, port=MILVUS_PORT, **{metric_type: IP, limit: 3, output_fields: [text…

STM32CubeMX学习笔记-USB接口使用(HID按键)

STM32CubeMX学习笔记-USB接口使用&#xff08;HID按键&#xff09; 一、USB简介1.1 USB HID简介 二、新建工程1. 打开 STM32CubeMX 软件&#xff0c;点击“新建工程”2. 选择 MCU 和封装3. 配置时钟4. 配置调试模式 三、USB3.1 参数配置3.2 引脚配置3.3 配置时钟3.4 USB Device…

【SimpleDateFormat】线程不安全问题分析及解决方案

前言 在日常开发中&#xff0c;我们经常需要去做日期格式转换&#xff0c;可能就会用到SimpleDateFormat类。但是&#xff0c;如果使用不当&#xff0c;就很容易引发生产事故&#xff01; 1. 问题推演 1.1 初始日期工具类 刚开始的日期转换工具类可能长这样&#xff1a; p…

设计模式2、抽象工厂模式 Abstract Factory

解释说明&#xff1a;提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定他们具体的类。 简言之&#xff0c;一个工厂可以提供创建多种相关产品的接口&#xff0c;而无需像工厂方法一样&#xff0c;为每一个产品都提供一个具体工厂 抽象工厂&#xff08;Abstra…

知识图谱02——使用python将信息录入neo4j

将文档传入chatgpt&#xff0c;生成对应的cypher语句 链接: https://pan.baidu.com/s/1Ny-ttbBSpqYEigwYiCWMeA?pwdc7sc 提取码: c7sc 使用命令行安装对应的包 pip install neo4jchatgpt生成出的txt文档中的内容如下&#xff1a; MERGE (Node1:Entity {name: 原始舱单提运单…

Redis BitMap+SpringBoot 实现签到与统计功能

前言&#xff1a; 在各个项目中&#xff0c;我们都可能需要用到签到和 统计功能。签到后会给用户一些礼品以此来吸引用户持续在该平台进行活跃。 签到功能&#xff0c;使用 Redis 中的 BitMap 功能来实现&#xff0c;就是一个非常不错的选择。 一、Redis BitMap 基本用法 Bi…