打印
[STM32F1]

STM32基础篇 LCD—— IIC 实验

[复制链接]
2849|30
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
最近有点繁忙,今天闲下来多发几篇,前面已经讲解过了 IIC,之前使用的是通过串口打印输出,本次试验我们使用按键 K_UP 进行 IIC 写入,按键 K_DOWN 进行 IIC 读取。将写入和读取的数据现在是TFTLCD 上 。
实验目标:
1. 学习 I2C 协议
2. 学会操作 AT24C02

沙发
aizaixiyuanqian|  楼主 | 2018-2-12 14:47 | 只看该作者
  I2C  简介
I2C 总线时 PHILIPS 公司推出的一种串行总线,具备多主机系统所需的包括总线仲裁
和高低速器件同步功能的高性能串行总线。它只需要两跟双向的信号线,一根数据线 SDA,
一个是时钟线 SCL。在 I2C 总线上面,每个器件都有自己相应的 I2C 地址,所以在两个
器件之间进行通信的时候,都要首先呼叫你想要通信的器件地址,然后等待相应的从器件进
行应答之后才开始通信。首先我们来看一下,一个 I2C 信号传输的一个过程

使用特权

评论回复
板凳
aizaixiyuanqian|  楼主 | 2018-2-12 14:48 | 只看该作者

从图中我们可以看出在 I2C 上面一个完整信号的传输过程,一定要有一个始信号,还有一
个结束信号,在每个字节传输结束的时候,从机还要提供一个应答信号。一个完整的信号传
输就是这样子。接下来我们来看一下,I2C 总线上面对起始信号、应答信号、结束信号、还
有高低电平的协定是怎么样的呢?这里有两个要注意的要点:
1、在总线空闲的时候,SDA 和 SCL 都是高电平的。
2、在 SCL 为高电平期间,SDA 必须保持稳定。所以 SDA 改变状态最好在 SCL 为低电
平的时候改变,如果在高电平改变的话回被认为是一种有效信号(如:起始信号或者结束信
号)

使用特权

评论回复
地板
aizaixiyuanqian|  楼主 | 2018-2-12 14:50 | 只看该作者
起始信号起始信号简介 SCL 线为高电平期间,SDA 线由高电平向低电平的变化表示起始信号,
信号时序如图:




使用特权

评论回复
5
aizaixiyuanqian|  楼主 | 2018-2-12 14:52 | 只看该作者
这里要注意的就是,在 I2C 总线上面,当总线空闲的时候,SCL 和 SDA 都是高电平
的。起始信号,它是需要有一定的保持时间的,在 SDA 从高电平向低电平跳变的时候,两
个先必须至少保持 4.7us 的时间,而跳变之后,也要保持 SCL 高电平和 SDA 低电平要至
少保持 4us 的时间(从这里我们看出 I2C 总高速率已经决定了) 。

使用特权

评论回复
6
aizaixiyuanqian|  楼主 | 2018-2-12 14:52 | 只看该作者
IO 口模拟起始信号
//产生起始信号
void I2C_Start(void)
{
I2C_SDA_OUT();
I2C_SDA_H;
I2C_SCL_H;
delay_us(5);
I2C_SDA_L;
delay_us(6);
I2C_SCL_L;
}

使用特权

评论回复
7
aizaixiyuanqian|  楼主 | 2018-2-12 14:57 | 只看该作者
结束信号
结束信号简介 SCL 线为高电平期间,SDA 线由低电平向高电平的变化表示终止信号。
信号时序如图:


使用特权

评论回复
8
aizaixiyuanqian|  楼主 | 2018-2-12 14:58 | 只看该作者
IO 口模拟结束信号
//产生停止信号
void I2C_Stop(void)
{
I2C_SDA_OUT();
I2C_SCL_L;
I2C_SDA_L;
I2C_SCL_H;
delay_us(6);
I2C_SDA_H;
delay_us(6);
}

使用特权

评论回复
9
aizaixiyuanqian|  楼主 | 2018-2-12 15:00 | 只看该作者
应答信号
应答,也叫响应。数据的传输必须要带应答。在响应的时钟脉冲期间(也就是 SCL 在高电
平的时候) ,发送器释放 SDA 线(释放 SDA 意思就是将 SDA 拉为高电平,这里要注
意的是,不能在 SCL 为高电平的时候讲 SDA 从低电平拉到高电平,可以在在 SCL 在低
电平的时候,将 SDA 拉为高电平等待),然后等待应答,在应答时钟脉冲器件,接收器
必须将 SDA 拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平。而一个字节传输
完毕之后,接收器没有应答则表示接收完毕。还有一种情况是,当主机作为接收器的时候,
接收完最后一个字节之后,必须向从机发出一个结束传送的信号。这个信号是由对从机“非
应答”来实现的。(从上面的规则我们知道,当主机作为接收器的时候,如果是进行应答,
那么在接收完一个字节的最后一位之后产生一个低电平的时钟,进行应答。而非应答呢,就
是产生一个高电平的时钟,进行应答) 。

使用特权

评论回复
10
aizaixiyuanqian|  楼主 | 2018-2-12 15:00 | 只看该作者
IO 口模拟应答信号
//主机产生应答信号 ACK
void I2C_Ack(void)
{
I2C_SCL_L;
I2C_SDA_OUT();
I2C_SDA_L;
delay_us(2);
I2C_SCL_H;
delay_us(5);
I2C_SCL_L;
}

使用特权

评论回复
11
aizaixiyuanqian|  楼主 | 2018-2-12 15:01 | 只看该作者
//主机不产生应答信号 NACK
void I2C_NAck(void)
{
I2C_SCL_L;
I2C_SDA_OUT();
I2C_SDA_H;
delay_us(2);
I2C_SCL_H;
delay_us(5);
I2C_SCL_L;
}

使用特权

评论回复
12
aizaixiyuanqian|  楼主 | 2018-2-12 15:01 | 只看该作者
//等待从机应答信号
//返回值:1 接收应答失败
//  0 接收应答成功
u8 I2C_Wait_Ack(void)
{
u8 tempTime=0;
I2C_SDA_IN();
I2C_SDA_H;
delay_us(1);
I2C_SCL_H;
delay_us(1);
while(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
{
tempTime++;
if(tempTime>250)
{
I2C_Stop();
return 1;
}
}
I2C_SCL_L;
return 0;
}

使用特权

评论回复
13
aizaixiyuanqian|  楼主 | 2018-2-12 15:06 | 只看该作者
逻辑“1 ”的表示
要传输数据,那么肯定要分传输“1”和“0” ,而在 I2C 上面是怎么表示这两个逻辑变量
的呢?如图

使用特权

评论回复
14
aizaixiyuanqian|  楼主 | 2018-2-12 15:06 | 只看该作者
一般 I2C 读取的时候,都是在 SCL 的为高电平的时候进行读取,所以在 SCL 为高电平
的时候,需要保持 SDA 稳定。而且注意的还有就是他们的保持时间要大于 4us。

使用特权

评论回复
15
aizaixiyuanqian|  楼主 | 2018-2-12 15:09 | 只看该作者
逻辑“0 ”的表示
逻辑“0”和逻辑“1”的表示其实差不多,只是 SDA 正好相反。如图:

使用特权

评论回复
16
aizaixiyuanqian|  楼主 | 2018-2-12 15:09 | 只看该作者
IO  口模拟发送一个字节数据
//I2C 发送一个字节
void I2C_Send_Byte(u8 txd)
{
u8 i=0;
I2C_SDA_OUT();
I2C_SCL_L;//拉低时钟开始数据传输
for(i=0;i<8;i++)
{
if((txd&0x80)>0) //0x80 1000 0000
I2C_SDA_H;
else
I2C_SDA_L;
txd<<=1;
I2C_SCL_H;
delay_us(2); //发送数据
I2C_SCL_L;
delay_us(2);
}
}

使用特权

评论回复
17
aizaixiyuanqian|  楼主 | 2018-2-12 15:10 | 只看该作者
IO  口模拟接收一个字节数据
//I2C 读取一个字节
u8 I2C_Read_Byte(u8 ack)
{
u8 i=0,receive=0;
I2C_SDA_IN();
for(i=0;i<8;i++)
{
I2C_SCL_L;
delay_us(2);
I2C_SCL_H;
receive<<=1;
if(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA))
receive++;
delay_us(1);
}
if(ack==0)
I2C_NAck();
else
I2C_Ack();
return receive;
}

使用特权

评论回复
18
aizaixiyuanqian|  楼主 | 2018-2-12 19:25 | 只看该作者
24C02  简介
1. 24C02 可以提供 2K 位,也就是 256 个 8 位字节的 EEPROM 内存。也就是说它可以
保存 256 个字节的数据。所以从这里我们可以了解到,256 个字节也就是有 256 个内存地
址,也正好对应一个字节的。当我们向 24C02 读写数据的时候,地址正好跟一个字节一一
对应。
2. 24C02 通过 I2C 总线接口进行操作。
3. 24C02 的写操作,可以一个地址一个地址的写,也可以一次写一页。所写的一页,在 24C02
这里是 8 个字节,(在有些数据手册上面是 16 个字节,不过开发板上面使用 24C02 是一
页 8 个字节,ARM 公司提供的官方例程里面 24C02 设定的也是一页 8 个字节。 )也就
是说当你写入的数据,在同一页的时候(注意是在同一页的时候) ,你可以只写入一次地
址,每写入一个字节,地址自动加 1。
4. 24C02 的读操作,24C02 的读操作就可以连续读,不管连续读的数据是不是在同一页,
每次读完一次数据之后,读取地址都会自动加 1。

使用特权

评论回复
19
aizaixiyuanqian|  楼主 | 2018-2-12 19:26 | 只看该作者
24C02的原理图


使用特权

评论回复
20
aizaixiyuanqian|  楼主 | 2018-2-12 19:27 | 只看该作者
从图上我们可以看出 24C02 使用的是 STM32 的 I2C2,使用的是 PB10、 PB11 两个 IO
口。我们知道,在 I2C 总线上面,每个器件都会有一个器件地址,而 24C02 的器件地址是
多少呢?我们来看一个图:


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

1353

帖子

6

粉丝