IIC概述
IIC介绍
I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。是半双工通信方式。
IIC特性
相对于UART,IIC的优点在于可以一对多,缺点在于无论主从器件均不对消息进行确认。
模拟IIC优点是可以任意选择SDA和SCL,不受管脚限制而比较灵活。它的缺点是不可用DMA。
硬件IIC优点是可用DMA减轻CPU负担,速度也比模拟IIC快,但是实际调试时可能会出现死锁。
IIC时钟信号是由主控器件产生,所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。
一般情况下,数据线SDA和时钟线SCL都是处于上拉电阻状态。因为:在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。
IIC各种状态解析
空闲状态
I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。
开/起始信号(必须的)
当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变(边沿触发)时序信号,而不是一个 电平信号。
停止信号(非必须)
当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
应答信号(非必须)
发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;
应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
注:如图接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。
数据的有效性
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。
数据传输
在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。
IIC底层代码
IIC.h
#ifndef __IIC_H
#define __IIC_H
#include "stm32f4xx.h"
#include "sys.h"
#define SCL PBout(8)
#define SDA_OUT PBout(9)
#define SDA_IN PBin(9)
void Iic_Init(void);
void AT24C02_Write(u8 addr, u8 *write_buf, u8 len);
void AT24C02_Read(u8 addr, u8 *read_buf, u8 len);
#endif
IIC.c
#include "iic.h"
#include "delay.h"
/*
引脚说明:
PB8 -- SCL
PB9 -- SDA
*/
void Iic_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //引脚8 9
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; //输出模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //快速
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOB, &GPIO_InitStruct);
//总线空闲
SCL = 1;
SDA_OUT = 1;
}
//SDA模式
void Iic_Sda_Mode(GPIOMode_TypeDef Mode)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //引脚9
GPIO_InitStruct.GPIO_Mode = Mode;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //快速
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
//开始信号
void Iic_Start(void)
{
Iic_Sda_Mode(GPIO_Mode_OUT);
//总线空闲
SCL = 1;
SDA_OUT = 1;
delay_us(5);
SDA_OUT = 0;
delay_us(5);
SCL = 0; //钳住总线
}
//停止信号
void Iic_Stop(void)
{
Iic_Sda_Mode(GPIO_Mode_OUT);
SCL = 0;
SDA_OUT = 0;
delay_us(5);
SCL = 1;
delay_us(5);
SDA_OUT = 1;
}
//发送一位数据
void Iic_Send_Ack(u8 ack)
{
Iic_Sda_Mode(GPIO_Mode_OUT);
SCL = 0;
//准备数据
//要发数据1
if(ack == 1)
{
SDA_OUT = 1; //引脚输1
}
//要发数据0
if(ack == 0)
{
SDA_OUT = 0; //引脚输0
}
delay_us(5);
SCL = 1;
delay_us(5);
SCL = 0;
}
//发一个字节
void Iic_Send_Byte(u8 data)
{
u8 i;
Iic_Sda_Mode(GPIO_Mode_OUT);
SCL = 0;
for(i=0; i<8; i++)
{
//准备数据 如数据 0x87 1 0 0 0 0 1 1 1
if(data & (1<<(7-i)))
{
SDA_OUT = 1; //引脚输1
}
//要发数据0
else
{
SDA_OUT = 0; //引脚输0
}
delay_us(5);
SCL = 1;
delay_us(5);
SCL = 0;
}
}
//接受一位数据
u8 Iic_Recv_Ack(void)
{
u8 ack = 0;
Iic_Sda_Mode(GPIO_Mode_IN);
SCL = 0;
delay_us(5);
SCL = 1;
delay_us(5);
if(SDA_IN == 1) //判断引脚电平是否为高电平
{
ack = 1;
}
if(SDA_IN == 0) //判断引脚电平是否为低电平
{
ack = 0;
}
SCL = 0;
return ack;
}
//接受一个字节
//表示读取一个字节之后,需要给对方应答信号或非应答信号。
u8 Iic_Recv_Byte(void)
{
u8 i, data = 0; //0 0 0 0 0 0 0 0
Iic_Sda_Mode(GPIO_Mode_IN);
SCL = 0;
//循环8次,接受一个字节
for(i=0; i<8; i++)
{
delay_us(5);
SCL = 1;
delay_us(5);
if(SDA_IN == 1) //判断引脚电平是否为高电平
{
data |= (1<<(7-i));
}
SCL = 0;
}
return data;
}
24C02–EEPROM
简介
24C02是一个2K位串行CMOS 的EEPROM,内部含有256个8位字节。
与 400KHz I2C 总线兼容
1.8 到 6.0 伏工作电压范围
低功耗 CMOS 技术
写保护功能 当 WP 为高电平时进入写保护状态
页写缓冲器
自定时擦写周期
1,000,000 编程/擦除周期
可保存数据 100 年
8 脚 DIP SOIC 或 TSSOP 封装
温度范围 商业级 工业级和汽车级
本人所用的stm32f4:总容量是256(2K/8)个字节,接口:IIC
写入过程
发送器件地址(0XA0)
发送要写入24C02的内存地址
发送要写入的数据
高四位1010是24Cxx系列的固定器件地址,接下来是A2、A1、A0是根据器件连接来决定,我们的原理图都接地所以是000。R/W为是选择读还是写,1的时候是读,0的时候是写。所以写的地址为0xA0。
读出过程
发送写入的器件地址(0XA0)
发送要读的24C02的内存地址
发送读出的器件地址(0XA1)
读取数据
当读取的时候,地址的最后一位R/W为是选择读,也就是该位为1。所以读取的地址为0xA1。
24C02的读写代码
void AT24C02_Write(u8 addr, u8 *write_buf, u8 len)
{
u8 ack;
//开始信号
Iic_Start();
//发送设置地址,并执行写操作
Iic_Send_Byte(0xA0);
ack = Iic_Recv_Ack();
if(ack == 1)
{
printf("ack failuren");
Iic_Stop();
return;
}
//发送写数据的起始地址
Iic_Send_Byte(addr);
ack = Iic_Recv_Ack();
if(ack == 1)
{
printf("ack failuren");
Iic_Stop();
return;
}
while(len--)
{
//发送数据
Iic_Send_Byte(*write_buf);
ack = Iic_Recv_Ack();
if(ack == 1)
{
printf("ack failuren");
Iic_Stop();
return;
}
//地址加1
write_buf++;
}
Iic_Stop();
printf("write finishn");
}
void AT24C02_Read(u8 addr, u8 *read_buf, u8 len)
{
u8 ack;
//开始信号
Iic_Start();
//发送设置地址,并执行写操作
Iic_Send_Byte(0xA0);
ack = Iic_Recv_Ack();
if(ack == 1)
{
printf("ack failuren");
Iic_Stop();
return;
}
//发送读数据的起始地址
Iic_Send_Byte(addr);
ack = Iic_Recv_Ack();
if(ack == 1)
{
printf("ack failuren");
Iic_Stop();
return;
}
//开始信号
Iic_Start();
//发送设置地址,并执行读操作
Iic_Send_Byte(0xA1);
ack = Iic_Recv_Ack();
if(ack == 1)
{
printf("ack failuren");
Iic_Stop();
return;
}
while(len--) //len = 5
{
// len 4 3 2 1 0
//接受数据
*read_buf = Iic_Recv_Byte();
//地址加1
read_buf++;
if(len > 0)
Iic_Send_Ack(0);
}
//发送非应答
Iic_Send_Ack(1);
Iic_Stop();
printf("read finishn");
}
IIC总结
进行数据传送时,在SCL为高电平期间,SDA线上电平必须保持稳定,只有SCL为低时,才允许SDA线上电平改变状态。并且每个字节传送时都是高位在前;
对于应答信号,ACK=0时为有效应答位,说明从机已经成功接收到该字节,若为1则说明接受不成功;
如果从机需要延迟下一个数据字节开始传送的时间,可以通过把SCL电平拉低并保持来强制主机进入等待状态;
主机完成一次通信后还想继续占用总线在进行一次通信,而又不释放总线,就要利用重启动信号。它既作为前一次数据传输的结束,又作为后一次传输的开始;
总线冲突时,按“低电平优先”的仲裁原则,把总线判给在数据线上先发送低电平的主器件;
在特殊情况下,若需禁止所有发生在I2C总线上的通信,可采用封锁或关闭总线,具体操作为在总线上的任一器件将SCL锁定在低电平即可;
SDA仲裁和SCL时钟同步处理过程没有先后关系,而是同时进行的。
上一篇:初学stm32-外部中断(EXTI按键中断)
下一篇:STM32进阶-独立看门狗应用的详细步骤
推荐阅读最新更新时间:2024-11-10 11:12
推荐帖子
- 基于ARM+fpga架构的运动控制卡
- 有从事ARM+FPGA架构运动控制卡底层开发的朋友,愿意出售方案的请联系我,企鹅号37353543需要4轴控制,最少3轴联动,带直线圆弧插补,S样条曲线等基本功能,最好是以太网接口。本论坛中有相关论文基于ARM+fpga架构的运动控制卡
- tanic1985 ARM技术
- 【ST NUCLEO-U5A5ZJ-Q开发板测评】01 开箱
- 前言感谢EEWorld提供这次试用STNUCLEO-U5A5ZJ-Q开发板的机会,也非常感谢ST提供这次机会,这是个人首次申请到试用ST开发板的机会,谢谢。在微信群里看到一些大佬推荐ST开发板时,多次提到这款开发板,并且也看到它的存储竟然有4MB,所以就想体验一下,这块开发板。一、开箱得知入围名单,还是很开心的,立马就去确认信息了。过了几天,收到快递,ST的包装是这样的,依然具有ST的特色,还采用了环保包装。先给开发板来一个怼脸照。二、板载资源
- 怀揣少年梦 stm32/stm8
- 硬件面试题目-基础知识
- 电阻、电容、电感封装的含义:0402、0603、0805表示的是尺寸参数。0402:40*20mil;0603:60*30mil;0805:80*50mil字母所代表的电容的精度:J、K、M、ZJ——±5%;K——±10%;M——±20%;Z——+80%~-20%电阻、电容、电感的封装大小分别与什么参数有关电阻封装大小与电阻值、额定功率有关;电容封装大小与电容值、额定电压有关;电感封装大小与电感量、额定电流有关。常
- cheungchew 模拟电子
- 找到个坦克底座,看起来不错!
- 找到个坦克底座,看起来不错!就是价格高了点找到个坦克底座,看起来不错!看不清,图片这么小也不说说哪里有还谈什么价格,显摆么大的弄不下来啊!TAOBAO里看到的368一台回复沙发wangfuchong的帖子有点贵啊!!你也看到这个底盘了啊近期我们也打算做个履带地盘,到时候来分享啦坐等楼上DIY履带地盘,,,,看看这个全金属的
- 蓝雨夜 DIY/开源硬件专区
- 【15周年庆】约不?一起来DIY电子工具箱~功能你做主
- Hello,大家好~~请看我搞事情的小眼睛。作为一名电子工程师,日常工作,生活中,总要备一些常用的小工具,比如一个下载器,一个多口的转接器。那么,我们是不是可以一起来做一个常用工具的DIY呢,嗯,再打上个咱们EE的大logo~趁着EEWorld15周年打造一波DIY工具做纪念品呀~~有没有兴趣呀~~要约的小伙伴来举个小手手呀~~想法是有了,那么具体要做些什么
- EEWORLD社区 DIY/开源硬件专区
- 五分钟科普—三大触摸屏技术In-cell、On-cell和OGS扫盲
- 本帖最后由jameswangsynnex于2015-3-320:02编辑目前,新兴嵌入式触摸屏技术主要可以分为三大阵营,分别是以苹果iPhone5为代表的in-cell阵营,以三星为代表的on-cell阵营和以HTC、谷歌Nexus7等为代表的OGS阵营。这三大技术在一段时间内将主导智能便携设备,这里对三大技术原理进行分析。一、OGSOGS全称OneGlassSolution,字面上的意思是单玻璃解决方案,其定义目前比较混乱。一部分技
- wstt 移动便携
设计资源 培训 开发板 精华推荐
- 【创意PCB】涂鸦zigbee无线开关
- 数控正弦波发生器
- RD-325,用于 PDP 电视的 384W、60V、210V DC 到 DC 多输出电源的参考设计
- LT3467AES67 5V 至 40V 升压转换器的典型应用
- MC78M12BDTRKG 12V 电流调节器的典型应用
- LTC2260-14 演示板,14 位,105Msps ADC,CMOS 输出,5-170MHz
- AD7847AQ 双路 12 位数模转换器的典型应用
- 使用 ROHM Semiconductor 的 BD49K30G-TL 的参考设计
- 55555
- EVAL-ADF7021DBZ2,基于 ADF7021 862 - 870 MHz ISM 频段收发器的子板