51控制24c02 EEPROM

      

         先大概分解IIC协议.找出其变化和不变的东西...                             */

  1. /*                                                                         */
  2. /*        IIC总线总是以下面这种结构出现                                     */
  3. /*        <开始信号>[通信过程(读/写)<ACK>|<NACK>]<停止信号>                */
  4. /*                                                                         */
  5. /*        当然了,这是我自己总结的,有不同意见我们再进行讨论.嘿嘿             */
  6. /*                                                                         */
  7. /*        也就有了                                                          */
  8. /*         Start(...);发开始信号                                        */
  9. /*         Stop(...);发停止信号                                        */
  10. /*         SendByte(...);发送一个字节                                  */
  11. /*         ReadByte(...);读取一个字节                                      */
  12. /*                                                                         */
  13. /*        以及一系列的ACK机制的东西                                        */
  14. /******************************************************************************/
  15. /* 上面的都是不变的,下面我们来看什么是可变的.                            */
  16. /*                                                                         */
  17. /*        时间间格.                                                           */
  18. /*          也就是各个脉冲的宽度间格,                                     */
  19. /*          由于单片机间的速度参差不齐(从几百KHz到几十MHz).                 */
  20. /*          因此,有Delay();                                            */
  21. /*          这个函数,供用户自行根据自己的单片机速度进行调整.             */
  22. /*                                                                         */
  23. /*        IO定义.                                                          */
  24. /*          具体的应用,不同的资源.设计的理念不一样,用的IO不一样.          */
  25. /*          这里以8051上可以位寻址的IO作例子:                            */
  26. /*             sbit SDA = P1 ^ 2;                                        */
  27. /*             sbit SCL = P1 ^ 3;                                        */
  28. /*                                                                         */
  29. /*        协议组合方式.                                                    */
  30. /*          不同的功能芯片,要求的具体协议不一致.功能分块后,可以任意组合     */
  31. /*          以应对不同的需求.具体的可以从功能芯片的手册里得出...          */
  32. /******************************************************************************/

 

 

#include "I2C.h"

/* 延时约5微秒,对于12M时钟 */
void delay5us()
{
         uint i;
         for (i=0;i<5;i++)
                 _nop_();        
}

/* 起始条件子函数 */
void start(void)
{
         SDA = 1;                         // 启动I2C总线
         SCL = 1;
         delay5us();
         SDA = 0;
         delay5us();
         SCL = 0;
}

/* 停止条件子函数 */
void stop(void)
{
         SDA = 0;                         // 停止I2C总线数据传送
         SCL = 1;
         delay5us();
         SDA = 1;
         delay5us();
         SCL = 0;
}

/* 发送应答子函数 */
void ack(void)
{
         SDA = 0;                         // 发送应答位
         SCL = 1;
         delay5us();
         SCL = 0;

        SDA = 1;

}

/* 发送非应答子函数 */
void n_ack(void)
{
         SDA = 1;                         // 发送非应答位
         SCL = 1;
         delay5us();
          SCL = 0;

         SDA = 0;

}

/* 应答位检查子函数 */
void checkack(void)
{
         SDA = 1;                     // 应答位检查(将p1.0设置成输入,必须先向端口写1)
         SCL = 1;
         nackFlag = 0;
         if(SDA == 1)             // 若SDA=1表明非应答,置位非应答标志F0
                 nackFlag = 1;
         SCL = 0;
}

/* 发送一个字节数据子函数 */
void sendbyte(uchar idata *ch)
{
         uchar idata n = 8;  
         uchar idata temp;
         temp = *ch;
         while(n--)
         {
                 if((temp&0x80) == 0x80)     // 若要发送的数据最高位为1则发送位1
                 {
                         SDA = 1;     // 传送位1
                         SCL = 1;
                         delay5us();
                          SCL = 0;   

                           SDA = 0;
  
                 }
                 else
                 {  
                         SDA = 0;     // 否则传送位0
                         SCL = 1;
                         delay5us();
                         SCL = 0;  
                 }
                 temp = temp<<1;     // 数据左移一位
         }
}


/* 接收一字节子程序 */
void recbyte(uchar idata *ch)
{
         uchar idata n=8;     // 从SDA线上读取一位数据字节,共8位
         uchar idata temp = 0;
         while(n--)
         {
                 SDA = 1;
                 SCL = 1;
                 temp = temp<<1;     // 左移一位
                 if(SDA == 1)
                         temp = temp|0x01;     // 若接收到的位为1,则数据的最后一位置1
                 else
                         temp = temp&0xfe;     // 否则数据的最后一位置0
                 SCL=0;
         }
         *ch = temp;
}

/* 发送n字节数据子程序 */
void sendnbyte(uchar idata *sla, uchar n)
{          
         uchar idata *p;
         start();                                
         sendbyte(sla);                    
         checkack();                            
     if(F0 == 1)                                                      
         {
                 NACK = 1;
                 return;                     
         }

         p = sbuf;
         while(n--)
         {
                 sendbyte(p);
                 checkack();             // 检查应答位
                 if (nackFlag == 1)
                 {
                         NACK=1;
                         return;             // 若非应答表明器件错误或已坏,置错误标志位NACK
                 }
                 p++;
         }
         stop();                             // 全部发完则停止
}

/* 接收n字节数据子程序 */
void recnbyte(uchar idata *sla, uchar n)
{
         uchar idata *p;
         start();                         // 发送启动信号
         sendbyte(sla);                 // 发送从器件地址字节
         checkack();                         // 检查应答位
         if(nackFlag == 1)
         {
                 NACK = 1;
                 return;
         }
         p = rbuf;                         // 接收字节存放在rbuf中
         while(n--)
         {
                 recbyte (p);
                 ack();                     // 收到一个字节后发送一个应答位
                 p++;
         }
         n_ack();                     // 收到最后一个字节后发送一个非应答位
         stop();
}

/* 主函数,模拟实现I2C总线的数据收发 */
void main(void)
{
         uchar i,numbyte;

         numbyte = 8;

         /* 需发送的8字节数据 */
         for (i=0;i<numbyte;i++)
                 sbuf[i] = i+0x11;

         SLAdd = 0x58;                 // 从器件地址
        
            sendnbyte(&SLAdd,numbyte);         // 向从器件发送存放在sbuf中的8字节数据

         for (i=0;i<10000;i++)
                 delay5us();

         recnbyte(&SLAdd,numbyte);         // 由从器件接收8字节数据,存放在rbuf中

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值