?? 零耗時低頻寬脈沖軟pwm信號控制keil c51演示程序.c
字號:
//零耗時低頻寬脈沖軟PWM信號控制Keil C51演示程序(hotpower)
/*----------------------------------------------------------------
零耗時低頻寬脈沖軟PWM信號控制Keil C51演示程序
C51文件PwmDemo.c
HotPower@126.com 作于2004.11.17與大雁塔村隊部
在uV3中對PWM信號進(jìn)行"實時仿真"效果逼真。
-----------------------------------------------------------------*/
#include
//#include
#include
/*------------------------------------------------
AT89S5X SFR定義(REGX52.h中未定義)
--------------------------------------------------*/
sfr AUXR = 0x8e;
sfr WDTRST = 0xa6;
sfr16 TIMEER2 = 0xcc;
sfr16 RCAP2 = 0xca;
/*-----------------------------------------------
PWM管腳定義
------------------------------------------------*/
sbit PWM = P1^0;//可以為任意IO管腳
typedef struct Systemstruct{//系統(tǒng)數(shù)據(jù)結(jié)構(gòu)
unsigned int PwmCount;//700~2300uS
unsigned int RamTest;//內(nèi)部ram自檢變量
/*--------------------------------------------------------------------
注意將STARTUP.A51中的IDATALEN改寫為0,RamTest才能完成MCU掉電自檢。
IDATALEN EQU 00H ; the length of IDATA memory in bytes.
---------------------------------------------------------------------*/
}SystemData;//系統(tǒng)數(shù)據(jù)結(jié)構(gòu)(此時只是定義了一個新的數(shù)據(jù)類型SystemData)
//全局變量定義(全局結(jié)構(gòu))
SystemData SystemBuffers;//申請系統(tǒng)數(shù)據(jù)結(jié)構(gòu)緩沖區(qū)
#define T2_20mS -20000 //MCU主頻12MHz,12分頻,T2_20mS=20MS
/*----------------------------------------------------------------------
系統(tǒng)函數(shù)
-----------------------------------------------------------------------*/
void MainInit(void);//系統(tǒng)初始化
void ClrWdt(void);//喂狗
void SystemInit(void);//系統(tǒng)初始化
void SystemSetup(void);//系統(tǒng)設(shè)置
void SystemIoInit(void);//系統(tǒng)接口初始化
void UserSetup(void);//用戶運行環(huán)境設(shè)置
void TimeInit(void);//定時器定時參數(shù)初始化
/*-----------------------------------------
主程序初始化
-------------------------------------------*/
void MainInit(void)//系統(tǒng)初始化
{
SystemIoInit();//系統(tǒng)接口初始化
ClrWdt();//清除看門狗計數(shù)器
if (SystemBuffers.RamTest != 0x55aa) {//內(nèi)存測試
SystemInit();//系統(tǒng)上電初始化
}
SystemSetup();//系統(tǒng)運行環(huán)境設(shè)置
UserSetup();//用戶運行環(huán)境設(shè)置
}
void SystemInit(void)//系統(tǒng)初始化
{
SystemBuffers.RamTest = 0x55aa;//內(nèi)存初始化
}
void SystemSetup(void)//系統(tǒng)設(shè)置
{
AUXR = 0x01;//關(guān)閉EMI
TimeInit();//定時器定時參數(shù)初始化
IP = 0x20;//中斷優(yōu)先級ET2
}
void UserSetup(void)//用戶運行環(huán)境設(shè)置
{
/*--------------------------------------------
在此加入用戶運行環(huán)境設(shè)置代碼
----------------------------------------------*/
}
void SystemIoInit(void)
{
IE = 0x00;//關(guān)閉中斷
P0 = 0xff;//P0口初始化
P1 = 0xfe;//P1口初始化,PWM=0
P2 = 0xff;//P2口初始化
P3 = 0xff;//P3口初始化
}
void TimeInit()
{
/*----------------------------------
定時器0定時參數(shù)設(shè)置
----------------------------------*/
TL0 = 0;
TH0 = 0;
// TR0 = 1;//啟動定時器0
/*----------------------------------
定時器1定時參數(shù)設(shè)置
----------------------------------*/
TL1 = 0xfd;
TH1 = 0xfd;
PCON = 0x00;//SMOD_=0,GF0_=0;//清除瘋狗標(biāo)志
// TR1 = 1;//啟動定時器1
/*----------------------------------
定時器2定時參數(shù)設(shè)置
----------------------------------*/
TIMEER2 = T2_20mS;//上電20mS后PWM開始工作
PWM = 0;//上電后無PWM信號
SystemBuffers.PwmCount = 700;//首次PWM脈寬為700uS
RCAP2 = 0 - SystemBuffers.PwmCount;//首次PWM脈寬為700uS
TR2 = 1;//啟動定時器2(上電后20mS內(nèi)PWM信號為低電平)
/*----------------------------------
定時器參數(shù)設(shè)置
----------------------------------*/
TMOD = 0x22;//定時方式(8位自動裝載)
}
/*---------------------------------------------------------------------
外部INT0中斷服務(wù)程序(PWM+10uS)
----------------------------------------------------------------------*/
void int0proc() interrupt IE0_VECTOR using 2
{
/*---------------------------------------------------------------------
用戶只能改寫全局變量SystemBuffers.PwmCount,不能改寫靜態(tài)變量PwmCount
----------------------------------------------------------------------*/
if (SystemBuffers.PwmCount <= 2290) //PWM高電平脈寬上界-10
SystemBuffers.PwmCount += 10;//遞增未越界
else
SystemBuffers.PwmCount = 700;//遞增越界翻到下界
}
/*---------------------------------------------------------------------
定時器T0中斷服務(wù)程序
----------------------------------------------------------------------*/
void t0proc() interrupt TF0_VECTOR using 2
{
if (PCON & GF0_) {//中斷是從主循環(huán)內(nèi)跳入的才能喂狗
ClrWdt();//清除看門狗計數(shù)器
PCON &= ~GF0_;//清除瘋狗標(biāo)志
}
}
/*---------------------------------------------------------------------
外部INT1中斷服務(wù)程序(PWM-10uS)
----------------------------------------------------------------------*/
void int1proc() interrupt IE1_VECTOR using 2
{
/*---------------------------------------------------------------------
用戶只能改寫全局變量SystemBuffers.PwmCount,不能改寫靜態(tài)變量PwmCount
----------------------------------------------------------------------*/
if (SystemBuffers.PwmCount > 700) //PWM高電平脈寬下界
SystemBuffers.PwmCount -= 10;//遞減未越界
else
SystemBuffers.PwmCount = 2300;//遞減越界翻到上界
}
/*------------------------------------
定時器T1中斷服務(wù)程序
------------------------------------*/
void t1proc() interrupt TF1_VECTOR using 2
{
/*--------------------------------------------
在此加入用戶代碼(與串口復(fù)用T1)
----------------------------------------------*/
}
/*------------------------------------
串口SIO中斷服務(wù)程序
------------------------------------*/
void sioproc() interrupt SIO_VECTOR using 2
{
if (RI) {//接收中斷
RI = 0;
/*--------------------------------------------
在此加入用戶串口接收代碼
----------------------------------------------*/
}
if (TI) {//發(fā)送中斷
TI = 0;
/*--------------------------------------------
在此加入用戶串口發(fā)送代碼
----------------------------------------------*/
}
}
/*-----------------------------------------------------------------------------
定時器T2中斷服務(wù)程序(20mS)
零耗時低頻寬脈沖軟PWM信號控制演示程序
軟件工作環(huán)境及要求:
MCU主頻12MHz,軟PWM控制IO模擬。PWM脈寬調(diào)節(jié)10uS
PWM頻率20mS=50Hz, PWM高電平脈寬700uS~2300uS,PWM低電平脈寬19300uS~17700uS
"零耗時"并非不耗時。只是沒用軟件空等待等惱人的函數(shù)。
其主要原理是利用低頻寬脈沖軟PWM信號的“低速”而T2的16位定時器自動裝載功能。
T2在每個PWM周期內(nèi)中斷兩次。即PWM高電平和PWM低電平各中斷1次。
合理應(yīng)用RCAP2的預(yù)裝載功能并進(jìn)行簡單的減法運算而輕松完成任務(wù)的要求。
本演示程序只需經(jīng)過簡單的修改,即可實現(xiàn)變PWM頻率等功能。
為演示方便未用宏定義,否則會更通用。但必須在“低頻寬脈沖”的相對條件下。
本文純屬虛構(gòu),若有雷同請原諒!
------------------------------------------------------------------------------*/
void t2proc() interrupt TF2_VECTOR using 1
{
static unsigned int PwmCount = 700;//系統(tǒng)內(nèi)部PWM高電平PwmCount(用戶無法訪問)
/*-----------------------------------------------------------------------------
PWM軟件IO模擬,任務(wù)中未加關(guān)PWM控制,可以再加限定/PWM電平信號翻轉(zhuǎn)標(biāo)志。
即:SystemBuffers.PwmCount=0為關(guān)閉PWM電平信號輸出(PWM=0)
注意SystemBuffers.PwmCount不能過小.
本軟PWM控制模塊與Windows的原則相同
--不主張用戶直接開展PWM管腳,而是控制SystemBuffers.PwmCount變量。
例:
-------------------------------------------------------------------------------
if (SystemBuffers.PwmCount == 0) {//關(guān)斷PWM信號。(不主張用戶直接開展PWM管腳)
PWM = 0;//關(guān)閉PWM電平信號輸出,并強迫執(zhí)行RCAP2 = 0 - PwmCount;RCAP2=0(最寬)
PwmCount = 0;//PWM高電平脈寬為0,PWM低電平脈寬為T2的最大定時時間。
}
else
------------------------------------------------------------------------------*/
PWM = ~PWM;//PWM電平信號翻轉(zhuǎn)
TF2 = 0;//清除標(biāo)志
if (PWM) {//在PWM高電平時至少有700uS的預(yù)算時間
/*---------------------------------------------------------------------
用戶只能改寫全局變量SystemBuffers.PwmCount,不能改寫靜態(tài)變量PwmCount
----------------------------------------------------------------------*/
PwmCount = SystemBuffers.PwmCount;//應(yīng)該在PWM下降沿處取用戶PWM高電平PwmCount
/*------------------------------------------------------------------------------
此時RCAP2早已將PWM高電平PwmCount裝入到TIMEER2中
故此時應(yīng)該計算PWM低電平20mS-PwmCount到RCAP2中
------------------------------------------------------------------------------*/
// RCAP2 = 0 - (20000 - PwmCount);//注意定時器是+1器
RCAP2 = PwmCount - 20000;//(優(yōu)化計算)注意定時器是+1器(RCAP2首次為-19300)
}
else {//在PWM低電平時至少有17700uS的預(yù)算時間
/*------------------------------------------------------------------------------
此時RCAP2早已將PWM低電平20mS-PwmCount裝入到TIMEER2中
故此時應(yīng)該計算PWM高電平PwmCount到RCAP2中
-------------------------------------------------------------------------------
*/
RCAP2 = 0 - PwmCount;//注意定時器是+1器(RCAP2首次為-700)
}
/*------------------------------------------------------------------------------
PWM高電平RCAP2定時時間 + PWM低電平RCAP2定時時間 = PWM周期20mS
-------------------------------------------------------------------------------
*/
}
void ClrWdt(void)//喂狗
{
WDTRST = 0x1e;//89s52內(nèi)狗
WDTRST = 0xe1;//89s52內(nèi)狗
}
void main(void)
{
MainInit();//系統(tǒng)初始化
while (1) {//主循環(huán)
IE |= 0xbf;//保證全部中斷可靠
TCON |= 0x55;//保證定時器打開,外部中斷為邊沿觸發(fā).
PCON |= GF0_ | IDL_;//喂瘋狗(GF0_=1)并進(jìn)入空閑狀態(tài)(IDL_=1)
_nop_();
_nop_();
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -