找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 19664|回复: 18
打印 上一主题 下一主题
收起左侧

关于51单片机输出频率和占空比可调的PWM波程序问题

  [复制链接]
楼主
ID:300215 发表于 2018-4-14 21:23 | 显示全部楼层
//------------------------------------------------------------------------------------ //程序功能简介:本程序产生15HZ~~~50KHZ的方波,并且实现频率和脉宽的独立调制,即可 //在改变频率的同时不改变脉宽,再改变脉宽的同时不改变频率;同时设置 //两个调节步长------在KEY键按下时,粗调,没有按下时,细调; //程序思路: 本程序用到两个定时器------定时器0和定时器1,其中定时器0工作在定时方式下, //决定方波的频率;定时器1,同样工作在定时方式下,用于设定脉宽; //------------------------------------------------------------------------------------    #include <reg52.h> #include <math.h> #define  uchar unsigned char #define  uint unsigned int #define  ALL  65536             //定时器工作方式1时,最大基数长度 65536; #define  F_osc 12000000         //晶振频率12M;  sbit KEY_F_UP=P0^2;             //频率上调按钮; sbit KEY_F_DOWN=P0^3;           //频率下调按钮; sbit KEY_W_UP=P0^4;             //脉宽上调按钮; sbit KEY_W_DOWN=P0^5;           //脉宽下调按钮; sbit KEY=P0^6;                  //粗细调节按钮-----按下为粗调,否则为细调; sbit OUTPUT=P1^0;               //波形输出;  uchar TIMER0_H,TIMER0_L,TIMER1_H,TIMER1_L;//定时器0和定时器1的初值设置; uchar PERCENT=50;               //初始占空比; uchar FLAG_F=0,FLAG_W=0;//频率调节标志和脉宽调制标志; uint  FREQ=50000;               //初始频率; float temp;                     //临时全局变量,用于数据传递; void delay(uchar t);           //延时函数,用于按键去抖; void init();                      //初始化函数,用于定时器的初始化; void calculate_F();      //频率计算函数,当频率变化,计算出定时器0初值; void calculate_W();      //脉宽计算函数,脉宽变化时,计算出定时器1初值; void key_scan();             //按键扫描函数; void timer0();                //定时器0中断函数; void timer1();                //定时器1中断函数; void delay(uchar t) {     uchar i,j;     while(t--)             //每个脉冲为1us      {       for(i=0;i<100;i++)        for(j=0;j<100;j++);      }   } void calculate_F() {     TIMER0_H = (uint)temp/256;     TIMER0_L = (uint)temp%256; } void calculate_W() {     float TEMP;     TEMP = (1 - PERCENT/100.0)*ALL + temp*PERCENT/100.0;     TIMER1_H = (uint)TEMP/256;     TIMER1_L = (uint)TEMP%256;   }   void key_scan()   {     delay(4);     if(!KEY_F_UP)     //频率上调键按下;     {       FLAG_F=1;    //置标志位;       if(!KEY)         FREQ+=10;       else         FREQ++;       if(FREQ>50000)         FREQ=1;     }     else if(!KEY_F_DOWN)   //频率下调键按下;     {       FLAG_F=1;    //置标志位;       if(!KEY)         FREQ-=10;       else         FREQ--;       if(FREQ<1)         FREQ=50000;      }      else if(!KEY_W_UP)    //脉宽上调键按下;      {        FLAG_W=1;    //置标志位;        if(!KEY)          PERCENT+=5;        else          PERCENT++;        if(PERCENT>49)          PERCENT=1;       }      else if(!KEY_W_DOWN)   //脉宽下调键按下;      {        FLAG_W=1;    //置标志位;        if(!KEY)          PERCENT-=5;        else          PERCENT--;        if(PERCENT<1)          PERCENT=49;       }        else ;       }   void timer0() interrupt 1      //决定频率    {      TH0=TIMER0_H;      TL0=TIMER0_L;      TR1=1;           //开定时器1;      OUTPUT=1;    }    void timer1() interrupt 3     //决定脉宽    {      TH1=TIMER1_H;      TL1=TIMER1_L;      TR1=0; //关定时器1,一定要这一步,因为定时器1的定时短于定时器0;      OUTPUT=0;    }    void init()    {      TMOD=0x11;      //定时器0和定时器1都工作在方式1,16位计数器;      calculate_F();  //初始为1KHZ,占空比为50%;      calculate_W();      TH0=TIMER0_H;      TL0=TIMER0_L;      TH1=TIMER1_H;      TL1=TIMER1_L;      ET0=1;      ET1=1;      EA=1;      TR0=1;      TR1=1;          } main() {     init();     while(1)     {        key_scan();        if(FLAG_F)     //改变频率时要注意要进行脉宽的重新设置;        {          calculate_F();          calculate_W();          FLAG_F=0;        }        if(FLAG_W)     // 脉宽改变,频率不改变;        {          calculate_W();          FLAG_W=0;        }      } }
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表