文章目录
- 前言
- 一、IIC简介
- 二、协议层
-
- 1.开始/停止动作
- 2.应答动作
- 3.写/读字节
- 4.空闲状态
- 三、AT24C02
-
- 1.概况
- 2.写操作
- 3.读操作
- 四、MCP4017可编程电阻
-
- 1.概况
- 2.读\写动作
- 总结
前言
提示:以下是本篇文章正文内容
一、IIC简介
I2C(IIC,Inter-Integrated Circuit), 两线式串行总线, 由PHILIPS公司开发用于连接微控制器及其外围设备
它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。IIC是半双工通信方式
IIC总线是不同的IC或模块之间的双向两线通信,这两条线是串行数据线(SDA)和串行时钟线(SCL)。这两条线必须通过上拉电阻连接正电源。数据传输只能在总线不忙时启动。
二、协议层
有效数据:在时钟的高电平周期内,SDA线上的数据必须保持稳定,数据线仅可以在时钟SCL为低电平时改
1.开始/停止动作
开始动作:当SCL为高电平的时候,SDA线上由高到低的跳变
void I2CStart(void)
{
SDA_Output(1); // SDA_Output只是一个输出电平函数delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);SDA_Output(0); // SDA拉低delay1(DELAY_TIME);SCL_Output(0); //为了下一步动作SDA,只能在SCL低地电平期间,电平反转delay1(DELAY_TIME);
}
结束动作:当SCL为高电平的时候,SDA线上由低到高的跳变
void I2CStop(void)
{
SCL_Output(0);delay1(DELAY_TIME);SDA_Output(0);delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);SDA_Output(1);delay1(DELAY_TIME);
}
注意起始和终止信号都是由主机发出的,总线在起始条件之后,视为忙状态,在停止条件之后被视为空闲状态
2.应答动作
每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据
从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答, 接收器成功地接收了该字节,1表示非应答,接收器没有成功接收该字节
等待从机发送应答或者非应答
unsigned char I2CWaitAck(void)
{
unsigned short cErrTime = 5;SDA_Input_Mode();delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);while(SDA_Input()){
cErrTime--;delay1(DELAY_TIME);if (0 == cErrTime){
SDA_Output_Mode();I2CStop();return ERROR;}}SCL_Output(0);delay1(DELAY_TIME);SDA_Output_Mode();return SUCCESS;
}
注:若采用官方给的参考,需做如下修改:将SDA放在他们最后
主机或者从机产生应答
void I2CSendAck(void)
{
SDA_Output(0);delay1(DELAY_TIME);delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);SCL_Output(0);delay1(DELAY_TIME);}
主机或者从机产生非应答
void I2CSendNotAck(void)
{
SDA_Output(1);delay1(DELAY_TIME);delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);SCL_Output(0);delay1(DELAY_TIME);}
3.写/读字节
数据传输过程中,数据传输保持稳定(在SCL高电平期间,SDA一直保持稳定,没有跳变),只有当SCL被拉低后,SDA才能被改变在SCL为高电平期间(有效数据时间段),发送数据,发送8次数据,如果数据为1,显然SDA是被拉高;如果数据为0,那么SDA被拉低
输出到SDA线上的每个字节必须是8位,数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)
写一个字节:
void I2CSendByte(unsigned char cSendByte)
{
unsigned char i = 8;while (i--){
SCL_Output(0);delay1(DELAY_TIME);SDA_Output(cSendByte & 0x80);delay1(DELAY_TIME);cSendByte += cSendByte;delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);}SCL_Output(0);delay1(DELAY_TIME);
}
读一个字节
unsigned char I2CReceiveByte(void)
{
unsigned char i = 8;unsigned char cR_Byte = 0;SDA_Input_Mode();while (i--){
cR_Byte += cR_Byte;SCL_Output(0);delay1(DELAY_TIME);delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);cR_Byte |= SDA_Input();}SCL_Output(0);delay1(DELAY_TIME);SDA_Output_Mode();return cR_Byte;
}
这里数据的移位采用的是cSendByte += cSendByte,每次最高位刚好等于次高位,从而达到左移效果
4.空闲状态
I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态
此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高
三、AT24C02
1.概况
引脚和封装
注意:A0、A1、A2、三个脚不同的电平可以形成不同的地址,最多8种
从机地址组成
硬件原理图
所以,前面固定为1010 000(r/w)
24C02的芯片地址为1010 (A2 A1 A0) (R=1,W=0)
0xA0写
0xA1读
2.写操作
AT24C02存储器写操作需要给出开始状态,器件地址和确认之后,紧跟着给出一个8为数据地址。一经收到该地址,EEPROM就通过SDA发出确认信号,并随时钟输入8位数据。在收到8位数据之后,EEPROM将向SDA确认,数据传输设备必须用停止状态来终止写操作。
EEPROM进入一个内计时固定存储器写周期,在该写周期,所以的输入被禁止,EEPROM直到写完才应答。
连续写
1KB/2KB EEPROM能进行8字节页面写入,4KB、8KB和16KB设备能进行16字节页面写入。激发写页面与激发写字节相同,只是数据传送设备无须在第一个字节随时钟输入之后,发出一个停止状态。在EEPROM确认收到第一个数据之后,数据传送设备能再传送7个(1KB、2KB)或15个(4KB、8KB、16KB)数据,每一个数据收到之后,EEPROM都将通过SDA回送一个确认信号,最后数据传送设备必须通过停止状态终止页面写序列。写页面时序如图3.18所示。
void iic_24c02_write(unsigned char *pucBuf,unsigned char ucAddr,unsigned char ucNum)
{
I2CStart();I2CSendByte(0xa0); // 器件地址I2CWaitAck();I2CSendByte(ucAddr); // 写数据地址I2CWaitAck();while(ucNum--){
I2CSendByte(*pucBuf++);I2CWaitAck();}I2CStop();delay1(500);
}
数据字地址的低3位(1KB、2KB)或低4位(4KB、8KB、16KB)在收到每个数据字后,内部自动加1,数据字地址的高位字节保持不变,以保持存储器页地址不变。
如果传送到EEPROM中的数据字超过8(1KB、2KB)或16 (4KB、8KB、16KB)字节,数据字地址将重复滚动,以前的数据将被覆盖
3.读操作
除了器件地址码中的读/写选择位置1,读操作与写操作是一样的。读操作有三种:立即地址读取,随机地址读取和顺序读取
立即地址读取
内部数据字地址指针保持在读写操作中最后访问的地址,按“1”递增
只要芯片保持上电,该地址在两个操作之间一直有效,如果最后一个操作是在地址n处读取,则立即地址是n+1;如果最后操作是在地址n处写入,则立即地址也是n+1。
随机地址读取:
随机地址读取时序如图所示。随机读取需要一个空字节写序列来载入数据地址,一旦器件地址码和数据码地址码时钟输入,并被EEPROM确认,数据传送设备就必须产生另一个开始条件。
读/写选择位处于高电平时,通过送出一个器件地址,数据传送设备激发出一个立即寻址读取,EEPROM确认器件地址,并随时钟串行输出数据。器件读数据不通过确认(使SDA总线处于高电平)应答,而通过产生一个停止条件应答。
顺序读取
顺序读取时序如图所示。顺序读取由立即地址读取或随机地址读取激发,在读数据器件收到一数据码之后,通过确认应答,只要EEPROM收到确认之后,便会继续增加数据码地址及串行输出数据码。当达到存储器地址极限时,数据码地址将重复滚动,顺序读取将继续。当读数据器件不通过确认(使SDA总线处于高电平)应答,而通过产生一个停止条件应答时,顺序读取操作被终止。
随机读取程序
// 开始是以写的方式,传入从机地址(假写)
void iic_24c02_read(unsigned char *pucBuf,unsigned char ucAddr,unsigned char ucNum)
{
I2CStart();I2CSendByte(0xa0); // 器件地址(写)I2CWaitAck();I2CSendByte(ucAddr); // 写数据地址I2CWaitAck();I2CStart();I2CSendByte(0xa1); // 读数据while(ucNum--){
*pucBuf++ = I2CReceiveByte();if(ucNum) // 没有接收完I2CSendAck();elseI2CSendNotAck();}I2CStop();
}
注:只有随机读取过程有一个假写过程
四、MCP4017可编程电阻
1.概况
内部结构
电阻的计算:Rs的阻值为 AB之间的总电阻除以127,其中Rw的阻值几乎为零,可以忽略不计。N为我们写入的数据。RAB为常量,可以根据数据手册查找
相当于每增加一个数,电阻增加787.402欧
从机器件的地址
前面几位都是固定的:0101 111(r/w)
原理图:
2.读\写动作
读一个字节
void write_resistor(uint8_t value)
{
I2CStart();I2CSendByte(0x5E);I2CWaitAck();I2CSendByte(value);I2CWaitAck(); I2CStop();
}
写一个字节
uint8_t read_resistor(void)
{
uint8_t value;I2CStart();I2CSendByte(0x5F);I2CWaitAck();value = I2CReceiveByte();I2CSendNotAck(); I2CStop(); return value;
}
注:读写时地址不一样
写进去的一个数字(0-127),读出来也是一个数字
转化为电阻阻值:R = 787.4 * read_resistor 欧
电压:3.3*(R/(R+10k)) (假设外接的电压为3.3)
总结
提示:这里对文章进行总结: