关于用51单片机产生pwm

能不能只是使用单片机来产生pwm?即是只是控制某端口输出5v的时间与间隔,能否产生1000hz的方波?

  #include<reg52.h>
  sfr CCON = 0xD8;
  sfr CMOD = 0xD9;
  sfr CL = 0xE9;
  sfr CH = 0xF9;
  sfr CCAP0L = 0xEA;
  sfr CCAP0H = 0xFA;
  sfr CCAPM0 = 0xDA;
  sfr CCAPM1 = 0xDB;
  #define uint unsigned int
  #define uchar unsigned char
  uchar whith_p=50;
  uchar max_p=255;
  uchar min_p=1;
  uint fre = 0xffff;
  sbit CR = 0xDE;
  sbit led = P2^0;
  void timer0_int (void) interrupt 1 using 1
  {
  TH0 = fre >> 8;
  TL0 = fre & 0xff;
  led = ~led;
  }
  void timer0_init(void)
  {
  TMOD &= 0xf0;
  TMOD |= 0x1;
  TH0 = 0xff;
  TL0 = 0xff;
  TR0 = 1;
  ET0 = 1;
  }

  void pwm_init(void)
  {
  CMOD = 0x4;
  CL = 0x0;
  CH = 0x0;
  CCAP0H = whith_p;
  CCAPM0 = 0x42;
  CR = 1;
  }

  void soft_delay(uint _1ms)
  {
  unsigned int tmp;
  while(_1ms--!=0) {
  for(tmp=0;tmp<144;tmp++);
  }
  }
  void pwm_out(void)
  {
  whith_p=50;
  while(whith_p<max_p)
  { CCAP0H =whith_p;
  soft_delay(10);
  whith_p=whith_p+5;
  CCAP0H = whith_p;
  soft_delay(10);
  }

  whith_p=max_p;
  while(min_p<whith_p)
  { CCAP0H = whith_p;
  soft_delay(10);
  whith_p=whith_p-5;
  CCAP0H = whith_p;
  soft_delay(10);
  }

  }

  void main (void)
  {
  pwm_init();
  timer0_init();
  EA = 1;
  while(1){
  pwm_out();
  }
  }

  STC单片机具有PWM输出功能,最近玩12864LCD万年历时,用的是杜洋的FT4时钟电路,用他提供的H文件控制时,具有调光功能,由于只是玩一玩,没有购买源码,而网上流行的程序都没有此功能,无奈,只能自己弄,好在杜老师及人所及早在网站中备下了资料,简单攒一下,居然成功了,并成功的汇入了万年历的程序中,现在将其改成完整的控制程序公开于此供参考。

  /*************************************************
  STC单片机单/双键控制LED亮度PWM调光程序 原创WanNengGong 2010/09/20
  参考程序: 杜洋工作室PWM功能程序模块
  *************************************************/
  #include<STC12C5A60S2.H> //头文件
  #define uchar unsigned char
  #define uint unsigned int
  uchar vx=5;
  //vx=5在用于12864LCD的LED背光调整时上电为半亮度状态,可根据自己的用途及要求任意设定
  sbit KEY_H=P2^4;
  sbit KEY_L=P2^5;
  /*******************************************************************************/
  void PWM_init (void){//PWM初始化函数
  CMOD=0x02; //设置PCA定时器
  CL=0x00;
  CH=0x00;
  CCAPM1=0x42; //PWM0设置PCA工作方式为PWM方式(0100 0010)
  CCAP1L=0x00; //设置PWM0初始值与CCAP0H相同
  CCAP1H=0x00; // PWM0初始时为0
  CR=1; //启动PCA定时器
  }
  /******************************************************************************/
  void PWM0_set (uchar a){//PWM0占空比设置函数
  CCAP1L=a; //设置值直接写入CCAP1L
  CCAP1H=a; //设置值直接写入CCAP1H
  }
  /*****************************************************************************/
  void DelayM(unsigned int a){//延时函数 1mS/次(用于1T单片机)
  unsigned char n,i,j;
  while(--a!=0){
  for(n=1;n>0;n--)
  for(j=222;j>0;j--)
  for(i=12;i>0;i--);
  } }
  /****************************************************************************/
  void main(void)
  {
  KEY_H = 1;KEY_L = 1;
  PWM_init ();
  while(1)
  {
  PWM0_set(vx*24);
  //数字24是配合vx调试取得的,此时vx的赋值范围约为1-10对应最暗-最亮

  //--------减调整---------//
  if (KEY_L == 0 ){
  DelayM(20); //延时20毫秒消抖动
  if(KEY_L == 0){ //如果20SM后KEY_L还是0状态则确认下调键是按下的
  vx--;
  if(vx<1){vx=5;}
  //如果设定vx=10,将语句改为if(vx<1){vx=10;}则为单按键循环控制,则可去除加调整控制部分
  }
  while(KEY_L == 0);//等待键松开
  }
  //--------加调整---------//
  if (KEY_H == 0 ){
  DelayM(20);
  if(KEY_H == 0){
  vx++;
  if(vx>10){vx=5;}
  }
  while(KEY_H == 0);
  }
  }
  }

  程序自己理解消化了,就可以编出你自己的程序了,你说的,完全可以实现,而且比这俩个例子简单N多。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-11-16
带PWM的单片机最容易实现,STC 12C系列,AVR,一些Atmel另外设计的51比较难找到~

控制时间和间隔可以产生,用定时器产生过1000左右的占空比50%的方波……本回答被网友采纳