<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        簡易12684液晶和Atmega32的電子萬年歷

        作者:未知   來源:本站原創   點擊數:  更新時間:2014年04月01日   【字體:

        //端口配置是這樣的:液晶的DB0-DB7數據口連接在單片機的PA口。

        //液晶直接定義成并口方式,所以也就的PSB直接接高電平,低電平是串行方式。

        //頭文件包含
        #include <avr/io.h>        //io端口寄存器配置文件,必須包含
        #include <util/delay.h>       //GCC中的延時函數頭文件
        #include <string.h>
        //端口位定義
        #define RS PC2          //數據/命令控制端 0命令,1數據
        #define RW PC1           //讀/寫選擇控制端 0寫,1讀
        #define E PC0            //使能端          下降沿讀,高電平寫
        //#define PSB PC7          //數據傳輸方式選擇端,H,8位或4位并口方式;L,串口方式

        //常量聲明
        #define BAUD 115200
        #define TURE 1
        #define FALSE 0
        //時鐘/日歷寄存器
        #define RD    0x01         //讀
        #define WR    0x00         //寫
        #define SECOND  0x80 //秒
        #define MINUTE  0x82 //分
        #define HOUR  0x84 //時
        #define DAY   0x86 //日
        #define MONTH  0x88 //月
        #define WEEK  0x8A //星期 DATE
        #define YEAR  0x8C //年
        #define WR_PROTECT 0x8E //控制(寫保護)
        #define CHARGE     0x90 //涓流充電
        #define BURST  0xBE //時鐘多字節
        //配置位
        #define CLK_HALT  0x80 //停止時鐘控制位    SECOND bit7
        #define CLK_START  0x00 //啟動時鐘
        #define M12_24   0x80 //12/24小時值選擇位 HOUR  bit7
        #define PROTECT   0x80 //寫保護控制位      CONTROL bit7
        #define UPROTECT  0x00 //寫保護控制位      CONTROL bit7
        //涓流充電控制常量
        #define TC_D1R2   0xA5 //充電時選擇一個二極管和2K電阻
        #define TC_D2R8   0xAB //充電時選擇二個二極管和8K電阻 
        #define TC_DISABLED  0x00 //禁止充電功能
        //RAM 命令
        #define RAMBASE  0xC0 //RAM起始位為0XCO,RAM范圍0-31

        //全局變量聲明
        unsigned char Get_Time[7] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00};

        //全局變量聲明
        unsigned char logo[]="==小電子萬年歷==";

        //函數聲明
        void Delayus(unsigned int lus);         //us延時函數
        void Delayms(unsigned int lms);        //ms延時函數
        unsigned char DS1302_ReadByte(void);         //從DS1302讀一個字節數據
        void DS1302_WriteByte(unsigned char dat);    //向DS1302寫一個字節數據
        unsigned char DS1302_ReadData(unsigned addr); //從DS1302的指定地址讀一個字節數據
        void DS1302_WriteData(unsigned char addr,unsigned data);
                                                         //向DS1302的指定地址寫一個字節數據
        void DS1302_SetTime(unsigned char *time);  //對DS1302設置時間
        void DS1302_GetTime(void);   //從DS1302讀取時間
        unsigned char DS1302_Check(void);           //DS1302是否工作檢測
        void DS1302_Init(void);                      //DS1302初始化
        void DS1302_DisCharge(void); //關閉涓流充電
        unsigned char DS1302_Alarm(unsigned char hour,unsigned char min); //鬧鈴
        void System_Beep(void);

        void Port_Init(void);   //端口初始化
        void LCD_Init(void);    //LCD初始化
        void Write_Com(unsigned char LCD_Com);   //LCD寫指令
        void Write_Data(unsigned char LCD_Data);  //LCD寫數據
        void Check_Busy(void);   //讀寫檢測函數,每次對液晶操作前都要進行讀寫檢測
        void Put_CHS_String(unsigned char x,unsigned char y,char *STR);

        int main(void)          
        {
         unsigned char Disp_Number;
         char str_time[64];
         unsigned char Set_Time[7] = {0x30,0x57,0x20,0x12,0x04,0x01,0x10};
                                       //設置秒,分,時,日,月,星期,年
         char chs_week[7][6]={"星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
         _delay_ms(200);

         Port_Init();   //端口初始化
         LCD_Init();    //LCD初始化

         DS1302_DisCharge();
         DS1302_GetTime();
         if(Get_Time[2] == 0x00)
          DS1302_SetTime(Set_Time);

         Put_CHS_String(0,0,logo);
         DS1302_GetTime();
         
         Put_CHS_String(0,1,"現在時間:");
         while(1)
         {
          sprintf(str_time,"20%01x%01x年%01x%01x月%01x%01x日",Get_Time[6] / 16,Get_Time[6] % 16
                             ,Get_Time[4] / 16,Get_Time[4] % 16
                             ,Get_Time[3] / 16,Get_Time[3] % 16 );
          Put_CHS_String(0,2,str_time);
         
          sprintf(str_time,"星期%01x %01x%01x:%01x%01x:%01x%01x",Get_Time[5] % 16       
                          ,Get_Time[2] / 16,Get_Time[2] % 16
                             ,Get_Time[1] / 16,Get_Time[1] % 16
                             ,Get_Time[0] / 16,Get_Time[0] % 16 );
          Put_CHS_String(0,3,str_time);
         
          DS1302_GetTime();
          _delay_ms(500);
         
         }

        }

        void Port_Init()
        {    
         //LCD數據端口設置
         PORTA = 0X00;         //
         DDRA = 0XFF;           //配置端口PA全部為輸出口,LCD數據端口
         
         PORTD = 0X00;
         DDRD |= 1<<PD6;
         PORTD |= 1<<PD6;
         
         //LCD控制端口設置
         PORTC = 0X00;         //
         DDRC |= (1 << RS) | (1 << RW) | (1 << E);

         PORTB = 0XFF;
         DDRB |= (1 << PB1) | (1 << PB0); //DS1302的IO和SCLK引腳設為輸出
         DDRB |= (1 << PB2);                //DS1302的RST引腳設為輸出

        }

        void LCD_Init()
        {
         Write_Com(0X01);  //清屏
         _delay_us(5);
         Write_Com(0X38);  //顯示模式設置 16x2顯示,5x7點陣,8位數據接口
         _delay_us(5);
         //Write_Com(0X0f);  //顯示開關控制,開顯示,光標顯示,光標閃爍
         Write_Com(0X0c);  //顯示開關控制,開顯示,光標不顯示,光標不閃爍
         _delay_us(5);
         Write_Com(0X06);  //光標設置,讀或寫一個字符后,地址指針加一,光標加一,整屏不移動
         _delay_us(5);
        }

        void Write_Com(unsigned char LCD_Com)
        {
         Check_Busy();
         
         PORTC &= ~(1 << RS);     //RS=0,寫命令
         PORTC &= ~(1 << RW);     //RW=0,寫指令
         PORTC |= (1 << E);       //E=1,寫操作
         _delay_us(5);
         PORTA = LCD_Com;         //指令送數據端口
         PORTC &= ~(1 << E);     //E=0,停止寫操作
         _delay_us(5);
         
        }

        void Write_Data(unsigned char LCD_Data)
        {
         Check_Busy();

         PORTC |= (1 << RS);      //RS=1,寫數據
         PORTC &= ~(1 << RW);    //RW=0,寫指令
         PORTC |= (1 << E);      //E=1,寫操作
         _delay_us(5);
         PORTA = LCD_Data;        // 數據送數據端口 
         PORTC &= ~(1 << E);    //E=0,停止寫操作
         _delay_us(5);
         
        }

        void Check_Busy()
        {
           
         DDRA = 0X00;             //PA口置為輸入口,準備讀取數據
         PORTC &= ~(1 << RS);      //RS=0,讀命令
         PORTC |= (1 << RW);    //RW=1,讀指令
         PORTC |= (1 << E);      //E=1,使能
         
         while(0X80 & PINA);   //監測忙信號,直到忙信號為0,才能進行讀寫操作
         PORTC &= ~(1 << E);   //E=0
         DDRA = 0XFF;          //PA口置為輸出口,準備向端口發送數據
        }

        void Put_CHS_String(unsigned char x,unsigned char y,char *STR)
        {
         unsigned char Disp_Number;
         switch(y)
         {
          case 0:
           Write_Com(0X80+x);
           break;
          case 1:
           Write_Com(0X90+x);
           break;
          case 2:
           Write_Com(0X88+x);
           break;
          case 3:
           Write_Com(0X98+x);
           break;
          default:
           break;
         }
         for(Disp_Number = 0;Disp_Number < strlen(STR);Disp_Number++)
         {
          Write_Data(STR[Disp_Number]);
          _delay_us(5);
         }
        }

        /************************************************************************/

        //從DS1302讀一個字節數據
        unsigned char DS1302_ReadByte(void)       
        {
         unsigned char i,dat = 0;  //dat存放讀出的數據,初始化為0
         PORTB &= ~(1 << PB1);     //DS1302的I/O口上拉不使能,
         DDRB &= ~(1 << PB1);      //DS1302的I/O口設置為輸入口,準備讀數據
         
         for(i = 0;i < 8;i++)     //讀8位,低位在前,右移
         {
          dat >>= 1;           //讀出的數據右移一位
          PORTB |= (1 << PB0);  //DS1302的SCLK端口拉高
          Delayus(10);          //
          PORTB &= ~(1 << PB0);  //DS1302的SCLK端口拉低,產生下降沿,
          Delayus(10);
          if(PINB & (1 << PB1))     //讀數據端口狀態
          {
           dat |= 0x80;          //如果數據端口位高,相應數據位置1
          }
         }
         DDRB |= (1 << PB1);   //最后將數據端口設置為輸出
            return dat;     //返回讀出的數據
        }

        //向DS1302寫一個字節數據
        void DS1302_WriteByte(unsigned char dat)  
        {
         unsigned char i;
         
         for(i = 0;i < 8;i++)      //寫8位,低位在前
         {
          PORTB &= ~(1 << PB0);  //DS1302的SCLK置低
          if(dat & 0x01)        //寫數據位
          {
           PORTB |= (1 << PB1);   //如果該位為1,則I/O口置高
          }
          else
          {
           PORTB &= ~(1 << PB1);   //如果該位為0,則I/O口置低
          }
          Delayus(10);          //
          PORTB |= (1 << PB0);   //DS1302的SCLK置高,產生上升沿
          dat >>= 1;               //數據右移1位
         }
        }

        //從DS1302的指定地址讀一個字節數據
        unsigned char DS1302_ReadData(unsigned addr)
        {
         unsigned char data;
         
         PORTB &= ~(1 << PB2); //拉低片選端
         PORTB &= ~(1 << PB0);//拉低時鐘端
         Delayus(10);
         PORTB |= (1 << PB2);//拉高片選端
         Delayus(10);
         DS1302_WriteByte(addr);//寫入操作命令(地址)
         Delayus(10);
         data = DS1302_ReadByte();//讀出數據
         Delayus(10);
         PORTB &= ~(1 << PB0);  //拉低時鐘端
         PORTB &= ~(1 << PB2); //拉低片選端
         
         return data;
        }

        //向DS1302的指定地址寫一個字節數據
        void DS1302_WriteData(unsigned char addr,unsigned data)
        {
         PORTB &= ~(1 << PB2); //拉低片選端
         PORTB &= ~(1 << PB0);//拉低時鐘端
         Delayus(10);
         PORTB |= (1 << PB2);//拉高片選端
         Delayus(10);
         DS1302_WriteByte(addr);//寫入操作命令(地址)
         Delayus(10);
         PORTB &= ~(1 << PB0);//拉低時鐘端
         Delayus(10);
         DS1302_WriteByte(data);//寫入數據
         PORTB &= ~(1 << PB0);  //拉低時鐘端

         Delayus(10);
         PORTB &= ~(1 << PB2); //拉低片選端
        }

        //對DS1302設置時間          
        void DS1302_SetTime(unsigned char *time)
        {
         unsigned char i;
         unsigned char addr = 0x80;//寫入地址從秒寄存器開始
         
         DS1302_WriteData(WR_PROTECT | WR,UPROTECT);//控制命令,WP位為0,允許寫操作
         Delayms(5);
         for(i = 0;i < 7;i++)
         {
          DS1302_WriteData(addr | WR,time[i]);// 秒 分 時 日 月 星期年 
          addr += 2;
          Delayms(1);
         }
         DS1302_WriteData(WR_PROTECT | WR,PROTECT);//控制命令,WP位為1,不允許寫操作  
        }

        //從DS1302讀取時間
        void DS1302_GetTime(void) 
        {
         unsigned char i;
         PORTB &= ~(1 << PB2);
         Delayus(10);
         PORTB |= (1 << PB2);
         Delayus(10);
         DS1302_WriteByte(0xbf);
         for(i = 0;i < 8;i++)
         {
          Get_Time[i] = DS1302_ReadByte();
         }
         PORTB &= ~(1 << PB2);
         PORTB &= ~(1 << PB0);
        }

        //DS1302是否工作檢測
        unsigned char DS1302_Check(void)         
        {
         DS1302_WriteData(WR_PROTECT | WR,UPROTECT);
         DS1302_WriteData(RAMBASE | WR,0x31);
         
         if(DS1302_ReadData(RAMBASE | WR) == 0x31)
         {
          return TURE;
         }
         else
         {
          return FALSE;
         }
        }

        void DS1302_DisCharge(void)
        {
         DS1302_WriteData(CHARGE|WR,TC_DISABLED);
         Delayus(10);
        }

        unsigned char DS1302_Alarm(unsigned char hour,unsigned char min)
        {

        }

        void System_Beep(void)
        {

        }

        //DS1302初始化
        void DS1302_Init(void)
        {
         DS1302_WriteData(WR_PROTECT | WR,UPROTECT);   //寫入寫允許命令
         DS1302_WriteData(SECOND | WR,CLK_START);      //啟動振蕩器,DS1302開始工作
         DS1302_WriteData( WR_PROTECT | WR,PROTECT);     //控制命令,WP位為1,不允許寫操作  
        }


        //us級別的延時函數
        void Delayus(unsigned int lus)
        {
         while(lus--)
         {
          _delay_loop_2(3);      //_delay_loop_2(1)是延時4個時鐘周期,參數為3則延時12
                     //個時鐘周期,本實驗用12M晶體,則12個時鐘周期為12/12=1us
            }
        }

        //ms級別的延時函數
        void Delayms(unsigned int lms)
        {
         while(lms--)
         {
          Delayus(800);        //延時1ms
            }
        }

        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