[問題] 8051的P0值會影響中斷嗎

看板C_and_CPP (C/C++)作者 (23254ihsakak)時間13年前 (2013/05/23 19:21), 編輯推噓3(307)
留言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
在鍵盤電路拉一個nor gate小電路,輸出腳拉到中斷I/O
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
型別不一樣呢 改keyboard 哪個副程式看看吧
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
你這樣不是只會進入if p0.7哪個case 應該不會去掃自己按的
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
you're right! 以前學51是這麼做的(年代久遠XDD)
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
文章代碼(AID): #1HdVlAkl (C_and_CPP)
文章代碼(AID): #1HdVlAkl (C_and_CPP)