单片机
返回首页

单片机pwm频率和周期可调

2020-02-20 来源:51hei

//------------------------------------------------------------------------------------

//程序功能简介:本程序产生15HZ~~~50KHZ的方波,并且实现频率和脉宽的独立调制,即可

//在改变频率的同时不改变脉宽,再改变脉宽的同时不改变频率;同时设置

//两个调节步长------在KEY键按下时,粗调,没有按下时,细调;

//程序思路: 本程序用到两个定时器------定时器0和定时器1,其中定时器0工作在定时方式下,

//决定方波的频率;定时器1,同样工作在定时方式下,用于设定脉宽;

//------------------------------------------------------------------------------------ 

  #include

#include

#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;

       }

     }

}


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • 用数字电路CD4069制作的万能遥控轻触开关

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 开关电源的基本组成及工作原理

  • 用NE555制作定时器

  • 带有短路保护系统的5V直流稳压电源电路图

    相关电子头条文章