花了四天时间终于搞定佐i2c,如果不是网上有很多demo,还有很多人帮助我调试,我想今晚通宵也弄不完。
写驱动程序前要知道i2c协议,eeprom的datasheet,还有相应的引脚图。
我用的开发板SCL是P1.2,SDA是P1.3,eeprom的地址是0xa0.
程序是利用I/O口来模拟SCL和SDA,首先是发送开始信息(函数: Start()),然后发送设备地址 (Writebyte(地址)),从 datasheet和电路图知道了eeprom的地址为0xa0,然后检查eeprom的 应答 (函 数: CheckACK()),如果ok就发送data的地址(测试我们直接写0x00),如果应答成功就可以传数据了(WriteNbyte(地址,地址,数据,个数))。
写完后,读出来看是否写进去的数据是否符合。这就用到了RANDOMREAD,先发送写的eeprom的地址和数据的地址,定位到了数据的地址后就发送读的命令(Writebyte(0x01),后面的1表示读)。然后就接受eeprom的数据,记住要记得接受完1byte数据就发送应答( ACK() )哦。
至于怎么看接受到得数据,我用的方法是把接到的数据保存到一个全局变量或静态变量里,然后设断点查看RAM的值就ok了。
以下是代码:
#include <msp430x14x.h>
#include"string.h"
#define SDA_1 P1OUT |= BIT3
#define SDA_0 P1OUT &= ~BIT3
#define SCL_1 P1OUT |= BIT2
#define SCL_0 P1OUT &= ~BIT2
#define SDA_out P1DIR |=BIT3
#define SDA_in P1DIR &= ~BIT3
unsigned char Readword[12];
void init_clk(void)
{
unsigned char j;
BCSCTL1&= ~XT2OFF ;
do
{
IFG1 &= ~ OFIFG;
for( j=0xff ; j>0 ; j--)
{
_NOP();
}
}
while((IFG1&OFIFG)!=0);
BCSCTL2|=SELM_2+SELS;
}
void Delay(void) //Delay
{
unsigned char t;
for(t=0;t<50;t++)
_NOP();
}
void Delay1(void) //Delay
{
unsigned char t;
for(t=0;t<200;t++)
_NOP();
}
void Start(void) //Start
{
SDA_out;
SCL_1;
_NOP();
SDA_1;
Delay();
SDA_0;
Delay();
SCL_0;
Delay();
}
void Stop(void) //Stop
{
SDA_0;
Delay();
SCL_1;
Delay();
SDA_1;
Delay();
}
void ACK(void) //ACK
{
SDA_0;
Delay();
SCL_1;
Delay();
SCL_0;
Delay();
SDA_1;
Delay();
}
void NACK(void) // NOT ACK
{
SDA_1;
Delay();
SCL_1;
Delay();
SCL_0;
Delay();
SDA_0;
Delay();
}
void Write1(void) //Write a bie : 1
{
SDA_1;
Delay();
SCL_1;
Delay();
SCL_0;
Delay();
}
void Write0(void) //Write a bit : 0
{
SDA_0;
Delay();
SCL_1;
Delay();
SCL_0;
Delay();
}
void Writebyte(unsigned char Wchar) //Write a byte(8 bit)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(Wchar&0x80) Write1();
else Write0();
Wchar<<=1;
}
SDA_1;
Delay();
}
unsigned char CheckACK(void) //receive ACK
{
unsigned char flag;
//SDA_1;
Delay();
SCL_1;
Delay();
SDA_in;
_NOP();_NOP();
flag = P1IN&BIT3 ; //read SDA
SCL_0;
Delay();
SDA_out;
if(flag) return 0;
else return 1;
}
unsigned char Readbyte(void)
{
unsigned char rchar=0 ,i,flag;
SCL_0;
Delay();
for(i=0;i<8;i++)
{
SDA_in;
Delay();
SCL_1;
Delay();
flag=P1IN&BIT3;
rchar<<=1;
if(flag) rchar |= 0x01;
_NOP();
SDA_out;
Delay();
SCL_0;
Delay();
}
SCL_0;
Delay();
return rchar;
}
void ReadNbyte(unsigned char address,unsigned char dataaddr,unsigned int n)
{
unsigned char i;
Start();
Writebyte(address); //find eeprom
if(!CheckACK())
{Stop();return ;}
Writebyte(dataaddr); //find unit address
if(!CheckACK())
{Stop();return ;}
Start();
Writebyte(0xa1); //read
if(!CheckACK())
{Stop();return ;}
for(i=0;i<n;i++)
{
Readword[i]=Readbyte();
ACK();
}
Stop();
Delay();
}
void WriteNbyte(unsigned char address,unsigned char dataaddr,unsigned char *sbuff,unsigned char n)
{
unsigned char i;
Start();
Writebyte(address); //find eeprom
if(!CheckACK())
{Stop();return ;}
Writebyte(dataaddr); //find unit address
if(!CheckACK())
{Stop();return ;}
for(i=0;i<n;i++)
{
Writebyte(sbuff[i]);
if(!CheckACK())
{Stop();return ;}
}
Stop();
Delay();
}
void main(void)
{
unsigned char write[9],i;
for(i=0; i<8; i++){
write[i] =49+i;
}
WDTCTL = WDTPW + WDTHOLD;
// init_clk();
P1DIR |= (BIT2 + BIT3);
// P1SEL = 0x0c; // P1.2,3 = SCL&SDA
while(1)
{
//write
WriteNbyte(0xa0,0x00,write,8);
Delay1();
//read
ReadNbyte(0xa0,0x00,8);
Delay1();Delay1();
}
}
(2012-08-05 23:03:50)