![]() |
本帖最后由 金溪小書童 于 2018-11-11 10:15 編輯 重復了 |
在原作者的基礎上,修改成了99分鐘倒計時,帶暫停, 設置好時間,按下開關,倒計時開始,再次按開關,計時停止,繼電器在倒計時開始就吸合,直到倒計時結束才松開,暫停不影響繼電器. 剛接觸單片機,程序還不能單獨寫,只停留在稍微能看懂. //#include<reg52.h> #include<STC12C2052AD.h> //庫文件 #include<intrins.h> #define uchar unsigned char //宏定義字符型變量 #define uint unsigned int //宏定義整型變量 /*聲明 SFR 相關 與 的 IAP*/ sfr IAP_DATA = 0xE2; sfr IAP_ADDRH = 0xE3; sfr IAP_ADDRL = 0xE4; sfr IAP_CMD = 0xE5; sfr IAP_TRIG = 0xE6; sfr IAP_CONTR = 0xE7; /******************************************************************** IO口定義 ********************************************************************/ uchar s1=0; bit write=0; uint txian,dxian; uchar txian1,txian2; uchar dxian1,dxian2; uchar T0RH=0,T0RL=0; uint ms=0; uchar A1,A2; uchar B1,B2; uchar C1,C2; uchar D1,D2; bit bz1=0; bit bz2=0; sbit P10=P1^0;//數碼管段 sbit P11=P1^1;//數碼管段 sbit P12=P1^2;//數碼管段 sbit P13=P1^3;//數碼管段 sbit P14=P1^4;//數碼管段 sbit P15=P1^5;//數碼管段 sbit P16=P1^6;//數碼管段 sbit AIN1=P1^7;//信號輸入 sbit P30=P3^0;//按鍵輸入 sbit P31=P3^1;//按鍵輸入 sbit P32=P3^2;//數碼管位 sbit P33=P3^3;//數碼管位 sbit LED1=P3^4;//? sbit LED2=P3^5;//? sbit OUT1=P3^7;//繼電器輸出 bit ts=1; // bit yxbz=0; // uint xianshi; /******************************************************************** 定義 ISP/IAP/EEPROM 命令 *********************************************************************/ #define CMD_IDLE 0 #define CMD_READ 1 #define CMD_PROGRAM 2 #define CMD_ERASE 3 #define ENABLE_IAP 0x83//SYSCLK<12MH #define IAP_ADDRESS 0x0000//存儲地址 /******************************************************************** 禁用 ISP/IAP/EEPROM functionmake 單片機 在 一 安全 狀態 *********************************************************************/ void IapIdle() { IAP_CONTR = 0; // IAP_CMD = 0; // IAP_TRIG = 0; // IAP_ADDRH = 0x80; // IAP_ADDRL = 0; // } /******************************************************************** 讀數據 *********************************************************************/ uchar IapReadByte(uint addr) { uchar dat; IAP_CONTR = ENABLE_IAP; IAP_CMD = CMD_READ; IAP_ADDRL = addr; IAP_ADDRH = addr >> 8; IAP_TRIG = 0x46; IAP_TRIG = 0xb9; _nop_(); dat = IAP_DATA; IapIdle(); return dat; } /******************************************************************** 寫數據 *********************************************************************/ void IapProgramByte(uint addr, uchar dat) { IAP_CONTR = ENABLE_IAP; IAP_CMD = CMD_PROGRAM; IAP_ADDRL = addr; IAP_ADDRH = addr >> 8; IAP_DATA = dat; IAP_TRIG = 0x46; IAP_TRIG = 0xb9; _nop_(); IapIdle(); } /******************************************************************** 擦除數據 *********************************************************************/ void IapEraseSector(uint addr) { IAP_CONTR = ENABLE_IAP; IAP_CMD = CMD_ERASE; IAP_ADDRL = addr; IAP_ADDRH = addr >> 8; IAP_TRIG = 0x46; IAP_TRIG = 0xb9; _nop_(); IapIdle(); } /******************************************************************** 初始定義 *********************************************************************/ code uchar seg7code[10]={0xfB,0x89,0xf5,0xdD,0x8F,0xdE,0xfE,0xc9,0xfF,0xdF}; //顯示段碼 數碼管字跟 /******************************************************************** 延時函數 *********************************************************************/ void delay(uchar t) { uchar i,j; for(i=0;i<t;i++) { for(j=130;j>0;j--); { ; } } } /******************************************************************** 顯示函數 接通時間 *********************************************************************/ //void tong(uchar tdate) //顯示函數 void tong() //顯示函數 { C1=txian%100/10; C2=txian%10; P32=1;P33=1; P1=seg7code[C1]; P32=0;P33=1; delay(80); P32=1;P33=1; P1=seg7code[C2]; P32=1;P33=0; delay(80); } void key() { if(P30==0) { delay(80); if(P30==0) { s1++; if(s1>=4){s1=0;} while(!P30); } }} //定時器0初始化 void t0_init(unsigned char ms0) //ms0最大71 { /*********************************************** 一個機器周期=12*時鐘周期。 11059200為時鐘周期,一共為11059200/12=921600,就是每秒為921600Hz, 八位定時器 最大計時 0.2777778ms 十六位定時器最大計時 71.111111ms 11.0592MHz除12為921600Hz,就是一秒921600次機器周期,10ms=9216次機器周期。 65536-9216=56320(dc00) TH0=0xdc,TL0=0x00 ***********************************************/ long tmp; //臨時變量 tmp = 11059200 / 12; tmp = (tmp * ms0) / 1000; tmp = 65536 - tmp; tmp = tmp + 3; T0RH = (unsigned char)(tmp>>8); T0RL = (unsigned char)tmp; TMOD &=0XF0; TMOD |=0X01; //方式一 一共四種方式 GATE0 C/T0 M0_1 M0_0 C/T0選擇時鐘計數還是外部計數 方式0是十三位定時器 ,方式1是十六位定時器,方式2是八位自動 方式4是兩個八位 TH0=T0RH; TL0=T0RL; ET0=1; //使能T0中斷 EA=1; TR0=1; } /******************************************************************** 主函數 *********************************************************************/ void main() { unsigned char flag=1,flag2=0;; txian1 = IapReadByte(0x01); //讀取0x01中的數據 并附給ca txian2 = IapReadByte(0x02); //讀取0x01中的數據 并附給ca t0_init(10); P1M0=0X00;P1M1=0X7f; txian=txian1*10+txian2; xianshi=txian; OUT1=1; //ts=0;bz1=1;ms=0;OUT1=0; while(1) { key(); if((AIN1==0)&&(bz1==0)&&(ts==0)){delay(80); if(AIN1==0){bz1=1;yxbz=!yxbz;}} if((AIN1==0)&&(bz1==0)&&(ts==1)){delay(80); if(AIN1==0){yxbz=1;ts=0;bz1=1;ms=0;OUT1=0;}} if((AIN1==1)&&(bz1==1)){bz1=0;} if(write==1) { TR0=0; write=0; IapEraseSector(0); IapProgramByte(0x01,txian1); IapProgramByte(0x02,txian2); TR0=1; xianshi=txian; } } } void t0(void) interrupt 1 using 0 //定時中斷服務函數 { TH0=T0RH; TL0=T0RL; switch (s1){ case 0: tong();break; case 1:ts=1;P1=seg7code[A1];P32=0;P33=1;if(P31==0){A1++;if(A1>9)A1=0;while(!P31);}break; case 2: P1=seg7code[A2];P32=1;P33=0;if(P31==0){A2++;if(A2>9)A2=0;while(!P31);}break; case 3: txian1=A1;txian2=A2;txian=txian1*10+txian2;write=1;break; default: break; } if(yxbz==1) { ms++; if(ms==4800) //ms=80是1秒 { ms=0; if(ts==0){txian--;if(txian<=0){bz1=0;OUT1=1;txian=txian1*10+txian2;ts=1;}} } } } |
程序來自這個帖子里的,http://www.zg4o1577.cn/bbs/dpj-107742-1.html |