|
本帖最后由 黑夜的星光 于 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é)則殆
    
代碼如下
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)
2020-3-22 20:00 上傳
點(diǎn)擊文件名下載附件
|
評分
-
查看全部評分
|