[DemoCode下载] PMW死区控制

[复制链接]
1915|18
 楼主| zhuotuzi 发表于 2017-1-27 11:32 | 显示全部楼层 |阅读模式
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
  4. * $Revision: 4 $
  5. * $Date: 14/02/10 3:06p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    M051 Series PWM Generator and Capture Timer Driver Sample Code
  7. *
  8. * @note
  9. * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
  10. *
  11. ******************************************************************************/
  12. #include <stdio.h>
  13. #include "M051Series.h"

  14. /*---------------------------------------------------------------------------------------------------------*/
  15. /* Macro, type and constant definitions                                                                    */
  16. /*---------------------------------------------------------------------------------------------------------*/

  17. #define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
  18. #define PLL_CLOCK           50000000


  19. /*---------------------------------------------------------------------------------------------------------*/
  20. /* Global variables                                                                                        */
  21. /*---------------------------------------------------------------------------------------------------------*/

  22. /**
  23. * @brief       PWMA IRQ Handler
  24. *
  25. * @param       None
  26. *
  27. * [url=home.php?mod=space&uid=266161]@return[/url]      None
  28. *
  29. * [url=home.php?mod=space&uid=1543424]@Details[/url]     ISR to handle PWMA interrupt event
  30. */
  31. void PWMA_IRQHandler(void)
  32. {
  33.     static uint32_t cnt;
  34.     static uint32_t out;

  35.     // Channel 0 frequency is 100Hz, every 1 second enter this IRQ handler 100 times.
  36.     if(++cnt == 100)
  37.     {
  38.         if(out)
  39.             PWM_EnableOutput(PWMA, 0xF);
  40.         else
  41.             PWM_DisableOutput(PWMA, 0xF);
  42.         out ^= 1;
  43.         cnt = 0;
  44.     }
  45.     // Clear channel 0 period interrupt flag
  46.     PWM_ClearPeriodIntFlag(PWMA, 0);
  47. }

  48. void SYS_Init(void)
  49. {
  50.     /*---------------------------------------------------------------------------------------------------------*/
  51.     /* Init System Clock                                                                                       */
  52.     /*---------------------------------------------------------------------------------------------------------*/

  53.     /* Enable Internal RC clock */
  54.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  55.     /* Waiting for IRC22M clock ready */
  56.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

  57.     /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
  58.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

  59.     /* Enable external 12MHz XTAL, internal 22.1184MHz */
  60.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk | CLK_PWRCON_OSC22M_EN_Msk);

  61.     /* Enable PLL and Set PLL frequency */
  62.     CLK_SetCoreClock(PLLCON_SETTING);

  63.     /* Waiting for clock ready */
  64.     CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk | CLK_CLKSTATUS_XTL12M_STB_Msk | CLK_CLKSTATUS_OSC22M_STB_Msk);

  65.     /* Switch HCLK clock source to PLL, STCLK to HCLK/2 */
  66.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_PLL, CLK_CLKDIV_HCLK(2));

  67.     /* Enable UART module clock */
  68.     CLK_EnableModuleClock(UART0_MODULE);

  69.     /* Enable PWM module clock */
  70.     CLK_EnableModuleClock(PWM01_MODULE);
  71.     CLK_EnableModuleClock(PWM23_MODULE);

  72.     /* Select UART module clock source */
  73.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));

  74.     /* Select PWM module clock source */
  75.     CLK_SetModuleClock(PWM01_MODULE, CLK_CLKSEL1_PWM01_S_HXT, 0);
  76.     CLK_SetModuleClock(PWM23_MODULE, CLK_CLKSEL1_PWM23_S_HXT, 0);

  77.     /* Reset PWMA channel0~channel3 */
  78.     SYS_ResetModule(PWM03_RST);

  79.     /* Update System Core Clock */
  80.     /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
  81.     //SystemCoreClockUpdate();
  82.     PllClock        = PLL_CLOCK;            // PLL
  83.     SystemCoreClock = PLL_CLOCK / 1;        // HCLK
  84.     CyclesPerUs     = PLL_CLOCK / 1000000;  // For SYS_SysTickDelay()

  85.     /*---------------------------------------------------------------------------------------------------------*/
  86.     /* Init I/O Multi-function                                                                                 */
  87.     /*---------------------------------------------------------------------------------------------------------*/
  88.     /* Set P3 multi-function pins for UART0 RXD and TXD  */
  89.     SYS->P3_MFP = SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0;
  90.     /* Set P2 multi-function pins for PWMA Channel0~3 */
  91.     SYS->P2_MFP = SYS_MFP_P20_PWM0 | SYS_MFP_P21_PWM1 | SYS_MFP_P22_PWM2 | SYS_MFP_P23_PWM3;
  92. }

  93. /*---------------------------------------------------------------------------------------------------------*/
  94. /*  Main Function                                                                                          */
  95. /*---------------------------------------------------------------------------------------------------------*/
  96. int32_t main(void)
  97. {
  98.     /* Init System, IP clock and multi-function I/O
  99.        In the end of SYS_Init() will issue SYS_LockReg()
  100.        to lock protected register. If user want to write
  101.        protected register, please issue SYS_UnlockReg()
  102.        to unlock protected register if necessary */

  103.     /* Unlock protected registers */
  104.     SYS_UnlockReg();

  105.     /* Init System, IP clock and multi-function I/O */
  106.     SYS_Init();

  107.     /* Lock protected registers */
  108.     SYS_LockReg();

  109.     /* Init UART to 115200-8n1 for print message */
  110.     UART_Open(UART0, 115200);
  111.     printf("+------------------------------------------------------------------------+\n");
  112.     printf("|                          PWM Driver Sample Code                        |\n");
  113.     printf("|                                                                        |\n");
  114.     printf("+------------------------------------------------------------------------+\n");
  115.     printf("  This sample code will output all PWMA channels with different\n");
  116.     printf("  frequency and duty, enable dead zone function of all PWMA pairs.\n");
  117.     printf("  And also enable/disable PWM output every 1 second.\n");
  118.     printf("  I/O configuration:\n");
  119.     printf("    waveform output pin: PWM0(P2.0), PWM1(P2.1), PWM2(P2.2), PWM3(P2.3)\n");

  120.     // PWM0 frequency is 100Hz, duty 30%,
  121.     PWM_ConfigOutputChannel(PWMA, PWM_CH0, 100, 30);
  122.     PWM_EnableDeadZone(PWMA, PWM_CH0, 400);

  123.     // PWM2 frequency is 300Hz, duty 50%
  124.     PWM_ConfigOutputChannel(PWMA, PWM_CH2, 300, 50);
  125.     PWM_EnableDeadZone(PWMA, PWM_CH2, 200);

  126.     // Enable output of all PWMA channels
  127.     PWM_EnableOutput(PWMA, 0xF);

  128.     // Enable PWMA channel 0 period interrupt, use channel 0 to measure time.
  129.     PWM_EnablePeriodInt(PWMA, PWM_CH0, 0);
  130.     NVIC_EnableIRQ(PWMA_IRQn);

  131.     // Start
  132.     PWM_Start(PWMA, 0xF);

  133.     while(1);

  134. }





 楼主| zhuotuzi 发表于 2017-1-27 11:33 | 显示全部楼层
