[技术问答] 如何提**唐硬件pwm的分辨率

[复制链接]
2534|18
 楼主| Harvard 发表于 2016-6-7 12:21 | 显示全部楼层 |阅读模式
如题,  新唐的pwm一般都是16bit, 其实也可以利用预分频比来提高一些所谓的分辨率.
现在有这样一个需求. 要求脉宽在0-65535us之间连续可调, 周期,也类似.但是肯定要大于65535,连续可调(分辨率为1us),有没办法通过软计数的方法,让pwm看上去的分辨率大于16bit呢


    目前针对这个应用,我想了一个i办法, 当然首先,把预分频比和时钟分配设置成合适参数,使得硬件pwm的最小时间分辨率为1us,
    利用pwm的oneshot模式. 第一个脉冲进行实际脉宽的输出,  
    如脉宽是32768us, 周期为2*65535这样一个脉冲, 利用实际的硬件pwm无法做到.硬件的16bitpwm只能做到32768us脉宽, 65535us周期,剩下的65535us的低电平期怎么办, 我想到了先用oneshot输出一个
            |-------32768us-----|________32767us____.
的oneshot波.然后再输出一个cmr=0,cnr=32768us的波,
            |___________________________________|-|,
但是,这个波会输出一个us的脉冲.         
然后重复.如此就组合成一个实际所需要的波.,基本可以达到要求.
请教大家还有没有合适的波,???
gejigeji521 发表于 2016-6-7 16:49 | 显示全部楼层
楼主可以用定时器模拟一个嘛,那样你想怎么样就怎么样了,通过IO翻转。
heisexingqisi 发表于 2016-6-7 17:24 | 显示全部楼层
这个是固定的吧,没听说过提高分辨率,另外分辨率高了其实耗电大的。
 楼主| Harvard 发表于 2016-6-9 08:51 | 显示全部楼层
我的意思是这样. 如果我设定pwm的tick为1us
那么周期最大为65535;  脉宽从1-65535可调.
现在的需求是脉宽不变; 要把周期从65535扩大,这样可以形成超低频.

|_____________________|--------D-------| 65535
|_____________________|--------D-------||___________________________________||___________________________________|
                                                            65535                                                 65535                                                           65535

不知道众看官 看懂了没有
 楼主| Harvard 发表于 2016-6-9 09:21 | 显示全部楼层
目前的实现思路是这样 .讲pmw设置到 oneshot模式 然后使能 period中断. 当pwm计数器减到0时,引发中断 ;

这里面分两种状态 ;

第一个状态是输出所需要的脉宽. 在65535的周内里 输出所需要的脉宽 .

第二个状态就是输出剩余的低电平时间,  此时将 CMR设置为0 cnr设置为所需要的数,如果不够 ,可以利用循环的形式, 无限制扩展,这样. 整个脉冲的周期就可以变得很长 ,
目前这个算法 只支持0-65535的脉宽,如果也需要扩展 ,就可以在第二个状态处理上下功夫;
zhuotuzi 发表于 2016-6-10 20:31 | 显示全部楼层
低频好做啊,弄个定时器中断来做,你想多久的周期就多久了。
 楼主| Harvard 发表于 2016-6-12 13:04 | 显示全部楼层
利用pwm来做 是为了保持一致性. 分辨率1us不变. 目前单路已经成功, 但是3路同时工作时, 会出现部分通道的计数停止 .
 楼主| Harvard 发表于 2016-7-18 18:47 来自手机 | 显示全部楼层
问题已经解决了
huangcunxiake 发表于 2016-7-19 10:08 | 显示全部楼层
楼主怎么解决的,方案说出来学习一下。
lai832 发表于 2016-7-19 16:45 | 显示全部楼层
你会发现:时钟源的1uS不准,造成你N个65535uS后会差1~几个uS. 越大,误差越大,
643757107 发表于 2016-7-19 21:29 | 显示全部楼层
楼上观点 我同意,误差会被放大。
 楼主| Harvard 发表于 2016-7-20 18:29 | 显示全部楼层
huangcunxiake 发表于 2016-7-19 10:08
楼主怎么解决的,方案说出来学习一下。
  1. /* 波形1的基波输出函数: 状态机
  2. *  |----stage1----| _______stage2____.
  3. *  stage1: CMR=CNR,输出高电平脉宽
  4. *  stage2: CMR=0; ,输出低电平脉宽,
  5. *  stage2中, 如果低电平的脉宽数大于65535,则
  6. */
  7. static u16 wave1_s2_n = 0;
  8. static u16 wave2_s2_n = 0;
  9. static u16 wave3_s2_n = 0;

  10. void pwm_wave1( void )
  11. {
  12.     /* 状态0:输出脉冲高电平(脉宽)*/
  13.     if(SYS_wave1_state == 0 )
  14.     {
  15.         /* 判断是否具有空周期,没有则一直在状态0 */
  16.         if( SYS_wave1_s2_n >0  )
  17.         {
  18.             SYS_wave1_state =1;
  19.             wave1_s2_n = SYS_wave1_s2_n;

  20.         }
  21.         else
  22.         {
  23.             SYS_wave1_state = 0;
  24.         }
  25.         /*根据pwm的硬件特性,输出时,cmr尽量在前面 */
  26.         
  27.         PWM_SET_CMR(PWMB,0,SYS_wave1_cmr_s1);
  28.         if( SYS_wave1_cnr_s1 == 0 ) SYS_wave1_cnr_s1 = 1250;
  29.         PWM_SET_CNR(PWMB,0,SYS_wave1_cnr_s1 );
  30.     }
  31.     else
  32.     {
  33.             SYS_UnlockReg();
  34.             SYS->P2_MFP &= ~(SYS_MFP_P24_Msk  );
  35.             SYS->P2_MFP |= SYS_MFP_P24_GPIO ;
  36.             SYS_LockReg();
  37.             WAVE1_PWM =0;
  38.    
  39.         /* 低电平重复次数 */
  40.         if( wave1_s2_n >0)
  41.         {
  42.             wave1_s2_n --;
  43.             /*s2 输出完毕,切换到s1*/
  44.             if(wave1_s2_n ==0)
  45.             {
  46.                 /* 推出低电平输出,*/
  47.                 SYS_wave1_state = 0;
  48.                 SYS_UnlockReg();
  49.                 SYS->P2_MFP &= ~(SYS_MFP_P24_Msk  );
  50.                 SYS->P2_MFP |= SYS_MFP_P24_PWM4 ;
  51.                 SYS_LockReg();
  52.             }           
  53.         }
  54.         
  55.             PWM_SET_CMR(PWMB,0,SYS_wave1_cmr_s2);
  56.             if( SYS_wave1_cnr_s2 == 0 ) SYS_wave1_cnr_s2 = 1250;
  57.             PWM_SET_CNR(PWMB,0,SYS_wave1_cnr_s2);  

  58.     }
  59.    
  60.      
  61. }




  1. /**
  2. * [url=home.php?mod=space&uid=247401]@brief[/url]       PWMA IRQ Handler,处理本项目的 PWM4-7
  3. *
  4. * @param       None
  5. *
  6. * [url=home.php?mod=space&uid=266161]@return[/url]      None
  7. *
  8. * [url=home.php?mod=space&uid=1543424]@Details[/url]     ISR to handle PWMB interrupt event
  9. */
  10. void PWMB_IRQHandler(void)
  11. {
  12.     uint32_t u32PwmIntFlag;

  13.     /* Handle PWMA Timer function */
  14.     u32PwmIntFlag = PWMB->PIIR;

  15.     /* PWMB channel 0 PWM timer interrupt */
  16.     if(u32PwmIntFlag & PWM_PIIR_PWMIF0_Msk)
  17.     {
  18.         PWMB->PIIR   =PWM_PIIR_PWMIF0_Msk;
  19.         pwm_wave1();
  20.     }
  21.      if(u32PwmIntFlag & PWM_PIIR_PWMIF2_Msk)
  22.     {
  23.         PWMB->PIIR  =PWM_PIIR_PWMIF2_Msk;
  24.         pwm_wave2();
  25.     }
  26.     if(u32PwmIntFlag & PWM_PIIR_PWMIF1_Msk)
  27.     {
  28.         PWMB->PIIR  =PWM_PIIR_PWMIF1_Msk;
  29.         pwm_wave3();
  30.     }

  31.     if(u32PwmIntFlag & PWM_PIIR_PWMIF3_Msk)
  32.     {
  33.         PWMB->PIIR  = PWM_PIIR_PWMIF3_Msk;
  34.         pwm_wave4();
  35.     }
  36.    
  37. }
capturesthe 发表于 2016-7-22 16:13 | 显示全部楼层
头一次听说PWM也有分辨率,学习知识了
这样的话是不是精度越高,可调范围越大
感觉和adc一样了
yiyigirl2014 发表于 2016-7-23 21:02 | 显示全部楼层
没有分辨率一说吧,只是占空比宽度而已。
zhuotuzi 发表于 2016-7-23 22:24 | 显示全部楼层
原来如此,多逛逛还是可以学到东西的
天灵灵地灵灵 发表于 2016-7-23 23:06 | 显示全部楼层
如果定时器是32位的就可以更大了。
 楼主| Harvard 发表于 2016-7-24 22:02 | 显示全部楼层
是的  不知道有没有更加好的方法 来扩展成32bit
gregoryw 发表于 2016-7-24 22:05 | 显示全部楼层
原来如此,多逛逛还是可以学到东西
zhuotuzi 发表于 2016-7-25 20:47 | 显示全部楼层
搞太多也没有太多意义。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:单片机工作者

74

主题

1732

帖子

21

粉丝
快速回复 在线客服 返回列表 返回顶部