全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:7770
推到 Plurk!
推到 Facebook!

8051中斷(INT0 & UART)

答題得分者是:
typenew
一般會員


發表:8
回覆:17
積分:5
註冊:2004-03-26

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-08-19 12:20:51 IP:210.66.xxx.xxx 訂閱
小弟最近再寫一個8051 firmware,此firmware可以利用UART接受Command之後,Decode Command再進行該做的事情,另外還利用P3.2的外部中斷( INT 0 )接上一顆按鈕,當按下按鈕產生中斷,就會跳至該中斷的函式中執行該做的事情。
以下是片斷的Source code
[code cpp]
void INT0_S(void) interrupt 0
{
EA = 0; // disable all MPU interrupt
P4_2 = !P4_2;
Delay_100x100Cycle();
EA = 1; // release MPU intterupt
}
void main(void)
{
char counter;

P4_2 = 0;
counter = 128;
/*----------------Init UART ------------------*/
InitUART();
while(1)
{
if(UART_ReadData()!= 0xAA) continue;
switch(UART_ReadData())
{
case FUN_EE_DATA_UNLOCK:
UART_WriteData(0xAA);
UART_WriteData(EE_DATA_UNLOCK_OK);
printf("\r\nFUN_EE_DATA_UNLOCK");
break;
//-------------------
// EEPROM Erase
//--------------------
case FUN_MASS_ERASE:
//EraseEE();
UART_WriteData(0xAA);
UART_WriteData(MASS_ERASE_OK);
printf("\r\nFUN_MASS_ERASE");
break;

case FUN_PROGRAM_CONTINUE:

//Write_EEPROM_Fun();
UART_WriteData(0xAA);
UART_WriteData(PROGRAM_CONTINUE_OK);
printf("\r\nFUN_PROGRAM_CONTINUE");
break;

default:
break;

}
}
}
//===================================================================
// F: InitUART()
//===================================================================
void InitUART(void)
{
IE = 0x93; // IE: enable UART interrupt
SCON = 0x50; // SCON: mode 1, 8-bit UART, enable rcvr
TMOD = 0x20;
TH1 = 255; // TH1: 9600 (10416.6) bit/sec , 20MHz
PCON = PCON | 0x80;
TCON = 5;

TR1 = 1; // TR1: timer 1 run
ET0 = 0;
}
//===================================================================
// F: UART_ReadData()
//===================================================================
BYTE UART_ReadData(void)
{
// EA = 0; // disable all interrupt
while (RI == 0);
RI = 0;
// EA = 1; // release EA bit
return SBUF;
}
//===================================================================
// F: UART_WriteData()
//===================================================================
void UART_WriteData(BYTE Data)
{
EA = 0; // disable all interrupt
SBUF = Data;

while (TI == 0);
TI = 0;
EA = 1; // release EA bit
}
[/code]
在main中會等待PC端利用UART來傳送Command,PC端會送出兩BYTE Command,第一個BYTE必為0xaa,第二個BYTE看user要做何動作,送出相對應的BYTE。
P4_2 有接一顆LED,當有外部中斷產生,也就是按下按鈕,就會讓燈熄滅或者打開。

問題1:
當reset之後,按下Button,燈光會有反應,只是如果PC有傳Command過來之後,不管怎麼按下Button都不能夠動作了。

問題2:
還沒傳Command前,按下Button會有動作,不過其動作不如預期,所謂不如預期是指,當目前Led是亮的話,按下Button理論上會熄滅,如果是熄滅的,按下去會打開;但是有時候會發生,按下去熄滅過一下子就又打開了。

請問各位先進針對以上的問題是否有任何的看法。
不知道是不是要將接收或傳送uart的function,寫成interrupt的方式 不要用busy loop來等待?
也就是說不管任何的interrupt都要寫成下面這種方式來做處理,連uart最好也是?
void xxxxx(void) interrupt x
{
....
....
....
....
}

版主


發表:261
回覆:2302
積分:1667
註冊:2005-01-04

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-08-20 01:54:12 IP:202.132.xxx.xxx 未訂閱
Q1: 看不到完整程式.  是不是傳一次 command 就掛了? 如果是, 你的主程式or UART 中斷有問題. 請自己多檢查.

Q2: 基本上不知道你delay多久(INT0), 如果只有10ms, 你的程式會不斷進入中斷(只要 PIN INT0 為Lo).
10ms 閃一次, 你應該看不到. 你可以直接加長到 500ms試試.


FYI
------
-------------------------------------------------------------------------
走是為了到另一境界,停是為了欣賞人生;未走過千山萬水,怎知生命的虛實與輕重!?
typenew
一般會員


發表:8
回覆:17
積分:5
註冊:2004-03-26

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-08-20 14:36:50 IP:210.66.xxx.xxx 訂閱
感謝㊣ 大的回覆
Q1:
Ans: 現在的情況是這樣,的確傳一次command之後,INTO這個中斷就無法進去,但是如果繼續傳第二次以上Command,針對於Command所對應的switch case(source code line 19 ~ 45) 還是會有反應。
小弟就加上如下的code
[code cpp]
void UART_S(void) interrupt 4
{
EA = 0; // disable all interrupt
RI = 0;
TI = 0;
EA = 1; // release EA bit
}
[/code]
只要將此interrupt routine加上去,雖然裡面做的事只是把TI RI clear,這樣子至少剛剛說的INT0就會有反應了。
Q2:
Ans:
關於此按鈕的功能,目前小弟所實作的方式是,Power on 時預設是Led亮,當按下第一次會"暗" ,再按下一次"亮",以此類推。
問題解決了,原來是因為所使用的按鈕機械結構的問題,明明手指只按一次,居然在示波器上會出現兩個Pulse,所以才會連續進去中斷的情形發生,所以就把按鈕換成另一種就可以解決了。(INT0 設定為 negative-edge triggered)

目前問題就是出現說當Power on 時按下Button(INT0) 都有反應,只要PC端透過UART送出Command一次之後,不管怎麼按下Button都沒反應了。
關於完整的source code 小弟已上傳至
http://delphi.ktop.com.tw/board.php?cid=31&fid=97&tid=94971

因為小弟用修改文章的方式發現無法再次上傳檔案,故只好去此空間開闢新文章上傳檔案,很抱歉浪費網路空間。
===================引 用 ㊣ 文 章===================
Q1: 看不到完整程式. 是不是傳一次 command 就掛了? 如果是, 你的主程式or UART 中斷有問題. 請自己多檢查.
Q2: 基本上不知道你delay多久(INT0), 如果只有10ms, 你的程式會不斷進入中斷(只要 PIN INT0 為Lo).
10ms 閃一次, 你應該看不到. 你可以直接加長到 500ms試試.

FYI


版主


發表:261
回覆:2302
積分:1667
註冊:2005-01-04

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-08-20 23:54:19 IP:202.132.xxx.xxx 未訂閱
1> 若程式只有 2 個中斷, 設定好中斷優先權, 不用進入一個中斷就關掉整個中斷.
2> 基本上UART read data 你不用特別寫一個 function 然後等在那邊去取資料. 中斷不是很好用嗎? 再由旗標去判斷是接收中斷或傳送中斷即可.

我覺得你有點把問題複雜化了.
你的這個問題可簡單規劃為INT0_interrupt, UART_interrupt, Main_loop 就這樣.
Main_loop : 初始化後 --> while(1){}; 其他事件通通交給中斷處理
INT0 : 處理按鈕
UART : 處理input or ouput


你寫的方式, PC端一傳data進來你就掛點了(繞圈圈, 且把EA關掉)

FYI.
------
-------------------------------------------------------------------------
走是為了到另一境界,停是為了欣賞人生;未走過千山萬水,怎知生命的虛實與輕重!?
typenew
一般會員


發表:8
回覆:17
積分:5
註冊:2004-03-26

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-08-22 01:25:28 IP:61.230.xxx.xxx 訂閱
感謝 大的回答,讓小弟知道整個大架構如何去實作了。
只是針對於"PC端一傳data進來你就掛點了(繞圈圈, 且把EA關掉)"這點感到疑惑,因為小弟作了一個實驗,就是將所有"EA = 0;"的地方都mark掉,原本在main.c 中 while(1)裡的判斷也都拿掉,發現PC端還沒傳資料前,INT0還可以正常運作,但是只要一傳資料進來,INT0一定會沒有反應,這就不知道為什麼了,這應該跟(繞圈圈, 且把EA關掉)
有關,只是不知道確切的地方在那,是否可以在勞煩 大解釋一下為什麼會這樣,謝謝。
===================引 用 文 章===================
1> 若程式只有 2 個中斷, 設定好中斷優先權, 不用進入一個中斷就關掉整個中斷.
2> 基本上UART read data 你不用特別寫一個 function 然後等在那邊去取資料. 中斷不是很好用嗎? 再由旗標去判斷是接收中斷或傳送中斷即可.

我覺得你有點把問題複雜化了.
你的這個問題可簡單規劃為INT0_interrupt, UART_interrupt, Main_loop 就這樣.
Main_loop : 初始化後 --> while(1){}; 其他事件通通交給中斷處理
INT0 : 處理按鈕
UART : 處理input or ouput


你寫的方式, PC端一傳data進來你就掛點了(繞圈圈, 且把EA關掉)

FYI.
系統時間:2024-05-02 10:51:22
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!