SOGO論壇
標題:
這個程式有些地方需要解惑
[列印本頁]
作者:
NICEPLAY1
時間:
2016-4-9 21:33:36
標題:
這個程式有些地方需要解惑
關於以下程式我想了解的是計時中斷副程式的TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
以及主程式的 IE=0x8A;
TMOD=0x11;
if (sw1==0){
while(sw1!=0);
cnt=(cnt+1)%2;
是什麼意思呢 ?
中斷副程式的-1000 據我所知為我所使用的震盪器是12MHz 所以掃描的速度為1u*1000 所以是1mS
但是不了解他的原理
而主程式的IE.TMOD則是完全沒有概念
在SW1的部分 我的開關是使用紅外線功能為 當感測到第一次 會開始計時 感測到第二次則會停止
但是不了為何程式的部分要這樣寫希望能解答
另外我的CNT=狀態 如高態低態這樣的想法是正確的嗎
以上希望能求解
# include<reg51.h>
sbit sw1=P1^7;
unsigned char seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x27,0x7f,0x67}; //0~9的字型碼
unsigned char com[]={0x10,0x20,0x40,0x80,0x01,0x02,0x04,0x08};
unsigned char cnt=0,hour,min,sec,ms,index,disp[8];
/* 顯示副程式 */
void display(void)
{ disp[0]=seg[hour/10]; // 放小時的拾位數
disp[1]=seg[hour%10]; // 放小時的個位數
disp[2]=seg[min/10];
disp[3]=seg[min%10];
disp[4]=seg[sec/10];
disp[5]=seg[sec%10];
disp[6]=seg[ms/10];
disp[7]=seg[ms%10];
}
/****** T0 計時中斷的副程式 ******/
void timer0 (void) interrupt 1
{ TH0=(65536-1000)/256; // TH0存放商數
TL0=(65536-1000)%256; // TL0存放餘數
P2=0xff; // 顯示器不亮
P0=~disp[index]; // 顯示的字型碼由P1輸出
P2=~com[index]; //顯示器的掃描碼由P0輸出
index++;if(index>=8) index=0; //輪流掃描顯示器
}
/***** T1 計時中斷的副程式 *****/
void timer1 (void) interrupt 3
{ TH1=(65536-10000)/256; // TH1存放商數
TL1=(65536-10000)%256; // TL1存放餘數
if(cnt==1){
ms++;}
if(ms > 99){
ms=0;
sec++;}
if(sec > 59){
sec=0;
min++;}
if(min > 59){
min=0;
hour++;}
if((hour==23)&&(min==59)&&(sec==59)&&(ms==99)){
TR1=0;}
display(); //呼叫顯示副程式
}
/***** 主程式 *****/
void main( ){
IE=0x8A;
TMOD=0x11;
TR0=TR1=1; //啟動Timer 0 ,Timer 1
while(1){
if (sw1==0){
while(sw1!=0);
cnt=(cnt+1)%2;
}}}
作者:
alphi
時間:
2016-4-10 16:02:49
本帖最後由 alphi 於 2016-4-10 16:03 編輯
1. 標準8051 的Timer Clock是Fosc/12 (也就是當外面石英震盪器為12MHz, 內部Timer為12MHz/12=1MHz 處理速度)
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
複製代碼
由於8051是Up-Counter , 也就是當計數值達到65536 才會發OVF中斷, 那要如何得到1ms ,已經知道8051 是要65536才會發生中斷,也就是設定
TIMER_COUNT = 65536-1000 = 64536
複製代碼
但由於8051 的TIMER 設定值只有TH0,TL0兩個8位元,而很明顯64536 超過8位元的長度,所以要分成兩個放在,所以TIMER設定就會像你提到的設定一樣
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
複製代碼
2.主程式中
void main( ){
IE=0x8A;
TMOD=0x11;
TR0=TR1=1; //啟動Timer 0 ,Timer 1
while(1){
if (sw1==0){
while(sw1!=0);
cnt=(cnt+1)%2;
}}}
複製代碼
IE = 0x8A 是設定中斷控制器開啟全域中斷(EA=1),TIMER1中斷(ET1=1),TIMER0中斷(ET0=1)
TMOD = 0x11 是設定TIMER模式為two-8bit, 這個跟你上面的TH0,THL1設定會衝突(8bit 計數值最高為255, 而你要設定到64336) 這在時間上會出問題,你應該設定為TMOD=0x01 (16bit 模式)
while(1){
if (sw1==0){
while(sw1!=0);
cnt=(cnt+1)%2;
}}
複製代碼
在嵌入式設計中使用% 取於數是很沒效率法.
cnt = (cnt +1) %2;
複製代碼
結果只會cnt = 0,cnt=1,cnt= 0 , cnt= 1,...
你可以改成
cnt ^=1 //(cnt 做xor) cnt =0, cnt =1, cnt =2
複製代碼
或者
cnt = (cnt +1) & 1 (對最後一個bit 做AND)
複製代碼
都比cnt = (cnt +1) % 2 有效率多
作者:
NICEPLAY1
時間:
2016-4-10 23:40:03
好的 謝謝解答
1.那麼如果有人問到 CNT是什麼該如何解釋呢?
2.為何0x01 會等於16位元可以請教計算方式嗎?
3如果未來此作品要延伸 是否可以朝向一次計時多個事件的方向呢?
如:常用的秒錶有記錄功能那樣子的
目前作品的元件只有簡單的七段顯示器及一個紅外線感測器
4.如果可以我應該加入什麼元件 ﹐程式該修改什麼呢?
作者:
alphi
時間:
2016-4-11 12:37:58
1. CNT 看程式碼應該是當你壓下按鈕送0,在壓一次送1, 一直循環(也就是當壓下開關就是啟動一次)
2. TMOD=0x01, 請參考8051 設計資源.網路上有許多老師授課資料
3. 這是可以甚至你可以使用到SoftTimer 技巧,用一個Timer 實現多個Timer 計時值
4. 網路上資源很多,看你的應用有電像是賽跑透過紅外線感測器紀錄多個跑者時間, 這個應該不適很難做
作者:
NICEPLAY1
時間:
2016-4-11 23:18:47
不好意思 想請教一下您所說的
3.使用SoftTimer 技巧,用一個Timer 實現多個Timer 計時值
是指一次能夠計時多個不同數值
還是......?
作者:
K.Justin
時間:
2016-4-13 01:40:27
記數的timer要看您使用的MCU有幾個可以用,如果只是要記數,那就在程式的中斷裡,多設幾個變數,不斷的++就好了,應該是這樣吧??
作者:
alphi
時間:
2016-4-20 14:58:12
本帖最後由 alphi 於 2016-4-20 15:03 編輯
K.Justin 發表於 2016-4-13 01:40
記數的timer要看您使用的MCU有幾個可以用,如果只是要記數,那就在程式的中斷裡,多設幾個變數,不斷的++就 ...
類似 不過可以改成更有可讀性的寫法
定義
#define MAX_SOFT_TIMER 4
struct soft_timer_t
{
int period;
int count;
bool flag;
}softtimer[MAX_SOFT_TIMER];
複製代碼
初始值
softtimer[0].period = 1000;
softtimer[0].count = 1000;
softrimer[0].flag = 0;
softtimer[1].period = 2000;
softtimer[1].count = 2000;
softrimer[1].flag = 0;
...
複製代碼
3.中斷處里
void TIMER_Handler(void)
{
if(--softtimer[count].count == 0) //當數到0
{
softtimer[count].flag = 1;
softtimer[count].count = softtimer[count].period; //重新給定值
}
count = (count < MAX_SOFTTIMER) ? (count +1) : 0;
}
複製代碼
可以根據需求去設定真實Timer 的interval (例如1ms,100us ,....) 等以此為Base
當Timer 不夠多,且解析度不用太高如100ns,1us 這種 , 可以考慮此方法(也可以長時間計數)
歡迎光臨 SOGO論壇 (https://oursogo.com/)
Powered by OURSOGO.COM