找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机的方波的输出频率和占空比

[复制链接]
跳转到指定楼层
楼主
ID:65022 发表于 2014-8-13 12:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如何改变51单片机输出方波的频率和占空比
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2014-8-13 13:57 来自手机 | 只看该作者
昨天在24小时必答区还讨论了这个问题,楼主你进这个去看一下
回复

使用道具 举报

板凳
ID:63752 发表于 2014-8-13 22:40 来自手机 | 只看该作者
一起研究吧!我也要这信息!
回复

使用道具 举报

地板
ID:65549 发表于 2014-8-28 16:35 | 只看该作者
我在网上找到得找个,试试还可以,刚刚学,还有好多地方不懂。
  //程序功能简介:本程序产生15HZ~~~50KHZ的方波,并且实现频率和脉宽的独立调制,即可
//    在改变频率的同时不改变脉宽,再改变脉宽的同时不改变频率;同时设置
//    两个调节步长------在KEY键按下时,粗调,没有按下时,细调;
//程序思路: 本程序用到两个定时器------定时器0和定时器1,其中定时器0工作在定时方式下,
//    决定方波的频率;定时器1,同样工作在定时方式下,用于设定脉宽;
//制作人:  陈卓;
//制作人单位: 武汉理工大学 信息工程学院 电信0504班;
//制作时间: 2007年12月26日;
//------------------------------------------------------------------------------------
#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中断函数;

//-----------------------------------------------------------------------------------
//函数名称:delay();
//入口参数:uchar t;
//出口参数:无;
//函数功能:延时;
//------------------------------------------------------------------------------------
void delay(uchar t)
  {
   uchar i,j;
   while(t--)
    {
     for(i=0;i<100;i++)
     for(j=0;j<100;j++)
     ;
     }
    }
//-----------------------------------------------------------------------------------
//函数名称:calculate_F();
//入口参数:无;
//出口参数:无;
//函数功能:频率计算函数,当频率变化,计算出定时器0初值;
//------------------------------------------------------------------------------------
void calculate_F()
  {
   
   temp=ALL-F_osc/12.0/FREQ;
   TIMER0_H=(uint)temp/256;
   TIMER0_L=(uint)temp%256;
   }

//-----------------------------------------------------------------------------------
//函数名称:calculate_W();
//入口参数:无;
//出口参数:无;
//函数功能:脉宽计算函数,脉宽变化时,计算出定时器1初值;
//------------------------------------------------------------------------------------  
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;
  }
//-----------------------------------------------------------------------------------
//函数名称:key_scan();
//入口参数:无;
//出口参数:无;
//函数功能:按键扫描函数;
//------------------------------------------------------------------------------------
    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 ;
     }

//-----------------------------------------------------------------------------------
//函数名称timer0();
//入口参数:无;
//出口参数:无;
//函数功能:定时器0中断函数;
//------------------------------------------------------------------------------------
  void timer0() interrupt 1
    {
    TH0=TIMER0_H;
    TL0=TIMER0_L;
    TR1=1;      //开定时器1;
    OUTPUT=1;
    }
//-----------------------------------------------------------------------------------
//函数名称timer1();
//入口参数:无;
//出口参数:无;
//函数功能:定时器1中断函数;
//制作人: 陈卓;
//制作人单位:武汉理工大学 信息工程学院 电信0504班;
//制作时间:2007年12月26日;
//------------------------------------------------------------------------------------
  void timer1() interrupt 3
    {
    TH1=TIMER1_H;
    TL1=TIMER1_L;
    TR1=0;      //关定时器1,一定要这一步,因为定时器1的定时短于定时器0;
    OUTPUT=0;
    }
//-----------------------------------------------------------------------------------
//函数名称init();
//入口参数:无;
//出口参数:无;
//函数功能:定时器初始化函数;
//------------------------------------------------------------------------------------
   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();
//入口参数:无;
//出口参数:无;
//函数功能:主函数入口;
//------------------------------------------------------------------------------------
main()
      {
    init();
    while(1)
     {
      key_scan();
      if(FLAG_F)     //改变频率时要注意要进行脉宽的重新设置;
       {
        calculate_F();
        calculate_W();
        FLAG_F=0;
        }
       if(FLAG_W)     // 脉宽改变,频率不改变;
       {
        calculate_W();
        FLAG_W=0;
        }
        }
}

评分

参与人数 1威望 +25 黑币 +30 收起 理由
admin + 25 + 30 帮助他人解决问题的 积分奖励!!!

查看全部评分

回复

使用道具 举报

5#
ID:63752 发表于 2014-8-29 12:57 | 只看该作者
很好呢,学习学习了。有没有PCA模块来改变占空比的例子啊?这个是用定时器中断。只是能单一输出PWM。如果我要输出三路呢,觉得就很麻烦了。最好有PCA模块的那程序,学习学习~~~
回复

使用道具 举报

6#
ID:26218 发表于 2014-9-3 22:02 | 只看该作者
建议你看看LED调光(PWM)的程序,细细钻研会有帮助
回复

使用道具 举报

7#
ID:308632 发表于 2018-4-23 21:18 | 只看该作者
可以用AD
回复

使用道具 举报

8#
ID:372402 发表于 2018-8-31 11:34 | 只看该作者
台老怪 发表于 2014-8-28 16:35
**** 作者被禁止或删除 内容自动屏蔽 ****

很好的东西,电路图有吗老铁?可否发一下?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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