8051中斷(INT0 & UART) |
答題得分者是:㊣
|
typenew
一般會員 發表:8 回覆:17 積分:5 註冊:2004-03-26 發送簡訊給我 |
小弟最近再寫一個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 發送簡訊給我 |
Q1: 看不到完整程式. 是不是傳一次 command 就掛了? 如果是, 你的主程式or UART 中斷有問題. 請自己多檢查.
Q2: 基本上不知道你delay多久(INT0), 如果只有10ms, 你的程式會不斷進入中斷(只要 PIN INT0 為Lo). 10ms 閃一次, 你應該看不到. 你可以直接加長到 500ms試試. FYI
------
------------------------------------------------------------------------- 走是為了到另一境界,停是為了欣賞人生;未走過千山萬水,怎知生命的虛實與輕重!? |
typenew
一般會員 發表:8 回覆:17 積分:5 註冊:2004-03-26 發送簡訊給我 |
感謝㊣ 大的回覆
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 發送簡訊給我 |
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 發送簡訊給我 |
感謝㊣ 大的回答,讓小弟知道整個大架構如何去實作了。
只是針對於"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. |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |