12444|14

6

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

PIC单片机产生PWM波波形出问题了 [复制链接]

 
本帖最后由 Sevenfee 于 2018-11-6 20:32 编辑

用PIC16F887单片机产生方波,当我把方波频率设为4KHz时波形是正常的,当我改变TIMER2的分频值,从4改为16 ,此时频率应该变为1KHz,此时频率是对了,可是波形却变得很奇怪。  求有经验的大神指导下!

这是产生的4KHZ正常波形,占空比为50%




这是1KHZ有问题的波形,占空比为60%。  这个高电平会突然下降到一个比较低的电平再上升。



1KHz占空比80%就正常了

此帖出自单片机论坛

最新回复

使用的是PIC16F677这款单片机  我采用了TMR2定时器的PWM输出,功能要求就是正占空比是100uS,然后频率可调节,从1k到3k的频率调节,然后我采用的是通过定时器1进行10ms的定时,在中断服务函数中进行处理,直接将PR2的值进行改变来实现频率的调节,在主函数中 通过操作 PSTRCONbits.STRB = 1;  T2CONbits.TMR2ON = 1; 来开启PWM输出 ,通过 PSTRCONbits.STRB = 0;  T2CONbits.TMR2ON = 0;来关闭PWM输出。 然后出现就是在输出PWM波形的时候会出现有1.3ms的持续低电平没有输出,如示波器图片所示。 //////////////////////////////////////////////////////////////////////// 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;              pr2num= PWM_FREQL;              PSTRCONbits.STRB = 1;              T2CONbits.TMR2ON = 1;            }         }         else         {           if(PWMOUT_on   == 1)           {                 PWMOUT_on  = 0;             TMR2 = 0;             pr2num= PWM_FREQL;       这里是将PR2赋初值 停止输出就会赋              PSTRCONbits.STRB = 0;             T2CONbits.TMR2ON = 0;           }         }   详情 回复 发表于 2020-4-2 16:51
点赞 关注(1)
 

回复
举报

6

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
主要的程序我也贴上来各位看一下

/********端口初始化函数********/
void init()
{
        ANSELH=0x00;                     //设置B口为数字I/O口
        OPTION_REG=0x00;
        WPUB=0xFF;         //设置B口弱上拉
        INTCON=0x00;       //关总中断
        PIE1=0;            //PIE1的中断禁止
        PIE2=0;            //PIE2的中断禁止
        TRISB0=1;
        TRISB1=1;          //将RB1设置为输入口,按按键
        TRISB2=1;          //将RB2设置为输入口,按按键
        TRISB3=1;
        TRISB4=1;
        RC1=0;
        TRISC1=0;          //脉宽调制输出引脚,设置为输出
}
/********PWM初始化函数********/
void PWM_Init()
{
        PR2=249;           //脉宽调制波形的周期为1000us        
        CCP2CON=0x0C;      //CCP2模块工作在PWM模式,占空因数的低两位为00
        T2CON=0x02;        //禁止TMR2,且前后分频值为16,同时开始输出PWM
        CCPR2L=0xB8;       //脉宽调制波形的占空比初始值
}
/********键盘扫描函数*******    */
void keyscan()
{
        if(RB1==0)                  //如果是RB1键按下
        {
                delay_ms(5);              //延时去抖
                if(RB1==0)              //确认是否有键按下
                {
                        while(!RB1);        //等待按键释放
                        CCP2CON=0x0C;
                        CCPR2L=0xB8;                   //80%占空比
                        TMR2ON=1;
                }
        }
        if(RB2==0)                  //如果是RB2键按下
        {
                delay_ms(5);              //延时去抖
                if(RB2==0)              //确认是否有键按下
                {
                        while(!RB2);        //等待按键释放
                        CCP2CON=0x0C;
                        CCPR2L=0x96;                   //60%占空比
                        TMR2ON=1;
                }
        }
        if(RB0==0)                  //如果是RB0键按下
        {
                delay_ms(5);              //延时去抖
                if(RB0==0)              //确认是否有键按下
                {
                        while(!RB0);        //等待按键释放
                        CCP2CON=0x00;                   //关PWM
                        TMR2ON=0;                        //禁止TMR2
                        //delay_ms(5);
                        RC1=0;
                }
        }
}
/********主函数********/
void main()
{
        init();                     //系统初始化
        PWM_Init();                 //脉冲宽度初始化
        while(1)
        {
                keyscan();              //调用按键扫描处理脉宽因数
        }
}
此帖出自单片机论坛
 
 

