⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ect_pwm.c

📁 移植到freescale 9s12系列单片机的uCOSII
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
*********************************************************************************************************
*                                      BOARD SUPPORT PACKAGE (BSP)
*                                         Frescale MC9S12
*
* File          : bsp.c
* By            : Eric Shufro
* Data          : 2/25/2007
* Description   : This file contains the source code necessary to implement Freescale application
*                 note AN2612, initially written by G.More/M.Gallop, on 1/10/03. AN2612 describes
*                 a method for implementing PWM channels in software via the ECT / TIM module on
*                 MC9S12 derivates that either do not have a hardware PWM, or do not have enough
*                 PWM channels to suite your application. The original source code provided in
*                 AN2612 required additional changes in order to provide portable data types,
*                 variable clock and ECT prescaler settings, and error checking.
*********************************************************************************************************
*/

#include <ect_pwm.h>

/*
*********************************************************************************************************
*                                MACROS
*********************************************************************************************************
*/

#ifdef   TIOS_IOS0_MASK                                                 /* These macros configure the software PWM for the number   */
#define  ECT_NBR_CHANNELS  8                                            /* of possible ECT channels. This value is determined by    */                                                                                                                
#else                                                                   /* checking the processor include file for TIOS_IOS0_MASK   */
#define  ECT_NBR_CHANNELS  4                                            /* which is only defined on parts that have 8 ECT channels. */
#define  TCTL2 TCTL1                                                    /* Ensure compilation on 4 channel devices, define TCTL2    */
#endif                                                                  /* to ensure compilation. Else, only channels 4-7 exist     */

#define  ECT_DIS           0                                            /* Indexes into the ECT_PWM_DisLast[][index] array          */
#define  ECT_LAST          1                                            

/*
*********************************************************************************************************
*                                GLOBALS
*********************************************************************************************************
*/

CPU_INT32U   Period[8];
CPU_INT32U   Mark[8];
CPU_INT32U   Space[8];
CPU_BOOLEAN  ECT_PWM_DisLast[8][2];                                     /* [channel][0] = Disable Bit, [channel][1] = Last Bit      */

/*
*********************************************************************************************************
*                                         ECT_PWM_Init()
*
* Description : This function initializes an ECT compare channel for use as a software PWM channel.
*               The specified channel number must be valid and not already running. This
*               function must be called before calling ECT_PWM_CfgChannel(). This function
*               DOES NOT start the specified PWM channel.
*
* Arguments   : channel,            The ECT and SW PWM channel to configure (0-7)
*                                   or (4-7) depending on the derivative
*                
*               pol                 The output pin polarity after the 1st toggle
*                                   ECT_PWM_POL_LOW  = Init output pin to 0, toggle thereafter
*                                   ECT_PWM_POL_HIGH = Init output pin to 1, toggle thereafter
* 
* Returns     : ECT_PWM_ERR_NONE,   No error has occured.
*               ECT_PWM_ERR_CHA,    Error. An invalid channel number was specified
*               ECT_PWM_ERR_RESV,   Error. The reserved channel number was specified
*               ECT_PWM_ERR_POL,    Error. An invalid polarity setting was specified
*               ECT_PWM_ERR_RUN,    Error. The specified channel is already running.
*********************************************************************************************************
*/

