原创 LM3S模拟I2C,时序标准。测试OK

2010-10-28 09:51 3190 9 9 分类: MCU/ 嵌入式

#define I2C0SCL_PERIPH          (SYSCTL_PERIPH_GPIOB)
#define I2C0SCL_PORT            (GPIO_PORTB_BASE)
#define I2C0SCL_PIN             (GPIO_PIN_2)


#define I2C0SDA_PERIPH          (SYSCTL_PERIPH_GPIOB)
#define I2C0SDA_PORT            (GPIO_PORTB_BASE)
#define I2C0SDA_PIN             (GPIO_PIN_3)


/*--------------------------------------------------------------------
函数功能: 机器周期延时                   
输入说明:
返回 值 :
说    明:
44.4M j=100时是360us
j=10时是40us
j=2时是12us
不用j时。是4.8us,读写也正确
--------------------------------------------------------------------*/
void DelayNop(unsigned int n)
{
 uint i,j;


 for (i = 0; i<n; i++)
 {
  //for(j=0; j<2; j++)
  WDR();


 }
 
}


 


/*--------------------------------------------------------------------
函数功能:                    
输入说明:
返回 值 :
说    明:
  
--------------------------------------------------------------------*/


void I2CStart(void)
{
 //SETBIT(I2C_DIR2,SDA2);             // Set SDA to output 
 //SETBIT(I2C_DIR2,SCL2);             // Set SCL to output
 SysCtlPeripheralEnable(I2C0SDA_PERIPH);
 GPIOPinTypeGPIOOutput(I2C0SDA_PORT, I2C0SDA_PIN);
 GPIOPadConfigSet(I2C0SDA_PORT, I2C0SDA_PIN, GPIO_STRENGTH_4MA,
                     GPIO_PIN_TYPE_STD_WPU); 
 
 SysCtlPeripheralEnable(I2C0SCL_PERIPH);
 GPIOPinTypeGPIOOutput(I2C0SCL_PORT, I2C0SCL_PIN); 
 GPIOPadConfigSet(I2C0SCL_PORT, I2C0SCL_PIN, GPIO_STRENGTH_4MA,
                     GPIO_PIN_TYPE_STD_WPU);
 
 //SETBIT(I2C_PORT2,SDA2);        // Set SDA High 
 //SETBIT(I2C_PORT2,SCL2);        // Set SCL High 
 GPIOPinWrite(I2C0SDA_PORT, I2C0SDA_PIN, I2C0SDA_PIN);
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, I2C0SCL_PIN); 
 DelayNop(40);
 //SDA从高电平到低电平至少时间
 ///1.8V~2.5V  4us
 ///4.5V~5.5V  0.6us
 
 //CLEARBIT(I2C_PORT2,SDA2);          // Clear SDA 
 //CLEARBIT(I2C_PORT2,SCL2);          // Clear SCL
 
 GPIOPinWrite(I2C0SDA_PORT, I2C0SDA_PIN, 0);
 DelayNop(20);
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0);
 
 DelayNop(40);
 //SCL时钟低电平至少时间
 ///1.8V~2.5V  4.7us
 ///4.5V~5.5V  1.2us
 //SCL时钟高电平至少时间
 ///1.8V~2.5V  4us
 ///4.5V~5.5V  0.6us
}


/*--------------------------------------------------------------------
函数功能:                    
输入说明:
返回 值 :
说    明:
  
--------------------------------------------------------------------*/
void I2CStop(void)
{
 //SETBIT(I2C_DIR2,SDA2);             // Set SDA to output 
 //SETBIT(I2C_DIR2,SCL2);             // Set SCL to output 
 //SysCtlPeripheralEnable(I2C0SDA_PERIPH);
 //GPIOPinTypeGPIOOutput(I2C0SDA_PORT, I2C0SDA_PIN); 
 
 //SysCtlPeripheralEnable(I2C0SCL_PERIPH);
 //GPIOPinTypeGPIOOutput(I2C0SCL_PORT, I2C0SCL_PIN); 
 
 //CLEARBIT(I2C_PORT2,SDA2);          // Clear SDA
 GPIOPinWrite(I2C0SDA_PORT, I2C0SDA_PIN, 0);
 DelayNop(10); 
 //SETBIT(I2C_PORT2,SCL2);          // Set SCL High
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, I2C0SCL_PIN);
 DelayNop(20);
 //SETBIT(I2C_PORT2,SDA2);          // Set SDA High 
 GPIOPinWrite(I2C0SDA_PORT, I2C0SDA_PIN, I2C0SDA_PIN);
 DelayNop(40);
 //CLEARBIT(I2C_PORT2,SCL2);          // Clear SCL
 //GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0);
 //nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();
 //nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();


}


