打印
[PIC®/AVR®/dsPIC®产品]

PIC单片机输出频率可变的PWM波形,出现了问题,请教各位

[复制链接]
2650|29
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 DonaldH 于 2020-4-21 09:28 编辑

使用的是PIC16F677这款单片机 求助大家 拜托了
我采用了TMR2定时器的PWM输出,功能要求就是正占空比是100uS,然后频率可调节,从1k到3k的频率调节,然后我采用的是通过定时器1进行10ms的定时,在中断服务函数中进行处理,直接将PR2的值进行改变来实现频率的调节,在主函数中 通过操作 PSTRCONbits.STRB = 1;  T2CONbits.TMR2ON = 1; 来开启PWM输出 ,通过 PSTRCONbits.STRB = 0;  T2CONbits.TMR2ON = 0;来关闭PWM输出。
出现了两个比较麻烦的问题,
1就是在输出PWM波形的时候会出现有1.3ms的持续低电平没有输出,如示波器图片所示。
2就是 我在主函数中进行开启和关闭PWM输出,当关闭PWM输出时,我又将PR2赋值为初值,可是再次开启PWM的时候却是在刚才关闭时的频率的那个值继续处理,而不是从初值那个时候产生其PWM。
这两个问题比较困扰 ,我把源码贴出来,大家帮忙看看是哪里问题。
////////////////////////////////////////////////////////////////////////
void TMR2_Initialize(void)///这是TMR2的初始化函数, 主频为1M
{
    T2CON = 0x00;
   
    TMR2 = 0x00;
//    PR2  = 0x00;

    INTCONbits.PEIE = 1;
    PIE1bits.TMR2IE = 0;
    PIR1bits.TMR2IF = 0;
   
    PSTRCON = 0x00;
    CCP1CON = 0x0c;
    CCPR1L =0x19;
   
}
////////////////////////////////////以下是对PR2 的操作    在定时器1 操作  10ms进一次中断服务函数
unsigned char     pr2num;
unsigned char     setp_num = 1;
unsigned char     PWM_FREQL = 249;    //1Khz  低频率的赋值
unsigned char     PWM_FREQH = 60;     //3.5kHZ  3521hz  高频率的赋值

void TMR1_Initialize(void)
{
    T1CON = 0x00;//T1时钟不分频 fosc/4   公式 65536-(X/4)
    TMR1H = 0x00; //1S定时初值0
    TMR1L = 0x00;
   
    PIE1bits.TMR1IE = 1;
    PIR1bits.TMR1IF = 0;
    INTCONbits.PEIE = 0; //外设中断关闭
}
void TMR1_ISR (void) //未使用
{
    TMR1H = 0xF6;//10ms
    TMR1L = 0x3C;
    flag_tick_count++;
   
    if(PWMOUT_on  == 1) //如果主函数中的PWMOUT_on =1 即开启PWM输出从1k-3.3k 变化即PR2-减后+
     {
              if(PWMOUT_up_dowm == 0)  
             {
                pr2num -= setp_num;
                if(pr2num <= PWM_FREQH)
                {
                 PWMOUT_up_dowm = 1;
                }
             }
             else
             {
                pr2num += setp_num;
                if(pr2num >= PWM_FREQL)
                {
                 PWMOUT_up_dowm  = 0;
                }
             }
              PR2 = pr2num;
        }
}

////////////////////////////////////////////以下是主函数中刚才所说的PWM开启和关闭 的操作

      if(pwm_start == 1)//  PWM开启时  pwm_start =1 关闭时=0
        {
          if(PWMOUT_on  == 0)
          {   
             PWMOUT_on   = 1;
             TMR2 = 0;
             PR2 = PWM_FREQL;
             PSTRCONbits.STRB = 1;
             T2CONbits.TMR2ON = 1;
          }
        }
        else
        {
          if(PWMOUT_on   == 1)
          {   
            PWMOUT_on  = 0;
            TMR2 = 0;
            PR2 = PWM_FREQL;       这里是将PR2赋初值 停止输出就会赋
            PSTRCONbits.STRB = 0;
            T2CONbits.TMR2ON = 0;
          }
        }

以下是示波器图片 即问题1 照片

数据手册内容如下

862085e84067285c61.png (153.85 KB )

862085e84067285c61.png

897975e8406832de07.png (102.44 KB )

897975e8406832de07.png

使用特权

评论回复
沙发
DonaldH|  楼主 | 2020-4-1 14:00 | 只看该作者
第二个问题是我自己挖的坑  其实在主函数里面赋初值不应该是直接赋给PR2  而是应该赋给 pr2num  因为一直没有改过pr2m 所以 就只是 操作了一次PR2  

使用特权

评论回复
板凳
ynwa| | 2020-4-1 14:24 | 只看该作者
1,你在主程序里有禁止/使能PWM输出的操作,那么在禁止PWM输出期间没有PWM输出不是很正常吗?(另,修改PR2寄存器,无需关闭PWM或禁止PWM输出)
2,只要PR2值变了,周期肯定会变。你可以改的变化幅度大一点,看你的TMR1中断里都是以1为步长在修改PR2

使用特权

