msp430利用i2c协议控制EEPROM

花了四天时间终于搞定佐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)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据