|
本帖最后由 liuyy 于 2015-1-11 14:55 編輯
1、效果圖
2、矩陣鍵盤按鍵
3、代碼
4、小結(矩陣鍵盤外部中斷的小細節)
參考資料:實時時鐘DS1302資料:http://www.zg4o1577.cn/bbs/dpj-22465-1.html
效果圖
小時

日期

星期與溫度

矩陣鍵盤按鍵

完整程序源代碼下載:http://www.zg4o1577.cn/f/shizhongcx.rar
代碼:
#include <reg51.h>
//管腳聲明
sbit dm = P2^0; //段碼
sbit wm = P2^1; //位碼
sbit st = P2^2; //使能(RST)
sbit da = P2^3; //i/o管腳(數據管腳)(i/o)
sbit cl = P2^4; //時鐘管腳(CLK)
sbit DQ = P2^5; //定義總線的I/O管腳
sbit ZD = P3^2;
//下面是一些需要提前聲明的函數(起始可以不用)
void DelayUs2x(unsigned char t); //u延時
void DelayMs(unsigned char t); //m延時
void x_sj(); //原始數據還原
void d_sj(); //數碼管顯示切換函數
void sjse(); //設置時間年月日函數
void szjia(unsigned char *ls,unsigned char j,unsigned char i,bit l); //數值加或減函數
void sjqh(unsigned char *ls,unsigned char i,unsigned char j,unsigned char k); //設置,數碼管緩存寫入函數
void ntb(); //年同步函數
unsigned char jpsm(); //矩陣鍵盤反轉掃描
void jpjm(unsigned char i); //矩陣鍵盤設置函數
void sm(); //數碼管掃描顯示函數
void smgql(); //數碼管緩存清零函數
void csh_hc(); //切換初始化數碼管緩存函數(這個函數的作用就是在切換時清理數碼管的緩存)
void sjse(); //設置時間年月日函數
//下面是ds1302時鐘芯片的低層函數
unsigned char d_1302(unsigned char addr,unsigned char l); //讀取8個bit(參數1:地址,參數2:啟用BCD處理)
void x_1302(unsigned char addr,unsigned char q,unsigned char l); //寫入8個bit(參數1:地址,參數2:數據,參數3:啟用BCD處理)
//下面是ds18b20溫度傳感器的函數
bit d18b20_qs(); //18b20 起始
void d18b20_x(unsigned char dat); //寫 8 位 數 據
unsigned char d18b20_d(); //讀 8 位 數 據
unsigned int wd(); //讀取溫度函數
void zh(unsigned int i); //數碼管顯示緩存寫入函數
//下面的常量是一些寄存器的地址
#define addr_m 0x80 //秒
#define addr_f 0x82 //分
#define addr_x 0x84 //小時
#define addr_r 0x86 //日期
#define addr_y 0x88 //月
#define addr_xq 0x8a //星期
#define addr_n 0x8c //年
#define addr_xbh 0x8e //寫保護
#define addr_ram 0xc0 //RAM 開始地址(這款芯片有31個8位的RAM起始地址是C0)
#define addr_ram2 0xc2
//下面的是一些用到的全局變量
unsigned char sz; //狀態標志位
unsigned char hc[8]; //數碼管緩存
unsigned char DM[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 顯示段碼值0~9
unsigned char WM[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //位碼。顯示的位置
unsigned char sjhc[8]={0,0,15,23,12,1,13,20}; //秒,分,小時,日期,月,星期,低位年,高位年
//unsigned char addr[]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a}; //秒,分,小時,日期,月,年,星期
unsigned char zt[5]; //小時,分鐘,秒 與 年,月,日的數據臨時變量
unsigned char shijian[8]; //全局臨時變量(用來干什么都可以理論上可以節省聲明數組的時間)
void csh_wbzd_0() //初始化外部中斷0
{
IT0=0; //外部中斷0下降沿觸發
EX0=1; //啟用外部中斷0
EA=1; //打開總中斷
}
void wbzd_0() interrupt 0 //外部中斷服務函數
{
if(!(sz & 0x80))
sz = sz |0x80; //有按鍵按下,把按鍵標志位 置 1
}
void DelayUs2x(unsigned char t) //延時
{
while(--t);
}
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
bit d18b20_qs() //18b20 起始
{
bit dat;
DQ = 1; //DQ復位
DQ = 0; //拉低總線
DelayUs2x(175);
DQ = 1; //拉高總線
DelayUs2x(45); //這里延時大概 45us
dat = DQ; //讀取返回值(0:有18b20存在 1:是沒有)
DelayUs2x(20); //這里延時大概 20us
return dat; //返回數值
}
void d18b20_x(unsigned char dat) //寫 8 位 數 據
{
unsigned char i;
for(i=0;i<8;i++) //8位計數器
{
DQ = 0; //拉低總線
DQ = dat & 0x01; //取最低位賦值給總線
DelayUs2x(45); //延時45us
DQ = 1; //拉過總線準備寫下一個數據(或者總線復位)
dat >>= 1; //數據右移一位
}
}
unsigned char d18b20_d() //讀 8 位 數 據
{
unsigned char i,dat=0;
for(i=0;i<8;i++) //8位計數器
{
DQ = 0; //拉低總線
dat >>= 1; //數據右移一位
DQ = 1; //拉過總線(準備讀取數據)
if(DQ) //判斷是否是 1 如果是就把數據賦值給變量的高位
dat |= 0x80;
DelayUs2x(25); //這里延時大概 25us
}
return dat; //返回讀取到數據數據
}
unsigned int wd() //讀取溫度函數
{
unsigned char i = 0; //低8位數據
unsigned char j = 0; //高8位數據
unsigned int k = 0; //無符號16整形用來存儲讀回來的 16位溫度數據(j和i組合后的數據)
sm();
d18b20_qs(); //初始化
d18b20_x(0xCC); //跳過序列號的操作(因為18b20在總線上可以掛很多個,這個序列號和網卡MAC地址類似)
d18b20_x(0x44); //開啟溫度轉換
sm();
sm();
sm();
d18b20_qs(); //初始化
d18b20_x(0xCC); //跳過序列號的操作(因為18b20在總線上可以掛很多個,這個序列號和網卡MAC地址類似)
sm();
d18b20_x(0xBE); //讀取溫度寄存器等(共可讀9個寄存器) 前兩個就是溫度
sm();
i = d18b20_d(); //讀取低8位
j = d18b20_d(); //讀取高8位
sm();
k = j;
k <<= 8;
k = k + i;
sm();
return k; //返回讀取到的16位數據
}
void zh(unsigned int i) //數碼管顯示緩存寫入函數
{
unsigned char x,z;
x = i & 0x0f; //取出小數
i >>=4;
z = i & 0xff; //取出整數
switch(x) //小數位寫人顯示緩存
{
case 0: hc[7]=DM[0];break;
case 1: hc[7]=DM[1];break;
case 2: hc[7]=DM[1];break;
case 3: hc[7]=DM[2];break;
case 4: hc[7]=DM[3];break;
case 5: hc[7]=DM[3];break;
case 6: hc[7]=DM[4];break;
case 7: hc[7]=DM[4];break;
case 8: hc[7]=DM[5];break;
case 9: hc[7]=DM[6];break;
case 10: hc[7]=DM[6];break;
case 11: hc[7]=DM[7];break;
case 12: hc[7]=DM[8];break;
case 13: hc[7]=DM[8];break;
case 14: hc[7]=DM[9];break;
case 15: hc[7]=DM[9];break;
}
x = z/10; //取出十位
hc[5]=DM[x];//十位緩存寫入
x = z%10; //取出個位
hc[6] = DM[x] | 0x80;//個位緩存寫入
}
/*下面這個函數是ds1302的最低層函數也是最重要的*/
void x_1302(unsigned char addr,unsigned char q,unsigned char l) //寫入8個bit(參數1:地址,參數2:數據,參數3:啟用BCD處理)
{
unsigned char i;
if(l) //BCD處理(處理成BCD格式)
{
i=q/10;
q=q%10;
q=q+i*16;
}
addr = addr & 0xFE; //最低位置零
cl = 0; //拉低時鐘
da = 0; //復位數據
st = 1; //使能芯片。寫入開始
for(i=0;i<8;i++) //寫入地址
{
addr >>= 1;
da = CY;
cl = 1;
cl = 0;
}
for(i=0;i<8;i++) //寫入數據
{
q >>= 1;
da = CY;
cl = 1;
cl = 0;
}
st = 0; //寫入結束
}
/*下面這個函數是ds1302的最低層函數也是最重要的*/
unsigned char d_1302(unsigned char addr,unsigned char l) //讀取8個bit(參數1:地址,參數2:啟用BCD處理)
{
unsigned char i,dat;
addr = addr | 0x01;//最低位置高
cl = 0; //拉低時鐘
da = 0; //復位數據
st = 1; //使能芯片,讀取開始
for(i=0;i<8;i++) //寫入地址
{
addr >>= 1;
da = CY;
cl = 1;
cl = 0;
}
for(i=0;i<8;i++) //讀取數據
{
dat >>= 1;
if(da)
dat = dat | 0x80;
cl = 1;
cl = 0;
}
st = 0; //讀取結束
if(l) //BCD處理(還原成10進制)
{
i = dat / 16;
dat = dat % 16;
dat = dat +i*10;
}
return dat;
}
/*以下函數就是反轉掃描的精華*/
unsigned char jpsm() //矩陣鍵盤反轉掃描
{
unsigned char i=0; //用于接收按鍵數值
P1 = 0x0f; //檢測低4位
if(0x0f != P1) //檢測按鍵是否按下
{
DelayMs(10); //去抖
if(0x0f != P1) //在次判斷按鍵是否真的按下而不是其他干擾
{
i = P1; //把低4位賦值給i
P1 = 0xf0; //檢測高4位
//DelayUs2x(5); //稍微延時。。這條語句可以去掉
i = i | P1; //把低4位和高4位組合成完整的按鍵數值
while( 0xf0 != P1 ) //檢測按鍵是否松開
{
sm();
}
P1 = 0xf0; //這里是一個狠重要的經驗(以為在檢測低4位時賦值了0x0f,就是這個0x0f導致外部中斷被無限的觸發)
sz = sz & 0x7f;
return i; //返回按鍵數值
}
}
P1 = 0xf0; //這里是一個狠重要的經驗(以為在檢測低4位時賦值了0x0f,就是這個0x0f導致外部中斷被無限的觸發)
sz = sz & 0x7f;
return 0; //按鍵沒有按下返回0
}
void sm() //數碼管掃描顯示
{
unsigned char i;
for(i=0;i<8;i++)
{
P0 = 0; //消影
dm = 1;
dm = 0;
P0 = WM[ i]; //寫入位碼
wm = 1;
wm = 0;
P0 = hc[ i]; //寫入段碼
dm = 1;
dm = 0;
DelayUs2x(10);
}
P0 = 0; //清空段碼數據
dm = 1;
dm = 0;
}
void jpjm(unsigned char i) //矩陣鍵盤設置函數
{
switch(i)
{
case 0xe7: //矩陣鍵盤按鍵 (切換)
{
switch((sz & 0x03))
{
case 0x00: //如果當前是時間模式則切換到日期模式模式
{
ntb();
sz++; //把模式設置成日期格式
csh_hc(); //清理數碼管緩存
break;
}
case 0x01: //如果當前是日期模式則切換到時間模式
{
sz++; //把模式設置成時間格式
csh_hc(); //清理數碼管緩存
break;
}
case 0x02:
{
sz = sz & 0xfc; //把模式設置成時間格式
csh_hc();
break;
}
}
break;
}
case 0xdb:
{
sjse(); //調用設置函數
csh_hc(); //初始化數碼管顯示緩存
break;
}
case 0xb7: //矩陣鍵盤 。還原原始時間
{
x_sj();
csh_hc();
break;
}
}
}
void x_sj() //原始數據還原
{
unsigned char i,j=addr_m;
x_1302(addr_xbh,0,0); //關閉寫保護
for(i=0;i<7;i++)
{
x_1302(j,sjhc[ i],1);
j += 2;
}
x_1302(addr_ram,sjhc[7],1); //把高2位年寫入DS1302的RAM的C0地址中
x_1302(addr_ram2,sjhc[6],1);
x_1302(addr_xbh,0x80,0); //打開寫保護
}
void d_sj() //數碼管顯示切換函數
{
unsigned char j;
switch((sz & 0x03))
{
case 0: //顯示時,分,秒
{
if((j = d_1302(addr_m,1)) != zt[2]) //讀取秒然后判斷時間 這樣來提升效率
{
zt[2] = j; //記錄秒的臨時數值
hc[6] = DM[zt[2]/10]; //寫入秒的十位數據到數碼管緩存
hc[7] = DM[zt[2]%10]; //寫入秒的個位數據到數碼管緩存
if(zt[2] == 0) //判斷秒是否是0,如果是0條件就成立就讀取分鐘
{
zt[1] = d_1302(addr_f,1); //記錄分鐘的臨時數值
hc[3] = DM[zt[1]/10]; //寫入分鐘的十位數據到數碼管緩存
hc[4] = DM[zt[1]%10]; //寫入分鐘的個位數據到數碼管緩存
if(zt[1] == 0) //判斷時鐘是否是0,如果是0條件成立就讀取小時
{
zt[0] = d_1302(addr_x,1); //記錄小時的臨時數值
ntb(); //每小時同步一下年
hc[0] = DM[zt[0]/10]; //寫入小時的十位數據到數碼管緩存
hc[1] = DM[zt[0]%10]; //寫入小時的個位數據到數碼管緩存
}
}
}
break;
}
case 1: //顯示年,月,日
{
if((j = d_1302(addr_r,1)) != zt[2]) //小時變化后讀取月年
{
csh_hc();
}
break;
}
case 2: //顯示周與溫度
{
csh_hc();
break;
}
}
}
void csh_hc() //切換初始化數碼管緩存函數(這個函數的作用就是在切換時清理數碼管的緩存)
{
switch((sz & 0x03))
{
case 0x00:
{
zt[2] = d_1302(addr_m,1); //讀取秒
zt[1] = d_1302(addr_f,1); //讀取分鐘
zt[0] = d_1302(addr_x,1); //讀取小時
hc[7] = DM[zt[2]%10]; //寫入秒的個位
hc[6] = DM[zt[2]/10]; //寫入秒的十位
hc[5] = 0x40; // -
hc[4] = DM[zt[1]%10]; //寫入分的個位
hc[3] = DM[zt[1]/10]; //寫入分的十位
hc[2] = 0x40; // -
hc[1] = DM[zt[0]%10]; //寫入時的個位
hc[0] = DM[zt[0]/10]; //寫入時的十位
break;
}
case 0x01:
{
zt[3] = d_1302(addr_ram,1); //讀取年的高2位(千位和百位)
zt[2] = d_1302(addr_r,1); //讀取日
zt[1] = d_1302(addr_y,1); //讀取月
zt[0] = d_1302(addr_n,1); //讀取年的低2位(個位和十位)
hc[7] = DM[zt[2]%10]; //寫入日的個位
hc[6] = DM[zt[2]/10]; //寫入日的十位
hc[5] = 0x80 | DM[zt[1]%10]; //寫入月的個位 + "."
hc[4] = DM[zt[1]/10]; //寫入月的十位
hc[3] = 0x80 | DM[zt[0]%10]; //寫入年的個位 + "."
hc[2] = DM[zt[0]/10]; //寫入年的十位
hc[1] = DM[zt[3]%10]; //寫入年的百位
hc[0] = DM[zt[3]/10]; //寫入年的千位
break;
}
case 0x02:
{
zh(wd());
zt[3] = d_1302(addr_xq,1);
hc[0] = 0x40;
hc[1] = DM[zt[3]];
hc[2] = 0x40;
hc[3] = 0;
hc[4] = 0;
break;
}
}
}
void smgql() //數碼管緩存清零函數
{
unsigned char i;
for(i=0;i<8;i++)
hc[ i] = 0;
}
void szjia(unsigned char *ls,unsigned char j,unsigned char i,bit l) //數值加或減函數
//參數1:數據,參數2:傳送要設置的位置,參數3:傳送模式,參數4:(0是:減,1是:加)
{
switch((sz & 0x03)) //區分時間,日期,周
{
case 0: //時間(從switch1:分支1)
{
switch(j) //區分 秒,分鐘,小時
{
case 1: //秒
{
if(l) //判斷是加還是減
{
ls[0]++;
if( 60 <= ls[0] )
ls[0] = 0;
}
else
{
if( 0 >= ls[0])
ls[0]=59;
else
ls[0]--;
}
sjqh(ls,6,0,1);
break;
}
case 2: //分鐘
{
if(l) //判斷是加還是減
{
ls[1]++;
if( 60 <= ls[1] )
ls[1] = 0;
}
else
{
if( 0 >= ls[1])
ls[1]=59;
else
ls[1]--;
}
sjqh(ls,3,1,1);
break;
}
case 3: //小時
{
if(l) //判斷是加還是減
{
ls[2]++;
if( 24 <= ls[2] )
ls[2] = 0;
}
else
{
if(0 >= ls[2])
ls[2]=23;
else
ls[2]--;
}
sjqh(ls,0,2,1);
break;
}
}
break;
}
case 1: //日期(從switch2:分支1)
{
switch(j) //區分 日期,月份,年
{
case 1: //日期
{
if(l) //判斷是加還是減
{
ls[3]++;
if( i <= ls [3]) //這里的i放在右移的按鍵里面處理,
ls[3] = 1;
}
else
{
if(1 >= ls[3])
{
ls[3]= i-1;
}
else
{
ls[3]--;
}
}
sjqh(ls,6,3,1);
break;
}
case 2: //月份
{
if(l)
{
ls[4]++;
if(13 <= ls[4])
ls[4] = 1;
}
else
{
if(1 >= ls[4])
ls[4] = 12;
else
ls[4]--;
}
sjqh(ls,4,4,1);
break;
}
case 3: //年
{
if(l)
{
ls[6]++;
if( 100 <= ls[6])
{
ls[6] = 0;
ls[7]++;
if( 100 <= ls[7] )
ls[7] = 0;
}
}
else
{
if( 0 >= ls[6] )
{
ls[6] = 99;
ls[7]--;
if( 0 >= ls[7] )
{
ls[7] = 99;
}
}
else
ls[6]--;
}
sjqh(ls,0,7,2);
break;
}
}
break;
}
case 2: //周(從switch3:分支3)
{
if(l)
{
ls[5]++;
if( 8 <= ls[5] )
{
ls[5] = 1;
}
}
else
{
if( 1 >= ls[5])
ls[5] = 7;
else
ls[5]--;
}
sjqh(ls,0,0,10);
break;
}
}
}
void sjqh(unsigned char *ls,unsigned char i,unsigned char j,unsigned char k) //設置,數碼管緩存寫入函數
//參數1:數據,參數2:緩存開始地址(0~7),參數3:寫入緩存的數據,參數4:寫入數據的個數
{
if(k<10)
for(;k>0&&i<8&&j<8;k--)
{
hc[ i]= DM[ls[j]/10];
i++;
if(i<8)
hc[ i]= DM[ls[j]%10];
j--;i++;
}
else
{
hc[0]=0x40;
hc[1]=DM[ls[5]];
hc[2]=0x40;
}
}
void sjse() //設置時間年月日函數
{
unsigned char ls[8],i,j=0x80;
unsigned int n; //保存年(計算閏年要用到)
for(i=0;i<7;i++) //讀取寄存器的所有數值
{
shijian[ i]=d_1302(j,1); //讀取數據
ls[ i] = shijian[ i]; //賦值給臨時設置數組
j += 2; //地址指針移動到下一個地址
}
shijian[7]=d_1302(addr_ram,1); //讀取高2位年。地址是0xc0
ls[7] = shijian[7];//賦值給臨時設置數組
j = 3; //初始化位置
smgql(); //數碼管緩存清零
switch((sz & 0x03))
{
case 0:sjqh(ls,0,2,1);break; //把小時寫入數碼管緩存
case 1:sjqh(ls,0,7,2);break; //把年寫入緩存
case 2:sjqh(ls,0,0,10); //星期
}
while(i)
{
if((sz & 0x80)) //這里是判斷是否有按鍵按下。
{
sz = sz & 0x7f; //按鍵標志位置0
switch (jpsm()) //按下的按鍵區分(主switch)
{
case 0xdd: //6 數值加(主switch:分支1)
{
szjia(ls,j,i,1); //寫入數碼管顯示緩存
break;
}
case 0xeb: //* 左移(主switch:分支2)
{
smgql(); //數碼管緩存清零
if( 1 < j )
j--;
else
j=3;
switch((sz & 0x03))
{
case 0: //時間左移
{
switch(j) //區分移動標志的數值
{
case 1: //移動標志1是6~7數碼管顯示
{
sjqh(ls,6,0,1); //寫入數碼管顯示緩存
break;
}
case 2:
{
sjqh(ls,3,1,1); //寫入數碼管顯示緩存
break;
}
case 3:
{
sjqh(ls,0,2,1); //寫入數碼管顯示緩存
break;
}
}
break;
}
case 1: //日期左移 >>
{
//標志1
switch(j)
{
case 1:
{
switch(ls[4]) //設置每個月天數的上限
{
case 2:
{
n = ls[7];
n = n*100+ls[6];
if( n % 400 ==0 ||((n%4) ==0 && (n%100))) //能被400整除與能被4整除且不能被100整除
//四年一閏,百年不閏,四百年再閏
i = 29;
else
i = 28;
break;
}
case 4: i=30;break;
case 6: i=30;break;
case 9: i=30;break;
case 11: i=30;break;
default : i = 31;
}
i++;
sjqh(ls,6,3,1); //寫入數碼管顯示緩存
break;
}
case 2:
{
sjqh(ls,4,4,1); //寫入數碼管顯示緩存
break;
}
case 3:
{
sjqh(ls,0,7,2); //寫入數碼管顯示緩存
break;
}
}
break;
}
case 2: sjqh(ls,0,0,10);break;
}
break;
}
case 0xdb: //9 設置或者確定(主switch:分支3)
{
j=0x80;
x_1302(addr_xbh,0,0);
for(i=0;i<7;i++)
{
if( shijian[ i] != ls[ i] )
{
x_1302(j,ls[ i],1);
}
j += 2;
}
x_1302(addr_ram,ls[7],1);
x_1302(addr_ram2,ls[6],1);
x_1302(addr_xbh,0x80,0);
i=0;
break;
}
case 0xbb: //8 右移(主switch:分支4) <<
{
smgql(); //數碼管緩存清零
if(j>=3)
j=1;
else
j++;
switch( (sz & 0x03) )
{
case 0: //時間
{
switch(j)
{
case 1: sjqh(ls,6,0,1);break;
case 2: sjqh(ls,3,1,1);break;
case 3: sjqh(ls,0,2,1);break;
}
break;
}
case 1: //日期
{
switch(j)
{
case 1: sjqh(ls,6,3,1);break;
case 2: sjqh(ls,4,4,1);break;
case 3: sjqh(ls,0,7,2);break;
}
break;
}
case 2: sjqh(ls,0,0,10);break;
}
break;
}
case 0xd7: //= 數值減(主switch:分支5)
{
szjia(ls,j,i,0);
break;
}
case 0xe7: //設置切換
{
j=3;
smgql(); //數碼管緩存清零
if((sz & 0x03) == 2)
sz = sz & 0xfc;
else
sz++;
switch((sz & 0x03))
{
case 0:sjqh(ls,0,2,1);break;
case 1:sjqh(ls,0,7,2);break;
case 2:sjqh(ls,0,0,10);break;
}
break;
}
case 0xb7: i=0;break; //.取消設置
}
}
sm(); //掃描顯示數碼管
}
}
void ntb() //年同步函數
{
shijian[5] = d_1302(addr_n,1);
shijian[6] = d_1302(addr_ram2,1);
if(shijian[6] != shijian[5])
{
if( shijian[6] == 99)
{
shijian[7] = d_1302(addr_ram,1);
if(shijian[7] != 99)
shijian[7]++;
else
shijian[7]=0;
x_1302(addr_xbh,0,0);
x_1302(addr_ram2,0,1);
x_1302(addr_ram,shijian[7],1);
x_1302(addr_xbh,0x80,0);
}
else
{
x_1302(addr_xbh,0,0);
x_1302(addr_ram2,shijian[5],1);
x_1302(addr_xbh,0x80,0);
}
}
}
void main() //主函數
{
sz = 0;
csh_hc();
csh_wbzd_0(); //外部中斷初始化
ntb();
P1 = 0xf0; //這個是用于檢測矩陣鍵盤是否按下的(外部中斷需要的)
while(1)
{
d_sj();
if((sz&0x80)) //這里是判斷是否有按鍵按下。
/*注:這里加這個判斷是因為鍵盤解碼后需要執行的函數打亂主函數中斷 d_sj()
函數造成數據有時無法寫入DS1302芯片*/
{
jpjm(jpsm());
}
sm(); //掃描顯示數碼管
}
}
代碼中關于ds18b20部分原理詳見:http://www.zg4o1577.cn/bbs/dpj-22807-1.html
注:代碼寫的狠垃圾。。根本沒有算法可言而且BUG很多 。。
沒有改的BUG有。在設置日期時存在日期可以設置成 2月31號的錯誤
矩陣鍵盤的外部中斷問題
1,如果矩陣鍵盤檢測按鍵完畢后 ,如果P1口的數值是 0x0f就會導致外部中斷
無限觸發。
這里P1口的數值要結合電路圖來判斷。 |
|