新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > I2C讀寫心得(DS1307)

        I2C讀寫心得(DS1307)

        作者: 時間:2017-06-04 來源:網(wǎng)絡 收藏
        由于是個初學者,對從來沒有接觸過,看了幾遍規(guī)則后,有了點了解,覺的在這樣IO口資源不是相對充足的芯片上,來擴展總線接口,I2C是最好的選擇了,他只占用的兩個IO口,還可以將不同和相同的I2C器件掛接在相同的總線上,
        但好的東西,簡潔的東西,操作起來不是那么簡單的,因為他只有兩根線,SDA和SCL,所有的讀寫都要通過這兩根線的不同電平來控制,看了幾遍總線規(guī)則,對他的讀寫時序還是不懂.最叫人郁悶的是對AT24C02的讀寫,我寫了一個晚上的程序,竟然讀不出來,時序什么好像都沒有錯,到現(xiàn)在我還是不知道什么原因,后來換了一個DS1307來試,還好這次可以了,對DS1307的讀寫,當每次向寫時,要等待從器件的應答位,我在這里就是這樣處理,用時間的延遲來代替對應答位的檢測,實踐證明這樣完全是可以的
        #include reg51.h>
        #include intrins.h>
        /*********************************LCD定義部分********************************/
        //輸入方式設置
        #define LCD_AC_AUTO_INCREMENT 0x06 //數(shù)據(jù)讀、寫操作后,AC自動增一
        #define LCD_AC_AUTO_DECREASE 0x04 //數(shù)據(jù)讀、寫操作后,AC自動減一
        #define LCD_MOVE_ENABLE 0x05 //數(shù)據(jù)讀、寫操作,畫面平移
        #define LCD_MOVE_DISENABLE 0x04 //數(shù)據(jù)讀、寫操作,畫面不動
        #define LCD_GO_HOME 0x02 //AC=0,光標、畫面回HOME位
        //設置顯示、光標及閃爍開、關(guān)
        #define LCD_DISPLAY_ON 0x0C //顯示開
        #define LCD_DISPLAY_OFF 0x08 //顯示關(guān)
        #define LCD_CURSOR_ON 0x0A //光標顯示
        #define LCD_CURSOR_OFF 0x08 //光標不顯示
        #define LCD_CURSOR_BLINK_ON 0x09 //光標閃爍
        #define LCD_CURSOR_BLINK_OFF 0x08 //光標不閃爍
        //光標、畫面移動,不影響DDRAM
        #define LCD_LEFT_MOVE 0x18 //LCD顯示左移一位
        #define LCD_RIGHT_MOVE 0x1C //LCD顯示右移一位
        #define LCD_CURSOR_LEFT_MOVE 0x10 //光標左移一位
        #define LCD_CURSOR_RIGHT_MOVE 0x14 //光標右移一位
        //工作方式設置
        #define LCD_DISPLAY_DOUBLE_LINE 0x38 //兩行顯示
        #define LCD_DISPLAY_SINGLE_LINE 0x30 //單行顯示
        #define LCD_CLEAR_SCREEN 0X01 //清屏
        /***********************LCD1602地址相關(guān)******************************/
        #define LINE1_HEAD 0x80 // 第一行DDRAM起始地址
        #define LINE2_HEAD 0xc0 // 第二行DDRAM起始地址
        #define LINE1 0 //第一行
        #define LINE2 1 //第二行
        #define LINE_LENGTH 16 //每行的最大字符長度
        /***********************LCD1602接線引腳定義**************************
        **********************可根據(jù)實際電路改變*******************************/
        #define LCDIO P2 //定義P2口與LCD1602的數(shù)據(jù)口相接
        sbit LCD_RS=P1^4;
        sbit LCD_RW=P1^3;
        sbit LCD_EN=P1^2;
        sbit LCD_BUSY=LCDIO^7;
        /**********************另外相關(guān)的定義*********************************/
        #define HIGH 1
        #define LOW 0
        #define TURE 1
        #define FALSE 0
        #define uchar unsigned char
        #define uint unsigned int

        /*************************以下是函數(shù)的申明部分*************************/
        void LCD_init(void); //LCD1602初始化
        void LCD_send_command(uchar command); //
        void LCD_send_data(uchar dat);
        void LCD_write_char(uchar x,uchar y,uchar dat);
        void LCD_write_string(uchar x,uchar y,char *Data);
        void delay_ms(uint n);
        void LCD_check_busy(void);
        /*********************結(jié)束***********************************************/
        /***************************DS1307開始*****************************************************************/
        #define Wait1us _nop_();
        #define Wait2us {_nop_();_nop_();}
        #define Wait4us {Wait2us;Wait2us;}
        #define Wait8us {Wait4us;Wait4us;}
        #define Wait10us {Wait8us;Wait2us;}
        #define WRITEDS1307 0xD0
        #define READDS1307 0xD1
        sbit SDA=P2^7; //DS1307 Serial-Data Input pin 5
        sbit SCL=P2^6; //DS1307 Serial-Clock Input pin 6
        /************************************************************/
        void I2C_start(void);//I2C start function
        void I2C_stop(void);//I2C stop function
        //void I2C_send_ack(void);//I2C send responsion function
        void I2C_send_noack(void);
        void I2C_write_byte(unsigned char IIC_data);//I2C bus write byte function
        unsigned char I2C_read_byte(void);//I2C bus read byte function
        /***********************************************************************/
        void Write1307(unsigned char add,unsigned char dat);//write information to ds1307
        unsigned char Read1307(unsigned char add);//read information from ds1307
        void Read_RTC(void);//read RTC
        void Set_RTC(void);//set RTC
        /***********************************************************************/
        code unsigned char set_rtc_code[7]={0,30,7,4,20,4,6};
        code unsigned char rtc_address[7]={0x00,0x01,0x02,0x03,0x04,0x05,0x06};
        code unsigned char *day[7]={Mon,Tue,Wen,Thu,Fri,Sat,Sun};
        unsigned char read_rtc_code[7];
        /***********************************************************************/
        void Initial(void);//system initize function
        void Display(void);//RTC display function
        /***********************************************************************/
        /***********************************************************************/
        void main(void)
        {
        Initial();
        while(1)
        {
        Read_RTC();
        Display();
        }
        }
        /***********************************************************************/
        void Initial(void)
        {
        LCD_init();
        Set_RTC();
        }
        /***********************************************************************/
        void I2C_start(void)
        {
        SDA=1;
        SCL=1;
        Wait8us;
        SDA=0;
        Wait8us;
        SCL=0;

        }
        /***********************************************************************/
        void I2C_stop(void)
        {
        SDA=0;
        SCL=1;
        Wait8us;
        SDA=1;
        Wait4us;
        SCL=0;
        }
        /***********************************************************************
        void I2C_send_ack(void)
        {
        SDA=0;
        SCL=1;
        Wait4us;
        SCL=0;
        }
        *************************************************************************/
        void I2C_send_noack(void)
        {
        SDA=1;
        SCL=1;
        Wait4us;
        SCL=0;
        }
        /***********************************************************************/
        void I2C_write_byte(unsigned char IIC_data)
        {
        unsigned char i;
        for(i=0;i8;i++)
        {
        SCL=0;
        if((IIC_datai) 0x80)
        SDA=1; //判斷發(fā)送位
        else SDA=0;
        Wait2us;
        SCL=1;
        Wait4us;
        SCL=0;
        }
        Wait4us;
        SDA=1; //發(fā)送完8bit,釋放總線準備接收應答位
        Wait2us;
        SCL=1;
        Wait4us; //sda上數(shù)據(jù)即是從應答位
        SCL=0; //不考慮從應答位 但要控制好時序
        }
        /***********************************************************************/
        unsigned char I2C_read_byte(void)
        {
        unsigned char i,dat;
        dat=0;
        SDA=1;
        for (i=0;i8;i++)
        {
        dat=dat1;
        SCL=1;
        Wait2us;
        if(SDA==1)
        {
        dat++;
        }

        SCL=0;
        }
        return (dat);
        }
        /***********************************************************************/
        /******************************** DS1307 PART START ****************/
        void Write1307(unsigned char add,unsigned char dat)
        {
        I2C_start();
        I2C_write_byte(WRITEDS1307);
        I2C_write_byte(add);
        I2C_write_byte(dat);
        I2C_stop();
        }

        /***********************************************************************/
        unsigned char Read1307(unsigned char add)
        {

        unsigned char dat;
        I2C_start();
        I2C_write_byte(WRITEDS1307);
        I2C_write_byte(add);
        I2C_start();
        I2C_write_byte(READDS1307);
        dat=I2C_read_byte();
        I2C_send_noack();
        I2C_stop();
        return (dat);
        }
        /****************************讀DS1307的寄存器*******************************************/
        void Read_RTC(void)
        {
        unsigned char i,*p;
        p=rtc_address;
        for(i=0;i7;i++)
        {
        read_rtc_code[i]=Read1307(*p);
        p++;
        }
        }
        /***************************DS1307的初始化********************************************/
        void Set_RTC(void)
        {
        unsigned char i,*p;
        p=rtc_address;
        for(i=0;i7;i++)
        {
        Write1307(*p,set_rtc_code[i]);
        p++;
        }
        }
        /******************** OTHER PART ******************************/
        void Display(void)
        {
        LCD_write_char(0x0f,LINE2,(read_rtc_code[0]%10) 0x30);
        LCD_write_char(0x0e,LINE2,(read_rtc_code[0]/10) 0x30);
        LCD_write_char(0x0c,LINE2,(read_rtc_code[1]%10) 0x30);
        LCD_write_char(0x0b,LINE2,(read_rtc_code[1]/10) 0x30);
        LCD_write_char(0x09,LINE2,(read_rtc_code[2]%10) 0x30);
        LCD_write_char(0x08,LINE2,(read_rtc_code[2]/10) 0x30);
        LCD_write_char(0x09,LINE1,(read_rtc_code[4]%10) 0x30);
        LCD_write_char(0x08,LINE1,(read_rtc_code[4]/10) 0x30);
        LCD_write_char(0x06,LINE1,(read_rtc_code[5]%10) 0x30);
        LCD_write_char(0x05,LINE1,(read_rtc_code[5]/10) 0x30);
        LCD_write_char(0x03,LINE1,(read_rtc_code[6]%10) 0x30);
        LCD_write_char(0x02,LINE1,(read_rtc_code[6]/10) 0x30);

        LCD_write_string(0x0d,LINE1,day[read_rtc_code[3]-1]);
        LCD_write_string(0x0d,LINE2,:);
        LCD_write_string(0x0a,LINE2,:);
        LCD_write_string(0x07,LINE1,-);
        LCD_write_string(0x04,LINE1,-);
        LCD_write_string(0x00,LINE1,20);
        }
        /*********************************************************/
        /**************LCD1602的初始化***************************/
        void LCD_init(void)
        {
        LCD_send_command(LCD_DISPLAY_DOUBLE_LINE);
        LCD_send_command(LCD_AC_AUTO_INCREMENT LCD_MOVE_DISENABLE);
        LCD_send_command(LCD_DISPLAY_ON LCD_CURSOR_OFF);
        LCD_send_command(LCD_CLEAR_SCREEN);
        }
        /***********************檢測LCD狀態(tài)*********************************/

        void LCD_check_busy(void)
        {
        do
        {
        LCD_EN=0;
        LCD_RS=0;
        LCD_RW=1;
        LCDIO=0xff;
        LCD_EN=1;
        }
        while(LCD_BUSY==1);

        LCD_EN=0;
        }
        /************LCD1602寫命令*******************************/
        void LCD_send_command(uchar command)
        {
        LCD_check_busy();
        LCD_RS=LOW;
        LCD_RW=LOW;
        LCD_EN=HIGH;
        LCDIO=command;
        LCD_EN=LOW;
        }
        /********************************************************/
        /*****************LCD1602寫數(shù)據(jù)**************************/
        void LCD_send_data(uchar dat)
        {
        LCD_check_busy();
        LCD_RS=HIGH;
        LCD_RW=LOW;
        LCD_EN=HIGH;
        LCDIO=dat;
        LCD_EN=LOW;
        }
        /***********************LCD1602顯示字符*********************************/
        void LCD_write_char(uchar x,uchar y,uchar dat)
        {
        unsigned char address;
        if (y == LINE1)
        address = LINE1_HEAD + x;
        else
        address = LINE2_HEAD + x;
        LCD_send_command(address);
        LCD_send_data(dat);
        }
        /******************LCD1602顯示字符串*********************/
        void LCD_write_string(uchar x,uchar y,uchar *Data)
        {
        if(y==LINE1)
        {
        if(xLINE_LENGTH)
        {
        LCD_send_command(LINE1_HEAD+x);
        for(;xLINE_LENGTH*Data!='' 主站蜘蛛池模板: 定南县| 泸水县| 沅陵县| 石河子市| 尚义县| 吴江市| 周宁县| 朝阳县| 阳春市| 汾西县| 定南县| 岳西县| 资中县| 宣威市| 吴旗县| 新营市| 石嘴山市| 治多县| 会泽县| 若尔盖县| 津南区| 瑞丽市| 双峰县| 石楼县| 嘉义县| 津市市| 万载县| 马边| 屏山县| 绍兴县| 兰州市| 平度市| 汉中市| 赣州市| 湄潭县| 呼伦贝尔市| 博客| 杂多县| 宁蒗| 克什克腾旗| 江北区|