⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 上载的程序可以用于PIC单片机,也可以用于430单片机,本人原创,到至今还没有发现哪位网友想出这种办法,希望站长能多加分.
💻 C
字号:

#include "i2c.h"


void I2C_Initial( void )
{
    //将SCL管脚设置为输出管脚
    SCLOUT;		
    I2C_Set_sck_low();
    I2C_STOP();
    Delay_ms(10);
    return;
}
void I2C_Set_sda_high( void )
{
    //将SDA设置为输出模式
    SDAOUT;		
    //SDA管脚输出为高电平
    SDA1;
    NOP();
    NOP();
    return;
}
void I2C_Set_sda_low ( void )
{
    //将SDA设置为输出模式
    SDAOUT;		
    //SDA管脚输出为低电平
    SDA0;		
    
    NOP();
    NOP();
    return;
}
void I2C_Set_sck_high( void )
{
    //将SCL设置为输出模式
    SCLOUT;		
    //SCL管脚输出为高电平
    SCL1;		
    
    NOP();
    NOP();
    return;
}
void I2C_Set_sck_low ( void )
{
    //将SCL设置为输出模式
    SCLOUT;	
    //SCL管脚输出为低电平
    SCL0;		
    
    NOP();
    NOP();
    return;
}
int  I2C_GetACK(void)
{
    int nTemp = 0;
    int j;
    
    NOP();
    NOP();
    I2C_Set_sck_low();
    for(j = 30;j > 0;j--);
    //将SDA设置为输入方向
    SDAIN;		
    I2C_Set_sck_high();
    
    for(j = 30;j > 0;j--);
    //获得数据
    nTemp = (int)(SDA_STATE);	   //读入SDA状态
    
    I2C_Set_sck_low();
    
    return (nTemp & LC24_SDA);
}
void I2C_SetACK(void)
{   
    I2C_Set_sck_low();
    I2C_Set_sda_low();
    I2C_Set_sck_high();
    I2C_Set_sck_low();
    return;
}
void I2C_SetNAk(void)
{
    I2C_Set_sck_low();
    I2C_Set_sda_high();
    I2C_Set_sck_high();
    I2C_Set_sck_low();
    return;
}
void I2C_START(void)
{
    int i;
    
    I2C_Set_sda_high();
    for(i = 5;i > 0;i--);
    I2C_Set_sck_high();
    for(i = 5;i > 0;i--);
    I2C_Set_sda_low();
    for(i = 5;i > 0;i--);
    I2C_Set_sck_low();
    return;
}
void I2C_STOP(void)
{
    int i;
    
    I2C_Set_sda_low();
    for(i = 5;i > 0;i--);
    I2C_Set_sck_low();
    for(i = 5;i > 0;i--);
    I2C_Set_sck_high();
    for(i = 5;i > 0;i--);
    I2C_Set_sda_high();
    for(i = 5;i > 0;i--);
    I2C_Set_sck_low();
    //延迟一点时间
    Delay_ms(10);		
    
    return;
}
void I2C_TxHToL(int nValue)
{
    int i;
    int j;
    
    for(i = 0;i < 8;i++)
    {
    	if(nValue & 0x80)
    	    I2C_Set_sda_high();
    	else
    	    I2C_Set_sda_low();
    	for(j = 30;j > 0;j--);
    	I2C_Set_sck_high();
    	nValue <<= 1;
    	for(j = 30;j > 0;j--);
    	I2C_Set_sck_low();
    }
    
    return;
}
void I2C_TxLToH(int nValue)
{
    int i;
    int j;
    
    for(i = 0;i < 8;i++)
    {
    	if(nValue & 0x01)
    	    I2C_Set_sda_high();
    	else
    	    I2C_Set_sda_low();
    	for(j = 30;j > 0;j--);
    	I2C_Set_sck_high();
    	nValue >>= 1;
    	for(j = 30;j > 0;j--);
    	I2C_Set_sck_low();
    }
    
    return;
}
/////////////////////////////////////////////
// 接收是从 LSB 到 MSB 的顺序
int  I2C_RxByte(void)
{
    int nTemp = 0;
    int i;
    int j;
    
    I2C_Set_sda_high();
    //将SDA管脚设置为输入方向
    SDAIN;			
    NOP();
    NOP();
    NOP();
    NOP();
    for(i = 0;i < 8;i++)
    {
    	I2C_Set_sck_high();
    	
    	if(SDA_STATE)       //读入SDA状态
    	{
    	    nTemp |= (0x01 << i);
    	}
    	for(j = 30;j > 0;j--);
    	I2C_Set_sck_low();
    }
    
    return nTemp;
}
/////////////////////////////////////////////
// 接收是从 MSB 到 LSB 的顺序
int  I2C_RxHToL(void)
{
    int nTemp = 0;
    int i;
    int j;
    
    I2C_Set_sda_high();
    //将SDA管脚设置为输入方向
    SDAIN;			
    NOP();
    NOP();
    NOP();
    NOP();
    for(i = 0;i < 8;i++)
    {
    	I2C_Set_sck_high();
    	
    	if(SDA_STATE)             //读入SDA状态
    	{
    	    nTemp |= (0x01 << (7 - i));
    	}
    	for(j = 30;j > 0;j--);
    	I2C_Set_sck_low();
    }
    
    return nTemp;
}

void Delay_ms(unsigned long nValue)//毫秒为单位,8MHz为主时钟
{
    unsigned long nCount;
    int i;
    unsigned long j;
    nCount = 2667;
    for(i = nValue;i > 0;i--)
    {
    	for(j = nCount;j > 0;j--);
    }
    return;
}
void Delay_us(unsigned long nValue)//微秒为单位,8MHz为主时钟
{
    int nCount;
    int i;
    int j;
    nCount = 3;
    for(i = nValue;i > 0;i--)
    {
    	for(j = nCount;j > 0;j--);
    }
    return;
}



//设备码 1010
void readByte24AA64(int addr,unsigned char *reby_p)
{
    char hi;
    char low;
    
    //高地址
    hi = (char)((addr >> 8) & 0xff);
    hi &= 0x1F;
    //低地址
    low = (char)(addr & 0xff);
    
    // 启动数据总线
    I2C_START();			
    // 发送写命令
    I2C_TxHToL(0xA0);			
    // 等待 ACK
    I2C_GetACK();	
    //发送高地址
    I2C_TxHToL(hi);	
    // 等待 ACK
    I2C_GetACK();
    //发送低地址
    I2C_TxHToL(low);	
    // 等待 ACK
    I2C_GetACK();
    
    // 启动数据总线
    I2C_START();	
    // 发送读命令
    I2C_TxHToL(0xA1);	
    // 等待 ACK
    I2C_GetACK();	
    //读一个数据
    *reby_p= I2C_RxHToL();
    //设置NAK
    I2C_SetNAk();
    // 停止总线
    I2C_STOP();
    
    return;
}
void writeByte24AA64(int addr,unsigned char *wrby_p)
{
    char hi;
    char low;
    
    //高地址
    hi = (char)((addr >> 8) & 0xff);
    hi &= 0x1F;
    //低地址
    low = (char)(addr & 0xff);
    
    // 启动数据总线
    I2C_START();			
    // 发送写命令
    I2C_TxHToL(0xA0);			
    // 等待 ACK
    I2C_GetACK();	
    //发送高地址
    I2C_TxHToL(hi);	
    // 等待 ACK
    I2C_GetACK();
    //发送低地址
    I2C_TxHToL(low);	
    // 等待 ACK
    I2C_GetACK();
    //写入数据
    I2C_TxHToL(*wrby_p);
    // 等待 ACK
    I2C_GetACK();
    // 停止总线
    I2C_STOP();	
    
    return;
}
int readPage24AA64(int addr,unsigned char *repa_p,int len)
{
    char hi;
    char low;
    int i;
    
    //高地址
    hi = (char)((addr >> 8) & 0xff);
    hi &= 0x1F;
    //低地址
    low = (char)(addr & 0xff);
    
    //高地址
    hi = (char)((addr >> 8) & 0xff);
    hi &= 0x1F;
    //低地址
    low = (char)(addr & 0xff);
    
    // 启动数据总线
    I2C_START();			
    // 发送写命令
    I2C_TxHToL(0xA0);			
    // 等待 ACK
    I2C_GetACK();	
    //发送高地址
    I2C_TxHToL(hi);	
    // 等待 ACK
    I2C_GetACK();
    //发送低地址
    I2C_TxHToL(low);	
    // 等待 ACK
    I2C_GetACK();
    
    // 启动数据总线
    I2C_START();	
    // 发送读命令
    I2C_TxHToL(0xA1);	
    // 等待 ACK
    I2C_GetACK();	
    for(i = 0;i < len - 1;i++)
    {
        //读一个数据
        *(repa_p+i) = I2C_RxHToL();
        //设置ACK
        I2C_SetACK();
    }
    //最后一个数据
    *(repa_p+(len -1))= I2C_RxHToL();
    //设置NAK
    I2C_SetNAk();
    // 停止总线
    I2C_STOP();
    //读32个数据
    return len;
}
void writePage24AA64(int addr,unsigned char *wrpa_p,int len)
{
    char hi;
    char low;
    int i;
    
    //高地址
    hi = (char)((addr >> 8) & 0xff);
    hi &= 0x1F;
    //低地址
    low = (char)(addr & 0xff);
    
    //页写最多能写入32个数据
    if(len > 32) len = 32;
    
    // 启动数据总线
    I2C_START();			
    // 发送写命令
    I2C_TxHToL(0xA0);			
    // 等待 ACK
    I2C_GetACK();	
    //发送高地址
    I2C_TxHToL(hi);	
    // 等待 ACK
    I2C_GetACK();
    //发送低地址
    I2C_TxHToL(low);	
    // 等待 ACK
    I2C_GetACK();
    for(i = 0;i < len;i++)
    {
        //写入数据
        I2C_TxHToL(*(wrpa_p+i));
        // 等待 ACK
        I2C_GetACK();
    }
    // 停止总线
    I2C_STOP();	
    
    return;
}



 void I2C_CLR(void)                      //清24LC子程序;
{
int a,b;
char clrda[8]={0};
for(a=0;a<400;a++)
  {
  b=a*8;
  writePage24AA64(b,clrda,8);
  }
}



//******************************************************
//检验两组数据是否正确,如在检验数据中有一组不正确,则退出.
//*Data_REF参考值数组,*Data_CHK被检验数组,n检验数量
//并返回一个成败标志.0为正确,1为错误;
unsigned char data_check(unsigned char *Data_REF, unsigned char *Data_CHK, unsigned char n)
{unsigned char chk ;
 while(n) 
  {
   if(Data_REF[n-1]==Data_CHK[n-1])     //进行校对
    { chk =0;                      //正确
      n--;                              //下一位
    }
   else
    { chk =1;                      //校对有错
      continue;                         //马上退出
    }
  }
   return chk ;                           //返回校对成败标志.
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -