|
- 我在上一篇文章中焊接了單片機最小系統板,并且成功驅動了LCD1602,我沒有在最后展示LCD顯示部分,就放到這篇文章在外接DS12C887的情況下和大家分享一下。
- 需要準備的模塊如下:
- 1.單片機的最小系統板(最好有復位電路)另外20引腳(地)和40引腳vcc要多引出來6個(后面接杜邦線很多地方要用)
- 2.DS12C887時鐘芯片(24腳的)
- 3.LCD1602模塊
這里的DS12C887買回不能直接用,得像51芯片一樣焊接個底座出來,旁邊兩列焊接兩列排針,作為芯片的引腳。焊接好的效果圖如下
因為要驅動LCD1602,電位器也是必不可少的,我把電位器單獨焊接在了另外一塊板子上,這個焊接地方沒有要求,合理安排空間即可,焊接電位器也要利用排針引出三個角,對于3296型電位器的各引腳說明如下1腳VCC,3腳GND,2腳接輸出。電位器的大小選擇位10k,如圖
還需要準備4個輕觸按鍵,因為設置時鐘時,需要選擇功能、增大鍵、減小鍵、鬧鐘查看鍵(我的板子上沒有焊接蜂鳴器,所以鬧鐘到點后,不會響,蜂鳴器是一個比較簡單的模塊,代碼里面都有定義,我在焊接的時候把他先忽視了,需要的話,外加上蜂鳴器模塊,看一下程序里的引腳定義就可以)
4個輕觸按鍵的接法從上到下排列,分別為功能選擇、增大、減小、鬧鐘查看。此處的焊接為選擇每個按鍵的兩個對角引腳,每個按鍵選擇的兩個引腳要相同,從上到下在板子上安插好,
按鍵圖.png (57.77 KB, 下載次數: 76)
下載附件
2021-6-15 14:44 上傳
按鍵原理圖.png (10.43 KB, 下載次數: 85)
下載附件
2021-6-15 14:44 上傳
原理圖和實物圖引腳一一對應,我們可以選擇1腳輸出,4腳接地(對角接通)4個按鍵的4號腳連接在一起并且引出一個插針到時候直接接單片機的GND完成接地,再把每個按鍵的1號腳用插針引出來,接代碼里定義的按鍵引腳。
在這里我給大家看一下DS12C887的芯片接法!
DS12C887實物圖.png (156.92 KB, 下載次數: 92)
下載附件
2021-6-15 14:44 上傳
DS12C887引腳圖.png (98.77 KB, 下載次數: 79)
下載附件
2021-6-15 14:44 上傳
我從左邊最上邊開始逆時針轉一圈來說明各引腳的接法
從第四引腳開始接4-11為數據傳輸,接單片機的P0口,12腳接單片機20腳的GND。
13腳cs接P1^4
14腳as接P1^5
15腳rw接P1^6
17腳ds接P1^7
18腳RESET接VCC
19腳IRQ接P3^3
24腳接VCC
現在DS12C887模塊的準備工作都完成了。只剩下LCD1602的接線部分,原理圖如下
1602接口.png (90.2 KB, 下載次數: 81)
下載附件
2021-6-15 14:44 上傳
1602液晶上都有每個管腳的名稱,可以對照著原理圖來接線
1602實物圖.JPG (1.85 MB, 下載次數: 72)
下載附件
2021-6-15 14:44 上傳
從左向右,1腳接地,2腳接vcc,3腳接電位器的第二腳,rs接單片機的P3^5,rw接地,E接單片機的P3*4,D0-D7接單片機的P2口,A、K為背光電源,A接vcc,K接gnd。至此所有外接模塊安裝包括接口對應引腳都完成了。
```c
/*總體要求*/
/*在1602上顯示年月日星期時分秒,并且按照秒來實時更新顯示
可以鬧鐘設定,到點報警功能,報警響起時,任意鍵可以取消報警
四個按鍵,根據功能可以調節參數,分別為功能鍵,數值增大鍵,數值減少鍵,鬧鐘查看鍵,
每次按鍵按下,蜂鳴器都會滴一聲,
利用DS12C887實現斷電后,再次上電,時間仍可以準確顯示 */
/*另外這個程序中文部分是學習了一個半月C語言的人的理解,難免有錯誤的地方
如果你想移植程序,除了開頭的各種腳需要修改,程序里面1602和DS12C887的寫指令寫數據,讀指令讀數據的IO口也要修改
應該是有4~6處,一定要注意,不然你的程序不會亮起來,然后初始化部分,記得初始化后去掉,但是仿真的時候不要去掉,去掉沒法顯示*/
/*非常非常非常重要的一個細節,總線上要加 AD[0..7] 這個名字,如果沒有永遠也仿真不起來*/
#include<reg52.h> //52系列單片機機頭文件
#define uchar unsigned char //宏定義 定義一個無符號字符型數據
#define uint unsigned int //宏定義 定義一個無符號整型數據
sbit lcdrs=P3^5; //自定義數據/命令選擇端口
sbit lcden=P3^4; //自定義使能信號
//sbit dula=P2^6;
//sbit wela=P2^7; /*P0口接液晶1602和時鐘芯片DS12C887的AD0-AD7*/
sbit beep=P2^3; //蜂鳴器。有的按鍵接rd為低電平,就需要也定義一下rd,我這里面四個按鍵采用的是接地的結構!
sbit dscs=P1^4; //定義地址選通輸入端 (讀到那里去)
sbit dsas=P1^5; //定義芯片片選端 (讀哪個芯片)
sbit dsrw=P1^6; //定義讀數據允許輸入腳,這里mot接地 (讓不讓讀的開關)
sbit dsds=P1^7; //定義中斷請求輸出
sbit dsirq=P3^3; //定義讀允許輸入 (讓讀以后,我來輸入數據)
sbit lcdrd=P3^7;
sbit s1=P1^0; //功能鍵
sbit s2=P1^1; //數值增大鍵
sbit s3=P1^2; //數值減少鍵
sbit s4=P1^3; //鬧鐘查看鍵
//因為功能鍵要8次才能推出,這里可以加一個直接退出按鍵,可以放在外部中斷上
bit flag1, flag_ri; //定義兩個位變量
uchar count,s1num,flag,t0_num; //定義幾個無符號字符型數據,用到時再解釋定義干啥用的
char miao,shi,fen,year,month,day,week,amiao,afen,ashi; //定義幾個字符型數據,這個基本上都能理解。
uchar code table[]=" 20 - - "; //讓液晶固定顯示的內容
uchar code table1[]=" : : "; //讓液晶固定顯示的內容
void write_ds(uchar, uchar); //函數申明 寄存器初始化
void set_alarm(uchar, uchar, uchar); //函數申明 設定鬧鐘
void read_alarm(); //函數申明 讀報警器
void set_time(); //函數申明 寄存器初始化
void delay(uint z) //延時函數
{
uint x,y; //定義兩個無符號整形數
for(x=z;x>0;x--) //如果x>0,則y執行110次
for(y=110;y>0;y--); //本小段為單位是1ms的延時
}
void di() //蜂鳴器報警
{
beep=0; //低電平有效,蜂鳴器開始蜂鳴
delay(100); //延時100毫秒,響0.1秒
beep=1; //蜂鳴器停止鳴叫
}
void write_com(uchar com) //寫液晶命令函數
{
lcdrs=0; //rs低電平,表示要寫命令
lcden=0; //en低電平,表示為了下面送入數據,防止此時還是高電平,無法制造高脈沖
P2=com; //D0-D7我接的是P0上面,數據送給它
delay(3); //延時3ms
lcden=1; //en高電平,延時三秒 再變成低電平,完成一次高脈沖,使數據送入液晶顯示屏
delay(3); //表示接下來,液晶顯示屏可以過來讀數據了
lcden=0;
}
void write_date(uchar date) //寫液晶數據函數
{
lcdrs=1; //高電平表示要寫數據
lcden=0; //en低電平,表示為了下面送入數據,防止此時還是高電平,無法制造高脈沖
P2=date; //D0-D7我接的是P0上面,數據送給它
delay(3); //延時3ms
lcden=1; //en高電平,延時三秒 再變成低電平,完成一次高脈沖,使數據送入液晶顯示屏
delay(3); //表示接下來,液晶顯示屏可以過來讀數據了
lcden=0;
}
void init() //液晶初始化
{
uchar num; //定義一個字符
EA=1; //打開全局中斷控制
EX1=1; //打開外部中斷1中斷
IT1=1; //設置負跳變沿觸發中斷
flag=0; // 自定義字符全部歸零,為了方便實用
flag1=0;
s1num=0; //鍵盤按下的次數
week=1; //星期顯示最低也是周一的一
lcden=0; //使能信號定義為零,表示還沒有數據
lcdrd=0;
// dula=0;//關閉數碼管顯示
// wela=0;
write_ds(0x0A,0x20); //首次使用ds12c887時使用,以后不必在寫。打開振蕩器
write_ds(0x0B,0x26); // 設置24小時模式,數據二進制格式,開啟鬧鐘中斷。
//0A,0B表示地址,20,26翻譯成二進制是00100000,00100110對應著對著寄存器A和B從D7-D0
set_time(); //設置默認上電時間
write_com(0x38); //設置16x2顯示,5x7點陣,8位數據接口
write_com(0x0c); //設置開顯示,不顯示光標
write_com(0x06); //寫一個字符后,地址指針自動加1
write_com(0x01); //顯示清0,數據指針清0
write_com(0x80); //設置數據指針位置,此處時數據指針第一行,第一處
for(num=0;num<15;num++) //<15原因是第一行顯示的數字或者空格一共14個
{
write_date(table[num]); //把要顯示的數據送入到液晶的第一行
delay(1); //延遲一毫秒
}
write_com(0x80+0x40); //設置數據指針位置,此處時數據指針第二行,第一處
for(num=0;num<11;num++) //<11原因是第二行顯示的數字或者空格一共10個
{
write_date(table1[num]); //把要顯示的數據送入到液晶的第二行
delay(1); //延遲一毫秒
}
}
void write_sfm(uchar add,char date) //1602液晶刷新時分秒函數4為時,7為分,10為秒 ,4.7.10均是顯示位置
{
char shi,ge; //定義兩個數,來表示十位數和個位數
shi=date/10; // 要送去顯示的十位
ge=date%10; //要送去顯示的個位
write_com(0x80+0x40+add); //時間是在第二行顯示,所以是加0X40,在add處顯示
write_date(0x30+shi); //shi和ge都是整形數值,但是液晶1602是內置ASCII表格,0在第048位
write_date(0x30+ge); //轉成十六進制就是0x30,
}
/*這個地方可能會有人迷糊,設置時分秒,怎么只設置十位和個,好像給人的感覺就是只設置時位,和分位,秒位怎么不設置,
實際上是,這里寫入并顯示的是 把時的十位和個位,分的十位和個位,秒的十位和個位,分別送去進行運算 ,然后先寫命令確定位置,
再寫數據,用來顯示,下面一個子函數也是同樣的道理*/
void write_nyr(uchar add,char date) //1602液晶刷新年月日函數,3為年,6為月9為天 ,369也分別是位置
{
char shi,ge; //定義兩個數,來表示十位數和個位數
shi=date/10; // 要送去顯示的十位
ge=date%10; //要送去顯示的個位
write_com(0x80+add); //時間是在第二行顯示,所以是加0X40,在add處顯示
write_date(0x30+shi); //shi和ge都是整形數值,但是液晶1602是內置ASCII表格,0在第048位
write_date(0x30+ge); //轉成十六進制就是0x30,
} /*實際上到了主函數,時分秒,年月日會有六個子函數進行分別調用,這里用兩個子函數來表示,不能用一個的原因是顯示的內容不在一行,
主要是寫入命令的位置不一樣,大家可以觀察一下*/
void write_week(char we) //寫液晶1602星期顯示函數
{
write_com(0x80+12); //讓we在0x80+12這個位置顯示
switch(we) //多分支結構的條件選擇語句,we等于幾就去執行幾號分支
{
case 1:write_date('M'); //寫入M。整個的意思是如果we等于1,則顯示MON,即星期一
delay(5); //延時5毫秒后寫入O
write_date('O'); //寫入O
delay(5); //延時5毫秒后寫入N
write_date('N'); //寫入N
break; //間斷,為了和后面分開
case 2:write_date('T'); //寫入T。整個的意思是如果we等于2,則顯示TUE,即星期二
delay(5); //延時5毫秒后寫入U
write_date('U'); //寫入U
delay(5); //延時5毫秒后寫入E
write_date('E'); //寫入E
break; // 間斷,為了和后面分開
case 3:write_date('W'); //寫入W。整個的意思是如果we等于3,則顯示WED,即星期三
delay(5); //延時5毫秒后寫入E
write_date('E'); //寫入E
delay(5); //延時5毫秒后寫入D
write_date('D'); //寫入D
break; //間斷,為了和后面分開
case 4:write_date('T'); //寫入T。整個的意思是如果we等于4,則顯示THU,即星期四
delay(5); //延時5毫秒后寫入H
write_date('H'); //寫入H
delay(5); //延時5毫秒后寫入U
write_date('U'); //寫入U
break; //間斷,為了和后面分開
case 5:write_date('F'); //寫入F。整個的意思是如果we等于5,則顯示FRI,即星期五
delay(5); //延時5毫秒后寫入R
write_date('R'); //寫入R
delay(5); //延時5毫秒后寫入I
write_date('I'); //寫入I
break; //間斷,為了和后面分開
case 6:write_date('S'); //寫入S。整個的意思是如果we等于6,則顯示SAT,即星期六
delay(5); //延時5毫秒后寫入A
write_date('A'); //寫入A
delay(5); //延時5毫秒后寫入T
write_date('T'); //寫入T
break; //間斷,為了和后面分開
case 7:write_date('S'); //寫入S。整個的意思是如果we等于7,則顯示SUN,即星期日
delay(5); //延時5毫秒后寫入U
write_date('U'); //寫入U
delay(5); //延時5毫秒后寫入N
write_date('N'); //寫入N
break; //間斷,為了和后面分開
}
}
void keyscan() //數字時鐘按鍵掃描函數
{
if(flag_ri==1) //如果標志位,鬧鐘等于1,則蜂鳴器會響 ,這一句和按鍵掃描沒有關系,主要是為了任意鍵可以消除
//鬧鐘的報警,可以理解為,為鬧鐘取消而增加的一個掃描小程序。
{
if((s1==0)||(s2==0)||(s3==0)||(s4==0)) //如果s1-s4有一個為零,低電平 ||這個符號是關系運算符, 或的意思,有一個是低電平,則進行下一步。
{
delay(5); //延時去抖動
if((s1==0)||(s2==0)||(s3==0)||(s4==0)) //再次確認,如果s1-s4有一個為零,低電平
{
while(!(s1&&s2&&s3&&s4)); /*/如果他們運算的結果為0 ,當鬧鐘響起,就會進入這個按鍵掃描程序,這沒有按下鍵盤的時候,
就會運行到這里,進行判斷循環,一直等在,四個按鍵,有一個為0,這個語句就會判斷為假,進行下一步運算,&&這個符號是關系運算的 與,
一個值為零,則整體結果運算為0*/
di(); //則蜂鳴器會響,鬧鐘有自己的蜂鳴程序,這里有個DI主要原因是,每次按鍵 都會響,這是事先規定號的
flag_ri=0; //清除報警標志
}
}
}
if(s1==0) //檢測按鍵s1
{
delay(5); //延時5毫秒,也可叫延時去抖動。
if(s1==0) //再次檢測按鍵s1
{
s1num++; //定義為鍵盤按下的次數
if(flag1 == 1) //這個是用來鬧鐘的,如果等予1,說明現在是在設置鬧鐘值,從下面來看這個只能調節每天的鬧鐘,不能調節年月
if(s1num == 4) //因為只能調節時分秒,讓他們在里面循環
s1num=1; //這個地方我卡了幾天,大家要綜合前后文,明白flag1是鬧鐘被按下了,flag是為了跳出主程序循環,為了設置時間
flag=1; //按鍵計數以后,則這個位變量變成1,
while(!s1); /*!s1 的意思是取s1相反的數,是用來測試判斷按鍵按下后有沒有松開,松開則計數一次后,電平
變成高電平,說明此時已經松開,也確定了s1num的具體數值,也就是按了幾下*/
di(); //每按下一次則響一聲
switch(s1num) //判斷是按了幾下,則選擇什么位置光標點閃爍。
{
case 1:write_com(0x80+0x40+10); //很明顯這是顯示屏第二行的顯示指令,10 說明光標調節的是秒
write_com(0x0f); /*/不管你按的再快,光標也會從第一步開始,所以把 開顯示,顯示光標,光標閃爍 這個lcd的這個
指令設置放在這里 */
break; //會不停的跳出,再去問現在是按了幾下了,按了幾下,就會進入對應的里面,下面都是一樣的不解釋了。
case 2:write_com(0x80+0x40+7); /*這個就是光標在分鐘上閃爍,(不光時分秒都是在他們的十位閃爍,
如果送的是兩位數,LCD的指針可以自動加一,把個位也給顯示了)*/
break;
case 3:write_com(0x80+0x40+4); //這個是在小時的位置顯示閃爍
break;
case 4:write_com(0x80+12); //這就是進入顯示屏第一行了,在顯示星期的位置,第十位,最右邊,是調節星期的位置。
break;
case 5:write_com(0x80+9); //日
break;
case 6:write_com(0x80+6); //月
break;
case 7:write_com(0x80+3); //年
break;
case 8:s1num=0; //把按鍵數置零,等這個小程序運行完,則光標不在閃縮,一切正常運行。相當于不選擇任何位置。
write_com(0x0c); //設置開顯示,不顯示光標
flag=0; //等于0就是回到主程序的正常運行(可以參看以下主程序,更能方便理解)
/*下面的幾句基本一樣,明白一個就全明白了,這個地方主要是查表,查寄存器A,功能列表有時分秒,鬧鐘的也有時分秒,年月日他們分別
對應的寄存器地址,比如秒對應的是00H,分鐘對應的是02H,所以0,2,4,6,7,8,9都是地址,往這個里面寫,就是寫的時分秒,
可能有人問,既然是00H,02H,為什么寫成0,2等等,其實是因為十六進制和十進制在0~9,書寫雖然有區別,但是結果都一樣*/
write_ds(0,miao);
write_ds(2,fen);
write_ds(4,shi);
write_ds(6,week);
write_ds(7,day);
write_ds(8,month);
write_ds(9,year);
break; //跳出
}
}
}
if(s1num!=0) //測試不等于 0,也就是只有當s1按下時才能檢測和用來啟動s2和s3.
{
if(s2==0) //問S2按鍵有沒有按下
{
delay(1); //延時1毫秒
if(s2==0) //再次來檢測
{
while(!s2); //給s2取反
di(); //滴一聲
switch(s1num) //根據s1按下的次數,來確定調節哪個位置
{ //下面給大家解釋一組,應該可以全部明白
case 1:miao++; //按鍵s2按一下,這里就會加一 設置秒鐘
if(miao==60) //如果加到了60 ,秒就會變成0
miao=0;
write_sfm(10,miao); //把秒的值經過運算,送到LCD相應的位置去顯示
write_com(0x80+0x40+10); /*這一句是調用寫指令,因為指針把秒顯示完畢后,光標就會在秒的個位,
所以這一句是把光標在拉回來,因為不能正好一下子就把秒的值設置的正好*/
break; //然后跳出,等待按鍵再次按下
case 2:fen++; //設置分鐘
if(fen==60) //分,秒都用到60,生活中并沒有60,這里也不能設置成59,但是可以改程序為>59.道理是一樣的
fen=0;
write_sfm(7,fen);
write_com(0x80+0x40+7);
break;
case 3:shi++; //設置時鐘
if(shi==24) //和上面一樣的道理
shi=0;
write_sfm(4,shi);
write_com(0x80+0x40+4);
break;
case 4:week++; //設置星期
if(week ==8) //當按下第八次的時候,則8就會變成1
week=1;
write_week(week);
write_com(0x80+12);
break;
case 5:day++; //設置天數
if(day==32)
day=1;
write_nyr(9,day);
write_com(0x80+9);
break;
case 6:month++; //設置月數
if(month==13)
month=1;
write_nyr(6,month);
write_com(0x80+6);
break;
case 7:year++; //設置年
if(year==100)
year=0;
write_nyr(3,year);
write_com(0x80+3);
break;
}
}
}
if(s3==0) //上面是增大鍵,下面就是減少鍵
{
delay(1); //延遲1毫秒
if(s3==0) //再次判斷有沒有按下
{
while(!s3); //取相反數,看看是不是為真
di();
switch(s1num) //根據按鍵1,就可以確定光標在什么位置,下面介紹和上面基本上一樣,
{ //只不過沒有60了,反而有59,可以好好理解一下,其實很簡單這個地方,就不解釋了
case 1:miao--; //設置秒鐘
if(miao==-1)
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
break;
case 2:fen--; //設置分鐘
if(fen==-1)
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+7);
break;
case 3:shi--; //設置小時
if(shi==-1)
shi=23;
write_sfm(4,shi);
write_com(0x80+0x40+4);
break;
case 4:week--; //設置星期
if(week==-0)
week=7;
write_week(week);
write_com(0x80+12);
break;
case 5:day--; //設置天數
if(day==0)
day=31;
write_nyr(9,day);
write_com(0x80+9);
break;
case 6:month--; //設置月數
if(month==0)
month=12;
write_nyr(6,month);
write_com(0x80+6);
break;
case 7:year--; //設置年
if(year==-1)
year=99;
write_nyr(3,year);
write_com(0x80+3);
break;
}
}
}
}
if(s4==0) //這個地方是鬧鐘設置鍵
{
delay(5); //延時5毫秒
if(s4==0) //再次判斷是否按下
{
flag1=~flag1; //如果按下,則按鍵1程序,進入時分秒的循環,這里的講解和前面相呼應。
while(!s4); //取反是不是為真
di(); //為真說明,有按鍵按下,響一聲,
s1num=0;
/*調試仿真時發現如果按下了按鍵一 在按鬧鐘,然后取消鬧鐘,在按按鍵一,會不出現光標,為了讓鬧鐘和按鍵一不沖突,我添加這一句
每當我按下按鍵一,不管按幾次,只要按下按鍵4,都會讓光標變成0位 */
if(flag1==0) //如果等于0,說明按得第二下,屬于退出鬧鐘設置。
{
flag=0; //程序運行到這一步,說明運行完這個程序,就要回到主程序了,
//把按鍵1標志指令以后,本程序結束,可以進入主程序,否則還要在去按鍵1,按幾下
write_com(0x80+0x40); //把指針選擇第二行,第一位,
write_date(' '); //寫入兩個空的符號,主要是為了區別狀態,是調整時間還是設置鬧鐘
write_date(' ');
write_com(0x0c); //關閉光標閃爍
write_ds(1,miao); //把時分秒送到DS12C887,程序正常運行
write_ds(3,fen); //這個時候的135要注意,可以看出是新設置鬧鐘值
write_ds(5,shi);
}
else //如果flag不等于0,則進入這個程序,實際上程序都是先運行這個
{ //進入鬧鐘設置
read_alarm(); //讀鬧鐘原來的數據
miao=amiao; //分別送入時分秒
fen=afen;
shi=ashi;
write_com(0x80+0x40); //寫指令,把指針,也就是光標位置放在第二排第一位
write_date('R'); //分別送入R I送去顯示,可以區分現在是在調整時間,還是修改鬧鐘
write_date('I');
write_com(0x80+0x40+3); /*這個地方還有一個指針,就會讓很多人不理解,其實這個地方設計很巧妙
3號位置,正好是時鐘前面一位,然后再那邊閃爍,接著等待按鍵1,來選擇調整時分秒,
按一下變換一個位置,在3號位閃爍還不影響開始時的鬧鐘值*/
write_sfm(4,ashi); //送到液晶去顯示
write_sfm(7,afen);
write_sfm(10,amiao);
}
}
}
}
void write_ds(uchar add,uchar date) //寫DS12C887函數
{
dscs=0; //根據時序圖,把相應的腳變化高低,片選端,低電平有效
dsas=1; //地址選通輸入端
dsds=1; //讀允許輸入腳
dsrw=1; //寫輸入腳
P0=add; //寫地址
dsas=0;
dsrw=0;
P0=date; //寫命令
dsrw=1;
dsas=1;
dscs=1;
}
uchar read_ds(uchar add) //讀DS12C887函數 ,這里沒有用void要注意
{
uchar ds_date; //定義一個無符號函數
dsas=1; //根據時序圖,進行高低電平設置
dsds=1;
dsrw=1;
dscs=0;
P0=add; //寫地址,確定要讀什么位置的值
dsas=0;
dsds=0;
P0=0xff; //先把P1進行置高,清理數據
ds_date=P0; //把新的得到了 12c887里面的數值,賦值給ds_date
dsds=1; //根據時序圖繼續設置電平
dsas=1;
dscs=1;
return ds_date; //誰調用它,什么位置調用的,就會把這個新得到的值在返回給他,
//看得出來只有讀鬧鐘值是調用了。
}
void set_time() //首次操作12c887時給寄存器初始化,完成后,要把這一段用 給屏蔽起來
{
write_ds(0,0); //根據寄存器A,相當于 所有的位置,全部顯示00。
write_ds(1,0);
write_ds(2,0);
write_ds(3,0);
write_ds(4,0);
write_ds(5,0);
write_ds(6,0);
write_ds(7,0);
write_ds(8,0);
write_ds(9,0);
}
void read_alarm() //讀取鬧鐘值
{
amiao=read_ds(1); //根據寄存器A,分別把鬧鐘值讀出來,并且賦值給時分秒
afen=read_ds(3);
ashi=read_ds(5);
}
void main() //主程序
{
init(); //調用初始化函數
while(1) //為真不斷循環,等待鬧鐘中斷
{
keyscan(); //按鍵子程序,不斷地掃描
if(flag_ri==1) //如果有鬧鐘,則進入這里
{
di();
delay(100); //一直響 滴滴
di();
delay(500);
}
if((flag==0) && (flag1==0)) //如果按鍵標志位和鬧鐘標志位都為0,則繼續
{
keyscan(); //按鍵繼續掃描
year=read_ds(9); //把DS12C887里面的數值不斷讀取
month=read_ds(8);
day=read_ds(7);
week=read_ds(6);
shi=read_ds(4);
fen=read_ds(2);
miao=read_ds(0);
write_sfm(10,miao); //這里把DS12c887的值不斷地寫入到lcd1602
write_sfm(7,fen);
write_sfm(4,shi);
write_week(week);
write_nyr(3,year);
write_nyr(6,month);
write_nyr(9,day);
}
}
}
void exter()interrupt 0 //中斷1程序
{
uchar c; //定義一個無符號數值
flag_ri=1; //鬧鐘中斷時間到了
c=read_ds(0x0c); //讀取c寄存器的值,表示響應了中斷
}
在這里插入代碼片
|
評分
-
查看全部評分
|