⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pwm_oem.c

📁 MCU主频12MHz
💻 C
字号:
/*----------------------------------------------------------------
       零耗时低频宽脉冲软PWM信号控制Keil C51演示程序
C51文件PwmDemo.c 
HotPower@126.com    作于2004.11.17与大雁塔村队部
在uV3中对PWM信号进行"实时仿真"效果逼真。
-----------------------------------------------------------------*/
#include 
//#include 
#include 
sfr   AUXR    = 0x8e;
sfr   WDTRST  = 0xa6;
sfr16 TIMEER2 = 0xcc;
sfr16 RCAP2   = 0xca;

sbit  PWM     = P1^0;//可以为任意IO管脚

typedef struct Systemstruct{//系统数据结构
  unsigned int PwmCount;//700~2300uS
  unsigned int RamTest;//内部ram自检变量

}SystemData;//系统数据结构(此时只是定义了一个新的数据类型SystemData)

//全局变量定义(全局结构)
SystemData SystemBuffers;//申请系统数据结构缓冲区

#define T2_20mS -20000 //MCU主频12MHz,12分频,T2_20mS=20MS

void MainInit(void);//系统初始化
void ClrWdt(void);//喂狗
void SystemInit(void);//系统初始化
void SystemSetup(void);//系统设置
void SystemIoInit(void);//系统接口初始化
void UserSetup(void);//用户运行环境设置
void TimeInit(void);//定时器定时参数初始化

void MainInit(void)//系统初始化
{
  SystemIoInit();//系统接口初始化
  ClrWdt();//清除看门狗计数器
  if (SystemBuffers.RamTest != 0x55aa) {//内存测试
    SystemInit();//系统上电初始化
  }
  SystemSetup();//系统运行环境设置
  UserSetup();//用户运行环境设置
}

void SystemInit(void)//系统初始化
{
  SystemBuffers.RamTest = 0x55aa;//内存初始化
}

void SystemSetup(void)//系统设置
{
  AUXR = 0x01;//关闭EMI
  TimeInit();//定时器定时参数初始化
  IP = 0x20;//中断优先级ET2
}

void UserSetup(void)//用户运行环境设置
{

}

void SystemIoInit(void)
{
  IE = 0x00;//关闭中断
  P0 = 0xff;//P0口初始化
  P1 = 0xfe;//P1口初始化,PWM=0
  P2 = 0xff;//P2口初始化
  P3 = 0xff;//P3口初始化
}

void TimeInit()
{
/*----------------------------------
      定时器0定时参数设置
----------------------------------*/
  TL0 = 0;
  TH0 = 0;
//  TR0 = 1;//启动定时器0
/*----------------------------------
      定时器1定时参数设置
----------------------------------*/
  TL1 = 0xfd;
  TH1 = 0xfd;
  PCON = 0x00;//SMOD_=0,GF0_=0;//清除疯狗标志
//  TR1 = 1;//启动定时器1
/*----------------------------------
      定时器2定时参数设置
----------------------------------*/
  TIMEER2 = T2_20mS;//上电20mS后PWM开始工作
  PWM = 0;//上电后无PWM信号
  SystemBuffers.PwmCount = 700;//首次PWM脉宽为700uS
  RCAP2   = 0 - SystemBuffers.PwmCount;//首次PWM脉宽为700uS
  TR2     = 1;//启动定时器2(上电后20mS内PWM信号为低电平)
/*----------------------------------
      定时器参数设置
----------------------------------*/
  TMOD    = 0x22;//定时方式(8位自动装载)
}




/*---------------------------------------------------------------------
         外部INT0中断服务程序(PWM+10uS)
----------------------------------------------------------------------*/
void int0proc() interrupt IE0_VECTOR using 2
{
/*---------------------------------------------------------------------
  用户只能改写全局变量SystemBuffers.PwmCount,不能改写静态变量PwmCount
----------------------------------------------------------------------*/
  if (SystemBuffers.PwmCount <= 2290) //PWM高电平脉宽上界-10
    SystemBuffers.PwmCount += 10;//递增未越界
  else 
    SystemBuffers.PwmCount = 700;//递增越界翻到下界
}

/*---------------------------------------------------------------------
         定时器T0中断服务程序
----------------------------------------------------------------------*/
void t0proc() interrupt TF0_VECTOR using 2
{
  if (PCON & GF0_) {//中断是从主循环内跳入的才能喂狗
    ClrWdt();//清除看门狗计数器
    PCON &= ~GF0_;//清除疯狗标志 
  }
}