回复

578

帖子

0

TA的资源

纯净的硅(初级)

板凳
 
有可能是切换占空比的时候出现的抖动
此帖出自单片机论坛
 
个人签名刻苦学习,共同进步
 
 

回复

360

帖子

0

TA的资源

纯净的硅(初级)

4
 
和關狗,有沒有關係?
此帖出自单片机论坛
 
 
 

回复

5260

帖子

239

TA的资源

管理员

5
 
帮你呼叫版主@dingzy_2002
此帖出自单片机论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
 
 

回复

638

帖子

2

TA的资源

版主

6
 
PIC8位普通单片机的PWM输出设置确实较其它8位单片机要不同,而且我也曾经走过类似的弯路。
主要还是要严格按数据手册的设置来:尤其是初始化时

另外,如果改变PWM的周期频率,分辨率等,也要按上图的设置来

如果是确定了PWM的周期频率,分辨率后,仅改变点空比,则只需要修改CCPR1L即可,不要顺便CCP1CON值,这会引起不必要的异常发生。

此帖出自单片机论坛

点评

我刚试过不修改CCP2ON,波形还是会出现图中异常  详情 回复 发表于 2018-11-6 20:15
 
 
 

回复

638

帖子

2

TA的资源

版主

7
 
另外,如果关闭PWM后再开启,也同样要按上楼图中设置初始化。
所以,想暂时使PWM无输出(PWM还要继续工作),只要设置CCPR1L=0就可以了
就不需要再次对PWM初始化了。(这对低功耗不利,因为PWM模块始终工作,在低功耗要求下,则只能关闭,再初始化开启)。
此帖出自单片机论坛
 
 
 

回复

638

帖子

2

TA的资源

版主

8
 
本帖最后由 dingzy_2002 于 2018-11-6 11:37 编辑

给个我的例程(基于PIC12F615):

1.初始化部分:
//PWM:
        CCP1CON        = 0x0C;        //普通PWM模式,CCP1输出高电平有效
        CCPR1L        = (PWM_MAX);

...
//管脚方向设置:
        TRISIO        =        0b00001011;
//        
        PIE1=WPUA=IOCA        =0;
        PR2        = (PWM_MAX-1);//2MHz/125=16kHz,后分频4时,中断频率4KHz

...
        PIR1        = 0x00;
        PIE1        = 0x00;
        TMR2IE        = 1;
        TMR2ON        = 1;
        INTCON        = 0xC0;                //打开外部,T2中断

...

2.在程序中修改点空比(连续调节):
                DA_TEMP=CCPR1L;
                if(I_AVE>Iset_value)
                {
                        if(--DA_TEMP>=(PWM_MAX))
                                DA_TEMP = 0x00;
                }
                if(I_AVE                 {
                        if(++DA_TEMP>=(PWM_MAX))
                                DA_TEMP = (PWM_MAX);
                }
                CCPR1L        =DA_TEMP;        



此帖出自单片机论坛
 
 
 

回复

6

帖子

0

TA的资源

一粒金砂(中级)

9
 
dingzy_2002 发表于 2018-11-6 11:36
给个我的例程(基于PIC12F615):

1.初始化部分:
//PWM:
        CCP1CON        = 0x0C;        //普 ...

感谢版主的回答,  现在我的问题是,我在选取了一个频率后,可能80%占空比是正常的波形,当我把占空比调到60% 就会出现图中的电平下降再上升的一段,我认为 这样程序主体应该是没有问题的。  今天我换了一个4MHZ的晶振重新编了几个波形,结果还是这个样子。 同一频率下 占空比不同,波形可能就会乱。    问题还是没有解决哎
此帖出自单片机论坛
 
 
 

回复

6

帖子

0

TA的资源

一粒金砂(中级)

10
 
迈尔风随 发表于 2018-11-5 23:56
有可能是切换占空比的时候出现的抖动

同一频率,80%占空比可得到正常波形,60%占空比出来就会跟上图的错误一样,应该不是抖动原因造成的,今天我还换了一个晶振,结果还是那样。  
此帖出自单片机论坛
 
 
 

回复

6

帖子

0

TA的资源

一粒金砂(中级)

11
 
dingzy_2002 发表于 2018-11-6 11:27
PIC8位普通单片机的PWM输出设置确实较其它8位单片机要不同,而且我也曾经走过类似的弯路。
主要还是要严格 ...

我刚试过不修改CCP2ON,波形还是会出现图中异常
此帖出自单片机论坛
 
 
 

回复

638

帖子

2

TA的资源

版主

12
 
再看下是否有其他程序影响PWM输出,如中断,引脚操作等。
此帖出自单片机论坛
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

13
 
dingzy_2002 发表于 2018-11-6 11:36 给个我的例程(基于PIC12F615): 1.初始化部分: //PWM: CCP1CON = 0x0C; //普 ...

直接改PR2寄存器不行吗  如果停止PWM输出 在赋初值给PR2 为啥再开pwm输出 是按照停止时的频率

此帖出自单片机论坛

点评

1.一般PR2是设定PWM周期/频率的,正常情况下,这个是根据应用要求来确定频率范围的;不作为改动 2.单独修改PR2,则将会使PWM周期变化较大,且分辨率不足。  详情 回复 发表于 2020-4-2 12:50
 
 
 

回复

638

帖子

2

TA的资源

版主

14
 
DonaldH 发表于 2020-4-1 10:54 直接改PR2寄存器不行吗  如果停止PWM输出 在赋初值给PR2 为啥再开pwm输出 是按照停止时的频率

1.一般PR2是设定PWM周期/频率的,正常情况下,这个是根据应用要求来确定频率范围的;不作为改动

2.单独修改PR2,则将会使PWM周期变化较大,且分辨率不足。

此帖出自单片机论坛
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

15
 
dingzy_2002 发表于 2020-4-2 12:50 1.一般PR2是设定PWM周期/频率的,正常情况下,这个是根据应用要求来确定频率范围的;不作为改动 2.单独 ...

使用的是PIC16F677这款单片机 
我采用了TMR2定时器的PWM输出,功能要求就是正占空比是100uS,然后频率可调节,从1k到3k的频率调节,然后我采用的是通过定时器1进行10ms的定时,在中断服务函数中进行处理,直接将PR2的值进行改变来实现频率的调节,在主函数中 通过操作 PSTRCONbits.STRB = 1;  T2CONbits.TMR2ON = 1; 来开启PWM输出 ,通过 PSTRCONbits.STRB = 0;  T2CONbits.TMR2ON = 0;来关闭PWM输出。

然后出现就是在输出PWM波形的时候会出现有1.3ms的持续低电平没有输出,如示波器图片所示。

////////////////////////////////////////////////////////////////////////
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;
             pr2num= PWM_FREQL;
             PSTRCONbits.STRB = 1;
             T2CONbits.TMR2ON = 1; 
          }
        }
        else
        {
          if(PWMOUT_on   == 1)
          {    
            PWMOUT_on  = 0;
            TMR2 = 0;
            pr2num= PWM_FREQL;       这里是将PR2赋初值 停止输出就会赋 
            PSTRCONbits.STRB = 0;
            T2CONbits.TMR2ON = 0;
          }
        }

PWM.jpg (535.28 KB, 下载次数: 0)

PWM.jpg
此帖出自单片机论坛
 
 
 

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

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表