標題: 二個很菜的單片機中斷延時計數問題請高手指教修正 [打印本頁]
作者: xmcai 時間: 2020-4-8 20:21
標題: 二個很菜的單片機中斷延時計數問題請高手指教修正
在一段中斷計數延時的單片機程序設計中,被二個很菜的問題困擾著,請高手師傅指教改正。
1、 利用中斷計數設計一段8小時的長時間延時程序,計數滿8小時后繼電器自動接通工作5分鐘,然后重新進入8小時延時程序,如此循環,直至外部打斷使flag_5計時標志為0止。測試時,每個計數節用(20*60)*2時(即2分鐘),9節共18分鐘,可以正常接通繼電器,然后5分鐘后斷開,程序正常執行。但當每個計數節用(20*60)*54時(即54分鐘,最大也只能設定為54分鐘,因為最大計數為65536),按理應該在8.1小時后繼電器接通,但實際卻執行不了,繼電器始終不接通,不知問題出在哪?請高手指教改正。
if( flag_5==1 ) //如果計時標志5為1,進入下面8小時延時
{
temp_5++; //中斷計數變時5自+1
if(temp_5>=(20*60)*54) //(20*60)為延時1分鐘基數,*54可延時54分鐘
{
temp_6++;
if(temp_6>=(20*60)*54)
{
temp_7++;
if(temp_7>=(20*60)*54)
{
temp_8++;
if(temp_8>=(20*60)*54)
{
temp_9++;
if(temp_9>=(20*60)*54)
{
temp_10++;
if(temp_10>=(20*60)*54)
{
temp_11++;
if(temp_11>=(20*60)*54)
{
temp_12++;
if(temp_12>=(20*60)*54)
{
temp_13++;
if(temp_13>=(20*60)*54)
{
Relay=1; //上面計數延時滿山8小時,繼電器接通
temp_4=0;
temp_5=0;
temp_6=0;
temp_7=0;
temp_8=0;
temp_9=0;
temp_10=0;
temp_11=0;
temp_12=0;
temp_13=0;
flag_5=0;
flag_6=1;
}
}
}
}
}
}
}
}
}
}
if(flag_6==1) //如果計時標位flag_6=1
{
temp_6++; //中斷變量temp_6+1
if(temp_6>=(20*60)*54) //(20*60)為延時1分鐘,*5可延時5分鐘
{
Relay=0; //繼電器斷開
temp_6=0;
flag_6=0; //計時標志6清零
flag_5=1; //計時標志5為1,重新進入上面的循環
}
}
2、用一段do-while的循環程序替代上面的九節計數環節,卻延時不了,錯在何處,也請高手師傅指教一下。
if( flag_5==1) //如果計數標志為1,進入下面的循環環節
{
temp_5=0;
temp_6=0;
do
{
temp_5++;
if(temp_5>=(20*60)*54)
{
temp_5=0;
temp_6=temp_6+1;
}
}
while(temp_6<=9);
}
if(temp_6>=9)
{
Relay0=1; //繼電器接通
flag_5=0;
flag_6=1;
}
作者: hujj 時間: 2020-4-8 22:29
既然項目最小的計時單位是5分鐘,為什么不設置一個5分鐘的變量,每隔5分鐘這個變量增1,這樣整個處理過程應該會簡化很多。
作者: f556 時間: 2020-4-9 01:30
1、把主頻分頻降低,據各種MCU,有128分頻,設寄存器就行了
2、用一個變量計中斷次數,不行設個unsigned long變量,幾個小時不成問題
作者: wulin 時間: 2020-4-9 08:12
給你一個示例,定時精度取決于晶振精度。未經實物驗證,只是供參考。如果加上數碼管顯示和進一步優化可以做成倒計時顯示并使計時誤差控制在1秒內。
- #include <reg51.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit key=P1^0;
- sbit LED=P1^6;
- sbit OUT=P1^7;
- uchar Cnt50ms=0;sec=0;//50毫秒、秒變量
- uint min=0;//分變量
- bit flag_5=0;//計時標志
- void Timer0Init() //50毫秒@12.000MHz
- {
- TMOD= 0x01; //設置定時器模式
- TL0 = 0xB0; //設置定時初值
- TH0 = 0x3C; //設置定時初值
- TR0 = 1; //定時器0開始計時
- EA = 1; //開總中斷
- ET0= 1; //開定時器0中斷
- }
- void keyscan()
- {
- static bit key_sign=0;//按鍵自鎖標志變量
- static uchar count=0; //消抖計數變量
- if(!key)
- {
- if(++count>=100 && key_sign==0)
- {
- key_sign=1;//自鎖
- flag_5=~flag_5;//取反
- if(flag_5==0)
- LED=1;//燈熄 定時器停止工作
- else
- LED=0;//燈亮 定時器工作中
- //清0 為重新計時準備
- Cnt50ms=0;
- sec=0;
- min=0;
- }
- }
- else//松手
- {
- count=0;//消抖計數變量清0
- key_sign=0;//自鎖標志清0
- }
- }
- void main()
- {
- OUT=0; //初始化輸出端口
- Timer0Init();//初始化定時器
- while(1)
- {
- keyscan();//按鍵掃描
- }
- }
- /**************中斷服務程序*****************/
- void timer0() interrupt 1
- {
- TL0 = 0xB0; //重裝定時初值
- TH0 = 0x3C; //重裝定時初值
- if(flag_5==1)
- {
- Cnt50ms++; //中斷變量Cnt50ms自+1
- if(Cnt50ms>=20) //1秒
- {
- Cnt50ms=0;
- sec++;
- if(sec>=60) //1分
- {
- sec=0; //秒計數
- min++;
- }
- }
- if(min<480) //8小時
- OUT=0;
- if(min>=480||min<485) //8小時與8小時零5分之間
- OUT=1;
- if(min>=485) //8小時零5分時間到
- {//全部清0
- OUT=0;
- Cnt50ms=0;
- sec=0;
- min=0;
- // flag_5=0;//不重復循環
- }
- }
- }
復制代碼
作者: 黃youhui 時間: 2020-4-9 08:46
看著代碼好費勁啊,你就不能將你的temp_5++ temp_6++封裝個函數調用一下嗎
作者: xmcai 時間: 2020-4-9 12:15
非常感謝wulin師傅的無私指導,您已多次指導,受您啟發,多次受益,均已成功,謝謝您!!
作者: game灬boy 時間: 2020-4-9 13:14
你的測試5分鐘可行對吧;然后在5分鐘的基礎上再定義1個變量 分鐘m;
假設你的5分鐘技數count=50時為5分鐘
8小時60*8=480分鐘480/5=96
m=96時;繼電器使能;m=97時;繼電器關閉使能;
if (count==50)
{
m++;
if(m==96)
使能flag=1;
if(m==97)
{
使能flag=0;
m=0;
}
count=0;
}
作者: xmcai 時間: 2020-4-9 21:38
謝謝指導!
| 歡迎光臨 (http://www.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |