2440 模拟IIC 可以读取 L3G4200D ,ADXL345

     因为 其中一个2440 板子的硬件IIC 使用有点问题,就结合51的IIC 程序写了 ARM9的 模拟IIC 程序 .连续读取 6字节  数据的时间为 0.5ms

代码如下 ,有需要的直接拿去用就可以了.博文为本人所有转载请表明出处2440 模拟IIC 读取 L3G4200D 代码 ,目前测试的情况,感觉模拟IIC 读取

数据的噪声略大于 硬件IIC读取的数据.未进行 EPROM读取和写入数据的测试,具体使用还是具体测试.

 两种IIC读取对比(ADXL345),左边的硬件IIC ,右边的是模拟IIC .

/*模拟iic  ,硬件iic 在另外一个板子上有问题*/
#include <S3C2440.H>
#include "iic_analog.h"

#define      IIC_SDA_L     (GPFDAT = GPFDAT & ~(1<<0))
#define      IIC_SDA_H  (GPFDAT = GPFDAT |  (1<<0))
#define    IIC_SCL_L  (GPFDAT = GPFDAT & ~(1<<1))
#define    IIC_SCL_H  (GPFDAT = GPFDAT |  (1<<1))

/*
    尝试利用模拟iic 通信    ,接口  CRO ( GPF0  GPF1 )( PA18 PA17  ) (EINT0  EINT1)    SDA  SCL
                                 NI ( GPG0  GPF1 )( 9   10     ) (EINT0  ENIT1)    SDA  SCL
  */
 
void Delay_moment(int x)  //这里如何延时 5us   x=10  
{
    int k;
    while(x)
    {
        for(k=0;k<=0x18;k++);  //0x20 = 6 us   0x18 = 5us 
        x--;
    }
}




//初始化:a,代表模拟
void IIC_Init_a()

{
//GPF0--SDA   GPF1--SCL
        GPFUP  = 0x00000000;  //这里是否需要上拉,我也不是太确定
        GPFCON = 0x00000005;
        IIC_SCL_L;
        IIC_SDA_H;
        Delay_moment(10);   //5us,
        IIC_SCL_H;
}

void IIC_Start()   //没问题,> 4us    
{
        IIC_SDA_H;
        IIC_SCL_H;
        Delay_moment(10);
        IIC_SDA_L;
        Delay_moment(10);
        IIC_SCL_L;    
}


void IIC_Stop()   //没问题

{
        IIC_SCL_L; 
        Delay_moment(10);
        IIC_SDA_L;
        Delay_moment(10);
                IIC_SCL_H;
                Delay_moment(10);
                IIC_SDA_H;
                Delay_moment(10);
}

/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void SendACK(unsigned char ack)    //相对主机的,第9个时钟脉冲
{              
        IIC_SCL_L;
        if(ack)         //写应答信号
        {
            IIC_SDA_H;   // not ack
    }
        else
        {
            IIC_SDA_L;   //ack
        }
    IIC_SCL_H;                    //拉高时钟线
    Delay_moment(10);               //延时
    IIC_SCL_L ;                    //拉低时钟线
}


/**************************************
接收应答信号
**************************************/
void RecvACK()                   //第9个时钟脉冲
{    
      IIC_SCL_L;
        Delay_moment(10);  
        IIC_SDA_H;                  //拉高信号号,释放SDA
        
      GPFCON=0x00000004;     //SDA input                      
        //while(SDA);
        while(GPFDAT &  (1<<0));  //程序容易卡在这里
         Delay_moment(2);    
      IIC_SCL_H;
      Delay_moment(10);    
    IIC_SCL_L;                    //拉低时钟线
    Delay_moment(10);                    //延时
        GPFCON=0x00000005;     //SDA output
    
    
    
}



//写8位数据:在SCL为低时把数据通过SDA输出,翻转SCL。

void Write_8bit(U8 data)

{
        unsigned int i;
        for(i=0;i<8;i++)
        {

                if(data & (1<<(7-i)))
                        IIC_SDA_H;
                else 
                        IIC_SDA_L;
                                Delay_moment(2);
                IIC_SCL_H;
                Delay_moment(10);
                IIC_SCL_L; 
                                Delay_moment(10);
        }
        RecvACK();
}

//读8位:在SCL为低时读取SDA上面的电平。
U8 Read_8bit()
{
        unsigned int i;
        U8 temp = 0;
                IIC_SDA_H;
        GPFCON = 0x00000004;       //SDA input ,这个方法体也是有点问题的
        for(i=0;i<8;i++)
        {
                        
                        if(GPFDAT & (1<<0))
                                        temp |= (1<<(7-i)); 
                        Delay_moment(2);
                        IIC_SCL_H;
                        Delay_moment(10);   //5us
                        IIC_SCL_L;
                        Delay_moment(10);
        } 
                GPFCON=0x00000005;    //SDA output
        return temp;
}




//写操作,可以连续写多个字节。
void IIC_Write_Byte(U32 slave_addr,U32 IIC_addr,U8 WriteData)
{      
        IIC_Start();
        Write_8bit(slave_addr);   
        Write_8bit(IIC_addr);   //写数据的起始地址    
                Write_8bit(WriteData);        
        IIC_Stop();
}


//读操作:读操作必须要先写设备地址和数据起始地址,然后再写设备地址(带读标志),读的最后一个字节NO ACK。
void IIC_Read_nByte(U32 slave_addr,U32 IIC_addr,U16 byte_Count,U8*ReadBuffer)
{
        unsigned int i;
        IIC_Start();
 
        Write_8bit(slave_addr);  //第一次写设备地址,写操作     
        Write_8bit(IIC_addr);   //写数据起始地址       
        IIC_Start();     //Restart
        Write_8bit(slave_addr+1);  //写设备地址,带读操作
        for(i=0;i<byte_Count;i++)  //读byte_Count-1个数据,最后一个数据时NO ACK,不能这读
        {
                ReadBuffer[i] = Read_8bit();
                if(i==byte_Count-1)              //之前在这里的错误是没有 noack
                                {
                                    SendACK(1);
                                }
                                else
                                {
                                    SendACK(0);
                                }
        }
                
                IIC_Stop();
                Delay_moment(10);   //5us
}

原文地址:https://www.cnblogs.com/dreamfactory/p/3075472.html