m0_74919493 2023-06-10 20:51 采纳率: 0%
浏览 111
已结题

51单片机输出pwm时无法调节频率,如何解决?

通过以下代码用51单片机输出pwm时可以调节占空比 但无法设定频率 帮忙看下是代码的问题还是什么问题 用keil5 用普中烧录


#include<reg51.h>
 
#define uint unsigned int 
#define uchar unsigned char        
 
uchar time; 
double count=55; //定义占空比,并初始占空比为55%
sbit PWM=P2^0;      //P2^0口输出PWM 
sbit key_add=P3^1;   //电机加速的按键 的I/O口
sbit key_dec=P3^0;   //电机减速的按键 的I/O口
 
 
/************函数声明**************/
void delayxms(uint z); //延时
void Motor_add();   //电机加速,即增加占空比
void Motor_dec();    //电机减速,即减少占空比
void timer0_init();  //定时器0初始化
 
/*********主函数********************/
void main()
{  
 timer0_init();
 delayxms(5);
 while(1)
 {
  Motor_add();
  Motor_dec();
 }
}
 
/****************延时处理**********************/
void delayxms(uint z) //延时xms程序
{
    uint x,y;
 for(x=z;x>0;x--)
  for(y=110;y>0;y--);
}
 
 
void Motor_add()  //电机加速
{
  if(key_add==0)
  {
   delayxms(2); //此处时间不能太长,否者会的中断产生冲突
  if(key_add==0)
  {
   count+=0.5; //每按一次加速按键占空比加0.5
   if(count>=70)     //限定占空比上限
 {
  count=70;
 }
  }
 while(!key_add);
  }
}
 
void Motor_dec()//电机减速
{
 if(key_dec==0)
 {
  delayxms(2);//此处时间不能太长,否者会的中断产生冲突
  if(key_dec==0)
  {
   count-=0.5;   //每按一次减速按键占空比减0.5
   if(count<=30)    //限定占空比下限
   {
 count=30;
   }
  }
 while(!key_dec);
   }
}
 
/***********定时器0初始化***********/
void timer0_init()
{
  TMOD=0x01; //定时器0工作于方式1
  TH0=(65536-20)/256;
  TL0=(65536-20)%256;
  TR0=1;
  ET0=1;
  EA=1;
}
 
/**************定时0中断处理******************/
void timer0_int() interrupt 1 
{
 
  TR0=0;    //设置定时器初值期间,关闭定时器
  TH0=(65536-20)/256;
  TL0=(65536-20)%256;
  TR0=1;
  
  time++;
  if(time<count)   //count为占空比
  {
 PWM=1;    //输出高电平
  }
  else 
 PWM=0; 
  if(time>=100)
  {
 time=0;
  }
 }

  • 写回答

10条回答 默认 最新

  • Jackyin0720 2023-06-10 21:34
    关注
    获得1.00元问题酬金

    对比下这个实例代码:

    #include <reg52.h>  
      
    sbit PWM = P1^0; // 定义PWM输出引脚  
      
    void main() {  
        TMOD = 0x01; // 定时器0工作在模式116位计数器)  
        TH0 = 0xFF; // 定时器0的高8位初始值  
        TL0 = 0xFF; // 定时器0的低8位初始值  
        TR0 = 1; // 启动定时器0  
      
        while (1) {  
            // 输出PWM信号,调整占空比和频率  
            for (int i = 0; i < 255; i++) {  
                PWM = i; // 设置PWM占空比  
                _nop_(); // 延时一段时间,控制PWM频率  
            }  
            for (int i = 255; i >= 0; i--) {  
                PWM = i; // 设置PWM占空比  
                _nop_(); // 延时一段时间,控制PWM频率  
            }  
        }  
    }
    
    评论
  • CSDN-Ada助手 CSDN-AI 官方账号 2023-06-10 22:04
    关注
    获得2.00元问题酬金
    评论
  • qllaoda 2023-06-11 08:29
    关注
    获得1.00元问题酬金

    无法调节频率是因为你代码里写死了

    if(time>=100)
      {
     time=0;
      }
    
    

    这里限定了PWM的周期是100次定时器中断,让这个100成为可调节的变量,即可调节PWM的频率。
    但是从你代码里看,并没有看出调节频率的意图啊,只有调节占空比的,两个按钮就被用来调节速度了而已,如果你要调节频率,还要写两个类似的按键处理函数。我估计这个代码根本不是你自己写的吧?
    另外,不建议用浮点数来计算占空比,会降低效率的,我看你每次增减0.5,直接用整数好了,数值上乘以2即可。对51来说,浮点运算效率太低了

    评论 编辑记录
  • cyjbj 2023-06-11 11:13
    关注
    获得1.00元问题酬金

    看你的代码是通过T0的计数0到100来确定频率的,你只需要更改T0的初值就可以条件频率了,现在是 T0初始为(65536-20),20数字变大你的PWM频率就降低,减小你的频率就升高

    评论
  • yy64ll826 2023-06-13 16:28
    关注
    获得0.80元问题酬金

    可以看看

    void Timer0_Init(void)        //100微秒
    {
        TMOD &= 0xF0;        //设置定时器模式
        TMOD |= 0x01;        //设置定时器模式
    //    TMOD = 0X01;
        TL0 = 0x9C;        //设置定时初值
        TH0 = 0xFF;        //设置定时初值
        TF0 = 0;        //清除TF0标志
        TR0 = 1;    //定时器0开始计时
        EA = 1;
        ET0 = 1;
        PT0 = 0;
    }
     
    unsigned int counter = 0;
    void Timer0_Routine() interrupt 1
    {
        TL0 = 0x9C;        //设置定时初值
        TH0 = 0xFF;        //设置定时初值
        counter++;
        if(counter == 100)
        {
            counter = 0;
        }
        
    }
    
    
    评论
  • 技术宅program 2023-06-14 11:44
    关注
    获得0.60元问题酬金
    评论
  • 会跑的小鹿 2023-06-17 19:55
    关注
    获得0.60元问题酬金

    检查一下时钟源、分频系数、定时器模式、计数器值等设置是否正确合理,同时通过调整占空比来改变PWM输出的平均电平。

    评论
  • 皮尔菲特 2023-06-10 21:55
    关注

    根据您提供的代码,我看到您使用的是定时器0(Timer 0)来生成PWM信号。从代码中可以看出,您设置了一个定时器中断,在中断处理函数中控制PWM输出的高低电平来实现占空比的调节。

    然而,关于您提到无法设定频率的问题,我注意到在定时器0的初始化部分,您设置了定时器工作于方式1(Timer Mode 1),这意味着它将作为一个16位定时器进行计数。

    根据代码中的设定,您将TH0和TL0的初值设置为(65536-20),这将导致定时器0在每个溢出周期中计数20个机器周期。这将导致定时器中断的频率为时钟频率除以20。

    要调整定时器0的频率,您可以尝试以下操作:

    1. 根据所需的频率计算初值:计算公式为初值 = 65536 - (时钟频率 / (目标频率 * 12))。其中,时钟频率是MCU的时钟频率(单位:Hz),目标频率是您期望的PWM频率。
    2. 使用计算得到的初值来设置TH0和TL0。

    例如,如果您希望PWM的频率为100Hz,且MCU的时钟频率为12MHz(12,000,000Hz),您可以进行如下计算:
    初值 = 65536 - (12,000,000 / (100 * 12)) = 45536
    将初值设置为TH0和TL0,即 TH0 = 45536 / 256 = 177,TL0 = 45536 % 256 = 144。

    请注意,这是一个简化的示例,您可能需要根据您的具体要求和MCU的特性进行调整。

    通过调整定时器0的初值,您应该能够更好地控制PWM的频率。请尝试上述方法,并确保在计算初值时考虑到您使用的MCU的时钟频率和目标PWM频率。

    评论
  • Answer348 2023-06-10 23:12
    关注

    回答部分参考、引用ChatGpt以便为您提供更准确的答案:

    根据您提供的代码,您使用51单片机实现了通过PWM输出调节占空比的功能。然而,您遇到了无法设定频率的问题。以下是可能导致该问题的原因和解决方法:

    1. 定时器设置错误:根据您的代码,使用了定时器0来生成PWM输出。您需要正确设置定时器0的工作模式和初值,以达到您期望的频率。请检查您的定时器设置代码,确保工作模式和初值设置正确。
    2. 时钟源选择问题:51单片机的定时器通常依赖于时钟源来确定计时频率。请确保您选择了适当的时钟源,并将其配置为您期望的频率。具体的时钟源设置可能因您所使用的单片机型号而有所不同,请查阅相关的芯片手册以获取准确的配置方法。
    3. 中断处理函数问题:根据您的代码,定时器0的中断处理函数被定义为timer0_int(),但是在主函数中并没有将该函数与中断向量关联起来。请确保在主函数中正确设置中断向量,使得定时器0的中断能够被正确处理。
    4. 晶振频率问题:如果您的单片机使用外部晶振作为时钟源,那么晶振的频率也会影响定时器的计时频率。请确保您的晶振频率与代码中的定时器设置相匹配。

    综上所述,您需要检查定时器的设置、时钟源选择、中断处理函数和晶振频率等方面,以解决无法设定频率的问题。根据您使用的开发环境和单片机型号的不同,具体的解决方法可能会有所差异。建议您仔细查阅相关的单片机手册、开发工具文档或在线资源,以获取准确的设置步骤和示例代码。

    评论

报告相同问题?

问题事件

  • 系统已结题 6月18日
  • 创建了问题 6月10日

悬赏问题

  • ¥15 win11系统打开软件很慢
  • ¥30 XIAO esp32c3 读取FDC2214的数据
  • ¥20 我用malloc申请了一块空间 判空显示指针不为null 但是在输出data指针所指的地址是缺全是0 空指针不能输入值进去数组为什么呀
  • ¥15 在工控机(Ubuntu系统)上外接USB蓝牙硬件进行蓝牙通信
  • ¥15 关于PROCEDURE和FUNCTION的问题
  • ¥100 webapi的部署(标签-服务器)
  • ¥20 怎么加快手机软件内部计时的时间(关键词-日期时间)
  • ¥15 C语言除0问题的检测方法
  • ¥15 为什么四分管的内径有的是16mm有的15mm,四分不应该是12.7mm吗
  • ¥15 macos13下 ios交叉编译的问题