久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

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

基于ATMEGA16的DS1302可調萬年歷程序

作者:佚名   來源:本站原創   點擊數:  更新時間:2012年02月29日   【字體:


 

程序:

main函數:

/*
程序功能:DS1302實時時鐘顯示
作者:朱波
時間:2012年2月3日
通信方式:3線串行通信
使用說明:本程序模仿家用萬年歷,能夠進行時間的設定
時間設定方法:1.按下設置鍵進入設置模式
                        2.按選擇鍵對要設置的項進行選擇
                        3.按加一鍵對選擇項加一
                        4.完成全部選擇后出現"please check OK!"
       此時按下確定鍵就回到時間模式
備注:可以通過主函數中的宏定義進行時間設置
*/
#include <iom16v.h>
#include <macros.h>
#include "delay.h" 
#include "display.h"
#include "ds1302.h"
#include "key.h"
#define  uchar unsigned char
#define  uint  unsigned int
//用于校準時間
#define year 12//年份
#define week 4//星期
#define month 12//月
#define daytime 23//日
#define hour  12//小時
#define minute 59//分鐘
#define seconds 55//秒
uint time_data[7]={year,week,month,daytime,hour,minute,seconds};//年星期月日時分秒(設置初始時間)
void  main()
{ 
     int_init();//中斷初始化
  SEI();//開啟總中斷
     LCD_init();//1602液晶初始化
  SCK_OUT;//對時鐘進行操作將SCK設置成輸出
  RST_OUT;//對時鐘進行操作將RST設置成輸出
  
  set_rtc();//設置時間
  hour_mode(24);//時間顯示模式設定,12小時顯示沒有做好處理
                //只是注意此函數的寫法
  while(1)
  {
      read_rtc();//讀取時間
   time_pro();//時間處理
  
   display();//顯示時間
  }
}

delay.c:

#include"delay.h"
void delay(unsigned int ms)
{
        unsigned int i,j;
 for(i=0;i<ms;i++)
    {
    for(j=0;j<1141;j++);
       }
}

delay.h:

#ifndef delay_h
#define delay_h
extern void delay(unsigned int ms);
#endif

ds1302.c:

#include <iom16v.h>
#include <macros.h>

#include "key.h"
#include "display.h"
#define  uchar unsigned char
#define  uint  unsigned int

#define SCK_CLR PORTA&=~BIT(6)
#define SCK_SET PORTA|=BIT(6)
#define SCK_OUT DDRA|=BIT(6)

#define RST_CLR PORTC&=~BIT(7)
#define RST_SET PORTC|=BIT(7)
#define RST_OUT DDRC|=BIT(7)

#define IO_CLR PORTA&=~BIT(7)//IO引腳輸出低電平
#define IO_SET PORTA|=BIT(7)//IO引腳輸出高電平
#define IO_OUT DDRA|=BIT(7)//IO引腳設置為輸出
#define IO_IN DDRA&=~BIT(7)//IO引腳設置為輸入
#define IO_R PINA&BIT(7)//IO引腳進行讀取操作


extern int time_data[7];

uchar write_add[7]={0X8C,0X8A,0X88,0X86,0X84,0X82,0X80};//寫地址(最低位為0)
uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};//讀地址(最低位為1)

uchar table[];//用于計算
void write_ds1302_byte(uchar dat)//在ds1302中寫指令字節
{
     uint i;
   IO_OUT;
  for(i=0;i<8;i++)//一位一位往里寫,共寫8位
  {
     SCK_CLR;//開始時時序為0
     //先準備好數據,在給上升沿
    if(dat&0x01)//如果數據位為1
  {
    IO_SET;//IO為1
  }
  else//如果數據位為0
  {
    IO_CLR;//IO為0
  }
  SCK_SET;//SCLK拉高開始傳輸數據
  dat=dat>>1;//移位進行下一個字節的傳輸(寫的時候放到后面)
  }
}

uchar read_ds1302(uchar add)//單字節讀
{
      uchar i,value;//定義變量
    RST_CLR;
   SCK_CLR;//開始RET和SCLK時序為低
   RST_SET;
   //根據時序要傳輸命令
   write_ds1302_byte(add);//執行完此句后,SCLK時序到下降沿處開始讀數據
   IO_IN;//IO設置成輸入
   for(i=0;i<8;i++)//一個字節為8位,一位一位的讀
   {
     SCK_CLR;//時鐘拉低開始傳輸
     value=value>>1;//讀的時候放到前面
     if(IO_R)//讀的結果如果為1
  {
    value=value|0X80;//從低位開始讀取
  }
  SCK_SET;//時鐘拉高結束傳輸
  
   }//循環結束后SCLK時序到了最后,將RST拉低
   RST_CLR;
   return value;//將數據返回  
}
void write_ds1302(uchar add,uchar dat)//單字節寫(傳遞兩個參數一個是地址一個是數據)
{
    RST_CLR;
   NOP();
   SCK_CLR;//開始RET和SCLK時序為低
   RST_SET;//根據時序開始寫入東西時將RST拉高
   write_ds1302_byte(add);//寫入地址
   write_ds1302_byte(dat);//寫入數據
   RST_CLR;//根據時序,當寫完東西時RST拉低
}

void set_rtc(void)//設置時間(初始化時間)
{
    uchar i,k;
   for(i=0;i<7;i++)//將十進制轉換為16進制
   {
     k=time_data[i]/10;//得到十位
  time_data[i]=time_data[i]%10;//得到個位
  time_data[i]=time_data[i]+k*16;//變成BCD碼
   }
   write_ds1302(0x8e,0x00);//去除寫保護(control寄存器)
   for(i=0;i<7;i++)//對時
   {
     write_ds1302(write_add[i],time_data[i]);
   }
   write_ds1302(0x8e,0x80);//(wp位置1)加入寫保護
}


void read_rtc(void)//讀時鐘
{
   uchar i;
  for(i=0;i<7;i++)
  {
    time_data[i]=read_ds1302(read_add[i]);//把時鐘放到數組里
  }
}

void time_pro(void)//時間處理函數(16進制轉換為十進制)
{
  table[0]=time_data[6]%16;//顯示秒個位
 table[1]=time_data[6]/16;//顯示秒十位
 
    table[2]=time_data[5]%16;//顯示分個位
 table[3]=time_data[5]/16;//顯示分十位
 
 table[4]=time_data[4]%16;//顯示小時個位
 table[5]=time_data[4]/16;//顯示小時十位
 
 table[6]=time_data[3]%16;//顯示日個位
 table[7]=time_data[3]/16;//顯示日十位
 
 table[8]=time_data[2]%16;//顯示月個位
 table[9]=time_data[2]/16;//顯示月十位
 
 table[10]=time_data[1]%16;//顯示星期
 
 
 table[12]=time_data[0]%16;//顯示年個位
 table[13]=time_data[0]/16;//顯示年十位
}
void hour_mode(uchar mode)//mode為12時為12小時格式,為24時為24小時格式
{
    uint value;
  write_ds1302(0x8e,0x00);//去除寫保護(control寄存器)
 if(mode==12)
 {
    value=read_ds1302(0x85);//讀取小時當前值
    value=value|0x80;       //將小時數據最高位置1
    write_ds1302(0x84,value);//將置1后的小時數據寫入小時寄存器
    //變為12小時格式
 }
 if(mode==24)
 {
    value=read_ds1302(0x85);//讀取小時當前值
    value=value&0x7F;       //將小時數據最高位置0
    write_ds1302(0x84,value);//將置1后的小時數據寫入小時寄存器
    //變為24小時格式
 }

}
 void int_init(void)
{
 MCUCR |= 0x00;
 MCUCSR|= 0x00;
 GICR  |= 0x40;
}

