|
本帖最后由 hxdby 于 2022-2-16 19:07 編輯
最近在調(diào)試中遇到一個非常詭異的問題!雖然我解決了,但是到現(xiàn)在我都不知道具體原因是啥, 特分享出來,與大家探討。
做了一個簡單的可以通過按鍵調(diào)整時間控制繼電器打開關(guān)閉的單片機(jī)板子,帶數(shù)碼管顯示,全部功能程序代碼都已經(jīng)完成,昨天板子我開了一夜做測試,今天早上起來突然發(fā)現(xiàn)一個鍵突然失靈了,不能切換分秒顯示了,我以為是按鍵壞了,結(jié)果不是。
先解釋板子的工作邏輯:1,板子帶一路繼電器,可以通過按鍵設(shè)置分和秒來設(shè)置繼電器打開和關(guān)閉的時間
2,繼電器打開時間設(shè)置函數(shù)是RELAY_SET_ON(), 繼電器關(guān)閉時間設(shè)置函數(shù)是RELAY_SET_OFF(); 這兩個函數(shù)實(shí)現(xiàn)功能和代碼都一樣,只是變量名不同
3,設(shè)置時間可以通過數(shù)碼管顯示,
4,總共三個按鍵,SW1, SW2, SW3。SW1是增加,SW2是減小。SW3是分和秒設(shè)置切換按鍵。簡單說就是,如果設(shè)置分鐘,按一下SW1,分鐘增加1,按一下SW2,分鐘減小1,如果要設(shè)置秒鐘,則按一下SW3,切換到秒鐘設(shè)置,然后在通過SW1/SW2來增減。
先上部分程序(不重要的單片機(jī)代碼就不貼出來,只貼重要的):
//全局變量
uint8_t relay_on_cnt =0; //打開時間設(shè)置中的分秒切換變量,通過SW3設(shè)置
uint8_t relay_off_cnt =0; //關(guān)閉時間設(shè)置中的分秒切換變量,通過SW3設(shè)置
uint8_t RELAY_min_set_ON =0 //繼電器打開時間設(shè)置中的分鐘變量
uint8_t RELAY_sec_set_ON = 0 //繼電器打開時間設(shè)置中的秒鐘變量
uint8_t RELAY_min_set_OFF =0 //繼電器關(guān)閉時間設(shè)置中的分鐘變量
uint8_t RELAY_sec_set_OFF = 0 //繼電器關(guān)閉時間設(shè)置中的分鐘變量
uint8_t key_number3 =0; //觸發(fā)的按鍵編號,當(dāng)SW3按下時,按鍵掃描KEY_SCAN()函數(shù)返回不同的key_number3鍵值
uint8_t key_number =0; //觸發(fā)的按鍵編號,當(dāng)SW1 或SW2按下時,key_number返回不同的鍵值
//函數(shù)原型
void RELAY_SET_ON(); //設(shè)置繼電器打開時間
void RELAY_SET_OFF(); //設(shè)置繼電器關(guān)閉時間
void KEY_SCAN() ; //按鍵掃描
void DISPLAY_MIN_SEC_SET(); //數(shù)碼管顯示設(shè)置的分秒?yún)?shù)
//主函數(shù)
int main (void)
{
while(1)
{
RELAY_SET_ON();
RELAY_SET_OFF();
KEY_SCAN() ;
}
}
// 函數(shù)定義
void RELAY_SET_ON(); //設(shè)置繼電器打開時間
{
switch (key_number3) //SW3按下
{
case 1: //SW3短按,relay_on_cnt計(jì)數(shù)器在0和1之間循環(huán)自加
relay_on_cnt ++;
if (relay_on_cnt >1)
{
relay_on_cnt=0;
}
key_number3=0;
break;
case 2:
relay_on_cnt --; //SW3長按超過1s,relay_on_cnt計(jì)數(shù)器在0和1之間循環(huán)連續(xù)自減,實(shí)現(xiàn)連擊功能
if (relay_on_cnt>1)
{
relay_on_cnt=1;
}
key_number3=0;
break;
default:; break;
}
/*以上的代碼主要是通過按下SW3來切換分鐘和秒鐘的設(shè)置,如果 relay_on_cnt=0,則進(jìn)入分鐘設(shè)置界面。如果 relay_on_cnt=1,則進(jìn)入秒鐘設(shè)置界面,這段代碼和RELAY_SET_OFF();中完全一樣,但是這里沒問題,RELAY_SET_OFF();會出現(xiàn)問題*/
if (relay_on_cnt==0) //繼電器打開分鐘設(shè)置
{
switch (key_number) //根據(jù)返回到鍵值進(jìn)行分鐘的加減操作
{
case 1: // SW1 觸發(fā),開始減操作
RELAY_min_set_ON --;
if (RELAY_min_set_ON >99)
{
RELAY_min_set_ON =99;
}
key_number=0;
break;
case 2: //SW2觸發(fā),開始加操作
RELAY_min_set_ON ++;
if (RELAY_min_set_ON >99)
{
RELAY_min_set_ON =0;
}
key_number=0;
break;
default: ; break;
}
}
if (relay_on_cnt==1) //秒設(shè)置
{
switch (key_number)
{
case 1: // SW1 觸發(fā),開始減操作
RELAY_sec_set_ON --;
if (RELAY_sec_set_ON >99)
{
RELAY_sec_set_ON =99;
}
key_number=0;
break;
case 2: //SW2觸發(fā),開始加操作
RELAY_sec_set_ON ++;
if (RELAY_sec_set_ON >99)
{
RELAY_sec_set_ON =0;
}
key_number=0;
break;
default: ; break;
}
}
DISPLAY_MIN_SEC_SET(); // 設(shè)置第參數(shù)在數(shù)碼管即時顯示
}
//函數(shù)定義
void RELAY_SET_OFF(); //設(shè)置繼電器關(guān)閉時間,該函數(shù)代碼與上述RELAY_SET_ON()中完全相同,只是變量名不同. 所以不再一一注釋
{
switch (key_number3)
{
case 1:
relay_off_cnt ++;
if (relay_off_cnt >1)
{
relay_off_cnt=0;
}
key_number3=0;
break;
case 2:
relay_off_cnt --;
if (relay_off_cnt>1)
{
relay_off_cnt=1;
}
key_number3=0;
break;
default:; break;
}
//上述紅色部分代碼出了問題。〕鰡栴}后,檢查了這部分代碼,和RELAY_SET_ON();中的完全一樣,后來復(fù)制了RELAY_SET_ON();中的這部分代碼到這里,改了變量名,問題就解決了!覺得很詭異,如果是這部分代碼出問題,那么在一開始就應(yīng)該有問題,而我的板子是跑了一夜之后出問題的,而且是100%必現(xiàn),我仔細(xì)檢查了代碼,完全一樣,手動修改某些變量,也不行。非得從RELAY_SET_ON();中復(fù)制才可以,why?????
if (relay_off_cnt==0)
{
switch (key_number)
{
case 1: // SW1 觸發(fā),開始減操作
RELAY_min_set_OFF --;
if (RELAY_min_set_OFF >99)
{
RELAY_min_set_OFF =99;
}
key_number=0;
break;
case 2: //SW2觸發(fā),開始加操作
RELAY_min_set_OFF ++;
if (RELAY_min_set_OFF >99)
{
RELAY_min_set_OFF =0;
}
key_number=0;
break;
default: ; break;
}
}
if (relay_off_cnt==1) //秒調(diào)整
{
switch (key_number)
{
case 1: // SW1 觸發(fā),開始減操作
RELAY_sec_set_OFF --;
if (RELAY_sec_set_OFF >99)
{
RELAY_sec_set_OFF =99;
}
key_number=0;
break;
case 2: //SW2觸發(fā),開始加操作
RELAY_sec_set_OFF ++;
if (RELAY_sec_set_OFF >99)
{
RELAY_sec_set_OFF =0;
}
key_number=0;
break;
default: ; break;
}
}
DISPLAY_MIN_SEC_SET();
}
現(xiàn)在的問題是,板子跑了一夜之后,繼電器關(guān)閉時間設(shè)置突然不顯示了,數(shù)碼管全黑。而繼電器打開設(shè)置界面是正常顯示的。我關(guān)閉板子電源,重新開機(jī),繼電器關(guān)閉時間設(shè)置界面可以顯示,但是只要一按SW3按鍵切換分秒設(shè)置,就沒顯示了,而且這個問題是100%必現(xiàn)。
我懷疑是RELAY_SET_OFF(); 中的程序出了問題,所以和RELAY_SET_ON(); 對比了一下,發(fā)現(xiàn)完全一樣,除了變量名不同,其他沒有任何區(qū)別。而且這個問題不是一直出現(xiàn)的,是板子開始是好的,我開機(jī)一夜,跑了一夜后突然變成這樣的。如果是程序問題,應(yīng)該從一開就會有問題。
我百思不得其解,因?yàn)槿绻荝ELAY_SET_OFF();程序問題,那RELAY_SET_ON();一定會出現(xiàn)問題,因?yàn)檫@兩個函數(shù)中的代碼邏輯完全相同,只是變量名不同,這套代碼也用了好幾月了,沒出過問題。但現(xiàn)在的問題是,兩個完全一樣的函數(shù),繼電器打開時間設(shè)置顯示沒有任何問題,而且問題只出在按下SW3按鍵的時候。
于是我開始研究SW3這一段代碼,也就是上述RELAY_SET_OFF();中紅色部分,我對比了幾百次,和RELAY_SET_ON();完全一樣,因?yàn)楸旧硪矝]有多少代碼。我突發(fā)奇想,把RELAY_SET_ON();中對應(yīng)部分代碼復(fù)制過來,然后改掉變量名,然后燒錄測試,板子居然好了!
我實(shí)在不理解為啥會這樣?非得復(fù)制才行?我覺得不可理解,究竟是啥原因,有沒有高人可以深入解釋下,感謝!
|
|