发 帖  
原厂入驻New
[问答] 如何产生带有死区时间控制的互补pwm?
543 死区时间 PWM
分享
想请教一下站内大神,想要产生如下图所示含有死区时间的互补的pwm,具体的编程语言怎么写。我自己写的这一段只能在上升沿出有死区。
always@(posedge CLK50M or negedge Rst_n)

begin
    IF(!Rst_n)begin
   cntd1<=5'd0;
   dpwm_od1<=1'b0;
   end
    else begin
        if(pwm_od1i==1'b0)begin
             cntd1<=5'd0;
     dpwm_od1<=1'b0;
     end
     else if(cntd1==d_set)begin
                 cntd1<=d_set;
         dpwm_od1<=1'b1;
         end
                  else begin
                       cntd1<=cntd1+1'd1;
           dpwm_od1<=1'b0;
          end
   end
end  
有大神可以解答一下吗,非常感谢!
0

自己的程序仿真图

自己的程序仿真图

期望得到的pwm

期望得到的pwm
奖励20积分
2019-9-26 09:37:01   评论 分享淘帖 邀请回答
6个回答
2019-9-26 16:19:49 1 评论

举报

1 条评论
用高级定时器TIM1产生一组互补PWM,用通用定时器TIM3输入捕获,测量PWM的频率和占空比。
1、互补PWM输出
使用高级定时器1的CH1和CH1N通道,该定时器可以选用144M的高频率,对应选用输出引脚PA8和PA7,参考库函数使用手册的步骤,大概概括一下:
1.使能时钟和配置相应GPIO,几乎所有外设使用的第一步
2.配置定时器分频值,重装载值,计数模式等基本参数
3.配置OC参数,也就是OCInitStructure结构体,注意CHxN的输出状态要使能,才能输出互补
4.完成上面步骤就可以输出互补PWM了,如果需要死区等功能,再配置BDTR
5.打开定时器,使能PWM输出
下面是使用144M频率产生100k PWM的主要部分代码:
  • RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
  •         RCC_TIMCLKConfig(RCC_TIM1CLK_PLLCLK);        // 选择144M时钟
  •         TIM_TimeBaseInitStructure.TIM_Prescaler = 0;
  •         TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  •         TIM_TimeBaseInitStructure.TIM_Period = 1440-1;//144M/100k=1440
  •         TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
  •         TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00;
  •         TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);
  •         TIM_OCStructInit(&TIM_OCInitStructure);
  •         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  •         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  •         TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//开启互补通道
  •         TIM_OCInitStructure.TIM_Pulse =720;//脉宽,50%占空比,1440/2
  •         TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
  •         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  •         TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
  •         TIM_OC1Init(TIM1,&TIM_OCInitStructure);
  •         TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
  •         TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
  •         TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Disable;
  •         TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
  •         TIM_BDTRInitStructure.TIM_DeadTime =1440*4/100;//5%死区,则实际占空比45%
  •         TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
  •         TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
  •         TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
  •         TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);
  •         TIM_Cmd(TIM1,ENABLE);
  •         TIM_CtrlPWMOutputs(TIM1,ENABLE);

复制代码
用示波器可以查看输出波形。
2、PWM输入捕获
用这个功能可以测量输入波形的频率或(和)占空比,使用的是定时器TIM3的Input capture mode,可以测量频率或者占空比,为了方便同时测量这两个量,使用该模式中的特殊情况PWM input mode,如图:


(截图自ST参考手册)
根据库函数说明手册的步骤:
1.开启时钟和配置GPIO
2.如果需要,配置定时器基本参数,如果不配置,将按默认配置运行
3.配置输入参数TIM_ICInitStruct,调用Call TIM_ICInit(TIMx, &TIM_ICInitStruct)配置测量频率或占空比中的一个,或者调用TIM_PWMIConfig(TIMx,               &TIM_ICInitStruct)同时测量者两个量
4.开启中断或者DMA并初始化,用来读取结果数据
5.如果用PWM input mode需要把定时器设为主从Reset模式
6.打开定时器,在中断或者DMA读取数据
(细节参考ST参考手册PWM input mode部分和库函数说明手册Input Capture management functions部分)
主要代码:
  • TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;
  •           TIM_ICInitStructure.TIM_ICFilter=0x0;
  •           TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
  •           TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
  •           TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
  •           TIM_PWMIConfig(TIM3,&TIM_ICInitStructure);
  •           TIM_SelectInputTrigger(TIM3,TIM_TS_TI2FP2);
  •           TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
  •           TIM_SelectMasterSlaveMode(TIM3,TIM_MasterSlaveMode_Enable);
  •           TIM_Cmd(TIM3,ENABLE);
  •           TIM_ITConfig(TIM3,TIM_IT_CC2,ENABLE);
  •            NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  •           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  •           NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  •           NVIC_Init(&NVIC_InitStructure);


复制代码
中断处理函数:
  • volatile uint16_t IC2Value = 0;
  • volatile uint16_t DutyCycle = 0;
  • volatile uint32_t Frequency = 0;
  • void TIM3_IRQHandler(void)
  • {
  •           TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
  •           IC2Value = TIM_GetCapture2(TIM3);
  •           if (IC2Value != 0)
  •           {
  •             DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC2Value;
  •             Frequency = 72000000 / IC2Value;
  •           }
  •           else
  •           {
  •             DutyCycle = 0;
  •             Frequency = 0;
  •           }
  •                  printf("DutyCycle= %d\n",DutyCycle);
  •                 printf("Frequency= %d\n",Frequency);
  • }

复制代码
将1、中输出引脚短接到2、中的输入引脚,即可以在串口打印出测量的结果,在一定误差范围内测量正确。
完整的源码:

2019-10-7 20:44:44 1 评论

举报

1 条评论
就是把死区时间化成两个比对数,通过比对两个数来产生死区。
2019-10-9 15:43:32 评论

举报

看看这个图形是不是你想要的的结果?
PWM_SIM.png
2019-10-24 16:59:38 1 评论

举报

1 条评论
  • 2019-10-24 17:01

    我对“死区时间”的各个参数名称不熟悉,名字随便取的。图中红色波形是输出波形,和你画的图应该是一致的。

补充一下代码和仿真代码:
pwm_top.png
pwm_sim_top.png
2019-10-24 17:12:30 评论

举报

学习学习,学习学习。
2019-10-26 10:31:40 评论

举报

撰写答案

你正在撰写答案

如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。

高级模式
您需要登录后才可以回帖 登录 | 注册

我要提问
关闭

站长推荐 上一条 /10 下一条

快速回复 返回顶部 返回列表