关于PWM+DMA多波形问题

在最近工作项目中使用PWM+DMA驱动WS1812B灯珠,测试的时候发现一开始的时候多波形问题。产看了很多资料。发现并不是网上描述的那种问题,而是DMA速度不够快,本身使用单片机时候L431的,项目为了减少功耗只采用了8M频率。后来实测DMA传输(PWM请求+DMA响应+传输)大概是800KHz。

感谢协助人:粤

也就是传输一个脉冲1.25us

第一种多波形现象:(常见网上的问题)

/*DMA缓存数据*/
const uint16_t RGB_G_Buff[RGB_Size] = { 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
                                        0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
                                        0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
                                      };

/*PWM初始化*/
static void TIM2_PWM_Mode(void)
{
//-------------------结构体------------------------------------//
    TIM_TimeBaseInitTypeDef      TIM_TimeBase_InitSturct;
    TIM_OCInitTypeDef                    TIM_OC_InitSturct;
    
//----------------------开启定时器时钟---------------------//
    ADVANCE_TIMx_APBxClk(ADVANCE_TIMx_Clk, ENABLE);

//-------------------时基初始化结构体-------------------------//
    //信号周期
    TIM_TimeBase_InitSturct.TIM_Period = TIM2_Period;
    //分频周期,记一次的时间
    TIM_TimeBase_InitSturct.TIM_Prescaler    =    (9);
    //计数模式
    TIM_TimeBase_InitSturct.TIM_CounterMode    =    TIM_CounterMode_Up;
    //死区(普通,通用定时器不需要配置)
    //TIM_TimeBase_InitSturct.TIM_ClockDivision    =    TIM_CKD_DIV1;                //CR1
    //重复寄存器,没用到不要管
    TIM_TimeBase_InitSturct.TIM_RepetitionCounter = 0;                                    //RCR
    TIM_TimeBaseInit(ADVANCE_TIMx, &TIM_TimeBase_InitSturct);
//--------------------输出比较寄存器结构体-----------------//
    //模式选择
    TIM_OC_InitSturct.TIM_OCMode = TIM_OCMode_PWM2;
    TIM_OC_InitSturct.TIM_OutputState = TIM_OutputState_Enable;
    //
    TIM_OC_InitSturct.TIM_Pulse = 0x02;    //占空比
    TIM_OC_InitSturct.TIM_OCPolarity = TIM_OCPolarity_High;
    //
    TIM_OC4Init(ADVANCE_TIMx, &TIM_OC_InitSturct);
    TIM_OC4PreloadConfig(ADVANCE_TIMx, TIM_OCPreload_Enable);
    
//-----------------------------------------------------------//
    TIM_Cmd(ADVANCE_TIMx, ENABLE);
    TIM_DMACmd(ADVANCE_TIMx, TIM_DMA_CC4, ENABLE);
}

这边省略了部分代码,只显示问题代码。

PS:占空比与配置有关,这里不在详述(0x06:高电平小 0x02:高电平多)

我们看到在DMA缓存数据中发送的(bit0-bit8)是0x06,但是按照我们的想法PWM触发DMA情况应该是跟缓存数据相关的。实际波形应该如下图所示:(为什么第一个波形是高电平呢???)

这里我们需要明白什么时候发送DMA情况!!!看下面注释即可

原来只有比较的时候才能触发DMA请求。这样我们不就知道为什么第一个波形会多出来了么,就是初始化的时候配置TIM_OC_InitSturct.TIM_Pulse = 0x02,在初始化的时候自然就会多出一个波形,为了消除这个波形我们只要将初始化的时候将其配置为高电平或者低电平即可(也就是占空比0%或者100%)我配置为TIM_OC_InitSturct.TIM_Pulse = 0x10--->占空比100%

这样就会产生第二张图的波形。

第二种多波形现象:(相对DMA速度??)

(8M单片机输出1.25us的可变PWM脉冲)

(72M单片机在配置PWM时分频到8M输出1.25us的可变PWM脉冲)

回归正传,这种情况是排除第一种情况下产生的,一般只有在不停切换占空比的时候会产生,比如要输出累死10101010101010的这种波形,实际上会跟配置(DMA速度、PWM分频、占空比)相关。目前会出现这两种情况

第一种:PWM配置、DMA处理

110101010101010 这个情况跟上述第一种类似

0x06:表示1 0x02:表示0