CPU_INT08U  ECT_PWM_Init (CPU_INT08U  channel, CPU_INT08U  pol) 
{
    CPU_INT08U  omn_bit;
    CPU_INT08U  oln_bit;
    CPU_INT16U *ptcn;
    
        
    if (channel > 7) {
        return (ECT_PWM_ERR_CHA);                                       /* Channel number > 7 is invalid                            */
    }
    
    if ((ECT_NBR_CHANNELS == 4) && (channel < 4)) {                     /* Only 4 channels, 4-7, supported on this derivative       */
        return (ECT_PWM_ERR_CHA);
    }
    
    if ((channel == 7) && (ECT_PWM_ERR_RESV > 0)) {
        return (ECT_PWM_ERR_RESV);                                      /* Invalid channel number. Channel 7 is reserved            */
    }

    if ((pol != ECT_PWM_POL_LOW) && (pol != ECT_PWM_POL_HIGH)) {        /* Return an error if an invalid polarity is specified      */
        return (ECT_PWM_ERR_POL);    
    }
    
    if ((TIE & (1 << channel)) > 0) {                                   /* Is PWM already running? If so return an error since the  */
        return (ECT_PWM_ERR_RUN);                                       /* must be safely stopped before changing channel settings  */
    }
    
                                                                        /* Initialize the PWM parameters                            */
    ECT_PWM_DisLast[channel][ECT_DIS]   =  0;                           /* PWM channel is not disabled                              */
    
    TIOS        |=   (1 << channel);                                    /* Set desired ECT channel to output compare mode           */
    
    if (channel >= 4) {                                                 /* Determine initial polarity of PWM channel                */
        oln_bit  =  ((channel - 4) * 2);                                /* Determine OLn bit position of desired channel            */
        omn_bit  =   (oln_bit + 1);                                     /* Determine OMn bit position of desired channel            */
        TCTL1   &=  ~((1 << omn_bit) | (1   << oln_bit));               /* Clear pin polarity bits                                  */
        TCTL1   |=    (1 << omn_bit) | (pol << oln_bit);                /* Set the initial pin polarity after the first compare     */
    } else {
        oln_bit  =   (channel * 2);                                     /* Determine OLn bit position of desired channel            */
        omn_bit  =   (oln_bit + 1);                                     /* Determine OMn bit position of desired channel            */
        TCTL2   &=  ~((1 << omn_bit) | (1   << oln_bit));               /* Clear pin polarity bits                                  */
        TCTL2   |=    (1 << omn_bit) | (pol << oln_bit);                /* Set the initial pin polarity after the first compare     */
    }
    
    TSCR1       |=   (TSCR1_TEN_MASK    |                               /* Ensure that the ECT timer is running,                    */
                      TSCR1_TSWAI_MASK);                                /* timer runs in wait mode,                                 */                      
                      
    return (ECT_PWM_ERR_NONE);                                          /* Return without error                                     */                         
}

/*
*********************************************************************************************************
*                                         ECT_PWM_CfgChannel()
*
* Description : This function starts the specified PWM channel. The specified channel number
*               must be valid, and may already be in the running state. This function may
*               be called multiple times during runtime in order to change the running
*               characteristics of the specified PWM channel. A call to ECT_PWM_Init() must
*               occur for the specified channel before calling this function.
*
* Arguments   : channel,            The ECT and SW PWM channel to configure (0-7)
*                                   or (4-7) depending on the derivative
*                
*               duty                The desired duty cycle, values 0 - 100, in percent.
*
*               frq_hz,             The desired PWM channel frequency.
* 
* Returns     : ECT_PWM_ERR_NONE,   No error has occured.
*               ECT_PWM_ERR_CHA,    Error. An invalid channel number was specified
*               ECT_PWM_ERR_RESV,   Error. The reserved channel number was specified
*               ECT_PWM_ERR_DUTY,   Error. An invalid duty cycle was specified.
*               ECT_PWM_ERR_FRQ,    Error. The specified PWM frequency is not obtainable
*                                   given the current bus frequency and prescaler values.
*
* Notes       : 1) For values of duty close to 0 or 100, it may be impossible to acheive an interrupt
*                  since the current ECT / TIM counter (TNCT) + Space[channel] or + Mark[channel]
*                  may be too close to the current value of TCNT when either Space[channel] or
*                  Mark[channel] are close to 0 (eg 0% or 100% duty cycle). Therefore, setting
*                  TCNT + 0 for example would NOT cause another interrupt right after the current
*                  interrupt because changing the value of the match register, TCn takes time, and
*                  the counter will have already passed the current match or small future match
*                  value. This results in an extended Mark or Space period that is highly excessive
*                  in length. Example:
*
*                      if TCNT = 100, and the next match value is set to 101, after writing
*                      101 to the TCn register, TCNT may equal 108. The next match occurs after 
*                      65535 - 108 + 101 ticks. 
*
*                  Therefore, values close to 0 or 100 % duty cycle are considered OFF values
*                  for the PWM, where the final state of the pin is either logic level LOW for
*                  values near 0% duty cycle, or logic level HIGH for values near 100% duty cycle.
*********************************************************************************************************
*/

CPU_INT08U  ECT_PWM_CfgChannel (CPU_INT08U channel, CPU_INT08U duty, CPU_INT16U frq_hz)
{
    CPU_INT32U  busclk_frq;
    CPU_INT32U  ECT_curr_frq;
    CPU_INT08U  ECT_prescaler;
               

    if (channel > 7) {
        return (ECT_PWM_ERR_CHA);                                       /* Channel number > 7 is invalid                            */
    }
    
    if ((ECT_NBR_CHANNELS == 4) && (channel < 4)) {                     /* Only 4 channels, 4-7, supported on this derivative       */
        return (ECT_PWM_ERR_CHA);
    }
    
    if ((channel == 7) && (ECT_PWM_ERR_RESV > 0)) {
        return (ECT_PWM_ERR_RESV);                                      /* Invalid channel number. Channel 7 is reserved            */
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -