|
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png (38.91 KB, 下載次數(shù): 108)
下載附件
2021-1-13 01:57 上傳
3~XXGOW`25LWCD7@CC(F}XO.png (96.69 KB, 下載次數(shù): 107)
下載附件
仿真電路圖
2021-1-12 22:34 上傳
單片機(jī)源程序如下:
- #include<reg51.h>
- #include<intrins.h>
- #include<string.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define delayNOP() {_nop_();_nop_();_nop_();_nop_();}
- sbit SDA=P1^0; // DS1302數(shù)據(jù)線
- sbit CLK=P1^1; // DS1302時(shí)鐘線
- sbit RST=P1^2; // DS1302復(fù)位線
- //DS18B20數(shù)據(jù)端口定義
- sbit DQ=P2^4; //DS18B20數(shù)據(jù)端口
- sbit LCD_RS=P2^5; // LCD寄存器選擇
- sbit LCD_RW=P2^6; // LCD讀寫/寫控制
- sbit LCD_EN=P2^7; // LCD啟用
- sbit K1=P3^2; // 選擇
- sbit K2=P3^3; // 確定
- sbit K3=P3^5; // 加
- sbit K4=P3^6; // 減
- sbit key_1=P3^0; //自動(dòng)手動(dòng)切換
- sbit key_2=P3^1; //關(guān)燈,按一下,關(guān)一個(gè)
- sbit key_3=P3^4; //開燈,按一下,開一個(gè)
- uchar code zz[]={0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09};
- uchar code fz[]={0x09,0x01,0x03,0x02,0x06,0x04,0x0c,0x08};
- sbit R_LED=P2^0; //紅燈
- sbit Y_LED=P2^1; //黃燈
- sbit G_LED=P2^2; //綠燈
- sbit B_LED=P2^3; //藍(lán)燈
- sbit guangmin=P1^3; //光敏電阻傳感器
- sbit ren1=P1^4; //紅外熱釋電傳感器1
- sbit ren2=P1^5; //紅外熱釋電傳感器2
- sbit ren3=P1^6; //紅外熱釋電傳感器3
- sbit ren4=P1^7; //紅外熱釋電傳感器4
- //溫度字符
- uchar code Temperature_Char[8]={0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00};
- //溫度小數(shù)對(duì)照表
- uchar code df_Table[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
- uchar CurrentT=0; //當(dāng)前讀取溫度的整數(shù)部分
- uchar Temp_Value[]={0x00,0x00}; //從DS18B20讀取的溫度值
- uchar Display_Digit[]={0,0,0,0};//待顯示的各溫度數(shù)位
- bit DS18B20_IS_OK=1;//傳感器正常標(biāo)志
- uchar tCount=0;
- //一年中每個(gè)月的天數(shù),2月的天數(shù)由年份決定
- uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};
- //周日,每周一到周六(0,1-6)【讀取DS1302時(shí)分別是1-7】
- uchar *WEEK[]={"SUN","MON","TUS","WEN","THU","FRI","SAT"};
- //LCD顯示緩沖
- uchar LCD_DSY_BUFFER1[]={"00-00-00 "};
- uchar LCD_DSY_BUFFER2[]={"00-00-00 "};
- uchar DateTime[7]; //所讀取的日期時(shí)間
- uchar Adjust_flag=0; //當(dāng)前調(diào)節(jié)的時(shí)間對(duì)像:秒,分,時(shí),日,月,年(1,2,3,4,5,6)
- uchar Change_Flag[]=" YMDHM";//(分,時(shí),日,月,年)(不調(diào)節(jié)秒與周)
- //延時(shí)
- void DelayMS(uchar x)
- {uchar i;
- while(x--)
- for(i=0;i<120;i++);
- }
- //向DS1302寫入一個(gè)字節(jié)
- void Write_A_Byte_TO_DS1302(uchar x)
- {uchar i;
- for(i=0;i<8;i++)
- {SDA=x&1; CLK=1; CLK=0; x>>=1;
- }
- }
- //從DS11302讀取一個(gè)字節(jié)
- uchar Get_A_Byte_FROM_DS1302()
- {uchar i,b,t;
- for(i=0;i<8;i++)
- {b>>=1; t=SDA; b|=t<<7; CLK=1;CLK=0;
- }
- //BCD碼轉(zhuǎn)換
- return b/16*10+b%16;
- }
- //從DS1302指定位置讀數(shù)據(jù)
- uchar Read_Data(uchar addr)
- {uchar dat;
- RST=0; CLK=0; RST=1;
- Write_A_Byte_TO_DS1302(addr);
- dat=Get_A_Byte_FROM_DS1302();
- CLK=1;RST=0;
- return dat;
- }
- //向DS1302某地址寫入數(shù)據(jù)
- void Write_DS1302(uchar addr,uchar dat)
- {CLK=0;RST=1;
- Write_A_Byte_TO_DS1302(addr);
- Write_A_Byte_TO_DS1302(dat);
- CLK=0;RST=0;
- }
- //設(shè)置時(shí)間
- void SET_DS1302()
- { uchar i;
- Write_DS1302(0x8e,0x00); //寫控制字,取消寫保護(hù)
- //分時(shí)日月年依次寫入
- for(i=0;i<7;i++)
- {
- //分的起始地址10000010(0x82),后面連續(xù)依次是時(shí),日,月,周,年,寫入 地址每次增2
- Write_DS1302(0X80+2*i,(DateTime[i]/10<<4)|(DateTime[i]%10));
- }
- Write_DS1302(0x8e,0x80);//加保護(hù)
- }
- //讀取當(dāng)前的時(shí)間
- void GetTime()
- {
- uchar i;
- for(i=0;i<7;i++)
- {
- DateTime[i]=Read_Data(0x81+2*i);
- }
- }
- //LCD忙等待
- bit LCD_Busy_Check()
- {bit result;
- LCD_RS=0;
- LCD_RW=1;
- LCD_EN=1;
- delayNOP();
- result=(bit)(P0&0x80);
- LCD_EN=0;
- return result;
- }
- //寫指令
- void Write_LCD_Command(uchar cmd)
- {while(LCD_Busy_Check());
- LCD_RS=0;LCD_RW=0;LCD_EN=0; _nop_(); _nop_();
- P0=cmd;
- delayNOP();
- LCD_EN=1;
- delayNOP();
- LCD_EN=0;
- }
- //寫數(shù)據(jù)
- void Write_LCD_Data(uchar dat)
- {while(LCD_Busy_Check());
- LCD_RS=1;LCD_RW=0;LCD_EN=0;
- P0=dat;
- delayNOP();
- LCD_EN=1;
- delayNOP();
- LCD_EN=0;
- }
- //初始化
- void Init_LCD()
- {Write_LCD_Command(0x01);DelayMS(5);
- Write_LCD_Command(0x38);DelayMS(5);
- Write_LCD_Command(0x0c);DelayMS(5);
- Write_LCD_Command(0x06);DelayMS(5);
- }
- //設(shè)置顯示位置
- void Set_LCD_POS(uchar pos)
- { Write_LCD_Command(pos|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);
- }
- }
- //日期與時(shí)間值轉(zhuǎn)換為數(shù)字字符
- 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開始的任何一天是星期幾
- 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;
- }
- //延時(shí)函數(shù)2
- void Delay(uint x)
- {while(--x);
- }
- /***************初始化18B20溫度函數(shù)******************/
- uchar Init_DS18B20()
- {
- uchar status;
- DQ=1;
- Delay(8);
- DQ=0;
- Delay(90);
- DQ=1;
- Delay(8);
- status=DQ;
- Delay(100);
- DQ=1;
- return status;
- }
- //讀一字節(jié)
- uchar ReadOneByte()
- {uchar i,dat=0;
- DQ=1;_nop_();
- for(i=0;i<8;i++)
- {DQ=0;dat>>=1;DQ=1;_nop_();_nop_();
- if(DQ)dat|=0x80;
- Delay(30);
- DQ=1;
- }
- return dat;
- }
- //寫一字節(jié)
- void WriteOneByte(uchar dat)
- {uchar i;
- for(i=0;i<8;i++)
- { DQ=0;DQ=dat&0x01;Delay(5);DQ=1;dat>>=1;
- }
- }
- //讀取溫度值
- void Read_Temperature()
- {
- //延時(shí)值與負(fù)數(shù)標(biāo)識(shí)
- uchar t=150,ng=0;
- //高5位全為1(0xf8)則為負(fù)數(shù),為負(fù)數(shù)時(shí)取反加1,并設(shè)置負(fù)數(shù)標(biāo)識(shí)
- if(Init_DS18B20()==1) //DS18B20故障
- DS18B20_IS_OK=0;
- else
- {WriteOneByte(0xcc); //跳過序列號(hào)
- WriteOneByte(0x44);//啟動(dòng)溫度轉(zhuǎn)換
- Init_DS18B20();
- WriteOneByte(0xcc); //跳過序列號(hào)
- WriteOneByte(0xBE);//讀取溫度寄存器
- Temp_Value[0]=ReadOneByte(); //溫度低8位
- Temp_Value[1]=ReadOneByte(); //溫度高8位
- DS18B20_IS_OK=1;
- if((Temp_Value[1]&0xf8)==0xf8)
- {
- Temp_Value[1]=~Temp_Value[1];
- Temp_Value[0]=~Temp_Value[0]+1;
- if(Temp_Value[0]==0x00)
- Temp_Value[1]++;
- //負(fù)數(shù)標(biāo)志置1
- ng=1;
- }
- //查表得到溫度的小數(shù)部分
- Display_Digit[0]=df_Table[Temp_Value[0]&0x0f];
- //獲取溫度整數(shù)部分(高字節(jié)中的低三位與低字節(jié)中的高4位,無符號(hào))
- CurrentT=((Temp_Value[0]&0xf0)>>4)|((Temp_Value[1]&0X07)<<4);
- //將整數(shù)部分分解為3位待顯示數(shù)字
- Display_Digit[3]=CurrentT/100;
- Display_Digit[2]=CurrentT%100/10;
- Display_Digit[1]=CurrentT%10;
- //刷新LCD顯示緩沖
- LCD_DSY_BUFFER2[13]= Display_Digit[0]+'0';
- LCD_DSY_BUFFER2[12]='.' ;
- LCD_DSY_BUFFER2[11]=Display_Digit[1]+'0';
- LCD_DSY_BUFFER2[10]=Display_Digit[2]+'0';
- LCD_DSY_BUFFER2[9]=Display_Digit[3]+'0';
- //高位為0時(shí)不顯示
- if(Display_Digit[3]==0) LCD_DSY_BUFFER2[9]=' ';
- //高位為0,且次高位為0時(shí),次高位不顯示
- if(Display_Digit[2]==0&&Display_Digit[3]==0)
- LCD_DSY_BUFFER2[10]=' ';
- //負(fù)數(shù)符號(hào)顯示在恰當(dāng)?shù)奈恢?br />
- if(ng)
- {if(LCD_DSY_BUFFER2[10]==' ')
- LCD_DSY_BUFFER2[10]='-';
- else
- if(LCD_DSY_BUFFER2[9]==' ')
- LCD_DSY_BUFFER2[9]='-';
- else
- LCD_DSY_BUFFER2[8]='-';
- }
- }
- }
- //鍵盤中斷 0
- void EX_INT0() interrupt 0
- {if(K1==0) //選擇調(diào)整對(duì)象(Y M D H M)
- { while(K1==0);
- Adjust_flag++;
- LCD_DSY_BUFFER1[13]='[';
- LCD_DSY_BUFFER1[14]=Change_Flag[Adjust_flag];
- LCD_DSY_BUFFER1[15]=']';
- if(Adjust_flag==6)
- {Adjust_flag=0;
- LCD_DSY_BUFFER1[13]=' ';
- LCD_DSY_BUFFER1[14]=' ';
- LCD_DSY_BUFFER1[15]=' ';
- }
- }
- }
- //鍵盤中斷1
- void EX_INT1() interrupt 2
- {
- while(K2==0);
- SET_DS1302();//將調(diào)整后的時(shí)間寫入DS1302
- LCD_DSY_BUFFER1[13]=' ';
- LCD_DSY_BUFFER1[14]=' ';
- LCD_DSY_BUFFER1[15]=' ';
- Adjust_flag=0;//操作索引重設(shè)為-1,時(shí)間繼續(xù)正常顯示
- }
- //定時(shí)器0每秒刷新LCD顯示
- void T0_INT() interrupt 1
- { uchar i;
- TH0=-50000/256;
- TL0=-50000%256;
- Set_LCD_POS(0X4e);Write_LCD_Data(0Xdf);
- Set_LCD_POS(0X4f);Write_LCD_Data('C');
- if(++tCount!=2) return;
- tCount=0;
- Read_Temperature();
- //按指定的格式生成待顯示的日期時(shí)間串
- Format_DateTime(DateTime[6],LCD_DSY_BUFFER1);
- Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+3);
- Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+6);
- //星期
- strcpy(LCD_DSY_BUFFER1+9,WEEK[DateTime[5]-1]);
- //時(shí)分秒
- Format_DateTime(DateTime[2],LCD_DSY_BUFFER2);
- Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+3);
- Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+6);
- //顯示年月日,星期,時(shí)分秒
- Display_LCD_String(0x00,LCD_DSY_BUFFER1);
- Set_LCD_POS(0x40);
- for(i=0;i<14;i++)
- {
- Write_LCD_Data(LCD_DSY_BUFFER2[i]);
- DelayMS(1);
- }
- }
- //手動(dòng)按鍵控制燈函數(shù)
- void key_LED()
- {
- R_LED=1;
- Y_LED=1;
- G_LED=1;
- B_LED=1;
- if(key_2==0)
- {
- R_LED=0;
- Y_LED=0;
- G_LED=0;
- B_LED=0;
- }
- if(key_3==0)
- {
- R_LED=1;
- Y_LED=1;
- G_LED=1;
- B_LED=1;
- }
- }
- //主程序
- void main()
- {
- Init_LCD();//液晶初始化
- IE=0X87;//允許INT0,T0中斷
- IP=0X05;
- IT0=0X01;
- IT1=0X01;
- TMOD=0X01;
- TH0=-50000/256;
- TL0=-50000%256;
- TR0=1;
- while(1)
- {
- R_LED=Y_LED=G_LED=B_LED=1;
- if(key_1==0) //手動(dòng)模式
- {
- key_LED(); //按鍵控制燈函數(shù)
- }
- else
- {
- if(DateTime[2]>18||DateTime[2]<6||guangmin==0)
- {
- if(ren1==0)
- {
- R_LED=0;
- Y_LED=1;
- G_LED=1;
- B_LED=1;
- }
- if(ren2==0)
- {
- R_LED=0;
- Y_LED=0;
- G_LED=1;
- B_LED=1;
- }
- if(ren3==0)
- {
- R_LED=0;
- Y_LED=0;
- G_LED=0;
- B_LED=1;
- }
- if(ren4==0)
- {
- R_LED=0;
- Y_LED=0;
- G_LED=0;
- B_LED=0;
- }
- }
- }
- switch(Adjust_flag)
- {
- case 0:GetTime(); break;
- case 1:
- if(K3==0&&DateTime[6]<99)
- {
- while(K3==0);
- DateTime[6]++;}
- if(K4==0&&DateTime[6]>0)
- {
- while(K4==0);
- DateTime[6]--;
- }
- MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;
- //如果年份變化后當(dāng)前月份的天數(shù)大于上限則設(shè)為上限
- if(DateTime[3]>MonthsDays[DateTime[4]])
- DateTime[3]=MonthsDays[DateTime[4]];
- RefreshWeekDay();//刷新星期
- break;
- case 2:
- if(K3==0&&DateTime[4]<12)
- {
- while(K3==0);
- DateTime[4]++;}
- if(K4==0&&DateTime[4]>1)
- {
- while(K4==0);
- DateTime[4]--;
- }
- //獲取2月份天數(shù)
- MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;
- //如果變化后當(dāng)前月份的天數(shù)大于上限則設(shè)為上限
- if(DateTime[3]>MonthsDays[DateTime[4]])
- DateTime[3]=MonthsDays[DateTime[4]];
- RefreshWeekDay();//刷新星期
- break;
- case 3://日00-28/29/30/31,調(diào)節(jié)之前首先根據(jù)年份得出該年中2月的天數(shù)
- MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;
- //根據(jù)當(dāng)前的月份決定調(diào)節(jié)日期的上限
- if(K3==0&&DateTime[3]<MonthsDays[DateTime[4]])
- {
- while(K3==0);
- DateTime[3]++;}
- if(K4==0&&DateTime[3]>0)
- {
- while(K4==0);
- DateTime[3]--;
- }
- break;
- case 4://時(shí)
- if(K3==0&&DateTime[2]<23)
- {
- while(K3==0);
- DateTime[2]++;}
- if(K4==0&&DateTime[2]>0)
- {
- while(K4==0);
- DateTime[2]--; }
- break;
- case 5://分
- if(K3==0&&DateTime[1]<59)
- { while(K3==0);
- DateTime[1]++; }
- if(K4==0&&DateTime[1]>0)
- {while(K4==0);
- DateTime[1]--;
- }
- break;
- }
- }}
復(fù)制代碼 全部資料51hei下載地址:
仿真與程序.rar
(222.13 KB, 下載次數(shù): 111)
2021-1-12 22:36 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|