本帖最后由 黑夜的星光 于 2020-3-22 21:14 編輯

Hellow !大家好,今天找個時間把第八屆的題也發出來 一起探討學習一下。自己呢也算做一個的經歷筆記吧 (哈哈哈哈)
試想一下 10年后的自己看到這淺陋的代碼,不知道會有什么感慨呢..................(hahaha....隔~)
ps:帖子今天用了 一個粉紅的顏色,哈哈哈,看著比較養眼舒服吧,若努力學習的 同學不嫌棄這些代碼的話,希望這粉紅能一定程度上減緩你們的疲勞
自己在調試的時候呢, 最頭大的地方就是DS1302不能讀取時間(DS1302驅動代碼都沒問題)
原因有二:
其一 :自己在上電初始化的函數中,將P22 = 0了,(我做了測試,將其P22 = 1時,可以正常工作) 詳細請看代碼
其二 :開發板是自己焊接的,可能P2引腳有短路的問題存在。
起初把自己調試的都懷疑人生了 啊哈哈哈。真的很難受。哎.......... 最后調試出來的時候又喜悅到了極點
說一下自己對賽題的看法吧,賽題沒有太新穎,生疏的考點,整體難度還是不低的。主要是按鍵的功能標志位的邏輯關系以及對數碼管的多工作界面的切換,數碼管玩的是真的很....ennenen
中斷不要多做事情,快進快出。一般LED的(指示燈之類的)標志位處理放在中斷處理比其他函數內要好很多。先把簡單的容易實現的功能調試出 來,最后再去寫復雜的邏輯代碼。
寫完一個邏輯功能就去編譯一下,看一下有沒有語法錯誤,不然等到最后錯誤太多,調試會復雜很多。然后單獨的模塊完成后記著上電驗證一下,使其逐漸能銜接起來。
好的算法有時會起到意想不到的好處,多看看一些大佬的算法,以及一些好的思維方式。慢慢積累,對自己的好處也會慢慢變的明顯。
以上都是自己的卑鄙拙見,期間也受到了一些大佬的思維啟蒙,非常感謝。
自己多單片機的感悟就是3點 多寫 多看 多想。 只有在自己親自寫的時候,才能體會到他們的真正含義,而且要多寫,形成自己的邏輯思維;多看別人的優秀的地方,如算法,思維,積累這些,自己學著去消化使用,慢慢變成自己的; 多想想自己編寫不出來的地方,想想功能模塊之間的聯系,怎樣做才能使完善,實現想要的結果。
學而不思則罔,思而不學則殆
    
