原创 搞了两天,终于把LM3S6916的I2C功能搞定了

2008-11-6 20:04 2011 1 1 分类: MCU/ 嵌入式

搞了两天,终于把LM3S6916的I2C功能搞定了:


与我以前用C51的I/O模拟做I2C的方法不同,它带有硬件的I2C接口,我以前没有用过硬件I2C接口,很久都没有明白怎么样读写,刚开始时以为这个接口不能做读写特殊的I2C设备,所以开始就没有好好研究这个硬件的I2C,先是想把C51下模拟做的I2C程序移值过来,结果在C51下能用的程序在这里改过之后会莫名的出错,也找不出问题出在哪里,现在把出错的程序贴上来,看有没有高手能帮我看看问题出在哪里。


void d10us(void)//20MHz lm3s6916
{
    unsigned char ii;


 for(ii=0;ii<0x43;ii++);
}



void d1ms(void)//20MHz lm3s6916
{
    unsigned int ii;


 for(ii=0;ii<0x1390;ii++);
}


void d5ms(void)//20MHz lm3s6916
{
    unsigned int ii;


 for(ii=0;ii<0x61d0;ii++);
}


 


void d5us(void)//20MHz lm3s6916
{
    unsigned char ii;


 for(ii=0;ii<0x14;ii++);
}



#define i2cSDA  GPIO_PIN_3
#define i2cSCL  GPIO_PIN_2

#define i2cGPIO_Port GPIO_PORTB_BASE


unsigned char bI2cError;


 


void SDA_H(void)
{
 GPIOPinWrite(i2cGPIO_Port, i2cSDA,0xff);
 GPIODirModeSet(i2cGPIO_Port, i2cSDA, GPIO_DIR_MODE_IN);
}


void SDA_L(void)
{
 GPIODirModeSet(i2cGPIO_Port, i2cSDA, GPIO_DIR_MODE_OUT);
 GPIOPinWrite(i2cGPIO_Port, i2cSDA,0x00);
}


void SCL_H(void)
{
 GPIOPinWrite(i2cGPIO_Port, i2cSCL,0xff);
 GPIODirModeSet(i2cGPIO_Port, i2cSCL, GPIO_DIR_MODE_IN);
}


void SCL_L(void)
{
 GPIODirModeSet(i2cGPIO_Port, i2cSCL, GPIO_DIR_MODE_OUT);
 GPIOPinWrite(i2cGPIO_Port, i2cSCL,0x00);
}


unsigned char SDA_S(void)
{
    if(GPIOPinRead(i2cGPIO_Port, i2cSDA))return 1;
 return 0;
}


unsigned char SCL_S(void)
{
    if(GPIOPinRead(i2cGPIO_Port, i2cSCL))return 1;
 return 0;
}


void IICInit(void)
{
 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
  GPIOPadConfigSet(i2cGPIO_Port, i2cSCL|i2cSDA,GPIO_STRENGTH_8MA,GPIO_PIN_TYPE_OD);


 GPIODirModeSet(i2cGPIO_Port, i2cSCL|i2cSDA, GPIO_DIR_MODE_OUT);


 GPIOPinWrite(i2cGPIO_Port, i2cSCL|i2cSDA,0xff);


}



//*******************************************************************************************************
void IICStart(void)//启动总线
{
    unsigned int ii;


 dat=0;
 ii=0;
    bI2cError=0;
 d5us();
 //i2cSCL=1;
 SCL_H();
 d5us();
 while(SCL_S()==0){
     if(++ii==20000){//100ms
   bI2cError=1;
   return;
  }
 Hex2Str(ii>>8,&buf[0]);
 Hex2Str(ii,&buf[2]);
 lcd_display1(0, 0, 16, buf);


  d5us();
 }
 //i2cSDA=1;
 SDA_H();
 d5us();
 d5us();
 d5us();
 d5us();
 //i2cSDA=0;
 SDA_L();
 d5us();
 //i2cSCL=0;
 SCL_L();
 d5us();
 //i2cSDA=1;
 SDA_H();
 d5us();


}
//*******************************************************************************************************
void IICStop(void)//停止IIC总线
{
 d5us();
 //i2cSDA=0;
 SDA_L();
 d5us();
 //i2cSCL=1;
 SCL_H();
 d5us();
 //i2cSDA=1;
 SDA_H();
 d5us();
 //i2cSCL=0;
 SCL_L();
 d5us();
}
//*******************************************************************************************************
unsigned char IICRecAck(void)//检查应答位
{
    unsigned int ii;
    unsigned char k;


 ii=0;
    bI2cError=0;
 d5us();
 //i2cSDA=1;
 SDA_H();


 d5us();


 //i2cSCL=1;
 SCL_H();
 d5us();
 while(SCL_S()==0){
     if(++ii==20000){//100ms
   bI2cError=1;
   return 0x01;
  }
  d5us();
 }


    k="SDA"_S();       


 d5us();
 //i2cSCL=0;
 SCL_L();
 d5us();
 return(k);
}
//*******************************************************************************************************
void IICAck(void)//对IIC总线产生应答
{
 d5us();
 //i2cSDA=0;
 SDA_L();
 d5us();
 //i2cSCL=1;
 SCL_H();
 d5us();
 //i2cSCL=0;
 SCL_L();
 d5us();
 //i2cSDA=1;
 SDA_H();
 d5us();
}


