新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > AVR單片機IO仿真I2C

        AVR單片機IO仿真I2C

        作者: 時間:2016-11-18 來源:網絡 收藏
        #include

        #define EEP_PORT PORTC //定義是使用PROTC口
        #define EEP_DDR DDRC //定義是使用PROTC口
        #define SDA 0X10 //定義sda連接的是portd1
        #define SCL 0X20 //定義scl連接的是portd0
        //#define WP 0X04 //定義wp連接的是portd2
        #define EEP_ADD_R 0xa1 //寫I2C從器件地址和讀方式 a0,a1接地
        #define EEP_ADD_W 0xa0 //寫I2C從器件地址和寫方式 a0,a1接地

        本文引用地址:http://www.104case.com/article/201611/315599.htm

        void delay(unsigned int us)
        {
        while(us--);
        }

        void eep_init(void)
        {
        EEP_DDR|= SDA | SCL ;//| WP ;
        EEP_PORT|=SDA | SCL ;//| WP ;
        }

        void send(void)
        {
        EEP_PORT|=SCL;
        asm("nop");
        EEP_PORT&=~SCL;
        }
        /********************************************
        內部函數,I2C開始
        ********************************************/
        void Start(void)
        {
        EEP_PORT|=SDA; //sda
        EEP_PORT|=SCL; //scl
        asm("nop");
        EEP_PORT&=~SDA;
        asm("nop");
        EEP_PORT&=~SCL;
        }
        /********************************************
        內部函數,I2C結束
        ********************************************/
        void Stop(void)
        {
        EEP_PORT&=~SDA;
        EEP_PORT&=~SCL;
        asm("nop");
        EEP_PORT|=SCL;
        asm("nop");
        EEP_PORT|=SDA;
        asm("nop");
        }

        /********************************************
        內部函數,等待ACK
        ********************************************/
        void ACK(void)
        {

        unsigned char errtime=20;
        EEP_PORT|=SDA; //上拉
        EEP_DDR&=~SDA; //設置為輸入口
        EEP_PORT|=SCL;
        asm("nop");
        while(PINC&SDA)
        { errtime--;
        if(!errtime)
        {
        Stop();
        EEP_PORT&=~SDA; //超時,給他個離開的理由
        }
        }
        EEP_PORT&=~SCL;
        asm("nop");
        EEP_DDR|=SDA; //設置為輸出口
        }
        /********************************************
        內部函數.輸出數據字節
        ********************************************/
        void writebyte(unsigned char wdata)
        {
        unsigned char i;
        for(i=0;i<8;i++)
        {
        if((wdata&0x80)){EEP_PORT|=SDA;}else{EEP_PORT&=~SDA;}
        wdata<<=1;
        send(); //發送一個位

        }
        }
        /********************************************
        內部函數.輸入數據
        ********************************************/
        unsigned char Readbyte(void)
        {
        unsigned char i,bytedata;
        EEP_DDR&=~SDA; //設置為輸入?
        for(i=0;i<8;i++)
        {
        EEP_PORT|=SCL;
        bytedata<<=1;
        if(PINC&SDA){
        bytedata|=0X01;
        }else{
        bytedata&=~0X01;
        }
        EEP_PORT&=~SCL;
        asm("nop");
        }
        EEP_DDR|=SDA;
        return(bytedata);

        }

        /********************讀24cxx--外部調用********************/
        unsigned char read_eep(unsigned char add1,unsigned char add2)
        { unsigned char mdata;
        Start(); //起始位
        writebyte(EEP_ADD_W); //寫eeprom地址+1個寫命令
        ACK(); //等待應答信號
        writebyte(add1); //寫如訪問地址
        ACK(); //等待應答信號
        writebyte(add2); //寫入訪問地址
        ACK(); //等待應答信號
        Start(); //起始位
        writebyte(EEP_ADD_R); //寫eeprom地址+1個讀命令
        ACK(); //等待應答信號
        mdata=Readbyte(); //獲取數據
        Stop(); //發送停止位置
        asm("nop"); //此處延時根據實際情況,如果不延時,可能會不正常
        return(mdata);
        }
        /********************寫24cxx--外部調用********************/
        void write_eep(unsigned char add1,unsigned char add2,unsigned char udata)
        {
        //EEP_PORT&=~WP; //關閉寫保護
        Start(); //起始位
        writebyte(EEP_ADD_W); //寫eeprom地址+1個寫命令
        ACK(); //等待應答信號
        writebyte(add1); //寫如訪問地址
        ACK(); //等待應答信號
        writebyte(add2); //寫如訪問地址
        ACK(); //等待應答信號
        writebyte(udata); //寫入數據
        ACK(); //等待應答信號
        Stop(); //發送停止位
        delay(24000);
        //delay_nms(4); //此處延時根據實際情況,大多EEPROM都需要3毫秒的寫入時間,如果不延時,可能會不正常
        //EEP_PORT|=WP; //打開寫保護
        }

        void main(void)
        {
        unsigned char tmp;
        eep_init();
        DDRC|=(1<<0);
        PORTC&=~(1<<0);
        write_eep(0,2,7);
        tmp=read_eep(0,2);
        if(tmp==7)
        PORTC|=(1<<0);
        while(1);
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 济阳县| 嘉义县| 凤城市| 乐平市| 依兰县| 定南县| 博客| 开远市| 六盘水市| 高淳县| 长沙市| 双峰县| 边坝县| 高台县| 湾仔区| 大城县| 河间市| 朝阳区| 蒲城县| 邵阳县| 同江市| 麻阳| 三门峡市| 雷州市| 曲沃县| 尉犁县| 明光市| 固原市| 富宁县| 土默特左旗| 洛隆县| 琼海市| 大连市| 凤凰县| 米林县| 阜新| 怀仁县| 偃师市| 马山县| 城口县| 大渡口区|