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

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

        avr MEGA16單片機控制DS1302時鐘芯片1602液晶顯示

        作者:肖邦   來源:本站原創   點擊數:  更新時間:2014年03月08日   【字體:
        /*
         
                  程序名(program name) :  時鐘芯片控制程序;

         
                  概述 :  基于本程序的開發板是本人自主研發的YF-A1 AVR MEGA16單片機芯片開發板,信號
             輔助硬件工具有一部8通道的24兆赫茲的邏輯分析儀和一部萬用表,通俗的講,此程序就
                      是開發板的操作系統,以MEGA16A為中央控制芯片,來控制DS1302時鐘芯片,使其時間數據
         顯示在1602液晶屏上;
             我用業余時間大概寫了三天左右....得以完善,這次我寫的比較順利,錯誤只有兩點,
                      一是將寫好的程序下載入芯片后,時間不走,錯誤在于寫錯了時序,用邏輯分析儀捕捉信號
                      后,修正,KO! 二是時間可以走,但是跑秒區并非從0走到59,問題在于顯示時,直接顯示
         BCD碼,并未將BCD碼轉換為十進制數,修正后OK!
                           此程序還用到了定時器模塊,定時每100毫秒讀一次時間數據,并顯示在液晶屏上;

         

         
                    心得:    此次又突破了以往的程序量,這是我寫的目前最大的一個程序,由于AVR芯片IO口
            控制比較復雜,所以程序語句比較多,但是此程序還有精簡的空間,IO口的初始化很重
        要!
         

         

         
                         finish time:   2014年3月7日13:16:14
                                作者: 肖邦;
                                  QQ: 14-545-07665 ;
                                 TEL:  SORRY 保密;
               地址:  新疆昌吉回族自治州昌吉市; 
                                夢想:  將 托尼*斯塔克成為現實;

         
        */

         

         
        #include <avr/io.h>
        #include <avr/interrupt.h>//此頭文件用于中斷服務,本程序中可以省略;

         
        typedef unsigned char uint8;
        typedef unsigned int uint16;

         
        void init_io(void) //====初始化所有io口;
        {
           DDRA=0XFF;
           PORTA=0XFF;

         
           DDRB=0XFF;
           PORTB=0X00;

         
           DDRC=0XFF;
           PORTC=0X00;

         
           DDRD=0XFF;
           PORTD=0X00;
        }

         
        //================IO口的位操作==================

         
        void rs(uint8 a)    //指令/數據位/ ===========DS1302時鐘位;
        {
          if(a) { PORTB|=1<<3; }

         
          else  { PORTB&=~(1<<3); }
        }

         
        void rw(uint8 a)  //讀/寫位/   ================DS1302數據位;
        {
          if(a) { PORTB|=1<<4; }

         
          else  { PORTB&=~(1<<4); }
        }

         
        void e(uint8 a)    //1602傳輸時能位;
        {
          if(a) { PORTB|=1<<5; }

         
          else  { PORTB&=~(1<<5); }
        }

         

         
        void ds(uint8 a)    //=========================DS1302傳輸使能位;
        {
          if(a) { PORTC|=1<<4; }

         
          else  { PORTC&=~(1<<4); }
        }

         

         
        //==============================================

         

         
        /*/======================================================
           模塊名:  1602LCD液晶屏函數 
             功能:  負責將視覺需要的數據顯示在屏幕上;
             
        *///=====================================================
        void pa7(uint8 a)  //繁忙檢測位=================
        {
          if(a) { DDRA|=0X80; PORTA|=0X80 ;} //輸出高電平狀態;
          else  { DDRA&=~(0X80); PORTA|=0X80; }//輸入內部有上拉電阻;
        }

         
        void busy(void)    //繁忙檢測函數
        {
           pa7(0);  // PA7引腳輸入狀態內部有上拉;
           do
           {
            e(0);
            rs(0);
            rw(1);
            e(1);   //注意!此處和讀寫數據指令不同,要置1傳輸使能位,再讀取,讀取完成后再清零此位;
           }

         
           while(PINA&0X80);//讀取PA7引腳是否是0;如果是0,表示液晶屏處于空閑狀態,可以進行操作;
           e(0);

         
           pa7(1);   //PA7引腳輸出狀態,輸出1;
        }

         
        void pa(uint8 a) //====向PA口裝載數據;
        {

         
          PORTA=a;

         
        }
        void lcd_dat(uint8 dat)//=========寫數據==============
        {
           busy();  //繁忙檢測;
            rs(1);  //數據;
            rw(0);  //寫入;
        e(1);   //傳輸開始;
            pa(dat);  //裝載數據;
            e(0) ;   //傳輸結束;
          
        }

         
        void lcd_cmd(uint8 cmd)  //=============寫指令=============
        {
           busy();  //繁忙檢測;
            rs(0);  //指令;
            rw(0);  //寫入;
        e(1);   //傳輸開始;
            pa(cmd);  //裝載數據;
            e(0);    //傳輸結束;
          
        }

         
        void init_lcd()  //初始化液晶屏指令;
        {
           lcd_cmd(0x3c);  //顯示數據,8位數據, 兩行,5X10顯示;
           lcd_cmd(0x0c);  //整屏顯示光標不閃,字符不閃.
           lcd_cmd(0x06);  //寫入一個數據時地址加一,整屏不移動;
           lcd_cmd(0x01);  //清屏指令;

         
        }

         
        void play(uint8 add,uint8 dat)//=======最終顯示函數===================
        {
          lcd_cmd(add);
          lcd_dat(dat);

         
        }

         
        void delay1(uint8 j,uint8 i)//====可編程延時函數========
        {
           uint16 a=0,s=10000;
           
            s=s*j;

         
            while(i--)
        {
         for(a=0;a<s;a++);
            }

         
        }

         

         
        void buzz(void)    //蜂鳴器=============
        {

         
          PORTC|=0X80;
          delay1(3,4);
          PORTC&=~(0X80);

         
        }

         
        //==========================================================

         

         

         

         
        //==================DS1302模塊===========

         
        void reset_1302()
        {
           ds(0);
           rs(0);
           rw(0);

         
        }
        void delay2(void)      //用于DS1302小延時函數;
        {
          uint8 j=0;
          for(j=0;j<200;j++);

         

         
        }

         
        void ds_write(uint8 dat)   //DS1302寫數據函數;
        {
           uint8 j=0;

         
           for(j=0;j<8;j++)
             {
            rw(dat&0x01);
                 
        rs(0);
        rs(1);
        dat>>=1;
        }
           
            
          
        }

         
        uint8 ds_read(void) // DS1302讀取函數;
        {
            uint8 j=0,temp=0;

         
            DDRB&=~(1<<4); //rw引腳輸入狀態;
            PORTB|=1<<4;   //內部有上拉電阻;
             rs(0);

         

         
            for(j=0;j<8;j++)
        {         
                temp>>=1;

         

         
           if((PINB&0X10)==0X10)//如果PB4口讀到1;
         {   
             temp|=0x80;//裝載數據;
         }
         
         
              rs(1);       //下降沿有效;
         delay2();    //時鐘脈寬延時;
              rs(0);        
        }
         
            DDRB|=1<<4; //  rw引腳輸出狀態;
            PORTB|=1<<4;   //rw引腳輸出1;
                rs(0);
        rw(0);

         
        return (temp);

         

         
        }

         
        void w_1302(uint8 addr,uint8 dat) //寫一個地址,寫一個數據;
        {
           ds_write(addr);
           ds_write(dat);

         
        }

         

         
        void ds_wp(uint8 j)  //j==1:不能夠寫入數據,j==0:可以寫入數據;
        {  
           reset_1302(); //初始化時鐘,數據,片選線;
           ds(1);
           w_1302(0x8e,j?0x80:0);  //三目運算;
           ds(0);
        }

         

         
        void set_time(uint8 * dat)   //設置時間;
         { 
          uint8 r=0 ,t=0, ad=0x80;
           for(r=0;r<7;r++)    //BCD碼的轉換.
             {
          t=dat[r]%10;
          dat[r]=dat[r]/10;
          dat[r]=(dat[r]*16)+t;
         
        }
              ds_wp(0);//可以寫入數據;
              for(r=0;r<7;r++)
          {     
             reset_1302();  //初始化1302;
                ds(1);    //傳輸使能開;
                ds_write(ad); //寫入"寫"操作地址;
                ds_write(dat[r]);//寫入時間數據;
        ds(0);
                 ad+=2;//地址加2;
               }
               ds_wp(1);//禁止寫入數據;  

         
        }

         
        void read_time(uint8 * dat)
        {
           uint8 j=0,addr=0x81 ;

         
           for(j=0;j<7;j++)
            {
              reset_1302();
         ds(1);          //傳輸使能開;
              ds_write(addr);  //發送讀取地址;
         dat[j]=ds_read(); //接收讀到的數據;
         ds(0);          //傳輸使能關;

         
         addr+=2;   //讀取地址加2;
        }

         
        }

         
        void timer0(void)  //定時器模塊函數;
        {

         
          TCNT0=22;  //每5毫秒溢出一次;
          TCCR0=0X04;  //256分頻;

         

         
        }

         

         
        int main(void)
        {
            uint8 j=0;
           uint8 sj[]={20,23,13,7,3,5,14};
           init_io();  //初始化所有io口;
           init_lcd();  //初始化1602液晶屏;

         
           play(0x82,'2');
           delay1(3,2);

         
          play(0x83,'0');
          delay1(3,2);
         
            play(0x86,'-');                    
           delay1(3,2);

         
             play(0x89,'-');             
           delay1(3,2);

         
            play(0x8d,'(');              
           delay1(3,2);

         
           play(0x8f,')');
           delay1(3,2);

         
           play(0xc4,':');
           delay1(3,2);

         
            play(0xc7,':');
           delay1(3,2);
            
           buzz();   //蜂鳴器叫;
           delay1(3,2);

         
          set_time(sj);  //設置時間;
          timer0();  //運行定時器;

         

         

         

         

         
         while(1)
          {  
            if(TIFR&0X01)  //定時器溢出了;
         j++;
              TCNT0=22;
         TIFR|=0X01;//溢出位置一清零;

         
             }

         
             if(j==20)
         {
            j=0;

         
              read_time(sj);
               
              play(0xc9,sj[0]%16+'0'); //秒個位;
         play(0xc8,sj[0]/16+'0'); //秒十位;

         
              play(0xc6,sj[1]%16+'0'); //分個位;
         play(0xc5,sj[1]/16+'0'); //分十位;

         
         play(0xc3,sj[2]%16+'0'); //時個位;
         play(0xc2,sj[2]/16+'0'); //時十位;

         
                                       
         play(0x8b,sj[3]%16+'0'); //號個位;
         play(0x8a,sj[3]/16+'0'); //號十位;

         
         play(0x88,sj[4]%16+'0'); //月個位;
         play(0x87,sj[4]/16+'0'); //月十位;

         

         
              play(0x8e,sj[5]+'0'); //星期;

         

         
              play(0x85,sj[6]%16+'0'); //秒個位;
         play(0x84,sj[6]/16+'0'); //秒十位;

         

         

         
              
           
         }

         

         

         
          }

         

         

         

         
         

         

         
        }
        關閉窗口

        相關文章

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