找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12736|回复: 2
打印 上一主题 下一主题
收起左侧

总结IIC协议学习心得

[复制链接]
跳转到指定楼层
楼主
ID:59284 发表于 2014-2-26 19:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
无论在51或者stm32的学习中,我们都会使用到IIC总线的数据传送,从当初51到现在的stm32的学习。iic一直都是只会简单的使用并未很仔细的去研究中间每一个过程或者时序。今天用了一天的时间去理解IIC。当然这都是建立在以往的学习经验之中而得。一下都是我自己的一些理解和对照程序而写的一些IIC的使用过程。PS:纯属本人手打,不喜勿碰!!!!iic总线时序理解:

24C04
引脚:
NC (1)VCC(8)
A1 (2)WP (7)
A2 (3)SCL(6)
GBD(4)SDA(5)
注:SCL
设置start信号和stop信号,由于此时是STM32对24c02发送信号,所以SCL和SDA设置为输出状态,即:SDA_OUT();
由时序图可知:
START:SCL=1,SDA=1,delay(),SDA=0,delay(),SCL=0,//时钟线为高,数据线从高到低的跳变
STOP :SCL=0,SDA=0,delay(),SCL=1,delay(),SDA=1,//时钟线为高,数据线从低到高的跳变
STM32程序:
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//发送I2C总线结束信号
delay_us(4);
}
iic每成功传送完一个字节后,接收器都必须产生一个应答信号,应答器件在第九个时钟周期讲SDA拉低,表示已经接
收到8位,此时对于24c02有两种可能的工作方式,第一种是24c02工作于读,另一种则是工作于写。
@当工作于读的方式时,SDA为输入状态,即:SDA_IN();此时24c02发送完一个8位数据之后,释放SDA线,将SDA为输出
状态,即:SDA_OUT();并等待stm32发送一个应答信号,若接收到应答信号,则SDA又切换为输入状态,即:SDA_IN();
然后继续发送下一个8位数据;若没有接受到应答信号,则不切换SDA的工作方式。等待STM32发送停止信号。
@当工作于写的方式时,则在每接收一个8位字节之后响应一个应答信号。
由时序图可知:
产生应答信号:SCL=0;SDA_OUT();SDA=0,delay(),SCL=1,delay(),SCL=1;
STM32程序:
void IIC_Ack(void)//产生ACK应答
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
void IIC_NAck(void)//不产生ACK应答
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
当iic发送一个起始信号或者是发送一个写操作时,我们必须要做出应答,因此便设计了应答查询程序。目的
是为了查询某一个操作以后通过是否应答来继续下一步的操作。
应答程序主要是对SDA的读操作,所以在读之前必须设置SDA为输入状态,即:SDA_IN();
STM32程序:
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN();
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime ;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
设置write信号,由于此时是STM32对24c02的发送信号,所以SCL和SDA设置为输出状态,即:SDA_OUT();
由时序图可知:
write:在SCL跳变时,对SDA赋值即位写数据,只需主要在一个周期内,SDA不许有电平变化,否则会认
为是开启或停止信号。
STM32程序:
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t )
{
if((txd&0x80)>>7)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(2); //对TEA5767这三个延时都是必须的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
设置Read信号,由于此时是24c02对STM32的发送信号,所以SCL设置为输出状态,SDA设置为输入状态,
即:SDA_IN();
由时序图可知:
Read:在8个SCL周期内,读取8个SDA的输入,就可以知道一个字节的数据。要弄清楚的很,在发送完
之后弄清楚是否需要应答。
STM32程序:
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;s
}
我们必须要知道芯片的器件地址:我用的是24C04:
1 0 1 0 A2 A1 a8 R/W(1/0)
A0 A1和A2对应器件的管脚1 2和3
a8 a9和a10对应存储阵列地址字地址
弄清楚完整数据读/写过程:
起始信号->发送地址->读/写->应答->数据->应答->数据->应答->终止信号
STM32程序:
//在AT24CXX指定地址读出一个数据
//ReadAddr:开始读数的地址
//返回值 :读到的数据
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
IIC_Send_Byte(0XA0 ((ReadAddr/256)<<1)); //发送器件地址0XA0,写数据
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%6); //发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1); //进入接收模式
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//产生一个停止条件
return temp;
}
//在AT24CXX指定地址写入一个数据
//WriteAddr :写入数据的目的地址
//DataToWrite:要写入的数据
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{
IIC_Start();
IIC_Send_Byte(0XA0 ((WriteAddr/256)<<1)); //发送器件地址0XA0,写数据
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%6); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite); //发送字节
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
delay_ms(10);
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:57736 发表于 2014-2-28 17:03 | 只看该作者
挺好的~!谢谢分享
回复

使用道具 举报

板凳
ID:139772 发表于 2016-10-21 16:44 | 只看该作者
谢谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表