/*---------------------------------------------------------------------
         外部INT1中断服务程序(PWM-10uS)
----------------------------------------------------------------------*/
void int1proc() interrupt IE1_VECTOR using 2
{
/*---------------------------------------------------------------------
  用户只能改写全局变量SystemBuffers.PwmCount,不能改写静态变量PwmCount
----------------------------------------------------------------------*/
  if (SystemBuffers.PwmCount > 700) //PWM高电平脉宽下界
    SystemBuffers.PwmCount -= 10;//递减未越界
  else 
    SystemBuffers.PwmCount = 2300;//递减越界翻到上界
}


/*------------------------------------
         定时器T1中断服务程序
------------------------------------*/

void t1proc() interrupt TF1_VECTOR using 2
{
/*--------------------------------------------
  在此加入用户代码(与串口复用T1)
----------------------------------------------*/
}

/*------------------------------------
         串口SIO中断服务程序
------------------------------------*/

void sioproc() interrupt SIO_VECTOR using 2
{
  if (RI) {//接收中断
    RI = 0;
/*--------------------------------------------
  在此加入用户串口接收代码
----------------------------------------------*/
  }
  if (TI) {//发送中断
    TI = 0;
/*--------------------------------------------
  在此加入用户串口发送代码
----------------------------------------------*/
  }
}


void t2proc() interrupt TF2_VECTOR using 1
{
static unsigned int PwmCount = 700;//系统内部PWM高电平PwmCount(用户无法访问)

/*-----------------------------------------------------------------------------
  PWM软件IO模拟,任务中未加关PWM控制,可以再加限定/PWM电平信号翻转标志。
  即:SystemBuffers.PwmCount=0为关闭PWM电平信号输出(PWM=0)
  注意SystemBuffers.PwmCount不能过小.
  本软PWM控制模块与Windows的原则相同
  --不主张用户直接开展PWM管脚,而是控制SystemBuffers.PwmCount变量。
例:
-------------------------------------------------------------------------------
  if (SystemBuffers.PwmCount == 0) {//关断PWM信号。(不主张用户直接开展PWM管脚)
    PWM = 0;//关闭PWM电平信号输出,并强迫执行RCAP2 = 0 - PwmCount;RCAP2=0(最宽)
    PwmCount = 0;//PWM高电平脉宽为0,PWM低电平脉宽为T2的最大定时时间。
  }
  else
------------------------------------------------------------------------------*/
  PWM = ~PWM;//PWM电平信号翻转

  TF2 = 0;//清除标志
  if (PWM) {//在PWM高电平时至少有700uS的预算时间
/*---------------------------------------------------------------------
  用户只能改写全局变量SystemBuffers.PwmCount,不能改写静态变量PwmCount
----------------------------------------------------------------------*/
   PwmCount = SystemBuffers.PwmCount;//应该在PWM下降沿处取用户PWM高电平PwmCount 

/*------------------------------------------------------------------------------
   此时RCAP2早已将PWM高电平PwmCount装入到TIMEER2中
   故此时应该计算PWM低电平20mS-PwmCount到RCAP2中
------------------------------------------------------------------------------*/
//    RCAP2 = 0 - (20000 - PwmCount);//注意定时器是+1器
    RCAP2 = PwmCount - 20000;//(优化计算)注意定时器是+1器(RCAP2首次为-19300)
  }
  else {//在PWM低电平时至少有17700uS的预算时间
/*------------------------------------------------------------------------------
   此时RCAP2早已将PWM低电平20mS-PwmCount装入到TIMEER2中
   故此时应该计算PWM高电平PwmCount到RCAP2中
-------------------------------------------------------------------------------
*/
    RCAP2 = 0 - PwmCount;//注意定时器是+1器(RCAP2首次为-700)
  }
/*------------------------------------------------------------------------------
   PWM高电平RCAP2定时时间 + PWM低电平RCAP2定时时间 = PWM周期20mS
-------------------------------------------------------------------------------
*/
}


void ClrWdt(void)//喂狗
{
  WDTRST = 0x1e;//89s52内狗
  WDTRST = 0xe1;//89s52内狗
}


void main(void)
{
  MainInit();//系统初始化
  while (1) {//主循环
    IE   |= 0xbf;//保证全部中断可靠
    TCON |= 0x55;//保证定时器打开,外部中断为边沿触发.
    PCON |= GF0_ | IDL_;//喂疯狗(GF0_=1)并进入空闲状态(IDL_=1)
    _nop_();
    _nop_();
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -