新手上路
- 积分
- 37
- 金钱
- 37
- 注册时间
- 2015-1-5
- 在线时间
- 0 小时
|
5金钱
最近在弄单片机的硬件i2c,tuner小板的硬件i2c有两个,i2c0和i2c1。但是80c51f340的i2c和他们又有区别,所以我将其对接的时候用i2c0写没问题,但是i2c0读的时候少了一个nack的操作(stop反而有,费解),导致每次读完操作以后下次读或者写发chipid的时候都会nack。现在连i2c1发完chipid给个nack都死机了,我真的无力了,求助,下面是时序图和程序
C8051F340的时序是
write:
start| chipid(7:1)+write(写0) | Ack | address(7:0) | Ack | data(7:0) | Ack | stop;
read:
start | chipid(7:1)+write(写0) | Ack | address(7:0) | Ack | Restart | chipid(7:1)+read(写1) | Ack | data(7:0) | Nack;
start | chipid(7:1)+write(写0) | Ack | address(7:0) | Ack | Restart | chipid(7:1)+read(写1) | Ack | data1(7:0) | Ack | data2(7:0) | Ack |……| dataN(7:0) | Nack;
而5158的是这样的
I2c0:
I2c1:
#include "c8051f340.h"
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define chip5158_I2C0 0xC4 //Device address for slave 5158_chip in i2c0
#define chip5158_I2C1 0xC2 //Device address for slave 5158_chip in i2c1
#define SYSCLS 12000000
//#define SMB_FQ 50000 //Target SCL clock rate
#define WRITE 0x00 //SMBUS WRITE command
#define READ 0x01 //SMBUS READ command
typedef struct
{
uchar TARGET; //从地址(读或写时要先写入它的值)
uchar SMB_RW;
}I2C_DATA;
void Wait(int x)
{
while(x--);
}
void SMBUS_Init()
{
SMB0CF = 0x5D; // Use Timer1 overflows as SMBus clock
// source;
// Disable slave mode;
// Enable setup & hold time extensions;
// Enable SMBus Free timeout detect;
// Enable SCL low timeout detect;
SMB0CF &= ~0x80;
SMB0CF |= 0x80; //Enable SMBUS
EIE1 &= 0xFE;
SMB0CN &= 0xCC; //Init SMB0CN
}
void Timer1_Init(ulong SMB_FQ)
{
// uchar SCALE;
if ((SYSCLS/SMB_FQ/3) < 255)
{
// SCALE = 1;
CKCON |= 0x08 ;
}
else if ((SYSCLS/SMB_FQ/3/4) < 255)//使用4分频
{
// SCALE = 4;
CKCON |= 0x01;
CKCON &= ~0x0A;
}
else if ((SYSCLS/SMB_FQ/3/8) < 255)//使用8分频
{
// SCALE = 8;
CKCON |= 0x03;
CKCON &= ~0x08;
}
else if ((SYSCLS/SMB_FQ/3/12) < 255)//使用12分频
{
// SCALE = 12;
CKCON |= 0x03;
CKCON &= ~0x0B;
}
else if ((SYSCLS/SMB_FQ/3/48) < 255)//使用48分频
{
// SCALE = 48;
CKCON |= 0x03;
CKCON &= ~0x09;
}
TMOD = 0x20;
TH1 = 256 -(SYSCLS/SMB_FQ/3);
TL1 = TH1;
TR1 = 1;
}
#if 0
void Timer3_Init()
{
TMR3CN = 0x00; //16位时钟,低字节中断
CKCON &= ~0x40; //使用12分频时钟信号
TMR3RLL = -(SYSCLS/12/40);
TMR3L = TMR3RLL; //25ms之后时钟3执行溢出重载
EIE1 |= 0x80; //时钟3中断使能
TMR3CN |= 0x04; //打开时钟3
}
#endif
void PORT_Init()
{
 0MDIN = 0xff;
 0MDOUT = 0x00;
 0SKIP = 0x00;
XBR0 = 0x04;
XBR1 = 0x40;
 0 = 0xFF;
}
void Send_Start(void)
{
STA = 1;
SI = 0;
}
void Send_Stop(void)
{
STO = 1;
SI = 0;
}
void Send_Addr(uchar target_addr,uchar smb_rw)
{
uchar dat;
dat = target_addr;
dat &= 0xFE;
dat |= smb_rw;
SMB0DAT = dat;
STA = 0;
SI = 0;
}
void Send_Data(uchar dat)
{
SMB0DAT = dat;
SI = 0;
}
void Receive_Data()
{
uchar dat;
dat = SMB0DAT;
ACK = 0;
SI = 0;
}
void Rec_Last_Data()
{
uchar dat;
dat = SMB0DAT;
ACK = 1;
SI = 0;
}
uchar get_SMBDAT()
{
return SMB0DAT;
}
void Reset_I2C(void)
{
SMB0CF &= ~0x80;
Wait(50);
SMB0CF |= 0x80; //重启SMBUS
SMB0CN &= 0xCC;
}
uchar Return_I2C_Status()
{
return SI;
}
void I2c0_Write(uchar dest_addr,uint src_data)
{
// I2C_DATA temp;
// SPI0CN &= ~0x01;
// temp.TARGET = chip5158_I2C0;
// temp.SMB_RW = WRITE;
uchar src_buf[2];
src_buf[0] = src_data>>8;
src_buf[1] = src_data;
Send_Start();
while(!Return_I2C_Status());
Send_Addr(chip5158_I2C0,WRITE);
while(!Return_I2C_Status());
Send_Data(dest_addr);
while(!Return_I2C_Status());
Send_Data(src_buf[0]);
while(!Return_I2C_Status());
Send_Data(src_buf[1]);
// STO = 1;
while(!Return_I2C_Status());
Send_Stop();
// while(!Return_I2C_Status());
Reset_I2C();
// SPI0CN |= 0x01;
}
void I2c0_Read(uchar *dest_buf,uchar src_addr)
{
// I2C_DATA temp;
// SPI0CN &= ~0x01;
// temp.TARGET = chip5158_I2C0;
// temp.SMB_RW = WRITE;
Send_Start();
while(!Return_I2C_Status());
Send_Addr(chip5158_I2C0,WRITE);
while(!Return_I2C_Status());
Send_Data(src_addr);
while(!Return_I2C_Status());
Send_Start();
while(!Return_I2C_Status());
Send_Addr(chip5158_I2C0,READ);
while(!Return_I2C_Status());
Receive_Data();
while(!Return_I2C_Status());
dest_buf[0] = get_SMBDAT();
Rec_Last_Data();
while(!Return_I2C_Status());
dest_buf[1] = get_SMBDAT();
// ACK = 1;
// ACK = 1;
// ACK = 1;
Send_Stop();
// while(!Return_I2C_Status());
Reset_I2C();
// SPI0CN |= 0x01;
}
void I2c1_Readbyte(uchar *dest_buf,ulong src_addr)
{
uchar temp[4];
temp[0] = (uchar)(src_addr<<1);
temp[0] |= 0x01; //get ADDR[6:0],1;
temp[1] = (uchar)(src_addr>>16);//get ADDR[23:16];
temp[2] = (uchar)(src_addr>>24);//get ADDR[31:24];
temp[3] = (uchar)(src_addr>>7); //get ADDR[14:7];
Send_Start();
while(!Return_I2C_Status());
Send_Addr(chip5158_I2C1,WRITE);
while(!Return_I2C_Status());
Send_Data(temp[0]);
while(!Return_I2C_Status());
Send_Data(temp[1]);
while(!Return_I2C_Status());
Send_Data(temp[2]);
while(!Return_I2C_Status());
Send_Data(temp[3]);
while(!Return_I2C_Status());
Send_Start();
while(!Return_I2C_Status());
Send_Addr(chip5158_I2C0,READ);
while(!Return_I2C_Status());
Receive_Data();
while(!Return_I2C_Status());
dest_buf[0] = get_SMBDAT();
Rec_Last_Data();
while(!Return_I2C_Status());
dest_buf[1] = get_SMBDAT();
Send_Stop();
while(!Return_I2C_Status());
Reset_I2C();
}
void I2c1_Writebyte(ulong dest_addr,uint src_data)
{
uchar temp[4],src_buf[2];
temp[0] = (uchar)(dest_addr<<1);
temp[0] |= 0x01; //get ADDR[6:0],1;
temp[1] = (uchar)(dest_addr>>16);//get ADDR[23:16];
temp[2] = (uchar)(dest_addr>>24);//get ADDR[31:24];
temp[3] = (uchar)(dest_addr>>7); //get ADDR[14:7];
src_buf[0] = src_data;
src_buf[1] = src_data>>8;
Send_Start();
while(!Return_I2C_Status());
Send_Addr(chip5158_I2C1,WRITE);
while(!Return_I2C_Status());
Send_Data(temp[0]);
while(!Return_I2C_Status());
Send_Data(temp[1]);
while(!Return_I2C_Status());
Send_Data(temp[2]);
while(!Return_I2C_Status());
Send_Data(temp[3]);
while(!Return_I2C_Status());
Send_Data(src_buf[0]);
while(!Return_I2C_Status());
Send_Data(src_buf[1]);
while(!Return_I2C_Status());
Send_Stop();
// while(!Return_I2C_Status());
Reset_I2C();
}
void I2c1_Start(void)
{
// uchar buff[2];
// I2c0_Write(0xea,0xccda);
// I2c0_Write(0xea,0x69c4);
// I2c0_Write(0xea,0xffff);
// I2c0_Read(buff,0xea);
// I2c0_Read(buff,0xea);
// I2c0_Read(buff,0xea);
#if 1
I2c0_Write(0xe2,0xccda);
// I2c0_Read(buff,0xe2);
I2c0_Write(0xe4,0x69c4);
// I2c0_Read(buff,0xe4);
I2c0_Write(0xf6,0x0000);
// I2c0_Read(buff,0xf6);
I2c0_Write(0xf2,0x0000);
// I2c0_Read(buff,0xf2);
I2c0_Write(0xf2,0x0001); //dsp reset
// I2c0_Read(buff,0xf2);
#endif
Wait(10);
I2c0_Write(0xea,0x8000);
// I2c0_Read(buff,0xea);
Wait(10);
}
#if 0
void I2c1_Stop()
{
;
}
#endif
void main(void)
{
// char in_buff[9];
// char out_buff[8]="ABCDEFGH";
// uchar in_buff0[2];
uchar in_buff1[2];
uint out_data0=0x4142;
uint out_data1=0x4143;
 CA0MD &= ~0x40; //stop WDT
OSCICN |= 0x03; //SYSCLK为内部高频正当期输出
RSTSRC = 0x04; //使能丢失时钟监测器
 ORT_Init();
Timer1_Init(30000);//Sumbus's frequence
// Timer3_Init();
SMBUS_Init();
EA = 1;
while(1)
{
// I2c0_Read(in_buff,0xe0); //read 2byte from 0xe0
// I2c0_Write(0xE2,out_data0);
// I2c0_Read(in_buff0,0xE2);
I2c1_Start();
I2c1_Writebyte(0x13145210,out_data1);
I2c1_Readbyte(in_buff1,0x13145210);
// I2c1_Stop();
}
}
|
最佳答案
查看完整内容[请看2#楼]
我去,原来程序是对的,只是因为clock太快了!!!所以不给反应啊.............谢谢了~~
|