/*--------------------------------------------------------------------
函数功能: 写完8个位后,第9位就是I2C应答信号为低                   
输入说明:
返回 值 :
说    明:
  
--------------------------------------------------------------------*/
unsigned char I2CRecAck(void)
{
 unsigned char Ackn = 0;          // Temp RAM for Ackn flag


 //CLEARBIT(I2C_DIR2,SDA2);           // Set SDA to input 
 //CLEARBIT(I2C_PORT2,SCL2);
 SysCtlPeripheralEnable(I2C0SDA_PERIPH);
 GPIOPinTypeGPIOInput(I2C0SDA_PORT, I2C0SDA_PIN);


 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0); 
 DelayNop(20);
 //SETBIT(I2C_PORT2,SCL2);          // Clock the ACK bit
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, I2C0SCL_PIN);
 DelayNop(2);
 //if ( CHECKBIT( I2C_IN2,SDA2 ) ) Ackn = 1;      // Check the ACK bit on SDA 
 if (GPIOPinRead(I2C0SDA_PORT, I2C0SDA_PIN)) Ackn = 1; 
 DelayNop(38);
 SysCtlPeripheralEnable(I2C0SDA_PERIPH);
 GPIOPinTypeGPIOOutput(I2C0SDA_PORT, I2C0SDA_PIN);
 //CLEARBIT(I2C_PORT2,SCL2);            // Clear the clock
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0); 
 GPIOPinWrite(I2C0SDA_PORT, I2C0SDA_PIN, I2C0SDA_PIN);// Set SDA to out  
 DelayNop(120);
 return Ackn;             // Return our ACK bit

/*--------------------------------------------------------------------
函数功能:                    
输入说明:
返回 值 :
说    明:
  
--------------------------------------------------------------------*/
void I2CAck(void)
{
 //SETBIT(I2C_DIR2,SDA2);             // Set SDA to output 
 //SETBIT(I2C_DIR2,SCL2);             // Set SCL to output 
 //SysCtlPeripheralEnable(I2C0SDA_PERIPH);
 //GPIOPinTypeGPIOOutput(I2C0SDA_PORT, I2C0SDA_PIN);
 
 //SysCtlPeripheralEnable(I2C0SCL_PERIPH);
 //GPIOPinTypeGPIOOutput(I2C0SCL_PORT, I2C0SCL_PIN);
 //nop();
 //CLEARBIT(I2C_PORT2,SDA2);          // Clear SDA
 //CLEARBIT(I2C_PORT2,SCL2);          // Clear SCL 
 GPIOPinWrite(I2C0SDA_PORT, I2C0SDA_PIN, 0);
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0); 
 //SETBIT(I2C_PORT2,SCL2);          // Set SCL High
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, I2C0SCL_PIN); 
 DelayNop(40);
 //CLEARBIT(I2C_PORT2,SCL2);
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0); 
}


/*--------------------------------------------------------------------
函数功能:  I2C不应答                  
输入说明:
返回 值 :
说    明:
  
--------------------------------------------------------------------*/
void I2CNoAck(void)
{
 //SETBIT(I2C_PORT2,SDA2);          // Set SDA High
 GPIOPinWrite(I2C0SDA_PORT, I2C0SDA_PIN, I2C0SDA_PIN);
 //CLEARBIT(I2C_PORT2,SCL2);          // Clear SCL
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0);
 DelayNop(20);
 //SETBIT(I2C_PORT2,SCL2);          // Set SCL High
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, I2C0SCL_PIN);
 DelayNop(40);
 //CLEARBIT(I2C_PORT2,SCL2);          // Clear SCL
 GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0);
 DelayNop(20);
}


/*--------------------------------------------------------------------
函数功能:                  
输入说明:
返回 值 :
说    明:
  
--------------------------------------------------------------------*/
void I2CSendByte(unsigned char byte)
{
 unsigned char i;


 //SETBIT(I2C_DIR2,SDA2);             // Set SDA to output 
 //SETBIT(I2C_DIR2,SCL2);             // Set SCL to output


 


 
 for (i = 0; i < 8; i++)         // Loop for our 8 bits
 {    
  if((byte & 0x80) == 0x80)
   //SETBIT(I2C_PORT2, SDA2); // Set I2C SDA PIN
   GPIOPinWrite(I2C0SDA_PORT, I2C0SDA_PIN, I2C0SDA_PIN);
  else
   //CLEARBIT(I2C_PORT2,SDA2);        // Clear I2C SDA PIN
   GPIOPinWrite(I2C0SDA_PORT, I2C0SDA_PIN, 0);
  DelayNop(20);
  //CLEARBIT(I2C_PORT2,SCL2);
  //GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0);
  //SETBIT(I2C_PORT2,SCL2);          // Set SCL High, Clock data
  GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, I2C0SCL_PIN);
  DelayNop(40);
  //CLEARBIT(I2C_PORT2,SCL2);          // Clear SCL 不能换位置
  GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0);
  DelayNop(20);
  byte = byte << 1;            // Shift data in buffer right one
 }


 
}


