打印
[STM32F1]

STM32 PWM 可变脉宽控制的疑问?

[复制链接]
963|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ipman|  楼主 | 2020-8-3 13:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了规格书,STM32的PWM的CCRx值在TIM_IT_Update中断发生时,从CCRx影子寄存器读取到真实寄存器。
现在的疑问是,比如TIM2CH1需要连续两个脉冲输出(CCR值分别为20,50),首次初始化时如果设定好CCR1=20,然后TIM_Cmd(TIM2, ENABLE);
此时,初始化时的CCR1值20已经读取到真实寄存器并生效执行,但是,我应该在哪里设置CCR1的第二次值50呢?如果在计时器溢出中断 TIM_IT_Update 中更新,岂不来不及?因为中断发生后,已经开始执行下次循环?

使用特权

评论回复
沙发
RunningX| | 2020-8-3 20:04 | 只看该作者
直接用GPIO去翻转更方便吧

使用特权

评论回复
板凳
ipman|  楼主 | 2020-8-3 20:18 | 只看该作者
本帖最后由 ipman 于 2020-8-3 20:26 编辑

我把要发送的10组PWM周期和占空比放到数组里面,然后再计数器更新中断里读取下一组赋值,很奇怪,第一组脉冲丢失了!!!
uint16_t pwmOutWave[10][2] = {{100,10}, {100,30},{100,30},{100,40},{100,40},{100,50},{100,50},{100,60},{100,60},{100,80}};
uint16_t SendIndex = 0;
void Tim16_Config(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, DISABLE);
        TIM_TimeBaseStructure.TIM_Prescaler = 48-1;                //1us per count
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseStructure.TIM_Period = period;
        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;
        TIM_OC1Init(TIM16, &TIM_OCInitStructure);
        TIM_OC1PreloadConfig(TIM16, TIM_OCPreload_Disable);
        //TIM_ARRPreloadConfig(TIM16, ENABLE);// DISABLE立即更新  ENABLE 影子
        TIM_CtrlPWMOutputs(TIM16, ENABLE);
        TIM_Cmd(TIM16, ENABLE);
        TIM_ITConfig(TIM16,TIM_IT_Update|TIM_IT_CC1, ENABLE);
}
void TIM16_IRQHandler(void)
{
        //匹配时
        if(TIM_GetITStatus(TIM16, TIM_IT_CC1) != RESET)
        {
                TIM_ClearITPendingBit (TIM16, TIM_IT_CC1);        //必须要清除中断标志位
        }
       //溢出时更新计数和匹配
        if (TIM_GetITStatus(TIM16, TIM_IT_Update) != RESET)        //TIM_IT_Update
        {
                if(SendIndex<9)
                {
                        SendIndex++;    // 数组0在初始化时候已经执行
                        //重新赋值影子寄存器
                        TIM_SetAutoreload(TIM16, pwmOutWave[SendIndex][0]);
                        TIM_SetCompare1(TIM16, pwmOutWave[SendIndex][1]);
                        
                }else{
                        //发送完成10组,关闭
                        TIM_Cmd(TIM16, DISABLE);
                        //确保输出电平为空闲设置
                        TIM_ForcedOC1Config(TIM16, TIM_ForcedAction_InActive);
                }
                TIM_ClearITPendingBit (TIM16, TIM_IT_Update);        //必须要清除中断标志位
        }

void testSend(void)
{
     SendIndex = 0;
     Tim16_Config(pwmOutWave[SendIndex][0],pwmOutWave[SendIndex][1]);
}

使用特权

评论回复
地板
ipman|  楼主 | 2020-8-3 20:19 | 只看该作者
RunningX 发表于 2020-8-3 20:04
直接用GPIO去翻转更方便吧

那要delay啊,系统是实时系统

使用特权

评论回复
5
香水城| | 2020-8-3 23:17 | 只看该作者
你可以在第一次比较事件的中断里修改第二个CCR值,在更新事件时就被更新了。
当然,你也可以使用DMA传输。

使用特权

评论回复
6
ipman|  楼主 | 2020-8-4 00:31 | 只看该作者
香水城 发表于 2020-8-3 23:17
你可以在第一次比较事件的中断里修改第二个CCR值,在更新事件时就被更新了。
当然,你也可以使用DMA传输。 ...

对啊,这个机会被忽略了,这是个好主意,老大就是睿智,我这就去试试

使用特权

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

本版积分规则

89

主题

550

帖子

4

粉丝