因为 其中一个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 }