找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4801|回復(fù): 1
收起左側(cè)

藍(lán)橋杯單片機(jī)第八屆省賽 程序題解析(完美調(diào)試,清晰解析)

[復(fù)制鏈接]
ID:586435 發(fā)表于 2020-3-22 21:04 | 顯示全部樓層 |閱讀模式
本帖最后由 黑夜的星光 于 2020-3-22 21:14 編輯

             Hellow !大家好,今天找個時(shí)間把第八屆的題也發(fā)出來 一起探討學(xué)習(xí)一下。自己呢也算做一個的經(jīng)歷筆記吧 (哈哈哈哈)
                                                      試想一下 10年后的自己看到這淺陋的代碼,不知道會有什么感慨呢..................(hahaha....隔~)


                                        ps:帖子今天用了 一個粉紅的顏色,哈哈哈,看著比較養(yǎng)眼舒服吧,若努力學(xué)習(xí)的                                                                                                         同學(xué)不嫌棄這些代碼的話,希望這粉紅能一定程度上減緩你們的疲勞



自己在調(diào)試的時(shí)候呢, 最頭大的地方就是DS1302不能讀取時(shí)間(DS1302驅(qū)動代碼都沒問題)
   原因有二:
                   其一 :自己在上電初始化的函數(shù)中,將P22 = 0了,(我做了測試,將其P22 = 1時(shí),可以正常工作) 詳細(xì)請看代碼
                   其二 :開發(fā)板是自己焊接的,可能P2引腳有短路的問題存在。
       起初把自己調(diào)試的都懷疑人生了   啊哈哈哈。真的很難受。哎..........     最后調(diào)試出來的時(shí)候又喜悅到了極點(diǎn)

說一下自己對賽題的看法吧,賽題沒有太新穎,生疏的考點(diǎn),整體難度還是不低的。主要是按鍵的功能標(biāo)志位的邏輯關(guān)系以及對數(shù)碼管的多工作界面的切換,數(shù)碼管玩的是真的很....ennenen
     中斷不要多做事情,快進(jìn)快出。一般LED的(指示燈之類的)標(biāo)志位處理放在中斷處理比其他函數(shù)內(nèi)要好很多。先把簡單的容易實(shí)現(xiàn)的功能調(diào)試出      來,最后再去寫復(fù)雜的邏輯代碼。
     寫完一個邏輯功能就去編譯一下,看一下有沒有語法錯誤,不然等到最后錯誤太多,調(diào)試會復(fù)雜很多。然后單獨(dú)的模塊完成后記著上電驗(yàn)證一下,使其逐漸能銜接起來。
   好的算法有時(shí)會起到意想不到的好處,多看看一些大佬的算法,以及一些好的思維方式。慢慢積累,對自己的好處也會慢慢變的明顯。

以上都是自己的卑鄙拙見,期間也受到了一些大佬的思維啟蒙,非常感謝。
  自己多單片機(jī)的感悟就是3點(diǎn) 多寫 多看 多想。  只有在自己親自寫的時(shí)候,才能體會到他們的真正含義,而且要多寫,形成自己的邏輯思維;多看別人的優(yōu)秀的地方,如算法,思維,積累這些,自己學(xué)著去消化使用,慢慢變成自己的; 多想想自己編寫不出來的地方,想想功能模塊之間的聯(lián)系,怎樣做才能使完善,實(shí)現(xiàn)想要的結(jié)果。


                                                   
     學(xué)而不思則罔,思而不學(xué)則殆



好了,咱們上題




