您的位置:首页 > 其它

2440 模拟IIC 可以读取 L3G4200D ,ADXL345

2013-05-13 12:35 211 查看
因为 其中一个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
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: