新聞中心

        8051模擬IIC操作EEPROM

        作者: 時(shí)間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
        注:
        本篇內(nèi)容和STM32模擬IIC操作EEPROM思路是一樣的,是一個(gè)程序到不同平臺(tái)的移植。

        首先是EEPROM.h文件內(nèi)容:

        #ifndef _eeprom_h_
        #define _eeprom_h_

        #include //包含頭文件,一般情況不需要改動(dòng),頭文件包含特殊功能寄存器的定義
        #include

        #define EEPROM_ADDRESS 0x57

        sbit SDA = P1^2; //EEPROM的數(shù)據(jù)線
        sbit SCL = P1^1; //EEPROM的時(shí)鐘線
        sbit WP = P1^0; //EEPROM的寫保護(hù),給低電平表示讀寫均允許,也就是標(biāo)準(zhǔn)的模式。

        extern void EEPROM_Init();

        extern unsigned char eeprom_continue_write(unsigned char c_slave_address7bit,unsigned char c_reg_address,
        unsigned char c_continue_write_arr[],unsigned int len);

        extern unsigned char read_eeprom_status(unsigned char c_slave_address7bit);

        extern unsigned char eeprom_continue_read(unsigned char c_slave_address7bit,unsigned char c_reg_address,
        unsigned char c_continue_read_arr[],unsigned int len);

        extern unsigned char EEPROM_Read(unsigned char c_slave_address7bit,unsigned char c_reg_address);

        extern unsigned char EEPROM_Write(unsigned char c_slave_address7bit,unsigned char c_reg_address,unsigned char u_data);

        #endif

        本文引用地址:http://www.104case.com/article/201612/325194.htm
        再個(gè)就是EEPROM.c文件的內(nèi)容:

        #include "eeprom.h"
        #include //頭文件的包含
        #include

        #include "usart.h"


        #define _Nop() _nop_() //定義空指令

        static void EEPROM_Stop( void );

        static void Delay_us(unsigned int i_delay_count)
        {
        int j = 0,i;
        for(j = 0 ; j < 5; j ++)
        for(i = 0 ; i < i_delay_count ; i ++)
        ;
        }

        /*******************************************************************************
        * I2C電路:
        * 單片機(jī) EEPROM
        * P10--------->WP
        * P11--------->SCL
        * P12--------->SDA
        *
        * A0,A1,A2均通過硬件拉高電平
        *
        * 我這里將EEPROM的地址按照如下方式規(guī)劃:
        * 0101 0(A2)(A1)(A0)
        * 因此EEPROM的地址為0x57.
        *
        * copyright by wit_yuan 2016-09-15 at 龍興園北區(qū)
        -------------------------------------------------------------------------------*/
        void EEPROM_Init()
        {
        //將WP設(shè)置為低電平即可
        WP = 0;
        //將IIC總線置高即可
        SCL = 1;
        SDA = 1;
        }

        /*
        *
        * EEPROM_Start():
        * 內(nèi)部函數(shù)
        *
        */
        static void EEPROM_Start()
        {
        SDA=1; //由于上一個(gè)SCL狀態(tài)是0或者是1,要讓SDA穩(wěn)定輸出,都可以設(shè)置為1
        Delay_us(2);

        SCL=1; //讓SCL發(fā)生變化,為0不變,為1則變化,表明數(shù)據(jù)可以變動(dòng)了。
        Delay_us(2);

        SDA=0; //SDA線數(shù)據(jù)變化,從而可以保證發(fā)出的是start信號(hào)。
        Delay_us(2);

        SCL=0; //將I2C總線鉗住,下一個(gè)時(shí)間SDA可以輸出高低電平。
        Delay_us(4);
        }

        /*
        *
        * EEPROM_Send_Byte():
        * 內(nèi)部函數(shù)
        *
        */
        static void EEPROM_Send_Byte( unsigned char txd)
        {
        unsigned char t;
        // SDA_OUT();
        SCL=0;//拉低時(shí)鐘開始數(shù)據(jù)傳輸
        Delay_us(2);
        for(t=0;t<8;t++)
        {
        if((txd&0x80)>>7)
        SDA=1;
        else
        SDA=0;
        txd<<=1;
        Delay_us(2);
        SCL=1;
        Delay_us(2);
        SCL=0;
        Delay_us(2);
        }
        }

        /*
        *
        * EEPROM_Read_Byte():
        * 內(nèi)部函數(shù)
        *
        */
        static unsigned char EEPROM_Read_Byte()
        {
        unsigned char i,u_receive=0;
        // SDA_IN();//SDA設(shè)置為輸入
        for(i=0;i<8;i++ )
        {
        SCL=0;
        Delay_us(4);
        SCL=1;
        Delay_us(1);
        u_receive<<=1;
        if(SDA)
        u_receive++;
        }

        return u_receive;
        }


        /*
        *
        * EEPROM_Ack():
        * 內(nèi)部函數(shù)
        * 2016-09-16 edited for 8051. by wit_yuan
        */
        static void EEPROM_Ack()
        {
        SCL=0;
        Delay_us(2);

        //////add 2016-09-16 by wit_yuan///////////
        SDA = 1;
        Delay_us(1);


        SDA=0;
        Delay_us(1);

        SCL=1;
        Delay_us(1);

        SCL=0;
        Delay_us(4);

        //////add 2016-09-16 by wit_yuan///////////
        SDA = 1;
        Delay_us(1);

        }


        /*
        *
        * EEPROM_Wait_Ack():
        * 內(nèi)部函數(shù)
        *
        */
        static unsigned char EEPROM_Wait_Ack()
        {
        unsigned char ucErrTime=0;

        SCL=0;
        Delay_us(1);

        while(SDA)
        {
        ucErrTime++;
        if(ucErrTime>250)
        {
        EEPROM_Stop();
        return 1; //超時(shí),表明數(shù)據(jù)傳輸有問題
        }
        }
        SCL=1;
        Delay_us(1);


        SCL=0;//時(shí)鐘輸出0
        Delay_us(2);

        return 0;
        }

        /*
        *
        * EEPROM_No_Ack():
        * 內(nèi)部函數(shù)
        *
        */
        static void EEPROM_No_Ack()
        {

        SCL=0;
        Delay_us(2);

        SDA=1;
        Delay_us(1);

        SCL=1;
        Delay_us(1);

        SCL=0;
        Delay_us(4);
        }

        /*
        *
        * EEPROM_Stop():
        * 內(nèi)部函數(shù)
        *
        */
        static void EEPROM_Stop()
        {
        SDA=0; //上一個(gè)狀態(tài)的SCL=0,這個(gè)狀態(tài)設(shè)置SDA=0,目的是讓狀態(tài)能反轉(zhuǎn)
        Delay_us(2);

        SCL=1; //該時(shí)刻設(shè)置SCL=1,然后就可以讓數(shù)據(jù)穩(wěn)定在改狀態(tài)下。
        Delay_us(2);

        SDA=1;
        Delay_us(4);
        }


        unsigned char EEPROM_Write(unsigned char c_slave_address7bit,unsigned char c_reg_address,unsigned char u_data)
        {
        unsigned char u_wait_err = 0;

        EEPROM_Start();
        EEPROM_Send_Byte(c_slave_address7bit << 1);
        u_wait_err |= EEPROM_Wait_Ack();

        EEPROM_Send_Byte(c_reg_address);
        u_wait_err |= EEPROM_Wait_Ack();

        EEPROM_Send_Byte(u_data);
        u_wait_err |= EEPROM_Wait_Ack();

        EEPROM_Stop();

        if( u_wait_err == 0)
        return 0;
        return 1;

        }

        unsigned char EEPROM_Read(unsigned char c_slave_address7bit,unsigned char c_reg_address)
        {
        unsigned char u_temp;
        unsigned char u_wait_err = 0;

        EEPROM_Start();
        EEPROM_Send_Byte(c_slave_address7bit << 1);
        u_wait_err |= EEPROM_Wait_Ack();

        EEPROM_Send_Byte(c_reg_address);
        u_wait_err |= EEPROM_Wait_Ack();

        EEPROM_Start();
        EEPROM_Send_Byte((c_slave_address7bit << 1)+1);
        u_wait_err |= EEPROM_Wait_Ack();

        u_temp = EEPROM_Read_Byte( );
        EEPROM_No_Ack();//不需要響應(yīng)

        EEPROM_Stop();

        return u_temp;

        }


        unsigned char eeprom_continue_read(unsigned char c_slave_address7bit,unsigned char c_reg_address,
        unsigned char c_continue_read_arr[],unsigned int len)
        {
        unsigned char u_wait_err = 0;
        int i = 0;

        EEPROM_Start();
        EEPROM_Send_Byte(c_slave_address7bit << 1);
        u_wait_err |= EEPROM_Wait_Ack();

        EEPROM_Send_Byte(c_reg_address);
        u_wait_err |= EEPROM_Wait_Ack();

        EEPROM_Start();
        EEPROM_Send_Byte((c_slave_address7bit << 1)+1);
        u_wait_err |= EEPROM_Wait_Ack();


        for(i = 0 ; i < len - 1 ; i ++)
        {
        c_continue_read_arr[i] = EEPROM_Read_Byte( );

        EEPROM_Ack();
        }

        c_continue_read_arr[len-1] = EEPROM_Read_Byte( );
        //u_wait_err |= EEPROM_Wait_Ack();
        EEPROM_No_Ack();//不需要響應(yīng)


        EEPROM_Stop();

        if(u_wait_err == 0)
        return 0;
        return 1;
        }


        unsigned char eeprom_continue_write(unsigned char c_slave_address7bit,unsigned char c_reg_address,
        unsigned char c_continue_write_arr[],unsigned int len)
        {
        unsigned int i;
        unsigned int i_err = 0;

        EEPROM_Start();
        EEPROM_Send_Byte(c_slave_address7bit << 1);
        i_err |= EEPROM_Wait_Ack();

        EEPROM_Send_Byte(c_reg_address);
        i_err |= EEPROM_Wait_Ack();

        for( i = 0 ; i < len ; i ++ )
        {
        EEPROM_Send_Byte(c_continue_write_arr[i]);

        i_err |= EEPROM_Wait_Ack();
        }

        EEPROM_Stop();

        if(i_err == 0)
        return 0;

        return 1;
        }




        unsigned char read_eeprom_status(unsigned char c_slave_address7bit)
        {
        unsigned int i = 0;
        int i_ret = 0;

        do
        {
        EEPROM_Start();
        EEPROM_Send_Byte(c_slave_address7bit << 1);

        i_ret = EEPROM_Wait_Ack();

        i ++;
        if(i >= 10000)
        {
        EEPROM_Stop();
        return 1;//表示無響應(yīng)
        }
        }while(i_ret);


        EEPROM_Stop();

        return 0;//表示操作序列結(jié)束
        }

        貼上usart.h文件的內(nèi)容:

        #ifndef _usart_h_
        #define _usart_h_

        #include //包含頭文件,一般情況不需要改動(dòng),頭文件包含特殊功能寄存器的定義
        #include


        extern void UART_Init(void);

        extern void Send_String(unsigned char *u_string);

        extern void Send_UHex(unsigned char u_tx);

        #endif

        然后是usart.c文件的內(nèi)容:

        #include "usart.h"

        /*------------------------------------------------
        串口通訊初始化
        ------------------------------------------------*/
        void UART_Init(void)
        {
        SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
        TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重裝
        TH1 = 0xFD; // TH1: 重裝值 9600 波特率 晶振 11.0592MHz
        TR1 = 1; // TR1: timer 1 打開
        TI = 1;
        }

        /*
        * Send_UChar:
        * 發(fā)送單個(gè)字符
        *
        *
        */
        void Send_UChar(unsigned char u_tx)
        {
        SBUF = u_tx;
        while(!TI);
        TI = 0;
        }

        /*
        * Send_String:
        * 發(fā)送字符串
        *
        *
        */
        void Send_String(unsigned char *u_string)
        {
        while(*u_string)
        {
        Send_UChar(*u_string);
        u_string++;
        }
        }

        void Send_UHex(unsigned char u_tx)
        {
        unsigned char u_high;
        unsigned char u_low;

        u_high = u_tx/16 ;
        u_low = u_tx%16 ;

        if((u_high >= 10) && (u_high <= 15))
        {
        u_high = (u_high - 10) + A;
        }
        else
        {
        u_high = u_high + 0;
        }
        if((u_low >= 10) && (u_low <= 15))
        {
        u_low = (u_low - 10) + A;
        }
        else
        {
        u_low = u_low + 0;
        }
        Send_UChar(u_high);
        Send_UChar(u_low);
        Send_UChar( );
        }


        最后就是main.c文件的內(nèi)容:

        /*-------------------------------------------------------------------------------
        * 名稱:51單片機(jī)控制EEPROM
        * 晶振使用11.0592M
        *
        * I2C電路:
        * 單片機(jī) EEPROM
        * P10--------->WP
        * P11--------->SCL
        * P12--------->SDA
        *
        * A0,A1,A2均通過硬件拉高電平
        *
        * copyright by wit_yuan 2016-09-15 at 龍興園北區(qū)
        -------------------------------------------------------------------------------*/
        #include //包含頭文件,一般情況不需要改動(dòng),頭文件包含特殊功能寄存器的定義
        #include
        #include
        #include "usart.h"

        unsigned char g_c_continue_write[16];
        unsigned char g_c_continue_read_array[16];

        /*------------------------------------------------
        主函數(shù)
        ------------------------------------------------*/
        void main (void)
        {
        unsigned char value,i;



        UART_Init();

        EEPROM_Init();

        Send_String("--------------------app run-----------------n");

        #if 0
        EEPROM_Write(EEPROM_ADDRESS,0,0x02);

        for(i = 0 ; i < 100 ; i ++);
        for(i = 0 ; i < 100 ; i ++);
        for(i = 0 ; i < 100 ; i ++);

        value = EEPROM_Read(EEPROM_ADDRESS,0);

        Send_String("n value :");
        Send_UHex(value);
        Send_String("n ");
        #else

        #if 1
        Send_String("array :n");

        for(i = 0 ; i < 16 ; i ++)
        {
        g_c_continue_write[i] = i + 1;
        Send_UHex(g_c_continue_write[i]);
        }
        Send_String("n");


        Send_String("write array : n");
        value = eeprom_continue_write(EEPROM_ADDRESS,0,g_c_continue_write,16);


        Send_String("read write status : n");
        #if 1
        value = read_eeprom_status(EEPROM_ADDRESS);

        Send_String("n status :");
        Send_UHex(value);
        Send_String("n ");
        #endif
        #endif

        #if 1
        Send_String("read array : n");

        eeprom_continue_read(EEPROM_ADDRESS,0,g_c_continue_read_array,16);

        Send_String("read:n");
        for(i = 0 ; i < 16 ; i ++)
        {
        Send_UHex(g_c_continue_read_array[i]);
        }
        Send_String("n");


        value = EEPROM_Read(EEPROM_ADDRESS,0x0D);

        Send_String("n value :");
        Send_UHex(value);
        Send_String("n ");
        #endif
        #endif

        Send_String("n ----------app end----------------n");
        while (1) //主循環(huán)
        {



        }
        }

        更多的具體講解,就參考stm32模擬IIC操作EEPROM那篇文章吧。



        關(guān)鍵詞: 8051模擬IIC操作EEPRO

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 广德县| 南京市| 友谊县| 棋牌| 兰考县| 富川| 南安市| 筠连县| 甘谷县| 思南县| 宁蒗| 车致| 根河市| 东丰县| 成安县| 浪卡子县| 吐鲁番市| 察隅县| 新泰市| 石狮市| 阿瓦提县| 德阳市| 井冈山市| 垣曲县| 华坪县| 吕梁市| 云阳县| 肃南| 浦江县| 客服| 沭阳县| 中江县| 镇宁| 图们市| 仙桃市| 都匀市| 商南县| 泾川县| 轮台县| 绿春县| 重庆市|