8DF@%P3H`JUC35OL5R9H@[R.png



OE(KS[_9P4C0YDI910M@S4N.png





代碼如下

main.c文件

/*****************************************************************************************************************************************
藍(lán)橋杯第八屆省賽習(xí)題


【細(xì)節(jié)提示】:在ds1302.c文件中定義了 有符號的數(shù)據(jù)變量 char Inittime[],以及必須在ds1302.h文件中進(jìn)行 extern 全局的調(diào)用聲明
【主要難點(diǎn)】:數(shù)碼管的工作界面的切換,按鍵對工作標(biāo)志位的使能以及互不干擾
【代碼說明】:不同的代碼編寫都有其高效的地方和一些功能需復(fù)雜實(shí)現(xiàn)的地方,要合理看待      
                 本題中:   多處使用了  P2 = (P2 & 0xFF) | 0x04; (對DS1302的工作使能)。
                                                                            我調(diào)試的很長時(shí)間,ds1302一直不能工作。加上這句代碼后(P22 = 1),一切都好了。
      【不知道是不是我開發(fā)板的問題,你要是使用的話,可以去掉這句代碼測試一下】
                       
******************************************************************************************************************************************/
#include "ds18b20.h"
#include "ds1302.h"
#include "smg.h"

#define uchar unsigned
#define uint  unsigned
       
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

uchar flag_S7 = 0;               //S7功能選擇位
uchar flag_S6 = 0;               //S6功能選擇位
uchar flag_S5 = 0;               //S5功能選擇位
uchar flag_S4 = 0;               //S4功能選擇位

bit flag_Clock = 0;              //鬧鐘響起標(biāo)志位
bit flag_led = 0;                //L1閃爍標(biāo)志位,用于鬧鐘重置恢復(fù)閃爍狀態(tài) 【0-led閃爍開始標(biāo)志;1-led閃爍停止標(biāo)志】
bit flag_1s = 0;                 //時(shí)鐘設(shè)置狀態(tài)下1s閃爍標(biāo)志位 【0是亮,1是滅】

uchar temp;                      //讀取溫度變量
char Clock_date[] = {0,0,0};     //鬧鐘數(shù)據(jù)

void KeyScan();                  //按鍵檢測
void SMGdisplay();                                                   //數(shù)碼管顯示                                               
void ConfigTime0();              //配置定時(shí)器0
void Detection_Clock();          //檢測鬧鐘
void Close_Clock();              //關(guān)閉鬧鐘
void ZSD_L1();                   //鬧鐘指示燈
void dateStyle();                //鬧鐘,時(shí)鐘數(shù)據(jù)轉(zhuǎn)換函數(shù)





void main()
{   
          Init_waise();
          ConfigTime0();
    InitDS1302();
          while(1)
                {         
      if(flag_S7 == 0)        R_time();                                  
                         KeyScan();
                         SMGdisplay();
                         Detection_Clock();
                }
}




/*********************************************************************************************
【函數(shù)】 數(shù)碼管顯示界面切換函數(shù)
【功能】 負(fù)責(zé)按鍵使能切換數(shù)碼管顯示狀態(tài)
【小難點(diǎn)】 在時(shí)鐘設(shè)置期間,使操作位1s間隔閃爍。在中斷或者S7按鍵中做好標(biāo)志位即可(本代碼在中斷)
*********************************************************************************************/
void SMGdisplay()
{
   if(flag_S7 >= 0 && flag_S6 == 0 && flag_1s == 0)       Time(Inittime[2],Inittime[1],Inittime[0]);
         else if(flag_S7 == 1 && flag_1s == 1)                  SetTime(0xFF, 0xFF, Inittime[1]/10,Inittime[1]%10, Inittime[0]/10, Inittime[0]%10);
         else if(flag_S7 == 2 && flag_1s == 1)                  SetTime(Inittime[2]/10,Inittime[2]%10, 0xFF, 0xFF, Inittime[0]/10, Inittime[0]%10);
         else if(flag_S7 == 3 && flag_1s == 1)                  SetTime(Inittime[2]/10,Inittime[2]%10, Inittime[1]/10, Inittime[1]%10, 0xFF, 0xFF);
         else if(flag_S7 == 0 && flag_S6 > 0)                   Time(Clock_date[2],Clock_date[1],Clock_date[0]);
}

/*********************************************************************************************************************************
【函數(shù)】 按鍵檢測函數(shù)
【功能】 按下按鍵觸發(fā)相應(yīng)工作標(biāo)志位
【優(yōu)化】 在按鍵彈起等待while(S? == 0)期間優(yōu)化了對應(yīng)數(shù)碼管功能,使數(shù)碼管不會再按鍵按下彈起期間閃爍或抖動
【算法】 使用的對按鍵功能選擇位的處理  加4為0(詳見S6)
【額外說明】對按鍵的工作使能位的操作以及對數(shù)碼管多狀態(tài)的選擇切換是本賽題中的最大的難點(diǎn),一定要理清好功能之間的邏輯關(guān)系
*********************************************************************************************************************************/
void KeyScan()
{
   if(S7 == 0)
         {
            delay(200);          
                  if(S7 == 0 && flag_S6 == 0 && flag_Clock == 0)
                        {
                                 flag_S7 ++;
                                 if(flag_S7 >3)  
                                 {
                                          flag_S7 = 0;
                                    flag_1s = 0;
                                 }                                         
                        }while(S7 == 0)
                        {
                                 if(flag_S6 == 0)       Time(Inittime[2],Inittime[1],Inittime[0]);
                                 else if(flag_S6 > 0)   Time(Clock_date[2],Clock_date[1],Clock_date[0]);
                        }
                        Close_Clock();
         }
         
         if(S6 == 0)
         {
            delay(200);
                  if(S6 == 0 && flag_S7 == 0 && flag_Clock == 0)
                        {
                                 flag_S6 ++;
                                 flag_S6 &= 0x03;    //加4為0
                        }while(S6 == 0)
                        {
                           if(flag_S6 == 0)       Time(Inittime[2],Inittime[1],Inittime[0]);
                                 else if(flag_S6 > 0)   Time(Clock_date[2],Clock_date[1],Clock_date[0]);
                        }
                        Close_Clock();
         }
         
         if(S5 == 0)
         {
            delay(200);
                  if(S5 == 0 && flag_Clock == 0)
                        {  
                                 if(flag_S7)
                                 {
                                    switch(flag_S7)
                                                {
                                                         case 1: Inittime[2] ++;   break;
                                                         case 2: Inittime[1] ++;   break;
                                                         case 3: Inittime[0] ++;   break;
                                                         default: break;
                                                }
                                 }
                                 else if(flag_S6)
                                 {
                                    switch(flag_S6)
                                                {
                                                         case 1: Clock_date[2] ++;  break;
                                                         case 2: Clock_date[1] ++;  break;
                                                         case 3: Clock_date[0] ++;  break;
                                                         default: break;
                                                }
                                 }
                                 dateStyle();
                                 InitDS1302();
                        }while(S5 == 0)
                        {
                           if(flag_S6 == 0)        Time(Inittime[2],Inittime[1],Inittime[0]);
                                 else if(flag_S6 > 0)   Time(Clock_date[2],Clock_date[1],Clock_date[0]);
                        }
                  Close_Clock();
         }
         
         if(S4 == 0)
         {
                                delay(200);
                                if(S4 == 0)
                                {
                                                 if(flag_S7)
                                                 {
                                                                        switch(flag_S7)
                                                                        {
                                                                                  case 1: Inittime[2] --;   break;
                                                                                  case 2: Inittime[1] --;   break;
                                                                                  case 3: Inittime[0] --;   break;
                                                                                  default: break;
                                                                        }
                                                 }
                                                 else if(flag_S6)
                                                 {
                                                                  switch(flag_S6)
                                                                  {
                                                                                        case 1: Clock_date[2] --;  break;
                                                                                        case 2: Clock_date[1] --;  break;
                                                                                        case 3: Clock_date[0] --;  break;
                                                                                        default: break;
                                                                  }
                                                 }
                                                 dateStyle();
                                                 InitDS1302();                                 
                                }while(S4 == 0)
                                {
                                                 if(flag_S7 == 0 && flag_S6 == 0 && flag_Clock == 0)
                                                 {
                                                                    temp = rd_temperature();   //溫度讀取
                                                                    Wendu_SMG(temp);
                                                                    R_time();                  //防止在長按S4情況下導(dǎo)致鬧鐘失效
                                                                    Detection_Clock();
                                                 }
                                                 else if(flag_S6 == 0)        Time(Inittime[2],Inittime[1],Inittime[0]);
                                                 else if(flag_S6 > 0)         Time(Clock_date[2],Clock_date[1],Clock_date[0]);
                                }
                                Close_Clock();
                }
}

/**********************************************************************************************************
【函數(shù)】      鬧鐘,時(shí)鐘數(shù)據(jù)轉(zhuǎn)換函數(shù)
【功能】      當(dāng) 時(shí) 設(shè)置時(shí)間大于23h時(shí),使其等于0;小于0時(shí),使其等于23;分,秒同理
【額外說明】  不加的話,時(shí)間更改會出現(xiàn)24小時(shí),62分鐘或秒的情況            ———相當(dāng)于對時(shí)間按鍵設(shè)置的優(yōu)化
**********************************************************************************************************/
void dateStyle()
{     
      if(Inittime[2] > 23)                      Inittime[2] = 0;
      else if(Inittime[2] < 0)                        Inittime[2] = 23;
                        else if(Inittime[1] >= 60)    Inittime[1] = 0;
      else if(Inittime[1] < 0)                        Inittime[1] = 59;
                        else if(Inittime[0] >= 60)    Inittime[0] = 0;
      else if(Inittime[0] < 0)                  Inittime[0] = 59;
       
            if(Clock_date[2] > 23)              Clock_date[2] = 0;
      else if(Clock_date[2] < 0)                Clock_date[2] = 23;
                        else if(Clock_date[1] >= 60)  Clock_date[1] = 0;
      else if(Clock_date[1] < 0)                Clock_date[1] = 59;
                        else if(Clock_date[0] >= 60)  Clock_date[0] = 0;
      else if(Clock_date[0] < 0)                Clock_date[0] = 59;  
}

/******************************************************************************
【函數(shù)】 鬧鐘檢測函數(shù)
【功能】 在main函數(shù)時(shí)刻檢測鬧鐘,鬧鐘到觸發(fā)鬧鐘使能標(biāo)志位,使鬧鐘打開
******************************************************************************/
void Detection_Clock()
{
     if(Inittime[2]==Clock_date[2] && Inittime[1]==Clock_date[1] && Inittime[0]==Clock_date[0])
                 {
                                         flag_Clock = 1;
                                         flag_led = 1;
                                         Selest573(5);
                                         P0 = 0x40;
                                         Selest573(0);
                                         P0 = 0xFF;
                 }
}

/********************************************************************
【函數(shù)】 鬧鐘關(guān)閉函數(shù)
【功能】 鬧鐘響起時(shí) 按下任意按鍵觸發(fā)鬧鐘使能標(biāo)志位,使鬧鐘關(guān)閉
********************************************************************/
void Close_Clock()
{
   if(flag_Clock == 1)
         {
                                flag_Clock = 0;
                                Selest573(5);
                                P0 = 0x00;
                                Selest573(0);
                                P0 = 0xFF;
         }
}

/*********************************************************
【函數(shù)】L1指示燈函數(shù)
【功能】每隔0.2s L1 閃爍一次
*********************************************************/
void ZSD_L1()
{   
          static uchar t = 0;
          static uint t_5s = 0;
    if( flag_led == 1)  
                {
                                 t++;
                                 t_5s++;
                                 if(t_5s > 2500)
                                 {
                                                  t_5s = 0;
                                                  t = 200;
                                                  flag_led = 0;                                 
                                 }
                                 
                                 if(t/100 == 1)       //每0.2s到
                                 {  
                                                        Selest573(0);
                                                        P0 = 0xFF;
                                                        Selest573(4);
                                                        P0 = 0xFE;
                                                        Selest573(0);
                                                        P0 = 0xFF;
                                                        P2 = (P2 & 0xFF) | 0x04;                                 
                                 }
                                 else if(t/100 == 2)
                                 {
                                                        t = 0;
                                                        Selest573(0);
                                                        P0 = 0xFF;
                                                        Selest573(4);
                                                        P0 = 0xFF;
                                                        Selest573(0);
                                                        P2 = (P2 & 0xFF) | 0x04;
                                 }                                 
                }
}

/*********************************************************************
【函數(shù)】:定時(shí)器0初始化函數(shù),中斷函數(shù)
【功能】:2ms中斷一次,控制L1指示燈閃爍,控制處于設(shè)置的時(shí)間閃爍
【晶振】:11.0592MHz
*********************************************************************/
void ConfigTime0()
{
    AUXR |= 0x80;                //定時(shí)器時(shí)鐘1T模式
                TMOD &= 0xF0;                //設(shè)置定時(shí)器模式
                TL0 = 0x9A;                  //設(shè)置定時(shí)初值
                TH0 = 0xA9;                  //設(shè)置定時(shí)初值
                TF0 = 0;                    //清除TF0標(biāo)志
       
          EA = 1;
          ET0 = 1;
                TR0 = 1;                   //定時(shí)器0開始計(jì)時(shí)
       
}

void InterruptTime0() interrupt 1
{
         static uchar t_1s = 0;
         if(flag_S7)
         {
                                t_1s ++;
                                if(t_1s / 500 == 1)        flag_1s = 1;     //1s到,熄滅數(shù)碼滅
                                else if(t_1s / 500 == 2)                    //2s到,數(shù)碼管顯示正常
                                {  
                                          t_1s = 0;
                                    flag_1s = 0;
                                }                                       
         }
         
         if(flag_S7 == 0 && flag_S6 == 0)
         {
              flag_1s = 0;
         }

         
    ZSD_L1();           //指示燈閃爍5s關(guān)閉
}





剩余篇幅鏈接如下;



第八屆.zip (70.77 KB, 下載次數(shù): 60)


評分

參與人數(shù) 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎勵!

查看全部評分

回復(fù)

使用道具 舉報(bào)

ID:463607 發(fā)表于 2022-4-4 21:40 | 顯示全部樓層
樓主說話好有趣,代碼已經(jīng)下載下來準(zhǔn)備好好學(xué)習(xí)下了
回復(fù)

使用道具 舉報(bào)

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

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表