//*******************************************************************************************************
void IICNoAck(void)//不对IIC总线产生应答
{
 d5us();
 //i2cSDA=1;
 SDA_H();
 d5us();
 //i2cSCL=1;
 SCL_H();
 d5us();
 //i2cSCL=0;
 SCL_L();
 d5us();
}
//*******************************************************************************************************
void IICSendByte(unsigned char sendbyte)//向IIC总线写数据
{
    unsigned int ii;
 unsigned char j="8";


 ii=0;
 bI2cError=0;
 for(;j>0;j--){
     if((sendbyte&0x80)!=0x00)SDA_H();
  else SDA_L();
  sendbyte<<=1;


  d5us();
  //i2cSCL=1;
  SCL_H();
  d5us();
  while(SCL_S()==0){
      if(++ii==20000){//100ms
    bI2cError=1;
    return;
   }
   d5us();
  }


  //i2cSCL=0;
  SCL_L();
  d5us();
 }
}
//*******************************************************************************************************
unsigned char IICReceiveByte(void)//从IIC总线上读数据子程序
{
    unsigned char ii;
 unsigned char receivebyte;
 unsigned char i;


 receivebyte=0xaa;
 ii=0;


 d5us();


 SDA_H();//


 bI2cError=0;
 d5us();
 for(i=0;i<8;i++){
  //i2cSCL=1;
  SCL_H();
  d5us();
  while(SCL_S()==0){
      if(++ii==20000){//100ms
    bI2cError=1;
    return 0xff;
   }
   d5us();
  }
  receivebyte=(receivebyte<<1)|SDA_S();


  d5us();
  //i2cSCL=0;
  SCL_L();
  d5us();
 }
 return(receivebyte);
}


 


 


unsigned char Read(unsigned char Addl)
{
    unsigned char m;


    d5ms();

 IICStart();if(bI2cError)goto ReadErr;

 IICSendByte(0xa0);if(bI2cError)goto ReadErr;

 if(IICRecAck())goto ReadErr;

 IICSendByte(Addl);if(bI2cError)goto ReadErr;

 if(IICRecAck())goto ReadErr;

 IICStart();if(bI2cError)goto ReadErr;

 IICSendByte(0xa1);if(bI2cError)goto ReadErr;

 if(IICRecAck())goto ReadErr;

 m=IICReceiveByte();if(bI2cError)goto ReadErr;

 IICNoAck();


 IICStop();
 return(m);


ReadErr:
    IICStop();
    return(0xf0);
}


 


/*--------------------------- main ------------------------------------------*/


int main (void) {



 unsigned char i;


    /* Set the clocking to run from the PLL at 20 MHz */
   SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ);


for(i=0;i<250;i++)d1ms();


 //-------------------------------------------------------


 IICInit();


 for(i=0;i<250;i++)d1ms();


  i="Read"(0x06);//运行的结果是bI2cError=1,bI2cError=1表示过程出错了


 while (1) {


 }
}


 


以上是有错误的程序,目前没有解决问题,现象是出错后SDA脚变成了低电平,


把24C02的DAT脚断开后,LM3S6916的SDA脚也还是低电平,让人想不明白。


由于硬件I2C已经搞通了,所以以上模拟的程序就不再搞了,这个问题留给高手弄吧。


LM3S6916硬件I2C的程序以后择机会发上来的。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
1
关闭 站长推荐上一条 /1 下一条