实验开发板为CT107D蓝桥官方板,编译环境为MDK5
由蓝桥官方驱动改写
AT24C02为地址可编程器件(CT107D可编程位均为0),因此可于总线上挂载多个相同的器件。
最后一位为读写位(0写1读)
IIC的开始和关闭时序图:
(具体操作请读代码)
IIC的读和写时序图:(操作请读代码)
IIC等待应答(写完一个字节)和发送应答(读完一个字节)(0应答1非应答):说白了
等待应答就是读完一个字节后发送(写)一位是否继续读的指令;发送应答就是写完一个字节后等待(读)一位器件是否接收到的指令;(操作请读代码)
AT24C02(页)写字节(内存是分为多页管理的AT24C02是一页8字节): 启动IIC写入24C02地址加上一位写指令等待/判断应答写入目标内存地址等待应答(基本可以保证写入的情况不用循环判断)单字节读写模式:1、写入目标字节;2、等待应答;3、关闭总线。页写模式:1、写入目标字节2、传回应答到页写函数中3、根据要写的字节数目判断是否关闭总线(结束写) AT24C02(页)读字节: 启动IIC写入24C02地址加上一位读指令等待/判断应答写入目标内存地址等待应答(基本可以保证写入的情况不用循环判断)单字节读写模式:1、读取目标字节;2、写入非应答;3、关闭总线。页写模式:1、读取目标字节;2、页写函数根据读取长度中传出一个应答或者非应答;3、结束后关闭总线(结束读)PS:页读或页写一页内存到达边界后就跳出函数,由于没有写自动换页的代码没办法连续写多页,需要在主函数中调控
iic.h:
#ifndef _IIC_H
#define _IIC_H
#include "config.h"
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
unsigned char IIC_readbyte(unsigned char addr,u8 len);
bit IIC_writebyte(unsigned char addr,unsigned char dat);
void EE_Write(u8 *buf, u8 addr, u8 len);
void EE_Read(u8 *buf, u8 addr, u8 len);
#endif
iic.c:
#include "iic.h"
#define DELAY_TIME 11
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop
SDA = 0;
somenop
SCL = 0;
}
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop
SDA = 1;
somenop
}
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit;
somenop
SCL = 1;
somenop
SCL = 0;
SDA = 1;
somenop
}
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
somenop
ackbit = SDA;
SCL = 0;
somenop
return ~ackbit;
}
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
somenop
if(byt & 0x80) SDA = 1;
else SDA = 0;
somenop
SCL = 1;
byt <<= 1;
somenop
}
SCL = 0;
}
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
somenop
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
somenop
}
return da;
}
unsigned char IIC_readbyte(unsigned char addr,u8 ack){
unsigned char dat;
do{
IIC_Start();
IIC_SendByte(SlaveAddrW);
IIC_Stop();
}while(!IIC_WaitAck());
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(SlaveAddrR);
IIC_WaitAck();
dat=IIC_RecByte();
IIC_SendAck(ack);
return dat;
}
bit IIC_writebyte(unsigned char addr,unsigned char dat){
bit ack ;
do{
IIC_Start();
IIC_SendByte(SlaveAddrW);
IIC_Stop();
}while(!IIC_WaitAck());
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
ack = IIC_WaitAck();
return ack;
}
void EE_Write(u8 *buf, u8 addr, u8 len)
{
u8 ack = 0;
while((len > 0) && ack == 0)
{
len --;
ack = IIC_writebyte(addr ++, *(buf ++));
if((addr & 0x07) == 0)
{
break;
}
}
IIC_Stop();
}
void EE_Read(u8 *buf, u8 addr, u8 len)
{
while(len > 1)
{
*buf = IIC_readbyte(addr ++, 0);
buf ++;
if((addr & 0x07) == 0)
{
break;
}
}
*buf = IIC_readbyte(addr ++, 1);
IIC_Stop();
}
PS:官方的延时又又又又又又不对,官方的为89C52RC的延时,somenop中含有应30个nop。