代碼如下
main.c文件
/*****************************************************************************************************************************************
藍橋杯第八屆省賽習題
【細節提示】:在ds1302.c文件中定義了 有符號的數據變量 char Inittime[],以及必須在ds1302.h文件中進行 extern 全局的調用聲明
【主要難點】:數碼管的工作界面的切換,按鍵對工作標志位的使能以及互不干擾
【代碼說明】:不同的代碼編寫都有其高效的地方和一些功能需復雜實現的地方,要合理看待
本題中: 多處使用了 P2 = (P2 & 0xFF) | 0x04; (對DS1302的工作使能)。
我調試的很長時間,ds1302一直不能工作。加上這句代碼后(P22 = 1),一切都好了。
【不知道是不是我開發板的問題,你要是使用的話,可以去掉這句代碼測試一下】
******************************************************************************************************************************************/
#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; //鬧鐘響起標志位
bit flag_led = 0; //L1閃爍標志位,用于鬧鐘重置恢復閃爍狀態 【0-led閃爍開始標志;1-led閃爍停止標志】
bit flag_1s = 0; //時鐘設置狀態下1s閃爍標志位 【0是亮,1是滅】
uchar temp; //讀取溫度變量
char Clock_date[] = {0,0,0}; //鬧鐘數據
void KeyScan(); //按鍵檢測
void SMGdisplay(); //數碼管顯示
void ConfigTime0(); //配置定時器0
void Detection_Clock(); //檢測鬧鐘
void Close_Clock(); //關閉鬧鐘
void ZSD_L1(); //鬧鐘指示燈
void dateStyle(); //鬧鐘,時鐘數據轉換函數
void main()
{
Init_waise();
ConfigTime0();
InitDS1302();
while(1)
{
if(flag_S7 == 0) R_time();
KeyScan();
SMGdisplay();
Detection_Clock();
}
}
/*********************************************************************************************
【函數】 數碼管顯示界面切換函數
【功能】 負責按鍵使能切換數碼管顯示狀態
【小難點】 在時鐘設置期間,使操作位1s間隔閃爍。在中斷或者S7按鍵中做好標志位即可(本代碼在中斷)
*********************************************************************************************/
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]);
}
/*********************************************************************************************************************************
【函數】 按鍵檢測函數
【功能】 按下按鍵觸發相應工作標志位
【優化】 在按鍵彈起等待while(S? == 0)期間優化了對應數碼管功能,使數碼管不會再按鍵按下彈起期間閃爍或抖動
【算法】 使用的對按鍵功能選擇位的處理 加4為0(詳見S6)
【額外說明】對按鍵的工作使能位的操作以及對數碼管多狀態的選擇切換是本賽題中的最大的難點,一定要理清好功能之間的邏輯關系
*********************************************************************************************************************************/
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情況下導致鬧鐘失效
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();
}
}
/**********************************************************************************************************
【函數】 鬧鐘,時鐘數據轉換函數
【功能】 當 時 設置時間大于23h時,使其等于0;小于0時,使其等于23;分,秒同理
【額外說明】 不加的話,時間更改會出現24小時,62分鐘或秒的情況 ———相當于對時間按鍵設置的優化
**********************************************************************************************************/
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;
}
/******************************************************************************
【函數】 鬧鐘檢測函數
【功能】 在main函數時刻檢測鬧鐘,鬧鐘到觸發鬧鐘使能標志位,使鬧鐘打開
******************************************************************************/
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;
}
}
/********************************************************************
【函數】 鬧鐘關閉函數
【功能】 鬧鐘響起時 按下任意按鍵觸發鬧鐘使能標志位,使鬧鐘關閉
********************************************************************/
void Close_Clock()
{
if(flag_Clock == 1)
{
flag_Clock = 0;
Selest573(5);
P0 = 0x00;
Selest573(0);
P0 = 0xFF;
}
}
/*********************************************************
【函數】L1指示燈函數
【功能】每隔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;
}
}
}
/*********************************************************************
【函數】:定時器0初始化函數,中斷函數
【功能】:2ms中斷一次,控制L1指示燈閃爍,控制處于設置的時間閃爍
【晶振】:11.0592MHz
*********************************************************************/
void ConfigTime0()
{
AUXR |= 0x80; //定時器時鐘1T模式
TMOD &= 0xF0; //設置定時器模式
TL0 = 0x9A; //設置定時初值
TH0 = 0xA9; //設置定時初值
TF0 = 0; //清除TF0標志
EA = 1;
ET0 = 1;
TR0 = 1; //定時器0開始計時
}
void InterruptTime0() interrupt 1
{
static uchar t_1s = 0;
if(flag_S7)
{
t_1s ++;
if(t_1s / 500 == 1) flag_1s = 1; //1s到,熄滅數碼滅
else if(t_1s / 500 == 2) //2s到,數碼管顯示正常
{
t_1s = 0;
flag_1s = 0;
}
}
if(flag_S7 == 0 && flag_S6 == 0)
{
flag_1s = 0;
}
ZSD_L1(); //指示燈閃爍5s關閉
}
剩余篇幅鏈接如下;
第八屆.zip
(70.77 KB, 下載次數: 60)
2020-3-22 20:00 上傳
點擊文件名下載附件
|