24C02能正常读取,老是写不进去引脚连接没问题附程序:
```c
#include<I2C.H>
void Delay5us() //@11.0592MHz
{
}
void I2cStrat()//I2C开始信号
{
SCL=1;//SCL在高电平时SDA由高电平变为低电平是开始
Delay5us();
SDA=1;
Delay5us();
SDA=0;
Delay5us();
SCL=0;
}
void I2cStop()//I2C结束信号
{
SCL=0;//SCL在高电平时SDA由低电平变为高电平是结束
Delay5us();
SDA=0;
Delay5us();
SCL=1;
Delay5us();
SDA=1;
Delay5us();
}
void I2cSendByte(u8 dat)//I2C发送一个字节的数据
{
/*发送数据时SCL在高电平时读取SDA的数据SCL在低电平时SDA变换数据
数据发送时顺序是由高到低的依次发送*/
u8 i=0;
for(i=0;i<8;i++)
{
u8 j=dat>>(7-i);
Delay5us();
SDA=j%2;
Delay5us();
SCL=1;
Delay5us();
SCL=0;
}
}
u8 I2c_GetAck()//主机获取应答信号
{
//时钟线处于低电平期间等待SDA数据线被从机拉低
SCL=0;
Delay5us();
SDA=1;
Delay5us();
SCL=1;
Delay5us();
if(SDA)//判断从机是否拉低信号
{
SCL=0;
return 1;//从机拉低信号表示接受成功
}
else
{
SCL=0;
return 0;//从机不拉低表示无应答或者接受不成功
}
}
void I2c_SendAck(u8 a)//主机发送应答信号
{
SCL=0;
Delay5us();
SDA=a;//主机发送应答信号
Delay5us();
SCL=1;//读取状态信息
Delay5us();
SCL=0;
}
u8 I2C_ReadByte()//主机读取一个字节数据
{
u8 i=0,dat=0;
for(i=0;i<8;i++)
{
dat<<=1;
SCL=0;
Delay5us();
SCL=1;
Delay5us();
dat|=SDA;
Delay5us();
}
SCL=0;
return dat;
}
void At24c02_WriteByte(u8 IC_Addr,u8 Byte_Addr,u8 dat)//AT24C02写入一字节的数据
{
I2cStrat();//I2C开始信号
I2cSendByte(IC_Addr);//I2C发送at24C02的地址
I2c_GetAck();//主机获取应答信号
I2cSendByte(Byte_Addr);//I2C发送at24C02写入数据的地址
I2c_GetAck();//主机获取应答信号
I2cSendByte(dat);//I2C发送at24C02要写入的数据
I2c_GetAck();//主机获取应答信号
I2cStop();//I2C结束信号
}
u8 At24c02_ReadByte(u8 IC_Addr,u8 Byte_Addr)//AT24C02读取一字节的数据
{
u8 dat=0;
I2cStrat();//I2C开始信号
I2cSendByte(IC_Addr);//I2C发送at24C02的地址
I2c_GetAck();//主机获取应答信号
I2cSendByte(Byte_Addr);//I2C发送at24C02写入数据的地址
I2c_GetAck();//主机获取应答信号
I2cstrat();//I2C开始信号
I2cSendByte(IC_Addr+1);//I2C发送at24C02的地址
I2c_GetAck();//主机获取应答信号
dat=I2C_ReadByte();//主机读取一个字节数据
I2c_SendAck(1);//主机发送应答信号
I2cStop();//I2C结束信号
return dat;
}
```
#include "iic.h"
#include "reg52.h"
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
unsigned char dat1 = 0,dat2 = 0,dat3 = 0;
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};
void delay(unsigned int t)
{
while(t--);
}
void Init_74HC138(unsigned char channel)
{
switch(channel)
{
case 4:P2 = (P2 & 0x1f) | 0x80;break;
case 5:P2 = (P2 & 0x1f) | 0xa0;break;
case 6:P2 = (P2 & 0x1f) | 0xc0;break;
case 7:P2 = (P2 & 0x1f) | 0xe0;break;
case 0:P2 = (P2 & 0x1f) | 0x00;break;
}
P2 = (P2 & 0x1f) | 0x00;
}
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
P0 = (0x01 << pos);
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void SMG_All(unsigned char dat)
{
P0 = 0xff;
Init_74HC138(6);
P0 = dat;
Init_74HC138(7);
}
void Init_System()
{
P0 = 0xff;
Init_74HC138(4);
P0 = 0x00;
Init_74HC138(5);
SMG_All(0xff);
}
void SMG_Display_Data()
{
SMG_DisplayBit(0,smg_data[dat1/10]);
delay(200);
SMG_DisplayBit(1,smg_data[dat1%10]);
delay(200);
SMG_DisplayBit(2,0xbf);
delay(200);
SMG_DisplayBit(3,smg_data[dat2/10]);
delay(200);
SMG_DisplayBit(4,smg_data[dat2%10]);
delay(200);
SMG_DisplayBit(5,0xbf);
delay(200);
SMG_DisplayBit(6,smg_data[dat3/10]);
delay(200);
SMG_DisplayBit(7,smg_data[dat3%10]);
delay(200);
SMG_All(0xff);
delay(200);
}
void AT24C02_Write(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char AT24C02_Read(unsigned char addr)
{
unsigned char temp = 0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
void Read_AT24C02_Init()
{
dat1 = AT24C02_Read(0x00);
delay(1000);
dat2 = AT24C02_Read(0x01);
delay(1000);
dat3 = AT24C02_Read(0x02);
delay(1000);
}
void Key_Scans()
{
if(S4 == 0)
{
delay(20);
if(S4 == 0)
{
dat1++;
if(dat1 > 13)
{
dat1 = 0;
}
AT24C02_Write(0x00,dat1);
}
}
else if(S5 == 0)
{
delay(20);
if(S5 == 0)
{
dat2++;
if(dat2 > 13)
{
dat2 = 0;
}
AT24C02_Write(0x01,dat2);
}
}
if(S6 == 0)
{
delay(20);
if(S6 == 0)
{
dat3++;
if(dat3 > 13)
{
dat3 = 0;
}
AT24C02_Write(0x02,dat3);
}
}
}
void main(void)
{
Init_System();
Read_AT24C02_Init();
while(1)
{
SMG_Display_Data() ;
Key_Scans();
}
}
问题分析:
根据程序内容和描述,可以猜测储存器24C02的写入操作存在问题。由于读取操作是正常的,因此第一步需要检查写入操作代码。
解决方案:
在AT24C02_Write()函数中,开头首先执行了IIC_Start()函数,再执行IIC_SendByte()函数将写入数据发送到地址0x90,然后执行IIC_WaitAck()等待确认信号,最后调用IIC_Stop()函数结束通信。如果IIC总线通信不正常,则可能导致写入失败。
可以在程序中添加调试信息,利用串口输出IIC总线通信信息,例如发送的地址、发送的数据、是否收到确认信号等,这样可以帮助快速定位问题。
示例代码:
void AT24C02_Write(unsigned char addr,unsigned char dat)
{
IIC_Start();
printf("IIC total line start\n");
IIC_SendByte(0x90);
printf("send address: 0x90\n");
IIC_WaitAck();
IIC_SendByte(addr);
printf("send address: 0x%02x\n", addr);
IIC_WaitAck();
IIC_SendByte(dat);
printf("send data: 0x%02x\n", dat);
IIC_WaitAck();
IIC_Stop();
printf("IIC total line stop\n");
}
通过添加这些调试信息,可以更好的了解IIC总线通信的细节,帮助快速找到问题所在。
在AT24C02_Write()函数中,将要写入的数据通过IIC_SendByte()函数发送到地址0x90。如果发送的数据不正确,也可能导致写入失败。
可以在程序中输出将要发送的数据,帮助快速定位问题。
示例代码:
void AT24C02_Write(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
printf("write data: 0x%02x\n", dat);
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
通过输出将要发送的数据,可以更好的判断是否是数据本身的问题导致写入失败。
在AT24C02_Write()函数中,IIC总线通信、数据本身都没有问题,但是如果IIC_Start()、IIC_SendByte()等函数不能正确执行,则可能导致写入失败。
可以利用调试工具查看函数的执行情况,或者在函数执行语句之间插入调试信息,帮助快速定位问题。
示例代码:
void AT24C02_Write(unsigned char addr,unsigned char dat)
{
IIC_Start();
printf("IIC_Start executed\n");
IIC_SendByte(0x90);
printf("send address: 0x90\n");
IIC_WaitAck();
IIC_SendByte(addr);
printf("send address: 0x%02x\n", addr);
IIC_WaitAck();
printf("write data: 0x%02x\n", dat);
IIC_SendByte(dat);
printf("send data: 0x%02x\n", dat);
IIC_WaitAck();
IIC_Stop();
}
通过添加这些调试信息,可以更好的了解函数的执行情况,帮助快速找到问题所在。
总结:
以上是检查储存器24C02不能正常写入数据的一些解决方案。当遇到这种问题时,需要结合程序的执行情况、实际硬件连接情况、调试信息等多个方面进行分析,才能更快地找到问题所在并进行修复。