可以看出这主要还是中断的一种应用。
 楼主| zhuotuzi 发表于 2017-1-27 11:34 | 显示全部楼层
中断作为单片机一个强大的打岔系统,真心强大。
 楼主| zhuotuzi 发表于 2017-1-27 11:37 | 显示全部楼层
void PWMA_IRQHandler(void)
{
    static uint32_t cnt;
    static uint32_t out;

    // Channel 0 frequency is 100Hz, every 1 second enter this IRQ handler 100 times.
    if(++cnt == 100)
    {
        if(out)
            PWM_EnableOutput(PWMA, 0xF);
        else
            PWM_DisableOutput(PWMA, 0xF);
        out ^= 1;
        cnt = 0;
    }
    // Clear channel 0 period interrupt flag
    PWM_ClearPeriodIntFlag(PWMA, 0);
}

 楼主| zhuotuzi 发表于 2017-1-27 12:18 | 显示全部楼层
每次操作寄存器都要解锁操作,完成锁定寄存器。
 楼主| zhuotuzi 发表于 2017-1-27 12:26 | 显示全部楼层
http://www.nuvoton.com/hq/produc ... &resourcePage=Y

新唐提供了PCB开发应用的资料。
wahahaheihei 发表于 2017-1-27 14:21 | 显示全部楼层
PWM输出时的Dead Zone(死区)作用是在电平翻转时插入一个时间间隔,避免关闭前一个设备和打开后一个设备时因为开关速度的问题出现同时开启状态而增加负荷的情况(在没有彻底关闭前打开了后一个设备),尤其是电流过大时容易造成短路等损坏设备,如:互补PWM波输出在逆变器(直流转交流)中的应用。
yiyigirl2014 发表于 2017-1-27 14:48 | 显示全部楼层
死区是不是就是互补到时候,什么都没了,都是0
dongnanxibei 发表于 2017-1-27 15:12 | 显示全部楼层
#define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
#define PLL_CLOCK           50000000
dongnanxibei 发表于 2017-1-27 15:13 | 显示全部楼层
通过宏可以简化很多地方,让调整时候更方便。
dongnanxibei 发表于 2017-1-27 15:26 | 显示全部楼层
#include "PWM.h"
#define EN_EXT_OSC       0
#define COMPLEMENT_MODE         0x00000020
#define DEAD_ZONE_INTERVAL      0xC8FF0000
#define PWM_ENABLE              0x01010101

#if     EN_EXT_OSC
#define PWM_CLOCK_SOURCE        0x00000000  //使用外部振荡12MHz
#else  
#define PWM_CLOCK_SOURCE        0xF0000000  //使用内部RC振荡22.1184MHz
#endif
#define PWM_PRESCALAE           0x0000C731  //PWM01预分频0x31(49),PWM23预分频0xC7(199)
#define PWM_CLOCK_DIVIDER       0x00004444  //输入时钟分频1
#define PWM_OUTPUT_INVERT       0x00040000
#define PWM_OUTPUT_ENABLE       0x0000000F   //PWM0、1、2、3输出使能
#define PWM_CMR_VALUE   0x0
#define PWM_CNR_VALUE       0x1000      //4096
/*
PWM频率=PWMxy_CLK/(prescale+1)*(clock divider)/(CNR+1)
(1)使用外部晶振12MHz
PWM频率=12000000/(49+1)*4097 =58.57Hz
(2)使用内部RC振荡22.1184MHz
PWM频率=22118400/(49+1)*4097 =107.97Hz
*/
#define LED_DARKING             0
#define LED_BRIGHTING   1
STATIC UINT32 g_unPWMCMRValue=PWM_CNR_VALUE;
STATIC UINT32 g_unLedStat=LED_DARKING;
/****************************************
*函数名称:PWMInit
*输    入:无
*输    出:无
*功    能:PWM初始化
******************************************/
VOID PWMInit(VOID)
{
    P2_MFP |= ~(P20_AD8_PWM0 | P21_AD9_PWM1 | P22_AD10_PWM2 | P23_AD11_PWM3);
P2_MFP |= (PWM0 | PWM1 | PWM2 | PWM3);   //使能P2.0~P2.3为PWM输出   
    P2_PMD &= ~Px0_PMD;                       //配置P2.0~P2.3为推挽输出
P2_PMD |= Px0_OUT;
P2_PMD &= ~Px1_PMD;
P2_PMD |= Px1_OUT;
P2_PMD &= ~Px2_PMD;
P2_PMD |= Px2_OUT;
P2_PMD &= ~Px3_PMD;
P2_PMD |= Px3_OUT;
    APBCLK |= PWM01_CLKEN | PWM23_CLKEN;                        //使能PWM0~3时钟
CLKSEL1 = PWM_CLOCK_SOURCE;                 //选择PWM0~3时钟源
   
PPRA = PWM_PRESCALAE | DEAD_ZONE_INTERVAL;                  //选择PWM0~3时钟预分频和死区间隔
    CSRA = PWM_CLOCK_DIVIDER;                                   //选择PWM0~3时钟分频
    PCRA = 0x08080808 | PWM_OUTPUT_INVERT | COMPLEMENT_MODE;    //PWM0~3自动重装载
    CNR0A = CNR1A = CNR2A = CNR3A = PWM_CNR_VALUE;              //PWM0~3计数值
    CMR0A = CMR1A = CMR2A = CMR3A = PWM_CMR_VALUE;              //PWM0~3比较值
    PIERA  |= PWMIE3 | PWMIE2 | PWMIE1 | PWMIE0 ;    //使能PWM0~3中断
    NVIC_ISER |= PWMA_INT;                                      //使能PWM0~3中断
    POEA = PWM_OUTPUT_ENABLE;                                   //PWM输出使能
    PCRA |= PWM_ENABLE;                                         //PWM使能,启动
}
/****************************************
*函数名称:PWMA_IRQHandler
*输    入:无
*输    出:无
*功    能:中断服务函数-PWMA
******************************************/
VOID PWMA_IRQHandler(VOID)
{
  switch(g_unLedStat)            //检查LED状态
  {
   case  LED_DARKING:         //LED状态渐暗
  {
    if(g_unPWMCMRValue < PWM_CNR_VALUE)
    {
     g_unPWMCMRValue+=50;
    }
    else
    {
       g_unLedStat = LED_BRIGHTING;
     g_unPWMCMRValue=PWM_CNR_VALUE;
    }  
  }break;
  case  LED_BRIGHTING:         //LED状态渐亮
  {
    if(g_unPWMCMRValue>=50)
    {
     g_unPWMCMRValue-=50;
    }
    else
    {
       g_unLedStat = LED_DARKING;
     g_unPWMCMRValue=PWM_CMR_VALUE;   
    }
  }break;
  default:break;  
  }
  CMR0A = CMR1A = CMR2A = CMR3A = g_unPWMCMRValue;  //设置PWM0~3比较值
     PIIRA = PIIRA;                           
}
/****************************************
*函数名称:main
*输    入:无
*输    出:无
*功    能:函数主体
******************************************/
INT32 main(VOID)
{
   PROTECT_REG                         //ISP下载时保护FLASH存储器
  (
   PWRCON |= XTL12M_EN;                   //默认时钟源为外部晶振
   while((CLKSTATUS & XTL12M_STB) == 0);                //等待12MHz时钟稳定  
   CLKSEL0 = (CLKSEL0 & (~HCLK)) | HCLK_12M;              //设置外部晶振为系统时钟
   PWMInit();              //PWM初始化
  )
     while(1);
}
稳稳の幸福 发表于 2017-1-27 15:32 | 显示全部楼层
PWM死区可以很好的起到控制作用。
稳稳の幸福 发表于 2017-1-27 15:33 | 显示全部楼层
Init System, IP clock and multi-function I/O
       In the end of SYS_Init() will issue SYS_LockReg()
       to lock protected register. If user want to write
       protected register, please issue SYS_UnlockReg()
       to unlock protected register if necessary
玛尼玛尼哄 发表于 2017-1-27 17:30 | 显示全部楼层
学习学习,这个控制电机,灯具都要用
wahahaheihei 发表于 2017-1-27 19:57 | 显示全部楼层
  //SystemCoreClockUpdate();
    PllClock        = PLL_CLOCK;            // PLL
    SystemCoreClock = PLL_CLOCK / 1;        // HCLK
    CyclesPerUs     = PLL_CLOCK / 1000000;  // For SYS_SysTickDelay
————————————————————————————————————
这个是不是为定时器用的?
 楼主| zhuotuzi 发表于 2017-1-28 09:06 | 显示全部楼层
例程中被注释的部分也很重要。可以帮助更好的修改程序。
稳稳の幸福 发表于 2017-1-28 12:59 | 显示全部楼层
每个参数怎么设置才是重点。
捉虫天师 发表于 2017-1-29 17:10 | 显示全部楼层
PWMA应该是PWM的A通道意思吧。
稳稳の幸福 发表于 2017-1-30 08:39 | 显示全部楼层
PWM_Start(PWMA, 0xF);
这里的0xF是什么意思
您需要登录后才可以回帖 登录 | 注册

本版积分规则

214

主题

3375

帖子

7

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