i2c总线程序
本程序是i2c总线读写一个字节的程序。在写过程序中,不一定非要检测i2c的应答位,可以直接延时过去就行,但是在读过程中必须给应答信号,读完发停止位,一定确认所发的信号都发上了。否则在连续地址读的过程中可能不会出错,但是在随机度过程中就会出错,我的程序就是在给停止信号时没有给上,24cxx一直在输出数据,结果读出错。找着问题后我的程序只加入了一条命令便完全正常。顺便提醒大家在调试24cxx时最好不要读些连续的地址,这样容易造成巧合因素导致疏忽,我这次犯的就是这个错误,程序一调试就通了,结果不再管它,到后来标定程序后算不出结果才有回头调试,折腾我两周。唉!郁闷呀!
/* *********************** EEPROM 24C256******************************* */
// 调试环境:时钟为DCO的时钟;频率4.00MHz
// 串行接口:P5.6 ------>SDA
// P5.7 ------>SCL
// 测试器件:MICROCHIP 24LC256
// 测试时间:2004-10-15
// 编写人员:石建华
/* *********************************************************************** */
#include <msp430x14x.h>
#define SDA_IN P5DIR &=~BIT6 // P5.6 IN
#define SDA_OUT P5DIR |=BIT6 // P5.6 OUT
#define SDA_LOW P5OUT &=~BIT6 // sda=0
#define SDA_HIGH P5OUT |=BIT6 // sda=1
#define SCL_IN P5DIR &=~BIT7 // P5.7 IN
#define SCL_OUT P5DIR |=BIT7 // P5.7 OUT
#define SCL_LOW P5OUT &=~BIT7
#define SCL_HIGH P5OUT |=BIT7
void delay (unsigned int TT)
{
for (;TT!=0;TT--);
}
unsigned char DATAR01,DATAR11,DATAR21,DATAR31,DATAR41;
void IIC_START (void)
{ SDA_OUT;
SDA_HIGH;
SCL_HIGH;
delay (50);
SDA_LOW;
delay (50);
SCL_LOW;
delay (50);
}
void IIC_STOP (void)
{ SDA_OUT;
SDA_LOW;
delay (50);
SCL_HIGH;
delay (50);
SDA_HIGH;
delay (50);
}
void IIC_ACK (void)
{ SDA_OUT;
SDA_LOW;
delay (50);
SCL_HIGH;
delay (50);
SCL_LOW;
delay (50);
}
void IIC_TX_DATA (unsigned char DATA)
{unsigned char Rn=8,RR=0x80;
SDA_OUT;
delay (50);
for (;Rn!=0;Rn--)
{
if ((DATA&RR)!=0)
SDA_HIGH;
else
SDA_LOW;
delay (50);
SCL_HIGH;
delay (50);
SCL_LOW;
delay (50);
RR>>=1;
}
SDA_HIGH;
delay (50);
SCL_HIGH;
delay (50);
SCL_LOW;
delay (50);
}
unsigned char IIC_RX_DATA (void)
{unsigned int Rn=8,DATA=0,RR=0x80;
SDA_IN; // 端口为输入
delay (50);
for (;Rn!=0;Rn--)
{
SCL_HIGH;
delay (50);
if ((P5IN&BIT6)!=0)
DATA|=RR;
else
DATA&=~RR;
RR>>=1;
SCL_LOW;
delay (50);
}
return DATA;
}
unsigned char READ_BYTE (unsigned int ADDR)
{ unsigned char DATA_R,ADDR_L,ADDR_H;
ADDR_L=ADDR%256;
ADDR_H=ADDR/256;
IIC_START ();
IIC_TX_DATA (0xA0);
delay(50);
IIC_TX_DATA (ADDR_H);
delay(50);
IIC_TX_DATA (ADDR_L);
delay(50);
IIC_START ();
IIC_TX_DATA (0xA1);
delay(50);
DATA_R=IIC_RX_DATA();
IIC_STOP ();
return DATA_R;
}
void WRITE_BYTE (unsigned int ADDR,unsigned char DATA_W)
{ unsigned char ADDR_H,ADDR_L;
ADDR_L=ADDR%256;
ADDR_H=ADDR/256;
SDA_OUT;
IIC_START ();
IIC_TX_DATA (0xA0); // E2PROM 片选
IIC_TX_DATA (ADDR_H); // 大于256BIT的EEPROM需加地址高位
IIC_TX_DATA (ADDR_L);
IIC_TX_DATA (DATA_W);
IIC_STOP ();
delay (0x3FFF); // 等待写时序
}
main()
{ unsigned int ADDRESS;
unsigned char DATAR0,DATAR1,DATAR2,DATAR3,DATAR4,DATAW;
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
DCOCTL = 0X73;
BCSCTL1= 0X87; // 设置时钟频率4.00MHz
P5DIR |=0XC0;
P5OUT |=0XC0;
DATAR01=0;
DATAR11=0;
DATAR21=0;
DATAR31=0;
DATAR41=0;
/* **********WRITE********** */
ADDRESS=0X0000;
DATAW=0X10;
WRITE_BYTE(ADDRESS,DATAW);
_NOP();
ADDRESS=0X0001;
DATAW=0X11;
WRITE_BYTE(ADDRESS,DATAW);
_NOP();
ADDRESS=0X0002;
DATAW=0X12;
WRITE_BYTE(ADDRESS,DATAW);
_NOP();
ADDRESS=0X0003;
DATAW=0X13;
WRITE_BYTE(ADDRESS,DATAW);
_NOP();
ADDRESS=0X0004;
DATAW=0X14;
WRITE_BYTE(ADDRESS,DATAW);
_NOP();
/* ***********READ************** */
ADDRESS=0X0005;
DATAR0=READ_BYTE(ADDRESS);
DATAR01 = DATAR0;
_NOP();
ADDRESS=0X0001;
DATAR1=READ_BYTE(ADDRESS);
DATAR11 = DATAR1;
_NOP();
ADDRESS=0X0002;
DATAR2=READ_BYTE(ADDRESS);
DATAR21 = DATAR2;
_NOP();
ADDRESS=0X0004;
DATAR3=READ_BYTE(ADDRESS);
DATAR31 = DATAR3;
_NOP();
ADDRESS=0X0000;
DATAR4=READ_BYTE(ADDRESS);
DATAR41 = DATAR4;
_NOP();
_NOP();
}