|
DS1302與1602LCD設計含仿真 自己做的 大家可以看看代碼
仿真原理圖
部分程序預覽:
- #include "DS1302.h"
- /*---------延時程序------------------*/
- void DelayMS(uint ms)
- {
- uchar i;
- while(ms--){for(i=0;i<120;i++);}
- }
- //-----------讀LCD狀態------------------//
- uchar Read_LCD_State()
- { uchar state;
- RS=0;RW=1;EN=1; //輸出:D0~D7=狀態字
- DelayMS(1);
- state=P0; //從P0口讀LCD狀態
- EN = 0;DelayMS(1);
- return state;
- }
- //-----------忙等待------------------//
- void LCD_Busy_Wait()
- {
- while((Read_LCD_State()&0x80)==0x80);
- DelayMS(5);
- }
- //-----------向LCD寫數據------------------//
- void Write_LCD_Data(uchar dat)
- {
- LCD_Busy_Wait();
- RS=1;EN=0;RW=0; //寫數據,EN為高脈沖,
- P0=dat;EN=1;DelayMS(1);EN=0;
- }
- //-------------寫LCD指令-------------------//
- void Write_LCD_Command(uchar cmd)
- {
- LCD_Busy_Wait();
- RS=0;EN=0; RW=0; //寫指令,EN高脈沖,輸出:D0~D7=數據
- P0=cmd;EN=1;DelayMS(1);EN=0;
- }
- //-------------LCD初始化-------------------//
- void Init_LCD()
- {
- Write_LCD_Command(0x38); //設置16*2顯示,5*7點陣,8位數據接口
- DelayMS(1);
- Write_LCD_Command(0x01); //顯示清零,數據指針清零
- DelayMS(1);
- Write_LCD_Command(0x06); //寫一個字符后地址指針自動加1
- DelayMS(1);
- Write_LCD_Command(0x0c); //設置開顯示,不顯示光標
- DelayMS(1);
- }
- //------------------------------------------
- //設置液晶顯示位置
- //------------------------------------------
- void Set_LCD_POS(uchar p){
- Write_LCD_Command(p|0x80);//相當于在0x80基礎上加入位置量
- }
- //----在LCD上顯示字符串---------//
- void Display_LCD_String(uchar p,uchar *s)
- { uchar i;
- Set_LCD_POS(p);
- for(i=0;i<16;i++)
- {
- Write_LCD_Data(s[i]); //在固定位置顯示時間日期
- DelayMS(1);
- }
- }
- //---------日期與時間值轉換為數字字符----------------//
- void Format_DateTime(uchar d,uchar *a)
- {
- a[0]=d/10+'0';
- a[1]=d%10+'0';
- }
- //判斷是否為閏年
- uchar isLeapYear(uint y)
- { return (y%4==0&&y%100!=0)||(y%400==0);}
- //求自2000.1.1開始的任何一天是星期幾
- //函數沒有通過,求出總天數后再求星期幾
- //因為求總天數可能會超出uint的范圍
- void RefreshWeekDay()
- { uint i,d,w=5; //已知1999.12.31是周五
- for(i=2000;i<2000+DateTime[6];i++)
- {
- d=isLeapYear(i)?366:365;
- w=(w+d)%7;
- }
- d=0;
- for(i=1;i<DateTime[4];i++)
- { d+=MonthsDays[i]; }
- d+=DateTime[3];
- //保存星期,0~6表示星期日,星期一,二,...,六,為了與DS1302的星期格式匹配,返回值需要加1
- DateTime[5]=(w+d)%7+1;
- }
- //*****年月日時分++/--********//
- void DateTime_Adjust(char x)
- { switch(Adjust_Index)
- {
- case 6: //年00-99
- if(x==1&&DateTime[6]<99) DateTime[6]++;
- if(x==-1&&DateTime[6]>0) DateTime[6]--;
- //獲取2月天數
- MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;
- //如果年份變化后當前月份的天數大于上限則設為上限
- if(DateTime[3]>MonthsDays[DateTime[4]])
- { DateTime[3]=MonthsDays[DateTime[4]];}
- RefreshWeekDay(); //刷新星期
- break;
- case 4: //月01-12
- if(x==1&&DateTime[4]<12) DateTime[4]++;
- if(x==-1&&DateTime[4]>1) DateTime[4]--;
- MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;
- if(DateTime[3]>MonthsDays[DateTime[4]])
- { DateTime[3]=MonthsDays[DateTime[4]];}
- RefreshWeekDay();
- break;
- case 3: //日00-28、29、30、31,調節之前首先根據年份得出該年中斷二月 天數
- MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;
- //根據當前月份決定調節日期的上限
- if(x==1&&DateTime[3]<MonthsDays[DateTime[4]]) DateTime[3]++;
- if(x==-1&&DateTime[3]>0) DateTime[3]--;
- RefreshWeekDay();
- break;
- case 2: //時
- if(x==1&&DateTime[2]<23) DateTime[2]++;
- if(x==-1&&DateTime[2]>0) DateTime[2]--;
- break;
- case 1: //分
- if(x==1&&DateTime[1]<59) DateTime[1]++;
- if(x==-1&&DateTime[1]>0) DateTime[1]--;
- break;
- }
- }
- //---定時器0每秒刷新LCD顯示----//
- void T0_INT() interrupt 1
- {
- TH0=-50000/256;
- TL0=-50000%256;
- if(++tCount !=2) return;
- tCount=0;
- //按指定格式生成待顯示的日期時間串
- Format_DateTime(DateTime[6],LCD_DSY_BUFFER1+5);
- Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+8);
- Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+11);
- //星期
- strcpy(LCD_DSY_BUFFER1+13,WEEK[DateTime[5]-1]);
- //時分秒
- Format_DateTime(DateTime[2],LCD_DSY_BUFFER2+5);
- Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+8);
- Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+11);
- //顯示年月日,星期,時分秒
- Display_LCD_String(0x00,LCD_DSY_BUFFER1);
- Display_LCD_String(0x40,LCD_DSY_BUFFER2);
- }
- //----------鍵盤中斷(INT0)-------------//
- void EX_INT0() interrupt 0
- {
- if(K1==0) //選擇調整對象(Y M D H M)
- {
- DelayMS(10);
- if(K1==0){
- //while(K1==0);
- if(Adjust_Index==-1||Adjust_Index==1)
- {
- Adjust_Index=7;
- }
- Adjust_Index--;
- if(Adjust_Index==5) Adjust_Index=4;
- LCD_DSY_BUFFER2[13]='[';
- LCD_DSY_BUFFER2[14]=Change_Flag[Adjust_Index]; //顯示調節對象
- LCD_DSY_BUFFER2[15]=']';
- }
- }
- else if(K2==0) //加
- { //while(K2==0);
- DelayMS(10);
- if(K2==0)
- DateTime_Adjust(1);
- }
- else if(K3==0) //減
- {
- DelayMS(10);//while(K3==0);
- if(K3==0)
- DateTime_Adjust(-1);
- }
- else if(K4==0) //確定
- {
- //while(K4==0);
- DelayMS(10);
- if(K4==0){
- SET_DS1302(); //將調整后的時間寫入DS1302
- LCD_DSY_BUFFER2[13]=' ';
- LCD_DSY_BUFFER2[14]=' ';
- LCD_DSY_BUFFER2[15]=' ';
- Adjust_Index=-1;
- }
- }
- }
- void main()
- { Init_LCD(); //液晶初始化
- IE=0x83; //允許INT0,T0中斷,EA=1,,ET0=1,EX0=1
- IP=0x01; //設置外部中斷0為高級中斷
- IT0=0x01; //外部中斷0為電平觸發,低電平有效
- TMOD=0x01; //設置定時器T0工作方式為方式1,
- TH0=-50000/256; //裝入初始值,定時1秒
- TL0=-50000%256;
- TR0=1; //啟動定時器
- while(1)
- {
- //如果未執行調整操作則正常讀取當前時間
- if(Adjust_Index==-1) GetTime();
- }
- }
復制代碼
所有資料下載:
A3020.rar
(104.25 KB, 下載次數: 228)
2016-6-22 23:42 上傳
點擊文件名下載附件
|
評分
-
查看全部評分
|