评论回复
地板
DonaldH|  楼主 | 2020-4-1 16:50 | 只看该作者
本帖最后由 DonaldH 于 2020-4-1 16:52 编辑
ynwa 发表于 2020-4-1 14:24
1,你在主程序里有禁止/使能PWM输出的操作,那么在禁止PWM输出期间没有PWM输出不是很正常吗?(另,修改PR2 ...

1.我在主函数禁止/使能PWM输出的操作是需要操作外围电路才会让其输出或者不输出 ,这个断续的现象是出现在一直使能输出的时候   修改PR2是我使能输出了 ,然后定时器10MS进一次 修改PR2的值 然后在输出这个PWM时偶尔会出现的这个断续 1.3ms左右

使用特权

评论回复
5
21ic小喇叭| | 2020-4-2 09:59 | 只看该作者
您的问题得到大家积极讨论,奖励您100家园币,家园币可以兑换礼品或抽奖,欢迎体验~

使用特权

评论回复
6
ynwa| | 2020-4-2 15:26 | 只看该作者
DonaldH 发表于 2020-4-1 16:50
1.我在主函数禁止/使能PWM输出的操作是需要操作外围电路才会让其输出或者不输出 ,这个断续的现象是出现在 ...

建议你可以先把程序中的判断控制部分去掉,看看PWM输出还有没有这种断续。

使用特权

评论回复
7
lcczg| | 2020-4-2 15:45 | 只看该作者
把关TMR2的代码都先屏蔽掉看看

使用特权

评论回复
8
DonaldH|  楼主 | 2020-4-2 16:52 | 只看该作者
lcczg 发表于 2020-4-2 15:45
把关TMR2的代码都先屏蔽掉看看

我现在主程序一直输出PWM 还是会出现这个问题

使用特权

评论回复
9
DonaldH|  楼主 | 2020-4-2 16:53 | 只看该作者
lcczg 发表于 2020-4-2 15:45
把关TMR2的代码都先屏蔽掉看看

嗯  主程序就光使能PWM输出,但是依旧有相关问题

使用特权

评论回复
10
elife| | 2020-4-3 23:23 | 只看该作者
好像与影子寄存器有关,PR2没有影子寄存器,如果更改PR2,最好是在TIM2周期复位中断中更改,相当于只影响这一次比较周期。如果在一个长周期的低电平时,更新了一个短的周期PR2,比较器会不会错过了匹配,等到整个TM2溢出后,才重新PWM周期呢。

使用特权

评论回复
11
elife| | 2020-4-3 23:23 | 只看该作者
好像与影子寄存器有关,PR2没有影子寄存器,如果更改PR2,最好是在TIM2周期复位中断中更改,相当于只影响这一次比较周期。如果在一个长周期的低电平时,更新了一个短的周期PR2,比较器会不会错过了匹配,等到整个TM2溢出后,才重新PWM周期呢。

使用特权

评论回复
12
DonaldH|  楼主 | 2020-4-7 13:58 | 只看该作者
elife 发表于 2020-4-3 23:23
好像与影子寄存器有关,PR2没有影子寄存器,如果更改PR2,最好是在TIM2周期复位中断中更改,相当于只影响这 ...

但是这个现象很随机  没有规律可循,具体是为什么会这样的,我平常是禁用PWM输出的 只有启动了才会PWM输出,然后10ms、改变一次

使用特权

评论回复
13
lcczg| | 2020-4-8 11:03 | 只看该作者
有可能逻辑有问题,建议把主函数的那些控制逻辑屏蔽掉再调试看看。中断里是调频的,看起来没问题。可能主函数的问题。

使用特权

评论回复
14
elife| | 2020-4-8 13:00 | 只看该作者
楼主在大循环中停止PWM,下次循环再开启,PWM的停止时间就和大循环的时间有关了。最好的应用,是周期匹配寄存器也有缓存寄存器,只有在周期复位的时刻才更新周期寄存器。 如果没有缓存寄存器,最好在周期复位中断中更改,这不能保证周期很小的时候也没有问题。最好的是硬件上有这些缓存器。

使用特权

评论回复
15
DonaldH|  楼主 | 2020-4-16 09:29 | 只看该作者
lcczg 发表于 2020-4-8 11:03
有可能逻辑有问题,建议把主函数的那些控制逻辑屏蔽掉再调试看看。中断里是调频的,看起来没问题。可能主函 ...

我尝试过让主函数只使能PWM输出没有进行控制pwm的停止,一上电就输出PWM,但是也会出现个问题。

使用特权

评论回复
16
DonaldH|  楼主 | 2020-4-16 09:32 | 只看该作者
elife 发表于 2020-4-8 13:00
楼主在大循环中停止PWM,下次循环再开启,PWM的停止时间就和大循环的时间有关了。最好的应用,是周期匹配寄 ...

大循环中并没有频繁的控制使能, 都是只控制一次输出,或者关闭,并不是进行每次进去在从新开  ,我发现可能就是没有缓存寄存器,

使用特权

评论回复
17
触觉的爱| | 2020-4-17 15:12 | 只看该作者
各系列应该有针对性的模块文档吧,比如关于PWM的。 通常还有例程参考

使用特权

评论回复
18
wooda| | 2020-4-18 22:26 | 只看该作者
所有的中断都在这里了么,我怎么感觉是其他中断跳了一下把这里的事情耽误了

使用特权

评论回复
19
DonaldH|  楼主 | 2020-4-21 09:26 | 只看该作者
触觉的爱 发表于 2020-4-17 15:12
各系列应该有针对性的模块文档吧,比如关于PWM的。 通常还有例程参考

额 历程都是调占空比啊

使用特权

评论回复
20
DonaldH|  楼主 | 2020-4-21 09:26 | 只看该作者
wooda 发表于 2020-4-18 22:26
所有的中断都在这里了么,我怎么感觉是其他中断跳了一下把这里的事情耽误了 ...

可能是因为没有影子寄存器

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

19

帖子

0

粉丝