[問題] 8051的P0值會影響中斷嗎
看板C_and_CPP (C/C++)作者kakashi45232 (23254ihsakak)時間13年前 (2013/05/23 19:21)推噓3(3推 0噓 7→)留言10則, 4人參與討論串1/1
開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
Keil C uVision 4
燒錄程式 ATMEL v1.2
額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
問題(Question):
我的開發版
P0為4*4的按鍵,P2為七斷顯示器顯示數字,P1.0~P1.2為七段顯示器選擇
--
我想做時鐘來練習
8個七段顯示器分別顯示日/時/分/秒
使用外部中斷INT0時 停止計時 且七段顯示器閃爍0.5秒此時功能都正常
但我加入了鍵盤掃描之後
一開始就直接卡在閃爍畫面 INT0壓下去時並無反應(但鍵盤功能是正常的)
但按鍵是可以掃描的
一行一行測試之後發現P0.4~P0.7只要有一個以上值為0就會產生這種情況
請問一下這大概是甚麼原因?
PS:把原本用的AT89S52改成AT89S51也是一樣的情形! 確認晶片無誤
餵入的資料(Input):
預期的正確結果(Expected Output):
錯誤結果(Wrong Output):
程式碼(Code):(請善用置底文網頁, 記得排版)
#include <AT89X51.H>
void delayms (int time);
char keyboard(void);
unsigned char
SEG[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x79,0x50,0x5c,0x00};
unsigned char flash=1,n=0,n1=0,n2=0,key=0,key1,ss=0,mm=0,hh=0,dd=0;
main()
{
TMOD=0x11;
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
TH1=(65535-50000)/256;
TL1=(65535-50000)%256;
IE=0x83;
TCON=0x51;
P1=7;
while(1)
{ key1=keyboard(); //呼叫掃描鍵盤附程式
if(key1!=0 && key!=key1)
key=key1; //當按鍵放開後值不會消失
dd=key; //將dd改顯示為按鍵值測試鍵盤掃描
if(flash==1 || ET0==1) //七段顯示器閃爍判斷
{
switch(P1) //顯示七段顯示器
{
case 7: P2=SEG[ss%10]; break;
case 6: P2=SEG[ss/10]; break;
case 5: P2=SEG[mm%10]|0x80; break;
case 4: P2=SEG[mm/10]; break;
case 3: P2=SEG[hh%10]; break;
case 2: P2=SEG[hh/10]; break;
case 1: P2=SEG[dd%10]; break;
case 0: P2=SEG[dd/10]; break;
}
delayms(5);
P2=0;
if(P1==0) P1=8;
P1--;
}
else
{
P2=0;
}
}
}
//==========副程式==========
void delayms(int time)
{
int n;
for(n=0;n<time;n++);
}
char keyboard(void) //掃描鍵盤的副程式回傳鍵盤值1~16
{
unsigned char i,j=0,k[4]={0xf7,0xfb,0xfd,0xfe};
for(i=0;i<4;i++)
{
P0=k[i]; //發現問題的地方
if(P0_4==0)
{j=(4*i)+1; break;}
if(P0_5==0)
{j=(4*i)+2; break;}
if(P0_6==0)
{j=(4*i)+3; break;}
if(P0_7==0)
{j=(4*i)+4; break;}
}
return j;
}
void int0(void) interrupt 0 //按INT0時T0停止計時T1計時
{
ET0=~ET0;
ET1=~ET1;
}
void timer0(void) interrupt 1 //T0為計時秒數
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
n1++;
if(n1==20)
{
n1=0;
ss++;
if(ss==60)
{
ss=0;
mm++;
if(mm==60)
{
mm=0;
hh++;
if(hh==24)
{
hh=0;
dd++;
if(dd==99) dd=0;
}
}
}
}
}
void timer1(void) interrupt 3 //拿來做閃爍0.5秒的計時
{
TH1=(65535-50000)/256;
TL1=(65535-50000)%256;
n2++;
if(n2==10)
{
n2=0;
flash*=-1; //每0.5秒flah為原值之-1倍讓主程式判斷閃爍
}
}
補充說明(Supplement):
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.170.136.179
推
05/23 19:29, , 1F
05/23 19:29, 1F
是每隔一段時間掃描一行判斷一次嗎
之前學鍵盤掃描就是使用這種方式
所以還沒想到用中斷這個方法! 我試試看!!
※ 編輯: kakashi45232 來自: 118.170.136.179 (05/23 19:37)
→
05/23 19:58, , 2F
05/23 19:58, 2F
→
05/23 19:59, , 3F
05/23 19:59, 3F
他是開發版
我沒辦法改變他的硬體設施 現階段也沒有多的材料可以動硬體
原本在想可不可以先處理軟體部分
等都成功
硬體要做出來的話再用成方便一點的接線方式
※ 編輯: kakashi45232 來自: 118.170.136.179 (05/23 20:10)
中斷式是這樣子嗎
http://ppt.cc/laH8
一按按鈕會有1經過NOR Gate 輸出會變為零
然後啟動中斷 再掃描一次
這樣就不用每執行一次while迴圈就會掃描一次 這個意思嗎??
→
05/23 22:47, , 4F
05/23 22:47, 4F
甚麼型號不同??
是那個副程式的P0=k[i];有問題 註解掉就不會有錯誤
而且測試發現只有P0=0xff 是正常的
 ̄↖這個一改就會有誤 所以才會問說P0.4~P0.7是否不能為零
把P0那行放到主程式或者別的地方也都有上述的問題
※ 編輯: kakashi45232 來自: 118.170.136.179 (05/23 23:12)
→
05/23 23:43, , 5F
05/23 23:43, 5F
→
05/23 23:45, , 6F
05/23 23:45, 6F
寫法應該是OK的
if是從上到下一個一個看呀
先看P0.4是不是0 是的話跳出迴圈
不是的話看P0.5是不是0 ......依此類推到P0.7
單獨用的時候很OK 我是把之前學PIC參考老師的範例
推
05/24 00:06, , 7F
05/24 00:06, 7F
了解 我這幾天去買邏輯IC測試
現在沒有設備只好先複習一下其他部份
※ 編輯: kakashi45232 來自: 118.170.136.179 (05/24 00:51)
剛剛突然發現是副程式的部分寫反了(有用紅色標記)
0xf7不小心KEY成0x7f太糗啦
不過還是謝謝兩位熱心人士
還多學到中斷式的鍵盤這個有效率的方法!
不過看了一下原廠的說明書(他強調要把那兩個短路)
發現一個最大的原因就是預設就先把鍵盤共通點連接到P3.2(INT0)
難怪都會有些莫名其妙的影響
(如圖)http://ppt.cc/br4~
不知道這樣子用二極體導通共接P3.2要做甚麼?
※ 編輯: kakashi45232 來自: 118.170.136.179 (05/24 01:44)
推
05/24 07:41, , 8F
05/24 07:41, 8F
→
05/24 07:54, , 9F
05/24 07:54, 9F
防止彈跳是接高電位或低電位還是拿來當輸入偵測?
因為他書上沒有提到要設定P3.2也沒學過防彈跳
所以不知道這個事
※ 編輯: kakashi45232 來自: 118.170.136.179 (05/24 08:59)
→
05/24 11:33, , 10F
05/24 11:33, 10F
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章