|
發布時間: 2024-5-19 07:40
正文摘要://60s倒計時 #include"stc8.h" #include "intrins.h" #define uint unsigned int #define uchar unsigned char #define SEG P1 sbit SCON1 = P3 ... |
| 去找《人人學會單片機》的課程資料 和 源代碼 每一份開源代碼 都是經過嚴格測試 千錘百煉 |
|
你的代碼有問題 中斷邏輯錯誤:定時器 0 中斷中使用if(flag=20)和if(flag=0)(賦值語句而非判斷語句),導致倒計時邏輯完全錯亂,無法正常遞減。 倒計時邊界處理缺失:未處理num減至 0 后的復位邏輯,且flag=60的賦值無意義,導致數值溢出或停滯。 動態掃描時序不合理:主函數中無延時直接切換數碼管位選,掃描頻率過快,肉眼無法識別,表現為 “不顯示” 或 “顯示模糊”。 數碼管段碼可能不匹配:若使用共陽極數碼管,當前段碼表(共陰極)會導致顯示異常,需確認硬件連接類型。
1. 修復中斷邏輯錯誤 將中斷中的if(flag=20)改為if(flag==200)(判斷語句而非賦值),且修正計時邏輯:5ms×200=1000ms(1 秒),確保每秒遞減 1。 增加num<0的邊界處理,倒計時結束后自動復位為 60,實現循環倒計時。 2. 優化數碼管動態掃描 新增Delay_ms()函數,在每位數碼管顯示后延時 5ms,降低掃描頻率,使肉眼能清晰識別數字(原代碼無延時,掃描過快導致 “不顯示”)。 初始位選設置為SCON1=1、SCON2=1(關閉狀態),避免初始化時數碼管串擾。 3. 修正數碼管段碼適配 段碼表標注共陰極 / 共陽極差異,若硬件使用共陽極數碼管,需替換段碼表(注釋中已給出共陽極段碼),否則會出現 “全亮” 或 “不顯示”。 4. 完善 IO 口初始化 明確 P1 口為推挽輸出(驅動數碼管段選),P3 口為準雙向模式(位選和按鍵輸入),匹配硬件驅動需求。 |
|
共陽的數碼管,你用共陰的代碼,提問之前請先說明清楚。 |
|
共陽極的那你得吧兩個SCON設置為推挽才行啊。要不然標準IO的高電平電流同時點亮8個段,即使亮也幾乎看不到吧。消隱要讓SCON=0,輸出SEG之后再把對應的SCON=1 |
hjx5548 發表于 2024-5-19 13:44 這樣也不能顯示? |
xiaobendan001 發表于 2024-5-19 10:19 //倒計時 #include"stc8.h" #include "intrins.h" #define uint unsigned int #define uchar unsigned char #define SEG P1 sbit SCON1 = P3^7; sbit SCON2 = P3^6; sbit KEY = P3^2; uchar count=0; char num=60,ge,shi; uchar flag; uchar code table[]={ 0x03,/*0*/ 0x9F,/*1*/ 0x25,/*2*/ 0x0D,/*3*/ 0x99,/*4*/ 0x49,/*5*/ 0x41,/*6*/ 0x1F,/*7*/ 0x01,/*8*/ 0x09,/*9*/}; void T0_init() //5毫秒@11.0592MHz { AUXR &= 0x7F; //定時器時鐘12T模式 TMOD &= 0xF0; //設置定時器模式 TMOD |= 0x01; //設置定時器模式 TL0 = 0x00; //設置定時初始值 TH0 = 0xEE; //設置定時初始值 TF0 = 0; //清除TF0標志 TR0 = 1; ET0 = 1; //使能定時器0中斷 EA = 1; } void IO_init() { P3M0 = 0x00; P3M1 = 0x00; P1M0 = 0xff; P1M1 = 0x00; } void TM0_Isr() interrupt 1 //5毫秒 { TL0 = 0x00; //設置定時初始值 TH0 = 0xEE; //設置定時初始值 flag++; if (flag=20) { flag=0; num--; if (num=0) { num=60; } } } void main() { IO_init(); T0_init() ; while (1) { SEG=0; shi=num/10; ge=num%10; switch (count) { case0:SCON1 = 0;SCON2=1; SEG = table[ge]; break; case1:SCON1 = 1;SCON2=0; SEG = table[shi]; break; default: break; } count++; if (count>1)count=0; } } |
xiaobendan001 發表于 2024-5-19 10:19 void TM0_Isr() interrupt 1 //5毫秒 { TL0 = 0x00; //設置定時初始值 TH0 = 0xEE; //設置定時初始值 flag++; if (flag=20) { flag=0; num--; if (num=0) { num=60; } } } |
|
原程序有多處錯誤:1. if (flag=20),應改為 if (flag==200) 2. 動態刷新時間太快,需合理設置count++的時間間隔 3. case0、case1應為case 0、case 1 …… 程序修改如下,僅供參考: void TM0_Isr() interrupt 1 //5毫秒 { TL0 = 0x00; //設置定時初始值 TH0 = 0xEE; //設置定時初始值 flag++; if(flag==200) { flag=0; num--; if (num==0) { num=60; } } //動態掃描刷新周期為10毫秒 count++; if (count>1) { count=0; } } void main() { IO_init(); T0_init() ; while(1) { shi=num/10; ge=num%10; SCON1 = 1; SCON2 = 1; //消隱 switch(count) { case 0: SCON1 = 1; SCON2 = 0; SEG = table[ge]; break; case 1: SCON1 = 0; SCON2 = 1; SEG = table[shi]; break; default: break; } } } |
| 每當flag++到20時,flag = 0然后立刻flag=60,然后flag++以后就得等他++到255再變0,重復++到20時再變60,再重復。就是大概flag計數215次num--一次,1075ms減一次,應該可以啊。為啥不顯示?是不顯示還是不計時?另外,SEG=0XFF是想消隱,但是你這是共陰的,因為你的SCON是設置的標準IO,那么只能共陰極了。共陰極的段碼要給0x00才行消隱,你這0xff不是一直亮著嗎?還有掃描切換不要放到主循環,這掃描速度得有多快啊。一個位的顯示時間可能太短了。消隱也可以把兩個SCON都置1。 |