zoukankan      html  css  js  c++  java
  • IIC Option

    #include <reg52.h>  
    #include "MY51.H"  
      
    sbit sda=P2^0;      //总线连接口定义  
    sbit scl=P2^1;      //总线连接口定义  
      
    void delayus()  //需要4个机器周期,大概4.34us  
    {  
        ;                   //晶振频率11.0592M,机器周期为1.085微秒  
    }  
      
    void iic_start()  //启动信号  
    {  
        sda=1;  
        scl=1;  
        delayus();      //sda和scl同为高电平保持4.7us以上  
        _nop_();            //1.085us,共5.78us,下面sda=0是下降沿,不能计算在延时时间中  
        sda=0;          //下降沿  
        delayus();      //sda低电平保持4us以上 ,这里是4.34us满足要求  
    }  
      
    void iic_stop() //停止信号  
    {  
        sda=0;_nop_();  //准备状态  
        scl=1;  
        delayus();      //该状态稳定时间要求保持4us以上  
        sda=1;          //scl高电平期间,sda来一个上升沿  
        delayus();      //sda保持4.7us以上,4.34加上函数返回时间大于4.7us  
                            //注:此时scl和sda都为1      
    }  
      
    void iic_sendByte(uchar byteData) //mcu发送一个字节  
    {  
        uchar i;  
        uchar temp=byteData;  
        for(i=0;i<8;i++)  
        {  
            temp=temp<<1;   //移动后最高位到了PSW寄存器的CY位中  
            scl=0;           //准备  
            _nop_();            //稳定一下  
            sda=CY;          //将待发送的数据一位位的放到sda上  
            _nop_();  
            scl=1;           //每一个高电平期间,ic器件都会将数据取走  
            _nop_();          
        }  
      
        scl=0;              //如果写成scl=1;sda=1就是停止信号,不能这么写  
        _nop_();                  
        sda=1;              //释放总线,数据总线不用时要释放  
        _nop_();  
    }  
      
    uchar iic_readByte() //读一个字节  
    {  
        uchar i,temp;  
        scl=0;              //准备读数据  
        _nop_();  
        sda=1;              //释放总线  
        _nop_();  
      
        for(i=0;i<8;i++)  
        {  
            scl=1;          //mcu开始取数据  
            delayus();      //scl为高电平后,ic器件就会将1位数据送到sda上  
                                //总共用时不会大于4.34us的,然后就可以让mcu读sda了  
            temp=(temp<<1)|sda; //读一位保存到temp中  
            scl=0;  
            delayus();        
        }  
        return temp;  
    }  
      
    bool iic_checkACK()     //处理应答信号  
    {  
        uchar errCounts=255; //定义超时量为255次  
        scl=1;  
        _nop_();  
          
        while(sda)  
        {   //在一段时间内检测到sda=0的话认为是应答信号  
            if(0==errCounts)  
            {  
                scl=0;        //钳住总线  
                _nop_();  
                return false; //没有应答信号  
            }  
            errCounts--;  
        }  
      
        scl=0;            //钳住总线,为下1次通信做准备   
        _nop_();  
        return true;      //成功处理应答信号  
    }  
      
    void iic_init() //总线初始化  
    {  
        scl=1;  
        sda=1;  
        delayus();  
    }  
      
    void iic_sendACK(bool b_ACK)    //发送应答或非应答信号  
    {  
        scl=0;          //准备  
        _nop_();  
      
        if(b_ACK)       //ACK  
        {  
            sda=0;  
        }  
        else               //unACK  
        {  
            sda=1;  
        }  
      
        _nop_();  
        scl=1;  
        delayus();      //大于4us的延时  
        scl=0;              //钳住scl,以便继续接收数据      
        _nop_();  
    }  
      
      
    void AT24C02_writeByte(uchar address,uchar dataByte)//向24c02写一字节数据  
    {  
        iic_start();  
        iic_sendByte(0xa0);//mcu写控制字,前4位固定1010,后三位地址0,末位0是写  
        iic_checkACK();        //mcu处理应答信号  
        iic_sendByte(address);  //准备在指定地址处写入      
        iic_checkACK();  
        iic_sendByte(dataByte); //写数据  
        iic_checkACK();  
        iic_stop();  
        delayms(2);   
        //按字节写入时,24c02在接收到停止信号后将数据擦写到内部,这需要时间  
        //并且在这段时间内不会响应总线上的任何请求,故让mcu有2毫秒以上的等待     
    }  
      
    void AT24C02_writeData(uchar address,uchar numBytes,uchar* buf)//写入任意长度数据  
    {  
        while(numBytes--)  
        {  
            AT24C02_writeByte(address++,*buf++);  
        }  
    }  
      
    void AT24C02_readData(uchar beginAddr,uchar dataSize,uchar* buf)//读取任意长度字节  
    {  
        iic_start();                    //起始信号  
        iic_sendByte(0xa0);         //控制字,写  
        iic_checkACK();             //处理应答信号  
        iic_sendByte(beginAddr);    //发送地址  
        iic_checkACK();             //处理应答信号      
        iic_start();                //发送起始信号  
        iic_sendByte(0xa1);         //控制字,读  
        iic_checkACK();             //处理应答信号  
        while(dataSize--)               //读取dataSize个字节  
        {  
            *buf++=iic_readByte();  //读取一个个字节并保存到缓冲区buf中  
            iic_sendACK(dataSize);  //发送应答,当dataSize为0时发送非应答  
        }  
        iic_stop();                     //发送停止信号  
    }  
      
    void main()  
    {  
        uchar buf[2];                   //接受数据的缓冲区  
        uchar arr[34]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,               //0x00-0x0f  
                            16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,//0x10-0x1f  
                            32,0x55};                                                   //0x20-0x21  
        iic_init();                                         //总线初始化  
        //AT24C02_writeByte(0x08,0x11);             //向指定地址处写入一个字节数据,代码测试  
        AT24C02_writeData(0x00,sizeof(arr),arr);    //向指定地址处开始写入34字节的数据  
        AT24C02_readData(0x20,sizeof(buf),buf);   //从指定地址开始读2个字节  
        P1=buf[1];  //buf中的第二个元素就是arr中的最后一个数据0x55  
                                                  
        while(1){P1=~P1;delayms(500);} //将这个0x55用led灯显示出来10101010变化  
    }  

    For your reference.

  • 相关阅读:
    POJ 3253 Fence Repair
    POJ 2431 Expedition
    NYOJ 269 VF
    NYOJ 456 邮票分你一半
    划分数问题 DP
    HDU 1253 胜利大逃亡
    NYOJ 294 Bot Trust
    NYOJ 36 最长公共子序列
    HDU 1555 How many days?
    01背包 (大数据)
  • 原文地址:https://www.cnblogs.com/lumao1122-Milolu/p/14012885.html
Copyright © 2011-2022 走看看