当前位置: 首页 > news >正文

51单片机快速入门之 IIC I2C通信

51单片机快速入门之 IIC 总线通信

协议:

  1. 空闲时 SCL/SDA 为高电平
  2. SCL高时   SDA下降沿 为开始信号
  3. 开始信号之后:

                                SCL高电平时 SDA不能变化  ,

                                SCL低电平时 SDA才可变  

                                SDA 传数据时 从高到低按位传输  SCL一个脉冲高电平对应一位数据

      4.SCL高电平时 SDA上升沿 为停止信号

数据格式:

1.单字节格式:

                        开始信号>数据(高到低)>应答(ACK)信号接收方SDA低电平>停止信号

2.多字节格式:

       开始信号>发送设备地址和读写方向>应答(ACK)信号>数据传输>应答(ACK)信号接收方SDA低电平>停止信号

I2C 元器件  24c02(E^2PROM)

读/写操作: 

1.单字节写流程:

开始信号>7位地址(1010固 0A 0B 0C)+读1/写0>24C02回复ACK信号>发送一个字节>ACK信号>停止信号

2.页写流程(多字节):

开始信号>7位地址(1010固 0A 0B 0C)+读1/写0>24C02回复ACK信号>发第一个字节数据地址>ACK>第一个字节数据>ACK>第二个字节数据...>一直到停止信号 或者16字节

最多可一次写入2-16字节!

超出会自动从初始位置覆盖数据 17时覆盖第一个字节数据,之后还有数据往后递增覆盖


3.立即地址读操作:

N范围(0~255)00H~FFH

开始信号>7位地址(1010固 0A 0B 0C)+读1/写0>ack回复>读取一个字节数据(上次操作地址N+1的数据)>停止信号

N=255时 下一个跳转读取 0 

4.选择读操作:

任选地址读

开始信号>7位地址(1010固 0A 0B 0C)+读1/写0>低0伪写操作>ack>N字节地址>从ack>开始信号>7位地址(1010固 0A 0B 0C)+读1/写0>读信号 1>从ack>获取N地址下的数据>停止信号

5.连续读操作:

立即地址读操作 连续

开始信号>7位地址+读1>读取FFH(255)为第一个数据,>主ACK>00H>主ack...直到出现主ack不回复 停下来>停止信号才结束本次读取

选择读操作 连续

开始信号>7位地址(1010固 0A 0B 0C)+读1/写0>低0伪写操作>ack>N字节地址>从ack>开始信号>7位地址(1010固 0A 0B 0C)+读1/写0>读信号 1>从ack>获取N地址下的数据>ack>N+1数据>ack .....直到停止信号

电路图:

捣鼓了好几天,终于调试通了原来这元器件和书上的不同 所以说还是要多看看元器件数据手册才好,不然出了问题都找不到在哪!  就是这里 地址位我弄错了,书上很模糊所以我理解为

A0 A1 A2  顺序错了 实际上是A2 A1 A0 

代码(简单发送):

#include <STC89C5xRC.H>//加载头文件,晶振12MHzsbit SCL=P2^0;  //时钟线
sbit SDA=P2^1;  //数据线void delay(unsigned int t); // 延时函数声明
void startI2C();//开始信号
void stopI2C();//停止信号void SendByte(unsigned char dat);//发送字节数据void main()
{SendByte(0xA2);//发送从机地址SendByte(0x00);//发送需要存入那个字节的地址 00H~FFHSendByte(0x44);    //发送需要存储的数据      P17=0;模拟环境提示操作成功用 ,实际使用可删除while(1); // 防止程序重复运行
}void startI2C() //开始信号
{SDA=1;  //首先拉高SDAdelay(10);//给他点时间SCL=1; //拉高SCLdelay(10);    //1usSDA=0; //拉低SDA 触发开始信号delay(10);    //1usSCL=0; //手动拉低确保时序准确 初始化以接受数据delay(10);    //1us
}void stopI2C() //停止信号
{if(SCL==1&&SDA==0) //只有当SCL=1 而且SDA=0时才触发 SDA=0保证已经接受到ACK回复信号{delay(10); //等一会SDA=1; //拉高SDA ,上升沿触发停止信号} else if(SCL==0)  //当SCL=0时,这句没啥用其实 ,防止   SCL=0 触发不了停止信号 
{delay(10);SCL=1; //把scl 拉高if(SDA==0)  //判断是否接收到ACK回复
{delay(10);SDA=1;}}}void SendByte(unsigned char dat)//发送字节数据
{unsigned char bita;startI2C();//发送开始信号for(bita=0; bita<8; bita++) {if((dat<<bita)&0x80) //每次根据bita 的值左移 bita位 再和 0x80(1000 0000) 与操作(只保最高位)
{SDA=1; //如果是1,拉高sda传送一个1 过去} else {SDA=0;// 反之给0}delay(10); //让它们稳定一下SCL=1;//上升读取  因开始信号已经拉低SCLdelay(10);  //稳定时间       SCL=0;   //下降写入数据  也可以说这是复位delay(10);  //稳定时间}  SDA=1;  //8位传完就拉高等待ACK触发SCL=0;   //下降写入数据 保证循环正确输出8位SCL=1;   //拉高以配合ACK delay(10);//等待if(SDA!=1)  //sda=0 证明 ack已回复 触发停止信号
{stopI2C();P30=0;  //模拟环境提示操作成功用 ,实际使用可删除} else {P10=0;//模拟环境提示操作成功用 ,实际使用可删除}}void delay(unsigned int t) // 简单延迟函数
{while(t--);
}

运行效果:

程序设置了一个监视,操作成功会拉低P30

 代码(简单读取):

#include <STC89C5xRC.H>sbit SCL=P2^0;  //时钟线
sbit SDA=P2^1;  //数据线
sbit DQ=P2^4;//读取按键
void delay(unsigned int t); // 延时函数声明
void startI2C();//开始信号
void stopI2C();//停止信号
bit x; //用于存储ACK信息
unsigned char u;void SendByte(unsigned char dat);//发送字节数据void main()
{SendByte(0xA2);//发送从机地址  最后一位置0 写入x=0;SendByte(0x01);//发送字节地址x=0;SendByte(0x66);    //发送需要存储的数据if(x==1) {stopI2C();   //停止信号}P1=0;x=0;while(DQ==1);//阻断程序运行,当按钮按下往下执行//按键判断读取并赋值给P1寄存器if(DQ==0) {SendByte(0xA3);//发送从机地址  最后一位置1 实际读取if(x==1) { //表示读取请求被响应unsigned char red,bint;P33=0;red=0;// 在读取数据的循环之前添加SDA释放if(SDA!=1&&SCL!=1) {SDA = 1; // 释放SDA线delay(0);}// 读取数据的循环for(bint=0; bint<8; bint++) {delay(20);//延时等待SCL=0;//读取数据delay(20);//延时等待SCL=1;//delay(20);// 检查SDA状态,并更新red的值if(SDA==1) { //如果读取到高电平red |=1<<(7 - bint); // 设置对应位为1} else {red |=0<<(7-bint);}delay(10);//延时等待}SCL=0;//读取数据delay(10);//延时等待SDA = 1; // nackdelay(10);P1=red;//把获取到的值直接用到P1中stopI2C(); //停止信号}}while(1); // 防止程序重复运行
}void startI2C()
{SDA=1;delay(10);SCL=1;delay(10);    //1usSDA=0;delay(10);    //1usSCL=0; //手动拉低确保时序准确delay(10);    //1us
}void stopI2C()
{if(SCL==1&&SDA==0) {delay(10);SDA=1;} else if(SCL==0) {delay(10);SCL=1;if(SDA==0) {delay(10);SDA=1;}}}void SendByte(unsigned char dat)//发送字节数据
{unsigned char bita;startI2C();//发送开始信号for(bita=0; bita<8; bita++) {if((dat<<bita)&0x80) {SDA=1;} else {SDA=0;}delay(10);SCL=1;//上升读取  因开始信号已经拉低SCLdelay(10);SCL=0;   //下降写入数据delay(10);}SDA=1;SCL=0;   //下降写入数据 保证循环正确输出8位SCL=1;delay(10);if(SDA==0) {x=1; //有回复为1P30=0;} else {x=0; //无回复为0// P10=0;}}void delay(unsigned int t) // 简单延迟函数
{while(t--);
}
读取运行效果 :

由图可以看出,元器件根本没有回复数据(试过选择地址读取,也没效果) 所以就这样吧!


最后更新于2024/10/24 0:01

相关文章:

51单片机快速入门之 IIC I2C通信

51单片机快速入门之 IIC 总线通信 协议: 空闲时 SCL/SDA 为高电平SCL高时 SDA下降沿 为开始信号开始信号之后: SCL高电平时 SDA不能变化 , SCL低电平时 SDA才可变 SDA 传数据时 从高到低按位传输 SCL一个脉冲高电平对应一位数据 4.SCL高电平时 SDA上升沿 为停止信号 数…...

腾讯推出ima.copilot智能工作台产品 由混元大模型提供技术支持

腾讯公司近期推出了一款名为ima.copilot&#xff08;简称ima&#xff09;的智能工作台产品&#xff0c;它由腾讯混元大模型提供技术支持。这款产品旨在通过其会思考的知识库&#xff0c;为用户开启搜读写的新体验。ima.copilot的核心功能包括知识获取、打造专属知识库以及智能写…...

1024是什么日子

【1024程序员日数字编织梦想的赞歌】 在这个由二进制构建的宇宙里&#xff0c;每一行代码都是通往未来的桥梁&#xff0c;每一位程序员都是这浩瀚数字海洋中的航海家。今天&#xff0c;10月24日&#xff0c;不仅是一个简单的日期&#xff0c;它是属于我们的节日——程序员日&a…...

驱动开发系列20 - Linux Graphics Xorg-server 介绍

一: 概述 X.Org Server 是由 X.Org 基金会管理的 X Window System (X11) 显示服务器的自由开源实现。客户端 X Window System 协议的实现以 X11 库的形式存在,这些库作为与 X 服务器通信的有用 API。有两个主要的 X11 库。第一个库是 Xlib,它是最初的 C 语言 X11 API;…...

晶台推出SOP5封装的高速光耦KLM45X,提供1MBit/s超快速率

KLM452 和 KLM453 器件均由一个红外发射二极管与一个高速光电检测晶体管组成&#xff0c;两者之间光学耦合。光电二极管偏置和输出晶体管集电极的独立连接可以通过减少输入晶体管的基极-集电极电容来使速度比传统的光电晶体管耦合器提高几个数量级。它们采用行业内标准的 5 引脚…...

软物质流变探究:从宏观微观差异,到水凝胶界面特性

大家好&#xff01;今天我们要探讨的是一篇关于纳米级界面水凝胶粘弹性的研究论文——《Nanoscopic Interfacial Hydrogel Viscoelasticity Revealed from Comparison of Macroscopic and Microscopic Rheology》发表于《Nano Letters》&#xff0c;该研究通过比较宏观和微观流…...

Axure中继器单选、多选和重置

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;Axure中继器单选、多选和重置 主要内容&#xff1a;根据查询条件&#xff0c;通过单选、多选和重置&#xff0c;从中继器中得到数据 应用场景&…...

微软公司用没有使用证据的商标申请驰名商标,该怎么维权?

收集证据&#xff1a;首先需要收集微软公司商标使用的证据&#xff0c;包括但不限于销售记录、广告宣传材料、市场调查报告等&#xff0c;以证明商标的实际使用情况和知名度。如果微软公司的商标确实没有在市场上使用&#xff0c;或者使用证据不足以证明其商标的知名度&#xf…...

学习分布式系统我来助你!【基本知识、基础理论、设计模式、应用场景、工程应用、缓存等全包含!】

基本知识 什么是分布式 分布式系统是一种通过网络连接多个独立计算机节点&#xff0c;共同协作完成任务的系统架构&#xff0c;具有高度的可扩展性、容错性和并发处理能力&#xff0c;广泛应用于大数据处理、云计算、分布式数据库等领域。 通俗来讲&#xff1a;分布式系统就…...

ubuntu查看系统版本命令

查看系统版本指令 在 Ubuntu 操作系统中&#xff0c;您可以使用多个命令来查看系统版本。以下是一些常用的命令&#xff1a; lsb_release -a 这个命令会显示详细的 Ubuntu 版本信息&#xff0c;包括发行版名称、版本号、代号等。lsb_release -acat /etc/os-release 这个命令会显…...

使用yield压平嵌套字典有多简单?

我们经常遇到各种字典套字典的数据&#xff0c;例如&#xff1a; nest_dict {a: 1,b: {c: 2,d: 3,e: {f: 4}},g: {h: 5},i: 6,j: {k: {l: {m: 8}}} } 有没有什么简单的办法&#xff0c;把它压扁&#xff0c;变成&#xff1a; {a: 1,b_c: 2,b_d: 3,b_e_f: 4,g_h: 5,i: 6,j_k_l_…...

express中使用morgan打印请求数据日志文件,按日期分割

使用morgan可以打印日志,但是要分割日志文件就需要使用file-stream-rotator,下面介绍使用方法: 1.安装2个依赖 npm i morgan file-stream-rotator 2.在入口文件app.js中引入相关插件 var express require("express"); var fs require("fs"); var pat…...

干货 | 2024 AI+智慧城市安全解决方案白皮书(免费下载)

导读&#xff1a;新型智慧城市是推动城市治理体系和治理能力现代化、提升城市居民幸 福感和满意度的新理念和新路径&#xff0c;也是网络强国建设和数字经济发展的重要载体。随着 AI 技术的不断发展和在智慧城市智领域广泛的应用&#xff0c;人们享受技 术红利的同时&#xff0…...

超越 React Query:探索更高效的数据请求策略

我们常常遇到组件间通信的难题。你是否也曾为如何优雅地在组件间传递信息而头疼&#xff1f;今天&#xff0c;我想和大家分享一个让我眼前一亮的解决方案——使用 alova。 跨组件触发请求的挑战 如果你正在构建一个电商应用&#xff0c;用户在更新了购物车后&#xff0c;需要…...

Scala trait

一.trait 基本使用 idea实例 二.实现单个特质 三.实现多个特质 idea实例 四.特质成员的处理方式...

AI大法之C语言哈希表算法比较两个文件去重

最近朋友在工作上遇到了一个问题&#xff0c;经常需要比对两个文件&#xff0c;筛选出文件中不同的订单号。比如有两个文件&#xff1a;计费.txt 和 受理.txt&#xff0c;文件中每一行都是一个订单号&#xff0c;需要找出计费.txt文件中有而受理.txt文件中没有的单号和计费.txt…...

Scala 提取器(Extractor)

Scala 提取器(Extractor) Scala 提取器(Extractor)是一个非常有用的特性,它允许你为任何类型定义自定义的解构赋值语法。在Scala中,提取器是一种用于从对象中提取值的工具,它可以帮助你以一种更直观和声明式的方式处理数据。本文将详细介绍Scala提取器的工作原理、使用场景…...

【主机漏洞扫描常见修复方案】:Tomcat安全(机房对外Web服务扫描)

文章目录 引言I SSL/TLS Not ImplementedTomcat 服务器 SSL 证书安装部署(JKS 格式)Tomcat 服务器 SSL 证书安装部署(PFX 格式)HTTP 自动跳转 HTTPS 的安全配置(可选)修复SSL证书版本低II 主机漏洞扫描常见修复方案Apache JServ protocol serviceSlow HTTP DEnial of Ser…...

MySQL数据库之——事务(Transaction)详解

一、MySQL 事务定义 MySQL 事务主要用于处理操作量大&#xff0c;复杂度高的数据。比如说&#xff0c;在银行管理系统中&#xff0c;用户张三向李四账户转账的操作&#xff0c;账户转账是一个完整的业务&#xff0c;最小的单元&#xff0c;不可再分&#xff0c;这样&#xff0c…...

LabVIEW提高开发效率技巧----事件日志记录

在LabVIEW开发中&#xff0c;集成事件日志记录系统是提升程序调试效率和确保系统运行稳定的关键步骤。通过记录关键操作和异常事件&#xff0c;开发人员可以快速定位问题、优化程序性能&#xff0c;并确保系统的稳定性和可靠性。 1. 事件日志的作用 事件日志是指在程序运行过…...

技术架构演进之路:从单体应用到Docker容器编排

文章目录 概念与指标阶段一&#xff1a;单机架构与应用数据分离阶段二&#xff1a;流量爆发引入应用集群与负载均衡阶段三&#xff1a;打破数据瓶颈的读写分离与缓存机制阶段四&#xff1a;垂直分库与微服务拆分阶段五&#xff1a;Docker 容器化与 K8S 编排 对于很多开发者而言…...

SenseVoice-Small语音识别模型ONNX量化部署教程:3步快速上手

SenseVoice-Small语音识别模型ONNX量化部署教程&#xff1a;3步快速上手 语音识别技术正在变得越来越普及&#xff0c;从手机助手到会议纪要&#xff0c;再到智能家居&#xff0c;到处都能看到它的身影。但对于开发者来说&#xff0c;想把一个效果不错的语音识别模型集成到自己…...

rchtxchs.dll文件丢失找不到 免费下载修复方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…...

高精度毫米级室内定位:机器人导航的“最后一厘米”难题如何破解

在机器人技术加速落地的今天&#xff0c;一个看似简单的问题始终困扰着行业&#xff1a;机器人到底能不能知道自己“精确”在哪&#xff1f;这个问题听起来有些哲学&#xff0c;但在工程实践中却极为现实。一台AGV在仓库中穿梭数百米后&#xff0c;能否准确停在货架前5毫米的位…...

TensorBoard 曲线“开头竖线/跳变”

在MMM2这个地图上异常结果如下&#xff1a;问题分析: &#xff08;1&#xff09;大概率没在跑 MMM2&#xff0c;通过查看日志&#xff0c;Experiment Parameters 里是&#xff1a;‘env_args’: {‘seed’: 2} 没有 map_name&#xff0c;这会让 sc2 环境回退到默认地图&#xf…...

为什么世界仍然运行在 SAP 上?——传统企业软件的顽强生命力

这篇来自 Andreessen Horowitz&#xff08;a16z&#xff09;的文章探讨了一个重要问题&#xff1a;在云计算和人工智能快速发展的今天&#xff0c;为什么像 SAP 这样的传统企业软件仍然深度主导全球企业运行&#xff1f;其核心结论是&#xff1a;SAP 的优势不在于技术先进&…...

如何快速学习数据科学:面向初学者的终极资源指南 [特殊字符]

如何快速学习数据科学&#xff1a;面向初学者的终极资源指南 &#x1f680; 【免费下载链接】Best-Data-Science-Resources This repository contains the best Data Science free hand-picked resources to equip you with all the industry-driven skills and interview prep…...

win10升级win11 修复系统不能自动更新

背景: 公司的电脑一直被安全部门提示由漏洞, 需要升级win11 方式1: 用官方的安装助手(需要保证当前系统window更新是正常的) 方式2: 下载系统镜像文件, 解压到其它盘, 然后运行 setup.exe(不用修复window更新) 安装win11的官网地址 下载 Windows 11 先下载安装助手, 如果不…...

Qwen2.5-1.5B开发者实操手册:基于官方Instruct版本的本地对话服务构建

Qwen2.5-1.5B开发者实操手册&#xff1a;基于官方Instruct版本的本地对话服务构建 1. 项目概述 想要在本地电脑上搭建一个完全私有的智能对话助手吗&#xff1f;今天介绍的方案基于阿里通义千问官方的Qwen2.5-1.5B-Instruct轻量级模型&#xff0c;让你无需复杂配置就能拥有一…...

从新手困惑到企业级认知:为什么我放弃了 PHP 集成环境,选择了 Docker?

&#x1f680; 从新手困惑到企业级认知&#xff1a;为什么我放弃了 PHP 集成环境&#xff0c;选择了 Docker&#xff1f; &#xff08;附&#xff1a;企业级 Docker 开发部署完整流程&#xff09;一、我的困惑起点 刚接触 PHP 开发时&#xff0c;我一直有个疑问&#xff1a;本地…...