久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1574|回復: 11
打印 上一主題 下一主題
收起左側

一個非常詭異的單片機程序調試問題

[復制鏈接]
跳轉到指定樓層
樓主
ID:997026 發表于 2022-2-16 13:25 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
本帖最后由 hxdby 于 2022-2-16 19:07 編輯

最近在調試中遇到一個非常詭異的問題!雖然我解決了,但是到現在我都不知道具體原因是啥, 特分享出來,與大家探討。

做了一個簡單的可以通過按鍵調整時間控制繼電器打開關閉的單片機板子,帶數碼管顯示,全部功能程序代碼都已經完成,昨天板子我開了一夜做測試,今天早上起來突然發現一個鍵突然失靈了,不能切換分秒顯示了,我以為是按鍵壞了,結果不是。

先解釋板子的工作邏輯:1,板子帶一路繼電器,可以通過按鍵設置分和秒來設置繼電器打開和關閉的時間
2,繼電器打開時間設置函數是RELAY_SET_ON(), 繼電器關閉時間設置函數是RELAY_SET_OFF(); 這兩個函數實現功能和代碼都一樣,只是變量名不同
3,設置時間可以通過數碼管顯示,
4,總共三個按鍵,SW1, SW2, SW3。SW1是增加,SW2是減小。SW3是分和秒設置切換按鍵。簡單說就是,如果設置分鐘,按一下SW1,分鐘增加1,按一下SW2,分鐘減小1,如果要設置秒鐘,則按一下SW3,切換到秒鐘設置,然后在通過SW1/SW2來增減。

先上部分程序(不重要的單片機代碼就不貼出來,只貼重要的):

//全局變量

uint8_t    relay_on_cnt =0; //打開時間設置中的分秒切換變量,通過SW3設置
uint8_t    relay_off_cnt =0; //關閉時間設置中的分秒切換變量,通過SW3設置
uint8_t    RELAY_min_set_ON =0 //繼電器打開時間設置中的分鐘變量
uint8_t    RELAY_sec_set_ON = 0 //繼電器打開時間設置中的秒鐘變量

uint8_t    RELAY_min_set_OFF =0  //繼電器關閉時間設置中的分鐘變量
uint8_t    RELAY_sec_set_OFF = 0 //繼電器關閉時間設置中的分鐘變量


uint8_t    key_number3 =0; //觸發的按鍵編號,當SW3按下時,按鍵掃描KEY_SCAN()函數返回不同的key_number3鍵值
uint8_t    key_number =0; //觸發的按鍵編號,當SW1 或SW2按下時,key_number返回不同的鍵值



//函數原型

void  RELAY_SET_ON(); //設置繼電器打開時間
void  RELAY_SET_OFF(); //設置繼電器關閉時間
void  KEY_SCAN() ;  //按鍵掃描
void  DISPLAY_MIN_SEC_SET();  //數碼管顯示設置的分秒參數

//主函數

int  main (void)
{
   while(1)
{
  RELAY_SET_ON();
  RELAY_SET_OFF();
  KEY_SCAN() ;
}


}




// 函數定義
void  RELAY_SET_ON();  //設置繼電器打開時間

{
     switch (key_number3) //SW3按下
        {
        case 1:  //SW3短按,relay_on_cnt計數器在0和1之間循環自加
        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計數器在0和1之間循環連續自減,實現連擊功能
        if (relay_on_cnt>1)
        {
                relay_on_cnt=1;
        }
        key_number3=0;
        break;
        
        default:; break;
        }
/*以上的代碼主要是通過按下SW3來切換分鐘和秒鐘的設置,如果 relay_on_cnt=0,則進入分鐘設置界面。如果 relay_on_cnt=1,則進入秒鐘設置界面,這段代碼和RELAY_SET_OFF();中完全一樣,但是這里沒問題,RELAY_SET_OFF();會出現問題*/      


       if (relay_on_cnt==0)  //繼電器打開分鐘設置
        {
                switch (key_number)  //根據返回到鍵值進行分鐘的加減操作
                {
                        case 1:  // SW1 觸發,開始減操作
                        RELAY_min_set_ON --;
                        if (RELAY_min_set_ON >99)  
                        {
                                RELAY_min_set_ON =99;
                        }
                        
                        key_number=0;
                        
                        break;
                        
                        case 2: //SW2觸發,開始加操作
                        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) //秒設置
        {
                        switch (key_number)
                        {
                                case 1:  // SW1 觸發,開始減操作
                                RELAY_sec_set_ON --;
                                if (RELAY_sec_set_ON >99)  
                                {
                                        RELAY_sec_set_ON =99;
                                }
                                
                                key_number=0;
                                
                                break;
                                
                                case 2: //SW2觸發,開始加操作
                                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();  // 設置第參數在數碼管即時顯示        


}



//函數定義
void  RELAY_SET_OFF();  //設置繼電器關閉時間,該函數代碼與上述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();中的完全一樣,后來復制了RELAY_SET_ON();中的這部分代碼到這里,改了變量名,問題就解決了!覺得很詭異,如果是這部分代碼出問題,那么在一開始就應該有問題,而我的板子是跑了一夜之后出問題的,而且是100%必現,我仔細檢查了代碼,完全一樣,手動修改某些變量,也不行。非得從RELAY_SET_ON();中復制才可以,why?????


       if (relay_off_cnt==0)
        {
                switch (key_number)
                {
                        case 1:  // SW1 觸發,開始減操作
                        RELAY_min_set_OFF --;
                        if (RELAY_min_set_OFF >99)  
                        {
                                RELAY_min_set_OFF =99;
                        }
                        
                        key_number=0;
                        
                        break;
                        
                        case 2: //SW2觸發,開始加操作
                        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) //秒調整
        {
                        switch (key_number)
                        {
                                case 1:  // SW1 觸發,開始減操作
                                RELAY_sec_set_OFF --;
                                if (RELAY_sec_set_OFF >99)  
                                {
                                        RELAY_sec_set_OFF =99;
                                }
                                
                                key_number=0;
                                
                                break;
                                
                                case 2: //SW2觸發,開始加操作
                                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();
        


}

現在的問題是,板子跑了一夜之后,繼電器關閉時間設置突然不顯示了,數碼管全黑。而繼電器打開設置界面是正常顯示的。我關閉板子電源,重新開機,繼電器關閉時間設置界面可以顯示,但是只要一按SW3按鍵切換分秒設置,就沒顯示了,而且這個問題是100%必現。

我懷疑是RELAY_SET_OFF(); 中的程序出了問題,所以和RELAY_SET_ON(); 對比了一下,發現完全一樣,除了變量名不同,其他沒有任何區別。而且這個問題不是一直出現的,是板子開始是好的,我開機一夜,跑了一夜后突然變成這樣的。如果是程序問題,應該從一開就會有問題。

我百思不得其解,因為如果是RELAY_SET_OFF();程序問題,那RELAY_SET_ON();一定會出現問題,因為這兩個函數中的代碼邏輯完全相同,只是變量名不同,這套代碼也用了好幾月了,沒出過問題。但現在的問題是,兩個完全一樣的函數,繼電器打開時間設置顯示沒有任何問題,而且問題只出在按下SW3按鍵的時候。

于是我開始研究SW3這一段代碼,也就是上述RELAY_SET_OFF();中紅色部分,我對比了幾百次,和RELAY_SET_ON();完全一樣,因為本身也沒有多少代碼。我突發奇想,把RELAY_SET_ON();中對應部分代碼復制過來,然后改掉變量名,然后燒錄測試,板子居然好了!

我實在不理解為啥會這樣?非得復制才行?我覺得不可理解,究竟是啥原因,有沒有高人可以深入解釋下,感謝!

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:213173 發表于 2022-2-16 17:32 | 只看該作者
代碼有點長,粗略看了一下,無非就是個可調定時開關。程序夠架不太合理,最關鍵的是main函數沒有約束在while(1)中運行,隨時都有可能跑飛。
回復

使用道具 舉報

板凳
ID:997026 發表于 2022-2-16 19:08 | 只看該作者
wulin 發表于 2022-2-16 17:32
代碼有點長,粗略看了一下,無非就是個可調定時開關。程序夠架不太合理,最關鍵的是main函數沒有約束在whil ...

不好意思,while(1)原程序中肯定有的,貼程序的時候漏掉了。
回復

使用道具 舉報

地板
ID:311903 發表于 2022-2-16 19:30 | 只看該作者
代碼太亂不想看,但是你可以試試編譯的時候全部文件重新編譯
回復

使用道具 舉報

5#
ID:213173 發表于 2022-2-16 19:42 | 只看該作者
hxdby 發表于 2022-2-16 19:08
不好意思,while(1)原程序中肯定有的,貼程序的時候漏掉了。

把你的確切需求和硬件環境詳細講清楚,有空給你寫一個示例。
回復

使用道具 舉報

6#
ID:429003 發表于 2022-2-17 16:13 | 只看該作者
代碼難得看,但從你描述來看,問題應該不是程序的問題。估計是單片機FLASH某個位置出了點故障了,不能置0又或者不能至1。如果這個板子燒寫你發生故障前的代碼每次必定出現,那么基本可以確定就是FLASH故障了。

你稍微調整一下代碼,編譯后燒寫文件發生了變化,恰巧與故障點位的值相符,也就巧妙的避開這一問題。
回復

使用道具 舉報

7#
ID:429003 發表于 2022-2-17 16:25 | 只看該作者
另外,你的設計是用單片機控制繼電器,是否繼電器控制線圈未設計續流二極管?
如果沒有續流二極管,這樣繼電器線圈斷開瞬間的感應電流無處泄放,線圈兩端會產生很高的感應電壓,這個感應電壓串入你的單片機系統,那就很有可能燒壞一些器件,單片機FLASH被燒壞一些位置,也不是沒有可能。
回復

使用道具 舉報

8#
ID:584814 發表于 2022-2-17 17:19 | 只看該作者
有些問題看似莫名其妙的,可能是程序中有肉眼不可見的啥,也可能硬件里出現了個啥;
有些問題真的莫名其妙的,曾經調試程序時只在中間加了個空行(多個回車)就完美解決問題……
別以為單片機個個都是完美的,編譯環境環境也全都是完美的......Bug無處不在
個人感覺,經驗就是不斷試錯,物理學上的成功有時未必都能講出道理。
先按書上寫的辦,畢竟是眾人的經驗集成,廣告可以看但別全信;
不行后按自己的想法去干,成了有機會多驗證再發展,又可能成長出一代宗師
回復

使用道具 舉報

9#
ID:997026 發表于 2022-2-17 17:38 | 只看該作者
xstong 發表于 2022-2-17 16:25
另外,你的設計是用單片機控制繼電器,是否繼電器控制線圈未設計續流二極管?
如果沒有續流二極管,這樣繼 ...

感謝回復。
繼電器端加了足夠的保護電路,包括續流二極管,壓敏電阻,二極管用的是1N4007反向電壓1000V,壓敏電阻并接在繼電器觸點端消電弧。所以應該不是繼電器的問題。
回復

使用道具 舉報

10#
ID:997026 發表于 2022-2-17 17:40 | 只看該作者
man1234567 發表于 2022-2-17 17:19
有些問題看似莫名其妙的,可能是程序中有肉眼不可見的啥,也可能硬件里出現了個啥;
有些問題真的莫名其妙 ...

有道理,但這個問題確實想不通,平常都是遇到代碼本身邏輯問題,但第一次遇見這樣的問題,也是見鬼了。

回復

使用道具 舉報

11#
ID:997026 發表于 2022-2-17 17:40 | 只看該作者
wulin 發表于 2022-2-16 19:42
把你的確切需求和硬件環境詳細講清楚,有空給你寫一個示例。

感謝!

但應該不是代碼本身問題,是一個莫名其妙的問題。我這個代碼連續開機測試好幾天了,挺穩定的。
回復

使用道具 舉報

12#
ID:236035 發表于 2022-2-18 09:36 | 只看該作者
出現問題,能恢復到正常,則跟蹤調試恢復過程中涉及到的代碼就可以了。只要是能重現故障的,就一定可以找到故障點。至于說以前正常,突然不正常,任何項目都有健壯度的,不論電路還是程序。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久蜜桃av一区二区天堂 | 国产欧美一级二级三级在线视频 | 黄a大片| 中文字幕av一区 | 韩国精品一区二区三区 | 久热国产精品视频 | 日韩一区二区三区在线视频 | 国产视频精品在线 | 日韩黄a| www.操com| 国产婷婷色综合av蜜臀av | 99re66在线观看精品热 | 日韩高清在线 | 欧美日韩在线一区 | 国产一区二区精品在线观看 | 午夜寂寞影院列表 | 日本中文字幕一区 | m豆传媒在线链接观看 | 2021天天干夜夜爽 | 亚洲精品电影在线观看 | 特黄色一级毛片 | 又黄又爽的网站 | 草久久| 日韩精品成人免费观看视频 | 国产精品成人一区二区三区 | 成人精品在线视频 | 精品一区久久 | 九九热这里只有精品在线观看 | 欧美国产一区二区 | 一级毛片免费 | 成人在线免费电影 | 日韩电影免费观看中文字幕 | 嫩草国产 | 久久久片 | av一级毛片| 免费在线看黄视频 | 四虎影院新地址 | 精品一区二区av | 亚洲成人av在线 | 草久久 | 99日韩|