×
嵌入式 > 技术百科 > 详情

模拟I2C程序设计

发布时间:2020-06-12 发布时间:
|
#include 

#include

#define uchar unsigned char
#define DELAY5US   _nop_(); _nop_(); _nop_(); _nop_();   //延时5us
#define WriteDeviceAddress   0xa0   //写I2C外围器件的寻址地址
#define ReadDeviceAddress   0xa1   //读I2C外围器件的寻址地址
           //注:写I2C外围器件的寻址地址为器件的地址,读为器件地址加1
uchar E0;    //非应答信号标志位
uchar NACK=0;    //错误标志位

//**************************修改硬件时要修改的部分********************************

sbit SDA    = P1^0;   //模拟数据线
sbit SCL    = P1^1;   //模拟时钟线

void Start(void)    //启动I2C总线子函数
{
   SDA=1;
SCL=1;
DELAY5US
SDA=0;
DELAY5US
SCL=0;
}

void Stop(void)    //停止I2C总线数据传送子函数
{
   SDA=0;
SCL=1;
DELAY5US
SDA=1;
DELAY5US
SCL=0;
}

void Ack(void)    //发送应答位子程序
{
   SDA=0;
   SCL=1;
   DELAY5US
   SCL=0;
   SDA=1;
}

void NoAck(void)   //发送非应答位子程序
{
   SDA=1;
   SCL=1;
   DELAY5US
   SCL=0;
   SDA=0;
}

void TestAck(void) //应答位检查子程序,若检测不到非应答信号,置位E0
{
   SDA=1;
   SCL=1;
   E0=0;
   _nop_(); //短延时
   if(SDA==1) //如果SDA为1,表明非应答,置位非应答标志E0
      E0=1;
   SCL=0;
}

void Write8Bit(uchar n) //写一个字节数据子程序,n为待发送的数据
{
   uchar i;
   for(i=8;i>0;i--)
   {
      SDA=(bit)(n&0x80);
   SCL=1;
   DELAY5US
   SCL=0;
   SDA=0;
   n=n<<1;
   }
}

void WriteI2C(uchar *Wdata,uchar RomAddress,uchar number) // 写n个字节数据子程序
{     //*Wdata为待发送数据的首地址,RomAddress为待I2C外围器件的数据写入首地址,number为写字节的个数
Start(); //启动
Write8Bit(WriteDeviceAddress); //写入器件的寻址地址
TestAck();    //应答检查
if(E0==1)
{
    NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
    return;
}
Write8Bit(RomAddress); //写入I2C器件的数据存储首地址
TestAck();    //应答检查
if(E0==1)
{
    NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
    return;
}
for(;number!=0;number--)   //循环,逐个字节发送
{
    Write8Bit(*Wdata); //写一个字节
    TestAck();    //应答检查
    if(E0==1)
    {
       NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
       return;
    }
    Wdata++;         //指针增加,指向下一个数据
}
Stop();     //全部发送完则停止
}

uchar Read8Bit(void)   //读一个字节数据子程序
{
    uchar temp,rbyte=0;
for(temp=8;temp>0;temp--)
{
    SDA=1;
    SCL=1;
    _nop_(); //短延时
       rbyte=rbyte<<1;
    rbyte=rbyte|((uchar)(SDA));
    SCL=0;
}
return(rbyte);
}

void ReadI2C(uchar *RamAddress,uchar RomAddress,uchar bytes) // 读n个字节数据子程序
{   //RamAddress为接收数据缓冲区的首地址,RomAddress为待I2C外围器件的数据读取首地址,bytes为写字节的个数
   Start(); //启动
Write8Bit(WriteDeviceAddress); //写入器件的寻址地址
TestAck();    //应答检查
if(E0==1)
{
    NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
    return;
}
Write8Bit(RomAddress); //写入I2C器件内部数据的读取首地址
TestAck();    //应答检查
if(E0==1)
{
    NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
    return;
}
Start(); //重新启动
Write8Bit(ReadDeviceAddress); //写入器件的寻址地址
TestAck();    //应答检查
if(E0==1)
{
    NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
    return;
}
while(bytes!=1)     //循环读入字节数据
{
    *RamAddress=Read8Bit(); //读入一个字节
    Ack();                //应答
    RamAddress++;      //地址指针递增
    bytes--;     //待读入数据个数递
}
*RamAddress=Read8Bit(); //读入最后一个字节数据
NoAck();   //非应答
Stop();    //停止
}

 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ADI 高精度低功耗精密放大器