#pragma interrupt_handler int0_isr:2
void int0_isr(void)//在外部中斷中進行時間設置
{
    uchar i=0,num=0,n=0,m=0,u=0,k=0,j=0,h=0;
    CLI();//進制中斷
    LCD_init();//清屏
 showprompt();//顯示提示信息
   write_ds1302(0x80,0x80);//時鐘停止
   write_ds1302(0x8e,0x00);//去除寫保護(control寄存器)
 while(!(num==4)) //num含義:1(加一),2(選擇),3(設置),4(確定)
 {  
       if(key_press())    //檢測是否有按鍵按下
        {
          num=key_scan();   //掃描并返回翻譯后的鍵碼
       if(num==2)//進入選擇狀態
    {
      i++;
   switch(i)
   { 
     case 1://設置年
       LCD_init();//清屏
 &nbs設置年
       LCD_init();//清屏
    while(!(n==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
      n=key_scan();   //掃描并返回翻譯后的鍵碼
      if(n==1)
      time_data[0]++;//按一下年加一
      }
    //以下是時間微調,因為在DS1302中寫入的是BCD碼,所以在實際中
    //可以用下面的調整方式,以下只處理到60年
         if(time_data[0]==0x0a)
         {
           time_data[0]=0x10;
         }
         if(time_data[0]==0x1a)
         {
           time_data[0]=0x20;
         }
         if(time_data[0]==0x2a)
         {
           time_data[0]=0x30;
         }
         if(time_data[0]==0x3a)
         {
           time_data[0]=0x40;
         }
         if(time_data[0]==0x4a)
         {
           time_data[0]=0x50;
         }
      write_ds1302(write_add[0],time_data[0]);//寫入地址和數據
      time_pro();//時間處理
      showyear();//顯示年
    }
       // break;不用終止程序,當程序跳出上邊循環時,會進入下邊程序
    case 2://月設置
    LCD_init();//清屏
    while(!(m==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        m=key_scan();   //掃描并返回翻譯后的鍵碼
        if(m==1)
         time_data[2]++;//按一下月加一
     if(time_data[2]==0x13)//一年有12個月
      time_data[2]=1;
      }
        //BCD碼處理
         if(time_data[2]==0x0a)
         {
           time_data[2]=0x10;
         }
         if(time_data[2]==0x1a)
         {
           time_data[2]=0x20;
         }       
      write_ds1302(write_add[2],time_data[2]);
      time_pro();//時間處理
      showmonth();//顯示月
    }
    //break;
     case 3: //日設置
    LCD_init();//清屏
    while(!(u==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        u=key_scan();   //掃描并返回翻譯后的鍵碼
        if(u==1)
         time_data[3]++;//按一下日加一
     if(time_data[3]==0x32)//一個月最多有31天
      time_data[3]=1;
      }
        //BCD碼處理
         if(time_data[3]==0x0a)
         {
           time_data[3]=0x10;
         }
         if(time_data[3]==0x1a)
         {
           time_data[3]=0x20;
         } 
       if(time_data[3]==0x2a)
         {
           time_data[3]=0x30;
         }          
      write_ds1302(write_add[3],time_data[3]);
      time_pro();//時間處理
      showdaytime();//顯示日
    }
    //break;
     case 4: //小時設置
    LCD_init();//清屏
    while(!(k==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        k=key_scan();   //掃描并返回翻譯后的鍵碼
        if(k==1)
         time_data[4]++;//按一下小時加一
     if(time_data[4]==0x25)//一天24小時
      time_data[4]=1;
      }
        //BCD碼處理
         if(time_data[4]==0x0a)
         {
           time_data[4]=0x10;
         }
         if(time_data[4]==0x1a)
         {
           time_data[4]=0x20;
         }          
      write_ds1302(write_add[4],time_data[4]);
      time_pro();//時間處理
      showhour();//顯示小時
      } 
      //break; 
     case 5: //分鐘設置
    LCD_init();//清屏
    while(!(j==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        j=key_scan();   //掃描并返回翻譯后的鍵碼
        if(j==1)
         time_data[5]++;//按一下分鐘加一
     if(time_data[5]==0x5a)//一小時60分鐘
      time_data[5]=0x00;
      }
        //BCD碼處理
         if(time_data[5]==0x0a)
         {
           time_data[5]=0x10;
         }
         if(time_data[5]==0x1a)
         {
           time_data[5]=0x20;
         }
      if(time_data[5]==0x2a)
         {
           time_data[5]=0x30;
         }
         if(time_data[5]==0x3a)
         {
           time_data[5]=0x40;
         }
      if(time_data[5]==0x4a)
         {
           time_data[5]=0x50;
         }
         if(time_data[5]==0x5a)
         {
           time_data[5]=0x60;
         }                   
      write_ds1302(write_add[5],time_data[5]);
      time_pro();//時間處理
      showminute();//顯示分鐘
       } 
    //break;
     case 6: //星期設置
    LCD_init();//清屏
    while(!(h==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        h=key_scan();   //掃描并返回翻譯后的鍵碼
        if(h==1)
         time_data[1]++;//按一下小時加一
     if(time_data[1]==0x08)//一天24小時
      time_data[1]=1;
      }
              
      write_ds1302(write_add[2],time_data[2]);
      time_pro();//時間處理
      showweek();//顯示星期
      } 
      default:
      LCD_init();//清屏
      showmessage();
      break;
     } 
    
      }
    
       }
   }
 
    write_ds1302(0x8e,0x80);//(wp位置1)加入寫保護
    write_ds1302(0x80,0x00);//時鐘開始
    LCD_init();//清屏
    SEI();
}

key.c:

#include <iom16v.h>
#include <macros.h>
#include "delay.h"

#define  uchar unsigned char
#define  uint&n月設置
    LCD_init();//清屏
    while(!(m==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        m=key_scan();   //掃描并返回翻譯后的鍵碼
        if(m==1)
         time_data[2]++;//按一下月加一
     if(time_data[2]==0x13)//一年有12個月
      time_data[2]=1;
      }
        //BCD碼處理
         if(time_data[2]==0x0a)
         {
           time_data[2]=0x10;
         }
         if(time_data[2]==0x1a)
         {
           time_data[2]=0x20;
         }       
      write_ds1302(write_add[2],time_data[2]);
      time_pro();//時間處理
      showmonth();//顯示月
    }
    //break;
     case 3: //日設置
    LCD_init();//清屏
    while(!(u==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        u=key_scan();   //掃描并返回翻譯后的鍵碼
        if(u==1)
         time_data[3]++;//按一下日加一
     if(time_data[3]==0x32)//一個月最多有31天
      time_data[3]=1;
      }
        //BCD碼處理
         if(time_data[3]==0x0a)
         {
           time_data[3]=0x10;
         }
         if(time_data[3]==0x1a)
         {
           time_data[3]=0x20;
         } 
       if(time_data[3]==0x2a)
         {
           time_data[3]=0x30;
         }          
      write_ds1302(write_add[3],time_data[3]);
      time_pro();//時間處理
      showdaytime();//顯示日
    }
    //break;
     case 4: //小時設置
    LCD_init();//清屏
    while(!(k==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        k=key_scan();   //掃描并返回翻譯后的鍵碼
        if(k==1)
         time_data[4]++;//按一下小時加一
     if(time_data[4]==0x25)//一天24小時
      time_data[4]=1;
      }
        //BCD碼處理
         if(time_data[4]==0x0a)
         {
           time_data[4]=0x10;
         }
         if(time_data[4]==0x1a)
         {
           time_data[4]=0x20;
         }          
      write_ds1302(write_add[4],time_data[4]);
      time_pro();//時間處理
      showhour();//顯示小時
      } 
      //break; 
     case 5: //分鐘設置
    LCD_init();//清屏
    while(!(j==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        j=key_scan();   //掃描并返回翻譯后的鍵碼
        if(j==1)
         time_data[5]++;//按一下分鐘加一
     if(time_data[5]==0x5a)//一小時60分鐘
      time_data[5]=0x00;
      }
        //BCD碼處理
         if(time_data[5]==0x0a)
         {
           time_data[5]=0x10;
         }
         if(time_data[5]==0x1a)
         {
           time_data[5]=0x20;
         }
      if(time_data[5]==0x2a)
         {
           time_data[5]=0x30;
         }
         if(time_data[5]==0x3a)
         {
           time_data[5]=0x40;
         }
      if(time_data[5]==0x4a)
         {
           time_data[5]=0x50;
         }
         if(time_data[5]==0x5a)
         {
           time_data[5]=0x60;
         }                   
      write_ds1302(write_add[5],time_data[5]);
      time_pro();//時間處理
      showminute();//顯示分鐘
       } 
    //break;
     case 6: //星期設置
    LCD_init();//清屏
    while(!(h==2))//再次按選擇鍵就進入下個項目的設置
    {
      if(key_press())
      {
        h=key_scan();   //掃描并返回翻譯后的鍵碼
        if(h==1)
         time_data[1]++;//按一下小時加一
     if(time_data[1]==0x08)//一天24小時
      time_data[1]=1;
      }
              
      write_ds1302(write_add[2],time_data[2]);
      time_pro();//時間處理
      showweek();//顯示星期
      } 
      default:
      LCD_init();//清屏
      showmessage();
      break;
     } 
    
      }
    
       }
   }
 
    write_ds1302(0x8e,0x80);//(wp位置1)加入寫保護
    write_ds1302(0x80,0x00);//時鐘開始
    LCD_init();//清屏
    SEI();
}

