線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:6129
推到 Plurk!
推到 Facebook!

8051計數器問題(C語言)

答題得分者是:DavidLo
kevin888
一般會員


發表:4
回覆:8
積分:2
註冊:2011-09-27

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-09-27 22:52:45 IP:120.126.xxx.xxx 訂閱
8051計數器問題(C語言) :

目的是利用光遮斷器測馬達轉速, 現在光遮斷器硬體功能正常,

如何利用8051計時/計數功能, 計算光遮斷器一分鐘所產生的脈波次數(rpm)??

我應該把光遮斷的輸出脈波, 接到8051的INT0 or INT1來做計數功能呢??

我在書本上看到, 當計時器T0的 C/T=1時, 由外部接腳T0來供給, 做為計數器使用,

這個部份我該如何定義?? 需要配合計時器嗎??
DavidLo
高階會員


發表:17
回覆:225
積分:168
註冊:2004-07-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2011-09-28 08:40:01 IP:111.240.xxx.xxx 訂閱
Check this if can help you

1.使用一個Timer去建立時基程序,10mS,100mS,1S,10S,....
2.外部中斷計數使用INT0,INT1,Timer都可以,原則上頻率高的用Timer/Counter
3.分析=> (Step2所得次數) / (所用時基單位),就是你要的東西

FYI
編輯記錄
DavidLo 重新編輯於 2011-09-27 18:41:02, 註解 無‧
kevin888
一般會員


發表:4
回覆:8
積分:2
註冊:2011-09-27

發送簡訊給我
#3 引用回覆 回覆 發表時間:2011-09-29 01:32:18 IP:111.240.xxx.xxx 訂閱
int count = 10; //0.1s = 10* 0.01s
void T0_int(void) interrupt 1 //計時器
{
TL0 = (65536 - 9217) % 256; // 計數時間 : 9217 * 1.085us = 0.01s
TH0 = (65536 - 9217) / 256;
if(count==0)
{
******************
}
else
{
count - - ;
}
}
void T1_int(void) interrupt 3 //計數器
{?????????????}
void main()
{

TMOD = 0x51; //0101 0001 設定 T1 T0 mode1
TL0 = (65536 - 9217) % 256; //0.01s
TH0 = (65536 - 9217) / 256;
TL1 = 0;
TH1 = 0;
ET0 = 1; //接受計時 T0 所產生的中斷
ET1 = 1; //接受計數 T1 所產生的中斷
EA = 1; //IE = 0x86; // 1000 1010
TR0 = 1; // 程式將啟動計時器 T0
TR1 = 1; // 程式將啟動計數器 T1
while(1)
{

}
}
目的利用計時器計算光遮斷脈波進入8051 P3_5 T0腳位的次數,
計時器T0與計數器T1都是用內部中斷源分別是1跟3,
現在大概用0.01s取樣一次!! 程式初步大略為上述:
問題: 當我TR0=1, TR1=1, 先執行哪個中斷?? 計時計數器應該同時執行不是嗎??
我的程式最終目的是計時器1分鐘能得到幾個計數器的光遮斷脈波!!
現在構想用0.1s採樣一次光遮斷脈波進而換算成1分鐘有幾個脈波!!
計時器/計數器該怎麼樣同時使用呢???
DavidLo
高階會員


發表:17
回覆:225
積分:168
註冊:2004-07-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2011-09-29 09:36:28 IP:111.240.xxx.xxx 訂閱
問題: 當我TR0=1, TR1=1, 先執行哪個中斷?? 計時計數器應該同時執行不是嗎??
->中斷有優先權設定(IP),可以設定哪個先執行,中斷程序處理時間要愈短愈好!

你可能需要再多了解51Tiemr/Counter運作方式
以下僅供參考:

void EnableTimer0(void)
{
// 12MHz Crystal PERIOD=-250 intcycle=4 250uS*4=1mS
/* setup the timer 0 interrupt */
TH0 = (unsigned char) PERIOD; /* set timer period */
TL0 = (unsigned char) PERIOD;
TMOD = TMOD | 0x02; /* select mode 2 */
TR0 = 1; /* start timer 0 */
ET0 = 1; /* enable timer 0 interrupt */
}

