單片機(jī)要想實(shí)現(xiàn)多個(gè)不同時(shí)基的控制,除了上系統(tǒng)外,本人采用分時(shí)段的方法,結(jié)合PLC的控制原理,實(shí)現(xiàn)出類似PLC定時(shí)器的控制方法,分別有0.01S定時(shí)器 12個(gè),0.1MS定時(shí)器 10個(gè),1S定時(shí)器10個(gè),可以單獨(dú)設(shè)定,同時(shí)使用。如果MCU的程序容量比較大,可以實(shí)現(xiàn)更多的定時(shí)器,不過一般建議根據(jù)實(shí)際項(xiàng)目要求來調(diào)整。實(shí)現(xiàn)過程思路代碼如下(STC89單片機(jī)):
//以下程序及算法由本人zyhlove813原創(chuàng),特別是soft_timer實(shí)現(xiàn)算法值得借鑒,適用所有MCU,源碼示例請(qǐng)下載附件 #include "reg51.h" typedef unsigned char uint8_t; typedef unsigned int uint32_t; /* define constants */ #define true 1 #define false 0 #define FOSC 11059200L //時(shí)鐘頻率 #define T1MS (65536-FOSC/12/1000) //1MS定時(shí)器設(shè)定值 #define T10ms 12 //0.01S定時(shí)器數(shù)組索引上限=12-1=11,因此0.01S定時(shí)器的個(gè)數(shù)=12個(gè) #define T100ms (T10ms+10) //0.1S定時(shí)器數(shù)組索引上限=22-1=21,因此0.1S定時(shí)器的個(gè)數(shù)=21-11=10個(gè) #define Timers 32 //1S定時(shí)器數(shù)組索引上限=32-1=31,因此1S定時(shí)器的個(gè)數(shù)=31-21=10個(gè) #define Timers_bit (Timers/8) //八個(gè)定時(shí)器為一組,共32/8=4組 #define SET_BIT(s,b,c)(s=(s&(~(1<<b)))+(c<<b)) //宏,設(shè)置某個(gè)位的值,0或1的狀態(tài) #define GET_BIT(s,b)((s>>b)&0x01) //宏,獲取某個(gè)位的值,返回0或1的狀態(tài) #define SET_EN(b,c) (SET_BIT(timer_en[b/8],b%8,c)) //設(shè)置對(duì)應(yīng)定時(shí)器使能狀態(tài) #define SET_ON(b,c) (SET_BIT(timer_on[b/8],b%8,c)) //設(shè)置對(duì)應(yīng)定時(shí)器對(duì)應(yīng)使能狀態(tài) #define GET_EN(b) (GET_BIT(timer_en[b/8],b%8)) //獲取對(duì)應(yīng)定時(shí)器對(duì)應(yīng)使能狀態(tài) #define GET_ON(b) (GET_BIT(timer_on[b/8],b%8)) //獲取對(duì)應(yīng)定時(shí)器線圈狀態(tài) uint8_t timer_en[Timers_bit]; //定時(shí)器使能狀態(tài)緩存 uint8_t timer_on[Timers_bit]; //定時(shí)器線圈狀態(tài)緩存 uint32_t timer_pv[Timers]; //定時(shí)器目標(biāo)值緩存 uint32_t timer_cv[Timers]; //定時(shí)器當(dāng)前值緩存 uint32_tcount_1ms; //硬件定時(shí)器1MS計(jì)數(shù)器 sbit LED1=P1^1; //測(cè)試用的IO1 sbit LED2=P1^2; //測(cè)試用的IO2 void soft_timer(void); //聲明函數(shù) void timer0_isr() interrupt 1 //定時(shí)器0中斷,每1MS中斷一次 { TL0 = T1MS; //reloadtimer0 low byte TH0 = T1MS>> 8; //reload timer0 high byte soft_timer(); //調(diào)用軟件定時(shí)器判斷 } void main() { TMOD = 0x01; //set timer0 as mode1 (16-bit) TL0 = T1MS; //initialtimer0 low byte TH0 = T1MS>> 8; //initial timer0 high byte TR0 = 1; //timer0 start running ET0 = 1; //enable timer0 interrupt EA = 1; //open global interrupt switch count_1ms = 0; //initial counter timer_pv[1]=1; //0.01S定時(shí)器(1)的目標(biāo)值設(shè)為1,即10MS timer_pv[2]=1; //0.01S定時(shí)器(2)的目標(biāo)值設(shè)為1,即10MS timer_pv[12]=5; //0.1S定時(shí)器(12)的目標(biāo)值設(shè)為5,即500MS timer_pv[13]=5; //0.1S定時(shí)器(13)的目標(biāo)值設(shè)為5,即500MS SET_EN(1,1); //0.01S定時(shí)器(1)使能有效,開始計(jì)時(shí) SET_EN(12,1); //0.1S定時(shí)器(12)使能有效,開始計(jì)時(shí) while (1) { if(GET_ON(1)) //如果0.01S定時(shí)器(1)的定時(shí)線圈為1,即定時(shí)時(shí)間到 { LED1=1; //LED1亮 SET_EN(2,1); //0.01S定時(shí)器(2)使能有效,開始計(jì)時(shí) SET_EN(1,0); //0.01S定時(shí)器(1)使能無(wú)效,停止計(jì)時(shí) } if(GET_ON(2)) //如果0.01S定時(shí)器(2)的定時(shí)線圈為1,即定時(shí)時(shí)間到 { LED1=0; //LED1滅 SET_EN(1,1); //0.01S定時(shí)器(1)使能有效,開始計(jì)時(shí) SET_EN(2,0); //0.01S定時(shí)器(2)使能無(wú)效,停止計(jì)時(shí) } if(GET_ON(12)) //如果0.1S定時(shí)器(12)的定時(shí)線圈為1,即定時(shí)時(shí)間到 { LED2=1; //LED2亮 SET_EN(13,1); //0.1S定時(shí)器(13)使能有效,開始計(jì)時(shí) SET_EN(12,0); //0.1S定時(shí)器(12)使能無(wú)效,停止計(jì)時(shí) } if(GET_ON(13)) { LED2=0; //LED2滅 SET_EN(12,1); //0.1S定時(shí)器(12)使能有效,開始計(jì)時(shí) SET_EN(13,0); //0.1S定時(shí)器(13)使能無(wú)效,停止計(jì)時(shí) } } } //軟件定時(shí)器的實(shí)現(xiàn) void soft_timer() { uint8_ti; uint8_ttemp; count_1ms++; //1MS計(jì)數(shù)值+1 if(count_1ms%10==0) //判斷是否0.01S時(shí)間到 { for(i=0;i<T10ms;i++) //更新0.01S定時(shí)器的當(dāng)前值 { timer_cv+=GET_EN(i); //如果EN=1,則當(dāng)前值+1,否則+0 timer_cv*=GET_EN(i); //如果EN=1,則當(dāng)前值不變,否則當(dāng)前值=0 保障當(dāng)前值根據(jù)使能狀態(tài)自動(dòng)加或清零 temp=GET_EN(i)*(timer_cv>=timer_pv); //計(jì)算是否到達(dá)目標(biāo)時(shí)間,如果使能無(wú)效的話,結(jié)果是0,如果使能有效的話,而且當(dāng)前值大于目標(biāo)值,結(jié)果是1 SET_ON(i,temp); //更新線圈是否到時(shí)狀態(tài) } } //以下算法相同 if(count_1ms%100==0) //判斷是否0.1S時(shí)間到 { for(i=T10ms;i<T100ms;i++) { timer_cv+=GET_EN(i); timer_cv*=GET_EN(i); temp=GET_EN(i)*(timer_cv>=timer_pv); SET_ON(i,temp); } } if(count_1ms%1000==0) //判斷是否1S時(shí)間到 { count_1ms=0; //1MS計(jì)數(shù)器重啟 for(i=T100ms;i<Timers;i++) { timer_cv+=GET_EN(i); timer_cv*=GET_EN(i); temp=GET_EN(i)*(timer_cv>=timer_pv); SET_ON(i,temp); } } }
全部資料51hei下載地址:
SoftTimer.rar
(31.31 KB, 下載次數(shù): 107)
2020-11-13 15:07 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|