STM32IO口模拟IIC时序
一、IIC总线

1. 物理层
(1)支持多设备,一个IIC通讯总线中可以连接多个IIC设备,支持多个通讯主机及多个通讯从机;
(2)两条线:双向串行数据线SDA,串行时钟线SCL,数据线用于传输数据,时钟线用于数据收发同步;
(3)每个连接到总线的设备都有一个独立的地址,主机通过这个地址对不同从机进行访问;
(4)总线通过上拉电阻接到电源,当IIC设备空闲时会输出高阻态。
(5)三种传输模式:标准模式(100kbit/s)、快速模式(400kbit/s)、高速模式(3.4Mbit/s)。
(6)连接相同总线的IC数量受总线最大电容400pf的限制。
2. 协议层
(1)起始信号:主机的IIC接口产生的传输,连接到IIC总线上的从机都会接收到这个信号。
(2)从机地址:起始信号产生后,所有从机开始等待主机广播从机地址信号,当广播地址与某个设备地址相同时,该设备就被选中,没有选择的设备会忽略之后的数据信号。IIC协议规定从机地址可以是7位或10位。
(3)传输方向位:地址位之后是传输方向选择位,该位为0时,表示后面数据传输方向是主机写数据到从机;该位为1时,主机读取从机数据。
(4)应答信号:
第一种,从机接收到匹配的地址,从机返回应答信号(ACK),表示找到对应的从设备;
第二种,当从机被寻址后,主机写数据到从机时,从机每收到一个字节的数据都需要给主机一个应答信号(ACK),主机只有接收到应答信号后才能继续发送数据。
(5)停止信号:发送停止信号结束通信。
S:起始信号
SLAVE ADDRESS:从机地址
R/W:传输方向,1读 0写
A:ACK表示应答信号
A非:NACK非应答信号,表示本次通信结束
P:停止信号
阴影部分为主机给从机发的,空白部分为从机给主机发的。
1、IIC主机写数据到从机

2、IIC主机由从机读取数据

3、IIC复合通信

4、IIC通信时序图

(1)起始信号、停止信号

起始信号:SDA、SCL均为高电平,首先处理器让SCL时钟保持高电平,然后让SDA数据信号由高变低就表示一个开始信号。同时IIC总线上的设备检测到这个开始信号就知道处理器要发送数据了,此时总线处于占用状态。
停止信号:处理器让SCL时钟保持高电平,然后让SDA数据信号由低变高就表示一个停止信号。同时IIC总线上的设备检测到这个停止信号就知道处理器已经结束了数据传输,此时总线处于空闲状态。
(2)数据格式/应答
字节从高位到低位传输。发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字
节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
(3)通信

开始标志(S)发出后,主设备会传送一个7 位的从机地址,并且后面跟着一个第8位,称为Read/Write 位。R/W 位表示主设备是在接收从设备的数据还是在向从设备写数据。然后,主设备释放SDA线,等待从设备的应答信号(ACK)。每个字节的传输都要跟随有一个应答位,应答产生时(把SDA拉低)。从设备将SDA 线拉低并且在SCL 为高电平时保持低。数据传输总是以停止信号标志结束,然后释放通信线路。然而,主设备也可以产生重复的开始信号去操作另一台从设备,而不发出结束标志。综上可知,所有的SDA 信号变化都要在SCL 时钟为低电平时进行,除了开始和结束标志。
二、软件模拟IIC通信
iic.h
#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"
//IO方向设置
#define SDA_IN() {GPIOA->CRL&=0X0FFFFFFF;GPIOA->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOA->CRL&=0X0FFFFFFF;GPIOA->CRL|=(u32)3<<28;}
#define IIC_SCL PAout(4) //SCL
#define IIC_SDA PAout(5) //输出SDA
#define READ_SDA PAin(5) //输入SDA
//IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 TX_DATA); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif
iic.c
#include "myiic.h"
#include "delay.h"
/*
*@Function :IIC_Init()
*@brief :初始化IIC GPIO
*@param :void
*@retval : void
*/
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); //使能GPIOA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;//PA4---SCL PA5---SDA
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4 | GPIO_Pin_5); //PA4,PA5 输出高
}
/*
*@Function :IIC_Start()
*@brief :产生IIC起始信号
*@param :void
*@retval : void
*/
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA=1; //处于空闲状态
IIC_SCL=1; //处于空闲状态
delay_us(4);//延时时间看从机设备
IIC_SDA=0;//时钟线为高时数据线由高变低
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
/*
*@Function :IIC_Stop()
*@brief :产生IIC停止信号
*@param :void
*@retval : void
*/
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//时钟线为高,数据线由低变高
delay_us(4);
}
/*
*@Function :IIC_Ack()
*@brief :产生ACK应答
*@param :void
*@retval : void
*/
void IIC_Ack(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//数据线为低电平表示应答
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
/*
*@Function :IIC_NAck()
*@brief :不产生ACK应答
*@param :void
*@retval : void
*/
void IIC_NAck(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
/*
*@Function :IIC_Wait_Ack()
*@brief :等待应答信号
*@param :1,接收应答失败 0,接收应答成功
*@retval : void
*/
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置为输入
IIC_SDA=1;//释放sda线
delay_us(1);
IIC_SCL=1;//从机返回ack
delay_us(1);
while(READ_SDA) //scl为高电平时读取sda
{
ucErrTime++;
if(ucErrTime>250) //超时判断
{
IIC_Stop();//sda高电平表示从机无应答
return 1;//接收应答失败
}
}
IIC_SCL=0;//时钟输出0,结束ack检查
return 0;
}
/*
*@Function :IIC_Send_Byte()
*@brief :IIC发送一个字节
*@param :TX_DATA 要发送的数据
*@retval : void
*/
void IIC_Send_Byte(u8 TX_DATA)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
//IIC_SDA=(TX_DATA&0x80)>>7;//先发高位,与运算取出最高位,移到最后一位
if((TX_DATA&0x80)>>7)
IIC_SDA=1;
else
IIC_SDA=0;
TX_DATA <<=1; //左移一位用于下一位发送,最高位已经发送出去
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
/*
*@Function :IIC_Read_Byte()
*@brief :IIC读1个字节
*@param :ack=1时,发送ACK,ack=0,发送nACK
*@retval : 读取的数据
*/
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;//先接收的高位,需要将接收的数据左移一位
if(READ_SDA) receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
STM32IO口模拟IIC时序的更多相关文章
- 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)
版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 ...
- 用I/O口模拟IIC总线协议遇到的一些问题
最近做的一个项目,是基于IIC总线通信的传感器系统.由于另外一个传感器使用的是类IIC协议,而不是标准IIC,所以MCU不能与其通信,最后没有办法,只有通过I/O口模拟的方式实现IIC的总线通信.具体 ...
- lpc1788IO口模拟IIC
#ifndef __MYIIC_H_ #define __MYIIC_H_ #include "common.h" #include "delay.h" #in ...
- 用I/O口模拟总线时序
在做总线通信过程中,我们很少会用到这样方法,一般在我们选择MCU的时候都会带有你所需要的通信接口.但是,对于一些简单的通信应该用的场合,一般在一些传感器的数据通信过程中,传感器厂商会将通信协议做一些改 ...
- GPIO软件模拟IIC时序
一.MPU6050中的IIC时序 1.1 START和STOP SDA和SCL在高电平时,SDA拉低表示START.SCL拉低,表示可以传输数据. SDA和SCL在低电平时,SDA拉高表示STOP. ...
- 模拟IIC协议时序
IIC是飞利浦公司开发的两线式串行总线,主要应用在单片机和外围电子器件之间的数据通讯. IIC总线优点是节约总线数,稳定,快速,是目前芯片制造上非常流行的一种总线,大多数单片机已经片内集成了IIC总线 ...
- C51—模拟IIC总线实现EEPROM存取数据
a - 什么是IIC总线 -什么是EEPROM -IIC总线的通信格式 模块化设计注解 整体代码 - 什么是IIC总线 IIC总线是同步通信的一种特殊形式,具有接线口少.控制简单.器件封装形式小.通信 ...
- stm32软件模拟IIC读取PX4FLOW光流传感器数据
这段时间在做全国光电设计大赛,用到了px4的px4flow光流传感器,用软件模拟iic读取数据不定期会导致px4flow死机,查了资料和光流的源码,发现这个光流用了stm32的硬件iic,所以对软件模 ...
- GPIO模拟IIC接口信号质量分析
信号质量有问题的波形001: 信号质量有问题的波形002: 从上图可以看出,GPIO口模拟的I2C接口,电平都存在半高的情况. 因为I2C的接口是通过GPIO模拟实现的,该时钟信号线SCL内部默认为下 ...
- MSP430的IO口模拟I2C总线对AT24C25进行读写程序
功能: 实现MSP430口线模拟I2C总线协议与24C04通信. ** 描述: 主系统工作时钟为12MHz,I2C工 ...
随机推荐
- 2024最新免费IP地址SSL证书申请
为IP地址申请免费的SSL证书相对较为困难,因为多数证书颁发机构(CA)提供的免费SSL证书主要是基于域名的.不过,还是可以尝试以下方法来申请免费的IP地址SSL证书: 一.确认IP地址与了解需求 确 ...
- SpringAI:Java 开发的智能新利器
一.SpringAI 简介 随着人工智能技术的飞速发展,越来越多的开发者开始探索如何将 AI 能力集成到现有的应用中来提升产品的智能化水平.Spring AI 正是为 Java 开发者提供的一款强大的 ...
- 文本转换利器之Pandoc
Pandoc 简介 如果你需要在不同的文件格式之间相互转换,多半听说或使用过文档转换的瑞士军刀--Pandoc.事实上,不仅人类知道 Pandoc,最近很火的人工智能 ChatGPT 也知道「将 Ma ...
- Kafka可视化工具之Kafka Tool
官网: https://www.kafkatool.com/download.html Kafka Tool是一个用于管理和使用Apache Kafka集群的GUI应用程序. Kafka Tool提供 ...
- MySQL管理工具之Beekeeper Studio
简介 Beekeeper Studio 是一个跨平台的 SQL 编辑器和数据库管理客户端,可以在 Linux.Mac.Windows 上使用. Beekeeper Studio 社区版是免费开源的,支 ...
- 理解Java BlockingQueue
数据结构与算法是天生一对. BlockingQueue叫做阻塞队列,在Java线程池相关的实现中有广泛的使用. BlockingQueue实现的功能如下: 当队列为空时,往队列中读数据将被阻塞. 当队 ...
- 开发Git分支管理
目前分支管理 AngularJS在github上的提交记录被业内大多数开发人员认可,逐渐被广泛引用. 代码提交Message格式 type (scope): message 参数介绍: 1.type: ...
- Vue.js 组件注册
1.前言 本节讲述组件和2.x版本和3.x版本的注册方式 2.全局注册 2.x版本直接调用Vue.component()方法进行全局注册,所有Vue实例都能使用,包括其组件 //组件代码省略 var ...
- 你真的懂System.out.println()吗?
简介 众所周知,Java语言是面向对象的,那如果让你用一行代码体现出来呢? 如果你能自己读懂System.out.println(),就真正了解了Java面向对象编程的含义. 面向对象编程即创建了对象 ...
- 中电金信新捷报:银行客户资源管理领域No.1
春暖花开,捷报频传 近日,中电金信 客户关系管理系统(CRM) 接连中标 让我们共同见证这波喜讯 01 中电金信凭借优秀的解决方案和丰富的服务案例经验,成功中标某全国性股份制银行同业CRM实施服务采购 ...