反思:此項目在做的時候我是直接用單片機引腳去驅動數碼管(P1口控制段選,P3口控制位選),發現單片機引腳不能直接控制驅動數碼管,所以我在思考後加了74HC138和74HC573來驅動,138控制位選,573控制段選。所以我在原來的PCB基礎上在洞洞板上焊接了驅動芯片。我在做PCB電路設計的時候,是因爲仿真的時候是單片機引腳直接驅動數碼管,然而通過此次教訓,發現並不能如此去做。
QQ:3177227373
個人思路:
在整個工程中只需要去讀取DS1302的時間數據,然後再用數碼管去顯示就行了。
①在按鍵修改時間部分,需要用一個bit標誌位來區別是正常讀取時間還是修改時間,用一個按鍵按下對bit標誌位取反,進入修改時間的while循環。
②定義一個變量:u8 SetPlace = 0;//修改時間順序:秒 分 時, 用一個按鍵讓SetPlace變量一直累加,而 TIME[SetPlace] 就是當前被修改的時間,例如SetPlace = 0,TIME[SetPlace] 就是TIME數組的第一個數據,就是當前被修改的時間是秒。
③然後再用倆個按鍵去修改 TIME[SetPlace] 的值(時間加的話需要對這個值進行上限幅),就達到了修改TIME數組任意數據值的目的。
④然後再用一個按鍵去退出這個修改時間的while循環,並初始化DS1302,對DS1302寫入修改後的時間。
數碼管顯示時分秒
DS1302介紹
DS1302 是美國DALLAS公司推出的一種高性能、低功耗、帶RAM的實時時鐘電路,它可以對年、月、日、週日、時、分、秒進行計時,具有閏年補償功能,工作電壓爲2.5V~5.5V。採用三線接口與CPU進行同步通信,並可採用突發方式一次傳送多個字節的時鐘信號或RAM數據。
DS1302結構
DS1302的引腳排列,其中Vcc1爲後備電源,VCC2爲主電源。在主電源關閉的情況下,也能保持時鐘的連續運行。DS1302由Vcc1或Vcc2兩者中的較大者供電。當Vcc2大於Vcc1+0.2V時,Vcc2給DS1302供電。當Vcc2小於Vcc1時,DS1302由Vcc1供電。X1和X2是振盪源,外接32.768kHz晶振。RST是復位/片選線,通過把RST輸入驅動置高電平來啓動所有的數據傳送。RST輸入有兩種功能:首先,RST接通控制邏輯,允許地址/命令序列送入移位寄存器;其次,RST提供終止單字節或多字節數據傳送的方法。當RST爲高電平時,所有的數據傳送被初始化,允許對DS1302進行操作。如果在傳送過程中RST置爲低電平,則會終止此次數據傳送,I/O引腳變爲高阻態。上電運行時,在Vcc>2.0V之前,RST必須保持低電平。只有在SCLK爲低電平時,才能將RST置爲高電平。I/O爲串行數據輸入輸出端(雙向)。SCLK爲時鐘輸入端。
數據流
在控制指令字輸入後的下一個SCLK時鐘的上升沿時,數據被寫入DS1302,數據輸入從低位即位0開始。同樣,在緊跟8位的控制指令字後的下一個SCLK脈衝的下降沿讀出DS1302的數據,讀出數據時從低位0位到高位7。
結論
DS1302存在時鐘精度不高,易受環境影響,出現時鐘混亂等缺點。DS1302可以用於數據記錄,特別是對某些具有特殊意義的數據點的記錄,能實現數據與出現該數據的時間同時記錄。這種記錄對長時間的連續測控系統結果的分析及對異常數據出現的原因的查找具有重要意義。傳統的數據記錄方式是隔時採樣或定時採樣,沒有具體的時間記錄,因此,只能記錄數據而無法準確記錄其出現的時間;若採用單片機計時,一方面需要採用計數器,佔用硬件資源,另一方面需要設置中斷、查詢等,同樣耗費單片機的資源,而且,某些測控系統可能不允許。但是,如果在系統中採用時鐘芯片DS1302,則能很好地解決這個問題。
引腳圖
電路圖
PCB圖
實物圖
實物演示視頻
百度網盤鏈接 (點擊藍色字體即可跳轉)
提取碼:fmg1
代碼
建議:只參考思路,不要直接複製粘貼,否則無法進步。
主函數
//主函數
void main()
{
// Ds1302Init();//DS1302初始化 第一次寫入後需註釋掉再下一遍,否則每次上電都會初始化時間
Timer0_Init();//定時器0初始化
while(1)
{
Timepros();//時間處理
SMG_Display();//時間顯示
Key_scan();//按鍵掃描
}
}
數碼管驅動
//數碼管位置及數據顯示 w;位置 dat;數據
void SMG_dat(u8 w,u8 dat)
{
Choose_W(w);//位選
P1 = smgduan[dat];//段選
delay_ms(1);//延時
}
//74HC138顯示位數選擇
void Choose_W(u8 w)
{
switch(w) //位選,選擇點亮的數碼管
{
case(1):
LSA=0;LSB=0;LSC=0; break;//顯示第1位
case(2):
LSA=1;LSB=0;LSC=0; break;//顯示第2位
case(3):
LSA=0;LSB=1;LSC=0; break;//顯示第3位
case(4):
LSA=1;LSB=1;LSC=0; break;//顯示第4位
case(5):
LSA=0;LSB=0;LSC=1; break;//顯示第5位
case(6):
LSA=1;LSB=0;LSC=1; break;//顯示第6位
case(7):
LSA=0;LSB=1;LSC=1; break;//顯示第7位
case(8):
LSA=1;LSB=1;LSC=1; break;//顯示第8位
}
}
數碼管顯示
//數碼管顯示
void SMG_Display()
{
SMG_dat(1,TIME[2]/16); //時十位
SMG_dat(2,TIME[2]&0x0f); //時個位
SMG_dat(3,10); //-
SMG_dat(4,TIME[1]/16); //分十位
SMG_dat(5,TIME[1]&0x0f); //分個位
SMG_dat(6,10); //-
SMG_dat(7,TIME[0]/16); //秒十位
SMG_dat(8,TIME[0]&0x0f); //秒個位
if(Flag)//LED 1秒閃爍一次
{
LED = 1;
}
else
{
LED = 0;
}
}
按鍵修改時間
//時間處理
void Timepros()
{
if(keynumber == 1)
{
keynumber = 0;
Flag_1 =~ Flag_1;//修改時間標誌位取反
}
if(!Flag_1)//0取非爲1 正常讀取時間
{
Ds1302ReadTime();//讀取時間
}
else
{
TR0 = 0;//關閉定時器0
SetPlace = 0;
while(1)
{
LED = 1; //LED常亮
Key_scan();//按鍵掃描
if(keynumber == 4) //按鍵K4 修改時間順序:秒 分 時
{
keynumber = 0;
SetPlace++;
if(SetPlace >= 3) //大於等於3則爲0
{
SetPlace = 0;
}
}
if(keynumber == 2) //時間加
{
keynumber = 0;
TIME[SetPlace]++;//時間加
if((TIME[SetPlace]&0x0f)>9) //換成BCD碼
{
TIME[SetPlace]=TIME[SetPlace]+6;
}
if((TIME[SetPlace]>=0x60)&&(SetPlace<2)) //分秒只能到59
{
TIME[SetPlace]=0;
}
if((TIME[SetPlace]>=0x24)&&(SetPlace==2)) //小時只能到23
{
TIME[SetPlace]=0;
}
}
if(keynumber == 3) //時間減
{
keynumber = 0;
TIME[SetPlace]--;//時間減
if((TIME[SetPlace]&0x0f)>9) //換成BCD碼
{
TIME[SetPlace]=TIME[SetPlace]-6;
}
if((TIME[SetPlace]<=0x00)&&(SetPlace<2)) //分秒只能到59
{
TIME[SetPlace]=0x59;
}
if((TIME[SetPlace]<=0x00)&&(SetPlace==2)) //小時只能到23
{
TIME[SetPlace]=0x23;
}
}
if(keynumber == 5) //寫入修改好的時間 退出
{
keynumber = 0;
SetPlace = 0;
Ds1302Init(); //DS1302初始化
Flag_1 = 0; //開始正常計時
TR0 = 1; //打開定時器0
break;
}
if(keynumber == 1) //不寫入修改好的時間 退出
{
keynumber = 0;
SetPlace = 0;
Flag_1 = 0; //開始正常計時
TR0 = 1; //打開定時器0
break;
}
SMG_Display();//數碼管顯示
}
}
}
按鍵掃描
//按鍵掃描
void Key_scan()
{
if(K1 == 0)//K1按下
{
delay_ms(10);//消抖
if(K1 == 0)
{
keynumber = 1;
while(K1 == 0);//鬆手檢測
}
}
if(K2 == 0)//K2按下
{
delay_ms(10);//消抖
if(K2 == 0)
{
keynumber = 2;
while(K2 == 0);//鬆手檢測
}
}
if(K3 == 0)//K3按下
{
delay_ms(10);//消抖
if(K3 == 0)
{
keynumber = 3;
while(K3 == 0);//鬆手檢測
}
}
if(K4 == 0)//K4按下
{
delay_ms(10);//消抖
if(K4 == 0)
{
keynumber = 4;
while(K4 == 0);//鬆手檢測
}
}
if(K5 == 0)//K5按下
{
delay_ms(10);//消抖
if(K5 == 0)
{
keynumber = 5;
while(K5 == 0);//鬆手檢測
}
}
}
2020/1/1
晴