key.c:

#include <iom16v.h>
#include <macros.h>
#include "delay.h"

#define  uchar unsigned char
#define  uint  unsigned int

uchar key_press()//判斷按鍵是否被按下(按下返回1,沒按下返回0)
{  
  uchar j;
   DDRD|=0X0F;//低四位為輸出
  PORTD|=0X0F;//低四位輸出低電平
 
  DDRD&=0XF0;//低四位為輸入
  j=PIND;//讀一下輸入寄存器
  j&=0X0F;//屏蔽高四位
  if(j==0X0F)//如果j沒變化,則返回0,否則返回1
  {
   return 0;
  }
  else
  {
   return 1;
  }
}
uchar key_scan()//按鍵掃描函數
{    
      uchar key;
    delay(10);
   if(key_press())//有按鍵按下時key_press()的值為1
   {
     key=PIND;//讀取PIND值
     key&=0X0F;//去掉高4位
     switch(key)//開關語句,用于判斷
     {
      case 0X0E://1110連接PD0的按鍵按下
    key=1;break;
   case 0X0D://1101連接PD1的按鍵按下
    key=2;break; 
   case 0X0B://1011連接PD2的按鍵按下
    key=3;break;
   case 0X07://0111連接PD3的按鍵按下
    key=4;break;
   default://都不是時隨便返回一個值
    key=16;       
     }
    while(key_press());//在按鍵按下時執行完上邊的程序后就執行此循環
                     //當按鍵松開時就跳出循環,目的是按一下就執行一次程序
   }
   else//沒有按下時隨便返回一個值
   {
   key=16;
   }
     return key;
}

程序未完,完整代碼下載: http://www.zg4o1577.cn/f/1302cc.rar

關閉窗口

相關文章

主站蜘蛛池模板: 久久久国产一区二区三区 | 欧美偷偷 | 免费一区二区三区 | 午夜一区| 欧美精品一区二区在线观看 | 国产精品成人一区二区三区 | 日本激情视频中文字幕 | 99精品99久久久久久宅男 | 亚洲精品免费视频 | 成人激情视频免费在线观看 | 亚洲人久久 | 日本高清不卡视频 | 成人午夜视频在线观看 | 国产精品18久久久久久白浆动漫 | 日韩二区| 精品一区二区三区在线播放 | 久久这里有精品 | 国产片一区二区三区 | 91精品国产综合久久精品图片 | 99re视频在线免费观看 | 伊色综合久久之综合久久 | 国产美女一区 | h视频在线免费观看 | 欧美日韩电影免费观看 | 一a一片一级一片啪啪 | 天天天天操 | 国产精品久久久 | 日本福利视频免费观看 | 久久999| 最新中文字幕第一页视频 | 干狠狠| 国产黄色av网站 | 成人免费在线视频 | 久久精品欧美电影 | 精品国产一区二区在线 | av黄色网 | 天天拍天天操 | 亚洲一区二区三区 | 新91视频网| 特黄特黄a级毛片免费专区 av网站免费在线观看 | 国产精品久久欧美久久一区 |