• 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.

  • 相关阅读:
    记一次坑爹的jconsole使用
    触发Full GC的时机
    java NIO之Selector
    java NIO之SelectedKey
    java泛型中的各种限制
    filebeat安装部署
    Kibana安装及简单使用
    elastucasearch基础理论以及安装
    Salt 与Salt API配置
    RabbitMQ 相关理论部分
  • 原文地址:https://www.cnblogs.com/lumao1122-Milolu/p/14012885.html
Copyright © 2020-2023  润新知