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.xdnf.cn/news/146551.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

B. Comparison String

题目&#xff1a; 样例&#xff1a; 输入 4 4 <<>> 4 >><< 5 >>>>> 7 <><><><输出 3 3 6 2 思路&#xff1a; 由题意&#xff0c;条件是 又因为要使用尽可能少的数字&#xff0c;这是一道贪心题&#xff0c;所以…

Linux CentOS7 vim临时文件

在vim中&#xff0c;由于断网、停电、故意退出、不小心关闭终端等多种原因&#xff0c;正在编辑的文件没有保存&#xff0c;系统将会为文件保存一个交换文件&#xff0c;或称临时文件&#xff0c;或备份文件。 如果因某种原因产生了交换文件&#xff0c;每次打开文件时&#x…

详解分布式搜索技术之elasticsearch

目录 一、初识elasticsearch 1.1什么是elasticsearch 1.2elasticsearch的发展 1.3为什么学习elasticsearch? 1.4正向索引和倒排索引 1.4.1传统数据库采用正向索引 1.4.2elasticsearch采用倒排索引 1.4.3posting list ​1.4.4总结 1.5 es的一些概念 1.5.1文档和字段 …

鞋类 整鞋试验方法 剥离强度

声明 本文是学习GB-T 3903.3-2011 鞋类 整鞋试验方法 剥离强度. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 GB/T 3903 的本部分规定了整鞋鞋底与鞋帮或外底与外中底之间剥离强度的试验方法。 本部分适用于采用模压、硫化、注塑、灌注、胶…

C进阶--字符函数和字符串函数介绍

✨ 更多细节参考 cplusplus.com/reference/cstring/ 使用方式&#xff1a; ⭕ 求字符串长度 &#x1f58c; strlen 函数原型&#xff1a; size_t strlen ( const char * str ); 作用&#xff1a; 获取字符串长度 ✨补充&#xff1a; ⭐字符串以 \0 作为结束标志&…

5.外部中断

中断初始化配置步骤&#xff1a; IO口初始化配置 开启中断总允许EA 打开某个IO口的中断允许 打开IO口的某一位的中断允许 配置该位的中断触发方式 中断函数&#xff1a; #pragma vector PxINT_VECTOR __interrupt void 函数名(void){}#pragma vector PxINT_VECTOR __int…

喝健康白酒 有益生心健康

中国的制酒史源远流长&#xff0c;酒渗透在中华五千年的文化中。酒与烟不同&#xff0c;烟对人体有百害而无一利&#xff0c;而对于酒&#xff0c;若掌握好饮酒的度&#xff0c;对人体有一定的养生作用&#xff0c;所以我们通常会说“戒烟限酒”。 据一些专家研究&#xff0c;…

云原生Kubernetes:对外服务之 Ingress

目录 一、理论 1.Ingress 2.部署 nginx-ingress-controller(第一种方式) 3.部署 nginx-ingress-controller(第二种方式) 二、实验 1.部署 nginx-ingress-controller(第一种方式) 2.部署 nginx-ingress-controller(第二种方式) 三、问题 1.启动 nginx-ingress-controll…

什么是 MyBatis?与 Hibernate 的区别

引言 在现代的应用程序开发中&#xff0c;与数据库的交互是至关重要的。为了简化数据库访问&#xff0c;许多开发者选择使用ORM&#xff08;对象-关系映射&#xff09;框架。MyBatis和Hibernate都是流行的ORM框架&#xff0c;它们可以帮助开发者更轻松地将Java对象映射到数据库…

Java-API简析_java.util.Objects类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/133463511 出自【进步*于辰的博客】 因为我发现目前&#xff0c;我对Java-API的学习意识比较薄弱…

Polygon Miden交易模型:Actor模式 + ZKP => 并行 + 隐私

1. 引言 前序博客&#xff1a; Polygon Miden&#xff1a;扩展以太坊功能集的ZK-optimized rollupPolygon Miden zkRollup中的UTXO账户混合状态模型 Polygon Miden为&#xff1a; ZK-optimized rollup由客户端生成证明完善Polygon ZK系列解决方案&#xff0c;致力于成为网络…

消息队列-RabbitMQ(二)

接上文《消息队列-RabbitMQ&#xff08;一&#xff09;》 Configuration public class RabbitMqConfig {// 消息的消费方json数据的反序列化Beanpublic RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory){Simple…

数据结构-哈希表

系列文章目录 1.集合-Collection-CSDN博客​​​​​​ 2.集合-List集合-CSDN博客 3.集合-ArrayList源码分析(面试)_喜欢吃animal milk的博客-CSDN博客 4.数据结构-哈希表_喜欢吃animal milk的博客-CSDN博客 文章目录 目录 系列文章目录 文章目录 前言 一 . 什么是哈希表&a…

【教学类-38-02】20230724京剧脸谱2.0——竖版(小彩图 大面具)(Python 彩图彩照转素描线描稿)

结果展示 背景需求&#xff1a; 前文体运用Python颜色提取功能&#xff0c;将“京剧脸谱”彩色图片转化为线描图案。 【教学类-38】20230724京剧脸谱1.0——横版“彩图线图等大”&#xff08;Python 彩图彩照转素描线描稿&#xff09;_reasonsummer的博客-CSDN博客 存在问题&…

计算机图形学、贝塞尔曲线及绘制方法、反走样问题的解决(附完整代码)

贝塞尔曲线 1. 本次作业实现的函数及简单描述&#xff08;详细代码见后&#xff09;2. 与本次作业有关的基础知识整理3. 代码描述&#xff08;详细&#xff09;4. 完整代码5. 参考文献 &#xff08;本篇为作者学习计算机图形学时根据作业所撰写的笔记&#xff0c; 如有同课程请…

数字时代古文的传承———云南文化瑰宝“爨文化“(我为家乡发声)

文章目录 前言⭐ "爨"意味着什么&#xff0c;究竟何为"爨文化"&#xff1f;⭐ 爨文化鲜明的特点1.经济生活2.政治生活3.文化艺术 ⭐ 数字时代古文的传承与传播1.藏品数字化2.建立数据库3.传播大众化 前言 爨文化是继古滇文化之后崛起于珠江正源南盘江流域…

根据GWAS数据估算样本量N和使用千人基因组填充maf的参考文献

https://github.com/GenomicSEM/GenomicSEM/wiki/2.1-Calculating-Sum-of-Effective-Sample-Size-and-Preparing-GWAS-Summary-Statistics

【SQL】mysql创建定时任务执行存储过程--20230928

1.先设定时区 https://blog.csdn.net/m0_46629123/article/details/133382375 输入命令show variables like “%time_zone%”;&#xff08;注意分号结尾&#xff09;设置时区&#xff0c;输入 set global time_zone “8:00”; 回车,然后退出重启&#xff08;一定记得重启&am…

【C++】手撕vector(vector的模拟实现)

手撕vector目录&#xff1a; 一、基本实现思路方针 二、vector的构造函数剖析&#xff08;构造歧义拷贝构造&#xff09; 2.1构造函数使用的歧义问题 2.2 vector的拷贝构造和赋值重载&#xff08;赋值重载不是构造哦&#xff0c;为了方便写在一起&#xff09; 三、vector的…

Apollo自动驾驶系统概述(文末参与活动赠送百度周边)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…