请选择 进入手机版 | 继续访问电脑版

芯虎论坛

 找回密码
 立即注册
查看: 232|回复: 0

华大单片机高级定时器输出0~100%占空比方法

[复制链接]

56

主题

94

帖子

4万

积分

论坛元老

Rank: 8Rank: 8

积分
40818

论坛元老

发表于 2021-8-31 16:37:57 | 显示全部楼层 |阅读模式
华大单片机可以通过种方式进行PWM输出,工程师反应使用高级定时器输出PWM的时候,不能输出占空比为0或100%的波形。这时由于高级定时器输出PWM时设置会比较特殊,下面进行相关的介绍。


高级定时器进行PWM输出时,波形主要由下面几个寄存器的值来决定:
PCONR.PERCx(x=A/B) :       CHA和CHB的周期匹配时,输出电平状态,设置的是PWM周期结束后电平状态
PCONR.CMPCx(x=A/B):       CHA和CHB的比较匹配时,输出电平状态,设置的是计数到计数点后电平的状态
PCONR.STASTPSx(x=A/B):   CHA和CHB的起始和停止电平选择
PCONR.STACx(x=A/B):        计数开始时CHA和CHB电平状态,PWM开始前端口的电平状态
PCONR.STPCx(x=A/B):        计数结束时CHA和CHB电平状态,PWM停止后端口的电平状态
前两个寄存器用来设置PWM输出周期的波形,后三个寄存器用来设置PWM开始和结束时端口的电平。


本文开头提到的问题通过设置前两个寄存器就可以实现。下面以起始低电平,计数匹配后高电平的PWM波形来说明。起始低电平说明PWM周期匹配后,新的周期开始时端口的电平为低电平,需要把PCONR.PERCx设置为低电平;计数匹配后为高电平,把PCONR.CMPCx设置为高电平就可以。这样的设置可以输出0~(<100%)占空比的波形。100%这点需要始终是高电平,也就是说周期匹配的时候不能输出低电平,设置为低电平的话,当周期匹配的时候会立刻输出一个低电平,再进行比较匹配的判断,匹配分输出高电平,这样就存在一个很小的低电平脉冲,不是我们所需要的。


当要输出100%占空比的时候,要把PCONR.PERCx设置为高电平,这样就周期匹配的时候会输出高电平,不会再有低电平脉冲。当占空比不是100%的时候,再把PCONR.PERCx设置回低电平就可以。


以HC32F003芯片TIM4定时器CHA通道为例,每一秒改变增加10%占空比,输出100%后,占空比改为0输出。代码部分如下:


  1. int32_t main(void)
  2. {
  3.         float fPwmDyty = 0.0;
  4.     en_adt_unit_t enAdt;
  5.     uint16_t u16Period;
  6.     en_adt_compare_t enAdtCompare;
  7.     uint16_t u16Compare;
  8.     stc_adt_basecnt_cfg_t stcAdtBaseCntCfg;
  9.     stc_adt_CHxX_port_cfg_t stcAdtTIM4ACfg;


  10.     DDL_ZERO_STRUCT(stcAdtBaseCntCfg);
  11.     DDL_ZERO_STRUCT(stcAdtTIM4ACfg);

  12.     Clk_SetPeripheralGate(ClkPeripheralGpio, TRUE);                       //端口外设时钟使能

  13.    
  14.     Gpio_SetFunc_TIM4_CHA_P23();


  15.     Clk_SetPeripheralGate(ClkPeripheralAdt, TRUE);                         //ADT外设时钟使能

  16.     enAdt = AdTIM4;
  17.     Adt_StopCount(enAdt);
  18.     Adt_ClearCount(enAdt);

  19.     stcAdtBaseCntCfg.enCntMode = AdtSawtoothMode;                    //ADT载波为三角波
  20.     stcAdtBaseCntCfg.enCntDir = AdtCntUp;                                               //向上计数
  21.     stcAdtBaseCntCfg.enCntClkDiv = AdtClkPClk0Div8;                    //PCLK8分频
  22.     Adt_Init(enAdt, &stcAdtBaseCntCfg);                                                       //ADT载波、计数模式、时钟配置
  23.    
  24.     u16Period = 0xEEEE;
  25.     Adt_SetPeriod(enAdt, u16Period);                                                              //设置PWM周期

  26.     enAdtCompare = AdtCompareA;
  27.     u16Compare = 0xEEEE;
  28.     Adt_SetCompareValue(enAdt, enAdtCompare, u16Compare);       //设置CHA通道PWM低电平时间
  29.    
  30.     enAdtCompare = AdtCompareC;
  31.     u16Compare = 0xEEEE;
  32.     Adt_SetCompareValue(enAdt, enAdtCompare, u16Compare);      //设置CHA通道比较缓存值

  33.     Adt_EnableValueBuf(enAdt, AdtCHxA, TRUE);                                           //使能CHA通道缓存输出

  34.     stcAdtTIM4ACfg.enCap = AdtCHxCompareOutput;                              //比较输出
  35.     stcAdtTIM4ACfg.bOutEn = TRUE;                                                                        //端口输出使能
  36.     stcAdtTIM4ACfg.enPerc = AdtCHxPeriodLow;                                         //周期匹配时输出低电平
  37.     stcAdtTIM4ACfg.enCmpc = AdtCHxCompareHigh;                               //比较匹配时输出高电平
  38.     stcAdtTIM4ACfg.enStaStp = AdtCHxStateSelSS;                                  //计数开始或停止时,CHA端口输出由STACB、STPCB决定
  39.     stcAdtTIM4ACfg.enStaOut = AdtCHxPortOutLow;                               //计数开始时CHA端口输出设定为低电平
  40.     stcAdtTIM4ACfg.enStpOut = AdtCHxPortOutLow;                               //计数停止时CHA端口输出设定为低电平
  41.     Adt_CHxXPortConfig(enAdt, AdtCHxA, &stcAdtTIM4ACfg);       //端口CHA配置
  42.    
  43.     Adt_StartCount(enAdt);                                                                                             //开启ADT
  44.    
  45.     while(1)
  46.         {
  47.                
  48.                    delay1ms(1000);
  49.                    if(fPwmDyty < 1)                                                                                          //占空比小于100%,将占空比加10%
  50.                   {
  51.                             fPwmDyty += 0.1;
  52.                   }
  53.                   else                                                                                                                          //占空比大于等于100%,将占空比设置为0%
  54.                   {
  55.                             fPwmDyty = 0;
  56.                   }

  57.                   if (fPwmDyty < 1)                                                                                     //占空比小于100%,将计数周期结束时输出设置为低
  58.                   {
  59.                              M0P_ADT0->PCONR_f.PERCA = 0;  
  60.                   }
  61.                   else                                                                                                                       //占空比大于等于100%,将计数周期结束时输出设置为高
  62.                   {
  63.                             M0P_ADT0->PCONR_f.PERCA = 1;
  64.                   }
  65.                
  66.                   Adt_SetCompareValue(AdTIM4, AdtCompareC, (1-fPwmDyty)*u16Period);
  67.                
  68.           }
  69. }
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|芯虎论坛 ( 辽ICP备18019618号 )

GMT+8, 2021-9-27 21:51 , Processed in 0.108724 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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