|
使用定時器T0產生PWM方波,
用按鍵調整占空比,20級可調
控制led燈的亮度等級.
源程序:
- #include "my51.h"
- #include "timer0.h"
- #define grading 20 //亮度20級變化
- sbit keyS3=P3^5; //按鍵調整占空比,PWM_keyChange++
- sbit keyS4=P3^6; // PWM_keyChange--
- u8 PWM_keyChange=10; //初值,按鍵調整在1~20之間變化
- //占空比 PWM_keyChange/grading
- void T0_work() //本函數由T0定時器中斷函數調用
- {
- if(timeMultiple1Flag)
- {
- led=off(7); //關閉7號燈
- timeMultiple1Flag=0; //清定時器復用置位標志
- }
-
- if(timeMultiple2Flag)
- {
- led=on(7); //打開7號燈
- timeMultiple2Flag=0; //清定時器復用置位標志
- }
- }
- void main() //測試
- {
- u8 keyFlag=1; //程序中沒有消抖處理,只是簡易的按鍵進出自鎖標志
- led0=ledon; //先打開0號燈,用于和7號燈對比亮度
- initT0(1,10,grading); //1毫秒的基本定時,亮的時間1*10毫秒,暗1*(grading-10)毫秒
- while(1)
- {
- if(0==keyS3)
- {
- if(keyFlag) //防止一次按鍵中多次執行
- {
- keyFlag=0; //清標志,類似同步鎖
- if(++PWM_keyChange>grading)
- {
- PWM_keyChange=grading; //占空比最大100%
- }
- initT0(1,PWM_keyChange,grading);
- }
- }
- else if(0==keyS4)
- {
- if(keyFlag)
- {
- keyFlag=0;
- if(0==--PWM_keyChange) //占空比減小
- {
- PWM_keyChange=1; //最小占空比 1/20
- }
- initT0(1,PWM_keyChange,grading); //占空比減小
- }
- }
- else
- {
- keyFlag=1; //按鍵鎖釋放標志,下一次按鍵時允許調整占空比
- }
- }
- }
復制代碼- #ifndef _MY51_H
- #define _MY51_H
- #include <reg52.h>
- //#include <math.h>
- #include <intrins.h>
- #include <stdio.h>
- #include "mytype.h"
- #ifndef _51LED_
- #define _51LED_
- #define led P1 //P1總線連8個led燈,燈連573鎖存器,P1置低電平點亮
- #define LED led
- #define ON(x) P1&(~(1<<(x))) //打開某個燈,開多個燈用 ON(m) & ON(n)
- #define OFF(x) P1|(1<<(x)) //關閉某個燈,關多個燈用 OFF(m)| OFF(n)
- #define on(x) ON(x) //包含大小寫
- #define off(x) OFF(x)
- #define ledon 0 //某個燈,打開
- #define ledoff 1 //某個燈,關閉
- sbit led0=P1^0;
- sbit led1=P1^1;
- sbit led2=P1^2;
- sbit led3=P1^3;
- sbit led4=P1^4;
- sbit led5=P1^5;
- sbit led6=P1^6;
- sbit led7=P1^7;
- sbit ledLock=P2^5; //鎖定當前8個led的狀態,0鎖定 ,1不鎖定
- #endif
- /*************二進制輸入宏****************************/
- #ifndef _LongToBin_
- #define LongToBin(n) \
- ( \
- ((n >> 21) & 0x80) | \
- ((n >> 18) & 0x40) | \
- ((n >> 15) & 0x20) | \
- ((n >> 12) & 0x10) | \
- ((n >> 9) & 0x08) | \
- ((n >> 6) & 0x04) | \
- ((n >> 3) & 0x02) | \
- ((n ) & 0x01) \
- )
- #define bin(n) LongToBin(0x##n##l)
- #define BIN(n) bin(n)
- #define B(n) bin(n)
- #define b(n) bin(n)
- #endif
- /*************單個數據位的置位宏*********************/
- #ifndef _BIT_
- #define BIT(n) (1<<n)
- #define bit(n) BIT(n)
- #endif
- #define high 1 //高電平
- #define low 0 //低電平
- sbit beep=P2^3; //蜂鳴器
- extern void delayms(u16 ms);
- extern void delayXus(u8 us); //函數執行(8+6x)個機器周期, 即t=(8+6x)*1.085
- /////////////////////////////////////////////////////////////////////////////
- #endif
復制代碼- #ifndef _TIMER0_H
- #define _TIMER0_H
- #include "my51.h"
- extern u8 timeMultiple1Flag; //中斷時間復用置位標志,須手動清零
- extern u8 timeMultiple2Flag; //中斷時間復用置位標志,須手動清零
- extern void T0_work(); //該函數未實現,需外部實現
- extern void initT0(u8 ms,u16 t_multiple1,u16 t_multiple2) ; //定時器初始化
- #endif
復制代碼- #include "timer0.h"
- u8 TH0Cout=0 ; //初值
- u8 TL0Cout=0 ;
- u16 T0IntCouts1=0; //中斷計數
- u16 T0IntCouts2=0; //中斷計數
- u16 timeMultiple1=0; //中斷復用時間的倍數
- u16 timeMultiple2=0; //中斷復用時間的倍數
- u8 timeMultiple1Flag=0; //中斷時間復用置位標志,須手動清零
- u8 timeMultiple2Flag=0; //中斷時間復用置位標志,須手動清零
- //開啟定時器,定時完成后需要手動關閉TR0,否則將循環定時
- //參數一是定時的毫秒數,參數二和三是定時基時的倍率數(定時復用)
- void initT0(u8 ms,u16 t_multiple1,u16 t_multiple2) //定時器初始化設定,ms取值不超過65
- {
- u16 N=11059.2*ms/12; //定時器總計數值
- TR0=STOP; //停掉定時器
- ET0=CLOSE; //關定時器中斷
- //對于110592晶振,ms為5的整數倍時沒有計算誤差,但ms最大不超過71毫秒
- TH0Cout =(65536-N)/256; //裝入計時值零頭計數初值
- TL0Cout =(65536-N)%256;
- if(0==t_multiple1) //0倍的基準時間是不合理的,至少1倍
- {
- t_multiple1=1;
- }
- if(0==t_multiple2) //0倍的基準時間是不合理的,至少1倍
- {
- t_multiple2=1;
- }
- timeMultiple1=t_multiple1; //倍時
- timeMultiple2=t_multiple2; //倍時
- TMOD &= 0xf0; //清定時器0配置
- TMOD |= 0x01; //配置定時器0的工作方式為1
-
- EA =OPEN; //打開總中斷
- ET0=OPEN; //打開定時器中斷
- TH0=TH0Cout; //定時器裝入初值
- TL0=TL0Cout;
- TR0=START; //啟動定時器
- }
- void T0_times() interrupt 1 //T0定時器中斷函數
- {
- TH0=TH0Cout; //重裝初值
- TL0=TL0Cout;
- if(++T0IntCouts1==timeMultiple1) //判斷是否復用定時器
- {
- T0IntCouts1=0; //中斷次數清零,重新計時
- timeMultiple1Flag=1; //復用定時器標志,須在T0_work()中手動清零
- }
- if(++T0IntCouts2==timeMultiple2) //判斷是否復用定時器
- {
- T0IntCouts1=0; //這個也要清,防止到達最小公倍數時亂掉
- T0IntCouts2=0; //中斷次數清零,重新計時
- timeMultiple2Flag=1; //復用定時器標志,須在T0_work()中手動清零
- }
- T0_work(); //調用工作函數
- }
復制代碼
|
|