const uint16_t RGB_G_Buff[RGB_Size] = { 0x10,0x10,
                                        0x06,0x02,0x06,0x02,0x06,0x02,
                                        0x06,0x02,0x06,0x02,0x06,0x02,
                                        0x06,0x02,0x06,0x02,0x06,0x02,
                                        0x00 };

//为了将第一种情况排除设置成如下,跟你的配置有关!!!
TIM_OC_InitSturct.TIM_Pulse = 0x10;    //PWM初始化占空比

在这个情况下就是DMA传输慢的现象,同时也跟你的PWM初始化配置、占空比有关。

首先要明白:捕获/比较模式寄存器(TIMx_CCMRx)

OCxPE:输出比较x预装载使能 (Output compare x preload enable) 这个是配置预装载寄存器的

下面来详细讲一下多波形产生的原因(仔细看图哦)

第一次产生比较的时候发出一次请求10,此时DMA响应后数据还没有返回,这时候依旧沿用预装载值来产生低电平(也是多波的,因为是低电平所以看不出)

第二次产生比较的时候发出一次请求10,第一次请求的值已经返回,放在了预装载值,同时更新影子寄存器(0x10)(这里的波形是第一次请求的数据)

第三次产生比较的时候发出请求06,第二次请求的值已经返回,放在了预装载值,同时更新影子寄存器(0x10)(这里的波形是第二次请求的数据)

第四次产生比较的时候发出一次请求03,第三次请求的值已经返回,放在了预装载值,同时更新影子寄存器电平(0x06)(于是下一个波形开始产生我们想要的数据,也就是第四个波形)

第五次产生比较的时候发出一次请求06,第四次请求的值还没有返回,这时候依旧沿用预装载值(0x06)来产生电平(为什么第四次值没有返回呢???这就是多波的原因)

原因:这PWM配置的时候,默认是比较产生请求,当技术值到达06产生请求后,只有3次计数(我这里设置的是9个计数周期哦)的时间给DMA处理反应,时间根本不够。于是沿用预装载值进行发出波形。同时利用了预装载值缓冲下一个请求值,这样为什么只有第一个波形会多。

第六次产生比较的时候发出一个请求03,第四次请求的值已经返回,放在了预装载值,同时更新影子寄存器(0x03)(这里的波形是第四次请求的数据)

第七次产生比较的时候发出一个请求06,第五次请求的值已经返回,放在了预装载值,同时更新影子寄存器(0x06)(这里的波形是第五次请求的数据)

---以此类推,除了第四、五次产生异常,后续的值都是沿用上上次请求的值。

其实还有个疑问,如果我第五个波形产生是一个足够第低电平,第四第五次的请求6没有发生之前都到预装载值中会如何呢?叠加还是覆盖。我想是覆盖了,毕竟第五个波是跟随第四个波形的,这要卡多极限呢(除非搞事情)!想想都很有趣啊。并且这个是在传数据的时候才会发生吧(1010都能传了,一个没人会搞这个极限的情况吧。。。哈哈哈哈)

第二种:(DMA处理、占空比、PWM配置)

1100110011001100110011001100

110110110110110110110

坑定还会出现其他现象,主要就是多波形问题

频率不一样问题也会不一样的

原理是跟上面一致的,就是请求DMA的数据没有传过来,当更新事件后会多重复一个波形

解决方法

上面两种解决方法很简单

1.25us的脉冲

1,25us左右的DMA处理

既然比较请求的速度不够,就使用溢出请求

在配置PWM 的时候,修改如下:(根据你的配置,我只是提供思路

/*输出配置、预装载配置*/
TIM2->CCMR2 |= 0x7800;
/*溢出请求*/
TIM2->CR2 |= 0x0008;

改善后情况得到改善

另外就是如果不改比较请求就改你的PWM频率>8MHz,比较时间与更新时间之间是时间必须大于DMA处理的时间。主要是单片机频率被项目限制了。。。

DMA速度慢么?

是DMA慢么?其实也不然,在PWM+DMA的情况下,每次请求DMA都只是传输一次数据

我每次产生请求都要DMA处理一下,如果在请求一次传输很多数据的情况下DMA自然是非常快速的,但是我每次请求都只要一个数据,你很说不慢么???浪费很多在处理的时间上。为此要考虑到DMA每次处理的数据,但是我们又不清楚,规格书上好像也没看到。目前实测8MHz单片机DMA速度大概是800KHz左右。

72M单片机在将PWM分频到800KHz也只有800KHz左右。

另外测试中发现DMA处理速度是根据外设速度来决定的

推算出可能是外设频率的1/10。如果有知道的大佬可以科普一下。

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值