[STM32F0] STM32的PWM使用影子寄存器脉冲问题

[复制链接]
1504|15
 楼主| ipman 发表于 2021-5-9 12:47 | 显示全部楼层 |阅读模式
使用了影子寄存器,在CC中断更新下一个脉冲的RELOAD,在RELOAD中断更新下一个CC,示波器跟踪发现,首个预装载的脉冲被丢弃了,启动PWM后,先进入RELAOD中断,然后进入CC,RELOAD中断,为何?
按照预想,应该输出初始化中设定的PWM配比,然后先进入CC中断,预装下一次RELOAD,再进入RELOAD中断,预装下一个CC,反复观察丢弃了启动PWM前预装的那一组。
 楼主| ipman 发表于 2021-5-9 22:32 | 显示全部楼层
很难吗?自己顶
香水城 发表于 2021-5-9 23:05 | 显示全部楼层
香水城 发表于 2021-5-9 23:08 | 显示全部楼层
本帖最后由 香水城 于 2021-5-9 23:09 编辑

这个要具体看看你的实现代码。
 楼主| ipman 发表于 2021-5-9 23:37 | 显示全部楼层
香水城 发表于 2021-5-9 23:08
这个要具体看看你的实现代码。

void TIM16_PWM_Init(uint16_t period, uint16_t pulse)
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;
        TIM_DeInit(TIM16);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16,ENABLE);
        TIM_ARRPreloadConfig(TIM16, ENABLE);        // ARR影子开启
        TIM_OC1PreloadConfig(TIM16, TIM_OCPreload_Enable);  //OC1影子开启
        TIM_TimeBaseStructure.TIM_Prescaler = 48-1;                //1us per count @48M clock
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        //向上计数
        TIM_TimeBaseStructure.TIM_Period = period;                        //首个PWM预装ARR
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;       
        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
        TIM_TimeBaseInit(TIM16, &TIM_TimeBaseStructure);

        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;                //比较匹配时输出高
        TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
        TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;        //空闲时刻输出高
        TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;
        TIM_OCInitStructure.TIM_Pulse =  pulse;   //这里初始化装入CC值,实际这个脉冲未发现输出
        TIM_OC1Init(TIM16, &TIM_OCInitStructure);
        TIM_Cmd(TIM16, ENABLE);
        TIM_CtrlPWMOutputs(TIM16, ENABLE);
        /* 注意,发现启动TIM后会立即进入中断,在中断中载入需要输出的PWM */
        TIM_ClearITPendingBit (TIM16, TIM_IT_Update);
        TIM_ClearITPendingBit (TIM16, TIM_IT_CC1);        //必须要清除中断标志位
        TIM_ITConfig(TIM16,TIM_IT_Update|TIM_IT_CC1, ENABLE);
}
初始化传入参数:
TIM16_PWM_Init(100,10);   //无论传入什么参数,这个脉冲都未发现
 楼主| ipman 发表于 2021-5-9 23:43 | 显示全部楼层
目前变通方法就是首个脉冲丢弃,倒是不影响设计,但毕竟是个疑问没有得到解答浑身不舒服
香水城 发表于 2021-5-10 08:33 | 显示全部楼层
本帖最后由 香水城 于 2021-5-10 12:18 编辑

预装值的生效须借助更新事件的,当然前提是你开启了预装功能。

检查下,是否第一个初始化脉冲没发生作用前又做了初始化并令新数据生效了,我怀疑这方面的原因。
 楼主| ipman 发表于 2021-5-10 11:22 | 显示全部楼层
香水城 发表于 2021-5-10 08:33
预装值的生效须借助更新事件的。

检查下,是否第一个初始化脉冲没发生作用前又做了初始化并令新数据生效 ...

为了分析原因,特意分析了中断顺序,启动TIM后,首先发生了一个ARR中断,然后依次CC中断,ARR中断,我在ARR中断中开始更新两个寄存器,如您所言,预装值(影子寄存器数据)进入真实执行寄存器需要借助更新事件,难道在启动TIM后,MCU强制产生了一个更新事件,并且此更新事件到来后并未将影子寄存器中的数据移入执行的寄存器,所以正好将我准备要发送的数据带入了影子寄存器覆盖了预装数据?
这确实很有趣,不知道初始化的那个数据在什么情况下会被覆盖?因为预装后马上使能了TIM,按理说没有办法停止这个预装值进入真正的寄存器中啊~
香水城 发表于 2021-5-10 12:04 | 显示全部楼层
本帖最后由 香水城 于 2021-5-10 12:12 编辑
ipman 发表于 2021-5-10 11:22
为了分析原因,特意分析了中断顺序,启动TIM后,首先发生了一个ARR中断,然后依次CC中断,ARR中断,我在A ...

这确实很有趣,不知道初始化的那个数据在什么情况下会被覆盖?因为预装后马上使能了TIM,按理说没有办法停止这个预装值进入真正的寄存器中啊~

===》如果你说的第一个配置没有完全发生作用完成前的某个时刻 又重新写了预装值同时软件产生更新事件。【注意 也可以通过软件方式产生更新事件的】,那么定时器就按新的配置工作了。 还有种可能,即预装功能是关闭的,修改的预装数据立即生效。建议你将那个 TIM_TimeBaseInit函数内容仔细看看。然后 锁定到底在哪里或说哪个时刻第一个配置就被覆盖抛弃了。
香水城 发表于 2021-5-10 12:08 | 显示全部楼层
 楼主| ipman 发表于 2021-5-10 12:22 | 显示全部楼层
香水城 发表于 2021-5-10 12:08
stm32定时器应用培训资料

谢谢香主,理解了,就是执行的是影子,写入的是预装,影子更新要借助ARR中断,所以自动产生一个中断,初始化中的值被覆写了
renzheshengui 发表于 2021-6-2 14:32 | 显示全部楼层
请问什么是影子寄存器啊
wakayi 发表于 2021-6-2 14:33 | 显示全部楼层
什么事件叫做更新事件呢
wowu 发表于 2021-6-2 14:36 | 显示全部楼层
预装无法被干扰到吗
xiaoqizi 发表于 2021-6-2 14:39 | 显示全部楼层
如何设定执行影子呢
木木guainv 发表于 2021-6-2 14:41 | 显示全部楼层
影子寄存器的地址是如何占用的呢
您需要登录后才可以回帖 登录 | 注册

本版积分规则

89

主题

550

帖子

4

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