/*--------------------------------------------------------------------
函数功能:                  
输入说明:
返回 值 :
说    明:
  
--------------------------------------------------------------------*/
unsigned char I2CReceiveByte(void)

 unsigned char i,buff = 0;
 
 //SETBIT(I2C_DIR2,SDA2);             // Set SDA to output 


 //CLEARBIT(I2C_DIR2,SDA2);              // Set SDA to input
 SysCtlPeripheralEnable(I2C0SDA_PERIPH);
 GPIOPinTypeGPIOInput(I2C0SDA_PORT, I2C0SDA_PIN); 
 
 for (i = 0; i < 8; i++)
 {  
  buff = buff << 1; 
  //CLEARBIT(I2C_PORT2,SCL2);               // Clear SCL
  GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0);
  DelayNop(40);
  //SETBIT(I2C_PORT2,SCL2);               // Set SCL High,Clock bit out
  GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, I2C0SCL_PIN);
  //nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();               // Read data on SDA pin
  //if (CHECKBIT(I2C_IN2,SDA2))
  if (GPIOPinRead(I2C0SDA_PORT, I2C0SDA_PIN))
  buff = buff | 0x01; 
  //CLEARBIT(I2C_PORT2,SCL2);               // Clear SCL
  GPIOPinWrite(I2C0SCL_PORT, I2C0SCL_PIN, 0);
 }
 
 SysCtlPeripheralEnable(I2C0SDA_PERIPH);
 GPIOPinTypeGPIOOutput(I2C0SDA_PORT, I2C0SDA_PIN);
 GPIOPadConfigSet(I2C0SDA_PORT, I2C0SDA_PIN, GPIO_STRENGTH_4MA,
                     GPIO_PIN_TYPE_STD_WPU);  
 return buff;              // Return our I2C byte
}


/**************24XX读写主函数*****************************************
 DataBuff      为读写数据输入/输出缓冲区的首址
 ByteQuantity  为要读写数据的字节数量
 Address       为EEPROM的片内地址
 ControlByte   为EEPROM的控制字节,具体形式为(1)(0)(1)(0)(A2)(A1)(A0)(R/W),其中R/W=1,
               表示读操作,R/W=0为写操作,A2,A1,A0为EEPROM的页选或片选地址;
 EEPROM_Type    为枚举变量,需为M2401至M24256中的一种,分别对应24C01至24C256;
 函数返回值:   位变量,1=次操作失效,0=操作成功;
 ErrorCount    为允许最大次数,若出现ErrorCount次操作失效后,则函数中止操作,并返回1
 SDA和SCL由用户自定义,这里暂定义为P0^0和P0^1;
 其余的用户不用管,只要把只子程序放在你的程序中并调用它就可以了;
 jiao注:器件型号,页大小。
   24C01C  16 字节
  24C02C  16 字节
  24LC04B  16 字节
  24LC08B  16 字节
  24LC16B    16 字节
  24LC32A  32 字节
  24LC64  32 字节 
  24C256页写容量:64字节
*******************************************************************************/
unsigned char  RW24XX(unsigned char *DataBuff, unsigned int ByteQuantity, unsigned int Address,unsigned char ControlByte)
{
 unsigned char j,i=3;
 unsigned char errorflag=1;
 
 while(i--)
 {
  I2CStart();
  I2CSendByte(ControlByte&0xfe);
  if(I2CRecAck()== 1)
  {
   UARTprintf("I2CRecAck error\r\n");
   continue;
  }
  //if(EEPROM_Type>M2416)
  //{
  // I2CSendByte((unsigned char)(Address>>8));
  // if(I2CRecAck()== 1) continue;
  //}
  I2CSendByte((unsigned char)Address);
  if(I2CRecAck()==1) continue;
  if((ControlByte&0x01)== 0)
  {
   j=ByteQuantity;
   errorflag=0;                      //********clr errorflag
   while(j--)
   {
    I2CSendByte(*DataBuff++);
    if(I2CRecAck()== 0) continue;
    errorflag=1;
    //Delay_E(1000);
    break;
   }
   if(errorflag==1) continue;
   break;
  }
  else
  {
   I2CStart();
   I2CSendByte(ControlByte);
   if(I2CRecAck()== 1) continue;
   while(--ByteQuantity)
   {
    *DataBuff++=I2CReceiveByte();
    I2CAck();
   }
   *DataBuff=I2CReceiveByte();    //read last byte data
   I2CNoAck();
   errorflag=0;
   break;
  }
 }
 I2CStop();
 if((ControlByte&0x01)== 0)
 {
  for (i=0; i<80; i++)
  {
   DelayNop(40);//一定要.要不然在写后马上又读会不成功
  }
 }
 return(errorflag);
}

文章评论0条评论)

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