打印
[DemoCode下载]

PMW死区控制

[复制链接]
1687|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhuotuzi|  楼主 | 2017-1-27 11:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
* $Revision: 4 $
* $Date: 14/02/10 3:06p $
* [url=home.php?mod=space&uid=247401]@brief[/url]    M051 Series PWM Generator and Capture Timer Driver Sample Code
*
* @note
* Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "M051Series.h"

/*---------------------------------------------------------------------------------------------------------*/
/* Macro, type and constant definitions                                                                    */
/*---------------------------------------------------------------------------------------------------------*/

#define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
#define PLL_CLOCK           50000000


/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/

/**
* @brief       PWMA IRQ Handler
*
* @param       None
*
* [url=home.php?mod=space&uid=266161]@return[/url]      None
*
* [url=home.php?mod=space&uid=1543424]@Details[/url]     ISR to handle PWMA interrupt event
*/
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);
}

void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Enable Internal RC clock */
    CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

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

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

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

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

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

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

    /* Enable UART module clock */
    CLK_EnableModuleClock(UART0_MODULE);

    /* Enable PWM module clock */
    CLK_EnableModuleClock(PWM01_MODULE);
    CLK_EnableModuleClock(PWM23_MODULE);

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

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

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

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

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

/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
    /* 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 */

    /* Unlock protected registers */
    SYS_UnlockReg();

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

    /* Lock protected registers */
    SYS_LockReg();

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

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

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

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

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

    // Start
    PWM_Start(PWMA, 0xF);

    while(1);

}





沙发
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);
}

使用特权

评论回复
5
zhuotuzi|  楼主 | 2017-1-27 12:18 | 只看该作者
每次操作寄存器都要解锁操作,完成锁定寄存器。

使用特权

评论回复
6
zhuotuzi|  楼主 | 2017-1-27 12:26 | 只看该作者
http://www.nuvoton.com/hq/produc ... &resourcePage=Y

新唐提供了PCB开发应用的资料。

使用特权

评论回复
7
wahahaheihei| | 2017-1-27 14:21 | 只看该作者
PWM输出时的Dead Zone(死区)作用是在电平翻转时插入一个时间间隔,避免关闭前一个设备和打开后一个设备时因为开关速度的问题出现同时开启状态而增加负荷的情况(在没有彻底关闭前打开了后一个设备),尤其是电流过大时容易造成短路等损坏设备,如:互补PWM波输出在逆变器(直流转交流)中的应用。

使用特权

评论回复
8
yiyigirl2014| | 2017-1-27 14:48 | 只看该作者
死区是不是就是互补到时候,什么都没了,都是0

使用特权

评论回复
9
dongnanxibei| | 2017-1-27 15:12 | 只看该作者
#define PLLCON_SETTING      CLK_PLLCON_50MHz_HXT
#define PLL_CLOCK           50000000

使用特权

评论回复
10
dongnanxibei| | 2017-1-27 15:13 | 只看该作者
通过宏可以简化很多地方,让调整时候更方便。

使用特权

评论回复
11
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);
}

使用特权

评论回复
12
稳稳の幸福| | 2017-1-27 15:32 | 只看该作者
PWM死区可以很好的起到控制作用。

使用特权

评论回复
13
稳稳の幸福| | 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

使用特权

评论回复
14
玛尼玛尼哄| | 2017-1-27 17:30 | 只看该作者
学习学习,这个控制电机,灯具都要用

使用特权

评论回复
15
wahahaheihei| | 2017-1-27 19:57 | 只看该作者
  //SystemCoreClockUpdate();
    PllClock        = PLL_CLOCK;            // PLL
    SystemCoreClock = PLL_CLOCK / 1;        // HCLK
    CyclesPerUs     = PLL_CLOCK / 1000000;  // For SYS_SysTickDelay
————————————————————————————————————
这个是不是为定时器用的?

使用特权

评论回复
16
zhuotuzi|  楼主 | 2017-1-28 09:06 | 只看该作者
例程中被注释的部分也很重要。可以帮助更好的修改程序。

使用特权

评论回复
17
稳稳の幸福| | 2017-1-28 12:59 | 只看该作者
每个参数怎么设置才是重点。

使用特权

评论回复
18
捉虫天师| | 2017-1-29 17:10 | 只看该作者
PWMA应该是PWM的A通道意思吧。

使用特权

评论回复
19
稳稳の幸福| | 2017-1-30 08:39 | 只看该作者
PWM_Start(PWMA, 0xF);
这里的0xF是什么意思

使用特权

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

本版积分规则

197

主题

3267

帖子

7

粉丝