IIC&EEPROM
2016-09-17 22:50
253 查看
1.IIC 时序的重要特点是在时钟SCK为高电平期间SDA作出各种变化来表示起始,终止,应答,非应答,发送数据时是在时钟为高电平期间让SDA稳定,读数据是在SCK为高电平期间采样从设备的数据,所以起始,终止,应答,非应答,发送数据都要先操作SDA,再操作SCK,如果先操作SCK,则会导致起始,终止,应答,非应答,发送数有干扰。
以START信号为例:
写成这样是对的
void IIC_START()
{
SDA = 1;
SCK = 1;
delay_us(1);
SDA = 0;
delay_us(1);
SCK = 0;
}
这样是有问题的
void IIC_START()
{
SCK = 1;
SDA = 1;
delay_us(1);
SDA = 0;
delay_us(1);
SCK = 0;
}
2.接收数据为读SDA线的数据,不会有这个问题。
3.IIC 时序的数据传送从高位开始
4.从本质上理解IIC,主机给从机发送数据,从机是在时钟的下降沿采集SDA的数据,所以主机给出的8个时钟是有讲究的,你要给出有8个下降沿的时钟,应当是这样的:
而不是这样的
所以代码这样写是对的:
void IIC_SendByte(unsigned char byte)
{
unsigned char i;
unsigned char temp;
temp = byte;
for(i = 0; i < 8; i++)
{
SDA = temp & 0x80;
SCK = 1;
delay_us(1);
SCK = 0;
delay_us(1);
temp <<= 1;
}
}
这样写会少了一个下降沿,丢掉一个数据位
void IIC_SendByte(unsigned char byte)
{
unsigned char i;
unsigned char temp;
temp = byte;
for(i = 0; i < 8; i++)
{
SCK = 0;
delay_us(1);
SDA = temp & 0x80;
SCK = 1;
delay_us(1);
temp <<= 1;
}
}
5.主机从从机读取数据,本质上是从机检测主机发出的时钟信号有8个上升沿
所以你的读数据代码一定要写出有8个上升沿
unsigned char IIC_ReceiveByte()
{
unsigned char temp = 0;
unsigned char i;
SDA = 1;
for(i = 0; i < 8; i++)
{
SCK = 0;
delay_us(1);
SCK = 1;
temp <<= 1;
if(SDA) temp = temp + 1;
delay_us(1);
}
SCK = 0;
return temp;
}
仔细体会其中奥妙,同样是8个时钟,发送接收数据对于时钟有不同的要求
6.很多人会遇到这样一个现象:连续从EEPROM读取数据,第一个读出来的是对的,往后读出来的都是0,原因是当读取第一个字节时,主机给从机的应答信号将SDA拉低,即SDA线被钳住,从从机读取数据时,SDA给出的高电平无法将SDA线拉高,导致读出来的数据都为0,所以在读取一个新的字节时,一定要将SDA拉高,才可以正常接收EEPROM的数据。
以START信号为例:
写成这样是对的
void IIC_START()
{
SDA = 1;
SCK = 1;
delay_us(1);
SDA = 0;
delay_us(1);
SCK = 0;
}
这样是有问题的
void IIC_START()
{
SCK = 1;
SDA = 1;
delay_us(1);
SDA = 0;
delay_us(1);
SCK = 0;
}
2.接收数据为读SDA线的数据,不会有这个问题。
3.IIC 时序的数据传送从高位开始
4.从本质上理解IIC,主机给从机发送数据,从机是在时钟的下降沿采集SDA的数据,所以主机给出的8个时钟是有讲究的,你要给出有8个下降沿的时钟,应当是这样的:
而不是这样的
所以代码这样写是对的:
void IIC_SendByte(unsigned char byte)
{
unsigned char i;
unsigned char temp;
temp = byte;
for(i = 0; i < 8; i++)
{
SDA = temp & 0x80;
SCK = 1;
delay_us(1);
SCK = 0;
delay_us(1);
temp <<= 1;
}
}
这样写会少了一个下降沿,丢掉一个数据位
void IIC_SendByte(unsigned char byte)
{
unsigned char i;
unsigned char temp;
temp = byte;
for(i = 0; i < 8; i++)
{
SCK = 0;
delay_us(1);
SDA = temp & 0x80;
SCK = 1;
delay_us(1);
temp <<= 1;
}
}
5.主机从从机读取数据,本质上是从机检测主机发出的时钟信号有8个上升沿
所以你的读数据代码一定要写出有8个上升沿
unsigned char IIC_ReceiveByte()
{
unsigned char temp = 0;
unsigned char i;
SDA = 1;
for(i = 0; i < 8; i++)
{
SCK = 0;
delay_us(1);
SCK = 1;
temp <<= 1;
if(SDA) temp = temp + 1;
delay_us(1);
}
SCK = 0;
return temp;
}
仔细体会其中奥妙,同样是8个时钟,发送接收数据对于时钟有不同的要求
6.很多人会遇到这样一个现象:连续从EEPROM读取数据,第一个读出来的是对的,往后读出来的都是0,原因是当读取第一个字节时,主机给从机的应答信号将SDA拉低,即SDA线被钳住,从从机读取数据时,SDA给出的高电平无法将SDA线拉高,导致读出来的数据都为0,所以在读取一个新的字节时,一定要将SDA拉高,才可以正常接收EEPROM的数据。
相关文章推荐
- 51单片机之IIC&EEPROM的驱动程序
- IIC&EEPROM总结
- Linux下的eeprom读写操作(IIC)
- IIC 针对EEPROM的驱动代码
- mini2440----keil for AMR之IIC读写EEPROM(AT24C08)
- mini2440----keil for AMR之IIC读写EEPROM(AT24C08)
- 很全的C51库函数(IIC类)(IIC、EEPROM、ADXL、PCF、HMC、L3G、BMP)
- At24C0X IIC-EEPROM的keil C操作程序.
- mini2440裸机试炼之——IIC控制EEPROM数据传输
- 8051学习笔记——IIC与EEPROM实验
- 2440&nbsp;iic&nbsp;驱动
- 24C02 -- EEPROM --IIC 加把劲!
- IIC实例的SDA_In和SDA_Out的代码理解GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;
- 2440&nbsp;iic&nbsp;驱动
- 用Hex2Bix将.hex转化为.iic,并烧写EEPROM
- 单片机模拟 IIC 总线与 EEPROM(AT24C02)通信
- 单片机控制IIC协议EEPROM芯片AT24C02模块化编程(持续更新中)
- STM8S学习01——SPI&IIC
- Linux ARM IIC I2C EEPROM 读写操作
- S3C2410 IIC EEPROM 总结