关于I2C的读写问题,我用的是新华龙的C8051F040

2024-12-21 11:25:30
推荐回答(3个)
回答1:

//**********************************//
// SMB0CN的初始化
//*********************************//
void SMB0CN_INIT(void)
{
SMB0CN =0x44 ; //ENABLE SMBUS,应答周期发ASK 01000100
EIE1 |=0x02; //扩展中断允许;允许SMBUS中断
}
//***********************************//
//SCL时钟频率设置的初始化
//***********************************//
void SMBUS0CR_INIT(void)
{
SMB0CR = 0xe0; //////11100000 时钟速率每隔1.446us产生一次低电平
///////每隔1.537us产生高电平

write_512framflg=0;

}
//********************************************//
//WRITE A BLOCK TO EEPROM24C64
//*******************************************//

//***************************************//

//***************************************//
//**********************************//
//READ A BLOCK FORM EEPROM
//**********************************//

//**********************************//
//中断处理子程序
//**********************************//

void SMBUS0_SI(void) interrupt 7
{
unsigned char i;
unsigned int l;
switch(SMB0STA) ////////SMB0STA状态寄存器
{ case 0x08:
SMB0DAT = COMMAND; //起始条件已发出,写控制字节
STA=0;
break;
case 0x10:
SMB0DAT = COMMANDR;
STA =0;
COMMANDR = 0;
break;
case 0x18:
SMB0DAT=ADDR_H ;//ADDR_H; //从地址+w已发出,并收到ACK
break;
case 0x20: //nack
STO=1;
STA=1;
break;
case 0x28:{
//数据字节已发出,收到ACK
switch(BYTE_NUMBER)
{
case 0: //数据已发送完毕
STO=1;
BUSY=0; //释放总线
i2c_mangflg = 0;
break;
case 2:
SMB0DAT =ADDR_L; //说明只发送了ADDR_H
BYTE_NUMBER--;
break;
case 1: //说明ADDR_L已发送
if((COMMANDR&0x01)==1)//读指定单元
{
STA =1;

}
else{

SMB0DAT =sys_con_temp[NUMBER];

NUMBER = NUMBER + 1;
if(NUMBER == info_length){
BYTE_NUMBER--;
NUMBER = 0;

//WDTCN = 0xA5; //使能WDT

}
}
break;
default: //数据已发送完毕

STO=1;

BUSY=0; //释放总线

}

}

break;
case 0x30:
STO =1; //smbus停止标志
STA =1; //smbus起始标志
break;
case 0x40:
AA =1;
break;
case 0x50:
sys_con_temp[x] = SMB0DAT;

x=x+1;

if(x==(info_length-1))
{
AA=0; /////smbus确认标志
}
break;
case 0x58:
sys_con_temp[x] = SMB0DAT;
x=x+1;

if(x==info_length){

BUSY =0;
STO =1;

//WDTCN = 0xA5; //使能WDT

for(i=0;i<40;i++){
l = (unsigned int)(sys_con_temp[i*2+1])<<8;
l = l + (unsigned int)(sys_con_temp[i*2]);
sys_con[i] = l;

}
TH1 = -(SYSCLK/sys_con[2]/16/12);
for(i=0;i<6;i++)
{
yc_mes_real[128+i*2] = sys_con[17+i*2];
yc_mes_real[128+i*2+1]=sys_con[17+i*2+1];

}
i2c_mangflg = 0;

}
break;
default:
STO =1;
BUSY =0;
break;

}

SI =0; //CLEAR SI smbus中断

}

/////////// 读写FRAM ////////////
void Read_512fram(void)
{

SMB0CN_INIT();
BYTE_NUMBER=2;
COMMAND=(0xA0|0x00); //CS ADDR=10100000=A0
COMMANDR=(0xA0|0x01); //CS ADDR=10100001=A1

ADDR_H =0;
ADDR_L =0;
info_length = 80; //
STA =1;
x = 0;

}
void write_512fram(void) //xie 512 ge fram
{
unsigned char i;
unsigned int l;
for(i=0;i<40;i++){
l = sys_con[i];

sys_con_temp[i*2] = (unsigned char)sys_con[i];

sys_con_temp[i*2+1] = (unsigned char)(l>>8);

}

SMB0CN_INIT();
BYTE_NUMBER=2;
COMMAND=(0xA0|0x00); //CS ADDR=10100000=A0
COMMANDR=0xa0;

ADDR_H =0;
ADDR_L =0;
info_length = 80; //
NUMBER = 0;
i2c_mangflg = 1;
STA =1;

}
//--------------------------------------------------------------------

回答2:

你要是怀疑没有写进去,你可以用示波器看看fm24c02有没有反馈ACK信号,即8个数据位后把SDA拉低。假如有的再看看读程序是否有问题。

回答3:

很明显你没有写到寄存器中,看看时序是否正确!