• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > LCD1602-DS1302時鐘程序

    LCD1602-DS1302時鐘程序

    作者: 時間:2012-08-24 來源:網絡 收藏
    //
    #include stc89c52.h>
    #include intrins.h>
    #define uchar unsigned char
    #define uint unsigned int

    /********************************************************************/
    //少占魚制作 河北正定歡迎您 長沙航空職業技術學院
    //2010 年QQ:411656434
    //版權所有:www.51hei.com
    #define _RS P2_5 //定義引腳
    #define _RW P2_6
    #define _E P2_7
    #define LCD1602_IO P0

    #define Busy 0x80 //用于檢測LCD1602狀態字中的Busy標識

    const uchar num[]=" 3456789+";
    uchar code a[] = {" E N v"};
    void WriteData(uchar DAT);
    void WriteCommand(uchar command,BuysC);
    uchar ReadData(void);
    void Readbusy(void);
    void LCD1602_Init(void);
    void DisplayOneChar(uchar X, uchar Y, uchar DData);
    void Displaystring(uchar X, uchar Y, uchar *DData);
    void Delay5Ms(void);
    void Delay400Ms(void);
    void delayms(uint);
    void delays(uint m) ;
    void delayus(uchar x) ;
    sbit _CLK =P2^0;// P1^0;
    sbit _IO =P2^1;// P1^1;
    sbit DS1302_RST =P2^2;// P1^2;

    uchar shuju;
    unsigned char time[]={0x11,0x03,0x28,0x01,0x12,0x39,0x00};// 初始化時間年月日星期時分秒
    uchar Display_Buffer[12]={"12:25:00"};//時、分、秒 的格式
    uchar riqi[12]={"11-03-28"};//年、月、日 的格式
    uchar xingqi[5]="week";//星期
    unsigned char second,minute,hour,week,day,month,year;
    /******************1602函數********************************/

    /********************************************************************/
    void delays(uint m)
    {
    uint i,j;
    for(i=0;im;i++)
    {
    for(j=0;j1000;j++)
    {;}
    }
    }


    void Delay(void)
    {
    unsigned char i;
    unsigned int j;
    for(i=0;i200;i++)
    for(j=300;j>0;j--);
    }

    /******************************************************
    函數功能:向DS1302送一字節數據子程序
    入口參數:
    出口參數:
    **********************************************************/
    void InputByte(unsigned char BYTE)
    {
    char i;
    for(i=8;i>0;i--)
    { //前面在read_ds1302()函數里已經把CLK清0了
    DS1302_CLK=0;//這里再清0一次,看著清楚。呵呵
    _nop_();
    DS1302_IO=(bit)(BYTE0x01);//取出低位數據給數據引腳
    _nop_();
    _nop_();
    DS1302_CLK=1;//置1,時鐘上升沿,引腳上的數據傳入1302寄存器中
    _nop_();
    _nop_();
    BYTE>>=1;//因為這里移位的BYTE不是最后要的結果,雖然最后循環完會多移一位,但沒影響。
    _nop_();
    //循環最后一次后,時鐘狀態是高電平。
    }
    _nop_();
    _nop_();
    }

    /**************************************************************
    函數功能:讀DS1302一個字節子程序,讀數據是下降沿讀
    入口參數:
    出口參數:
    *******************************************************/
    unsigned char OutputByte(void)
    {
    unsigned char i;
    unsigned char ucdat=0;
    for(i=8;i>0;i--)
    { //前面時鐘狀態是高電平。
    ucdat>>=1; //移位注意,移位不能放在循環語句末,否則最后循環完會多移一位。得到結果就錯了。
    DS1302_IO=1;//單片機端置高防止破壞1302傳來的數據,開始接收1302端的高低數據對數據線的改變。
    DS1302_CLK=0;//緊接著時鐘變低,下降沿數據輸出。
    if(DS1302_IO)//數據已經輸出,判斷是1還是0.
    ucdat|=0x80;//如果引腳是高則此位保存1。低不保存,右移的時候自然補0了。
    _nop_();
    DS1302_CLK=1;//讀完一位數據,再置高時鐘,準備讀下一個。
    _nop_();//延時一下。

    }
    //讀完數據還是把時鐘清0,下次好直接用。
    DS1302_CLK=0;//讀完數據還是把時鐘清0,下次好直接用。
    _nop_();
    _nop_();
    DS1302_RST=0;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    DS1302_CLK=0;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    DS1302_RST=0;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    return(ucdat);

    }

    /*****************************************************
    函數功能:向DS1302某地址寫一字節數據子程序
    入口參數:addr,TDat
    出口參數:
    ************************************************/
    void write_ds1302(unsigned char addr,unsigned char TDat)
    {
    DS1302_RST=0;
    _nop_();
    _nop_();
    DS1302_CLK=0;
    _nop_();
    _nop_();
    DS1302_RST=1;
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    InputByte(addr);//先寫地址
    _nop_();
    _nop_();
    InputByte(TDat);//再寫數據
    DS1302_IO=1;//單片機端置高防止破壞1302傳來的數據,開始接收1302端的高低數據對數據線的改變。
    DS1302_RST=0;
    delayus(10);
    DS1302_CLK=0;
    delayus(10);
    }

    /*****************************************************
    函數功能:讀DS1302地址子程序
    入口參數:add
    出口參數:timedata
    *************************************************************/
    unsigned char read_ds1302(unsigned char addr)
    {
    unsigned char timedata;
    DS1302_RST=0;
    _nop_();
    DS1302_CLK=0;
    _nop_();
    DS1302_RST=1;
    InputByte(addr);//先寫入讀命令
    timedata=OutputByte();//再讀出數據
    DS1302_IO=1;//單片機端置高防止破壞1302傳來的數據,開始接收1302端的高低數據對數據線的改變。
    DS1302_RST=0;
    delayus(10);
    DS1302_CLK=0;
    delayus(10);
    return(timedata);
    }

    /***************************************
    函數功能:初始化DS1302子程序
    入口參數:time[](全局變量)
    出口參數:
    *************************************************************/
    void initial_ds1302()
    {
    DS1302_IO=1;//單片機端置高防止破壞1302傳來的數據,開始接收1302端的高低數據對數據線的改變。
    DS1302_RST=0;
    delayms(100);
    DS1302_CLK=0;
    delayms(100);
    write_ds1302(0x8e,0x00); //寫保護寄存器,在對時鐘或RAM寫前WP一定要為0
    write_ds1302(0x8c,time[0]); //年
    write_ds1302(0x88,time[1]); //月
    write_ds1302(0x86,time[2]); //日
    write_ds1302(0x8A,time[3]); //星期
    write_ds1302(0x84,time[4]); //時
    write_ds1302(0x82,time[5]); //分
    write_ds1302(0x80,time[6]); //秒
    write_ds1302(0x8e,0x80); //寫保護寄存器
    }

    /***********************************************
    函數功能:讀DS1302時間子程序
    入口參數:
    出口參數:全局變量(second,minute,hour,week,day,month,year)
    ************************************************************/
    void read_time()
    {
    second=read_ds1302(0x81); //秒寄存器
    _nop_();
    minute=read_ds1302(0x83); //讀分
    _nop_();
    hour=read_ds1302(0x85); //讀時
    _nop_();
    week=read_ds1302(0x8B); //讀星期
    _nop_();
    day=read_ds1302(0x87); //日
    _nop_();
    month=read_ds1302(0x89); //月
    _nop_();
    year=read_ds1302(0x8d); //年
    _nop_();
    }

    void main(void)
    {uchar shuju;
    delayms(2);
    Delay400Ms(); //啟動等待,等LCM講入工作狀態
    delays(1);
    LCD1602_Init(); //LCM初始化
    Delay5Ms(); //延時片刻(可不要)
    DS1302_RST=0;
    delayms(1000);
    DS1302_CLK=0;
    delayms(1000);
    shuju=ReadData();
    Displaystring(2, 0, a);
    Delay();Delay();
    delayms(2000);
    Displaystring(3,0,riqi);
    Displaystring(12,0,xingqi);
    delayms(4000);
    // initial_ds1302(); //初始化DS1302
    delayms(1200);
    while(1)
    {
    read_time();//讀取時間
    Display_Buffer[0]=hour/16+'0';//存儲下時的高位進數組
    Display_Buffer[1]=hour%16+'0';//存儲下時的低位進數組
    Display_Buffer[3]=minute/16+'0';//注意+'0'后存儲的是ASCII。用于下面液晶顯示。
    Display_Buffer[4]=minute%16+'0';//注意+'0'后存儲的是ASCII。用于下面液晶顯示。
    Display_Buffer[6]=second/16+'0';
    Display_Buffer[7]=second%16+'0';
    riqi[0]=year/16+'0';
    riqi[1]=year%16+'0';
    riqi[3]=month/16+'0';
    riqi[4]=month%16+'0';
    riqi[6]=day/16+'0';
    riqi[7]=day%16+'0';
    Displaystring(3,0,riqi);
    delayms(1);
    DisplayOneChar(14,1,week+'0');
    Displaystring(3,1,Display_Buffer);

    }
    }


    //寫數據
    void WriteData(uchar DAT)
    {
    Readbusy();
    LCD1602_RS = 1;
    LCD1602_RW = 0;
    LCD1602_IO = DAT;
    LCD1602_E = 0; //若晶振速度太高可以在這后加小的延時
    LCD1602_E = 0; //延時
    LCD1602_E = 1;
    LCD1602_E=1;
    LCD1602_E=0;
    }

    //寫指令
    void WriteCommand(uchar command,BuysC) //BuysC為0時忽略忙檢測
    {
    LCD1602_IO=0x00;
    if (BuysC)
    Readbusy(); //根據需要檢測忙

    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_IO = command;
    LCD1602_E = 0;
    LCD1602_E = 0;
    LCD1602_E = 1;
    LCD1602_E = 1;
    LCD1602_E=0;
    }

    //讀數據
    uchar ReadData(void)
    {
    Readbusy();
    LCD1602_RS = 1;
    LCD1602_RW = 1;
    LCD1602_E = 0;
    LCD1602_E = 0;
    LCD1602_E = 1;
    delayms(1);
    LCD1602_E = 0;
    return(LCD1602_IO);

    }

    //讀忙
    void Readbusy(void)
    {
    LCD1602_IO = 0xff;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    LCD1602_E = 0;
    LCD1602_E = 0;
    LCD1602_E = 1;
    delayms(2);

    while (LCD1602_IO0x80); //檢測忙信號
    LCD1602_E = 0;
    }
    //初始化
    void LCD1602_Init(void) //LCM初始化
    {
    Delay400Ms();
    LCD1602_E = 0;
    LCD1602_IO=0x00;
    WriteCommand(0x38,0); //三次顯示模式設置,不檢測忙信號
    Delay5Ms();
    WriteCommand(0x38,0);
    Delay5Ms();
    WriteCommand(0x38,0);
    Delay5Ms();

    WriteCommand(0x38,1); //顯示模式設置,開始要求每次檢測忙信號
    Delay5Ms();
    WriteCommand(0x08,1); //關閉顯示 ]
    Delay5Ms();
    WriteCommand(0x01,1); //顯示清屏
    Delay5Ms();
    WriteCommand(0x06,1); // 顯示光標移動設置
    Delay5Ms();
    WriteCommand(0x0f,1); // 顯示開及光標設置
    Delay5Ms();
    }

    //按指定位置顯示一個字符
    void DisplayOneChar(uchar X, uchar Y, uchar DData)
    {
    Y = 0x01;
    X = 0x0f; //限制X不能大于15,Y不能大于1
    if (Y) X |= 0x40; //當要顯示第二行時地址碼+0x40;
    X |= 0x80; // 算出指令碼
    WriteCommand(X, 0); //這里不檢測忙信號,發送地址碼
    WriteData(DData);
    }

    //按指定位置顯示一串字符
    void Displaystring(uchar X, uchar Y, uchar *DData)
    {
    uchar ListLength;

    ListLength = 0;
    Y = 0x01;
    X = 0x0f; //限制X不能大于15,Y不能大于1
    while (DData[ListLength]>0x20) //若到達字串尾則退出
    {
    if (X = 0x0f) //X坐標應小于0x0f
    {
    DisplayOneChar(X, Y, DData[ListLength]); //顯示單個字符
    ListLength++;
    X++;
    }
    }
    }

    //5ms延時
    void Delay5Ms(void)
    {
    unsigned int t = 5552;
    while(t--);
    }

    //400ms延時
    void Delay400Ms(void)
    {
    uchar i = 5;
    uint j;
    while(i--)
    {
    j=7269;
    while(j--);
    }
    }
    //
    void delayms(uint k)
    {
    uint data i,j;
    for(i=0;ik;i++)
    {
    for(j=0;j121;j++)
    {;}
    }
    }
    void delayus(uchar x)
    {
    while(--x);
    }


    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 囊谦县| 阿瓦提县| 黑龙江省| 西畴县| 马尔康县| 乐昌市| 宿州市| 龙南县| 绥宁县| 抚松县| 湖南省| 精河县| 乌兰察布市| 怀化市| 司法| 上思县| 女性| 东源县| 原平市| 伽师县| 宁强县| 莲花县| 西充县| 德保县| 阳春市| 泰顺县| 泸州市| 威海市| 黎城县| 科技| 北流市| 腾冲县| 安乡县| 广宗县| 酒泉市| 建始县| 西藏| 西平县| 新邵县| 兰溪市| 仙游县|