void timer0 (void) interrupt 1
{
ET0=0;
if( intcycle >= 4)
{ // every 1ms execute once
intcycle = 0;
if( currenttime.msec >= 1000)
{// every 1s execute once
currenttime.msec = 0;
GetInt0Data();
}
}
ET0=1;
}

void EnableInt0(void)
{
IT0=1; //set falling edge trigger
EX0=1; //enaable external input 0
}
void int0process(void) interrupt 0 //use int0 as an example
{
flowPulseS ;
}
void GetInt0Data(void)//every one second run once
{
EX0=0;
flowPulseT =flowPulseS;//save for future use
flowPulseS=0;//reset pulse count
EX0=1;
}

void main(void)
{
.
.
EnableTimer0(); //SendTX("Timer0 initial ok");//system clock
EnableInt0(); //SendTX("Int0 initial ok"); //flow pulse
.
.
while(1)
{
//process pulse values and display flowPulseT
}
,
}
kevin888
一般會員


發表:4
回覆:8
積分:2
註冊:2011-09-27

發送簡訊給我
#5 引用回覆 回覆 發表時間:2011-09-29 11:36:14 IP:120.126.xxx.xxx 訂閱
void timer0 (void) interrupt 1
{
ET0=0;
if( intcycle >= 4)
{ // every 1ms execute once
intcycle = 0;
if( currenttime.msec >= 1000)
{// every 1s execute once
currenttime.msec = 0;
GetInt0Data();
}
}
ET0=1;
}
關於這段程式有2個問題:
1. 我是不是應該在最前面先宣告int cycle=0 , int currenttime=0
2.最後一行的ET0=1, 是不是會再次執行void timer0 (void) interrupt 1,
而形成迴圈讓time0執行時間為1s?? (250us*4*1000=1s) 概念是這樣嗎??
DavidLo
高階會員


發表:17
回覆:225
積分:168
註冊:2004-07-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2011-09-29 12:06:20 IP:111.240.xxx.xxx 訂閱
1. 我是不是應該在最前面先宣告int cycle=0 , int currenttime=0
-> Yes,變數要自行先告

2.1 最後一行的ET0=1, 是不是會再次執行void timer0 (void) interrupt 1,
->Not quite right
ET0=1 -> 是重新Enable Timer0中斷接收,以便接受Timer0產生的中斷
為避免中斷程序處理時間太長,進入時 ET0=0 是先將中斷關閉, 當然離開時 ET0=1 必須Enable回去

2.2 而形成迴圈讓time0執行時間為1s??
timer0()執行時間很短!每250uS執行一次.
不太能講是 "迴圈",CPU是固定被中斷後跳去執行timer0(),完成後再返回原中斷點下一步
2.3 (250us*4*1000=1s) 概念是這樣嗎??
Yes
kevin888
一般會員


發表:4
回覆:8
積分:2
註冊:2011-09-27

發送簡訊給我
#7 引用回覆 回覆 發表時間:2011-09-29 12:49:16 IP:120.126.xxx.xxx 訂閱
2.2的問題: 

程式執行順序: main()→EnableTimer0();→ timer0() → EnableInt0();

1. 所以不是迴圈的概念, 那time0()花了250us結束後,
不就會直接去執行 EnableInt0()的初始設定, 之後main主程式
就結束了, 那怎麼讓1s的設定完成??

2.是利用while(1)嗎??

DavidLo
高階會員


發表:17
回覆:225
積分:168
註冊:2004-07-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2011-09-29 14:04:03 IP:111.240.xxx.xxx 訂閱

中斷的觀念,可能要釐清


程式執行順序:
main()
EnableTimer0(); => initial timer0 and enable T0 interrupt => 這個之後就會每隔250uS中斷CPU目前的工作去執行 timer0()一次,
這個程序會一直做,一直做,一直做,一直做,直到當機為止,不管程式執行到哪
EnableInt0(); => enable INT0 interrupt => 外部中斷INT0 致能,開始接收中斷處理

while (1)
{
//中斷 一直工作中(背景)
//你的程式執行中
.
.
}


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