📄 pwm.c
字号:
//*****************************************************************************
//
// pwm.c - API for the PWM modules
//
// Copyright (c) 2005-2007 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. Any use in violation
// of the foregoing restrictions may subject the user to criminal sanctions
// under applicable laws, as well as to civil liability for the breach of the
// terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 1234-conf of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************
//*****************************************************************************
//
//! \addtogroup pwm_api
//! @{
//
//*****************************************************************************
#include "../hw_ints.h"
#include "../hw_memmap.h"
#include "../hw_pwm.h"
#include "../hw_types.h"
#include "debug.h"
#include "interrupt.h"
#include "pwm.h"
//*****************************************************************************
//
// Misc macros for manipulating the encoded generator and output defines used
// by the API.
//
//*****************************************************************************
#define PWM_GEN_BADDR(_mod_, _gen_) \
((_mod_) + (_gen_))
#define PWM_OUT_BADDR(_mod_, _out_) \
((_mod_) + ((_out_) & 0xFFFFFFC0))
#define PWM_IS_OUTPUT_ODD(_out_) \
((_out_) & 0x00000001)
//*****************************************************************************
//
//! Configures a PWM generator.
//!
//! \param ulBase is the base address of the PWM module.
//! \param ulGen is the PWM generator to configure. Must be one of
//! \b PWM_GEN_0, \b PWM_GEN_1, or \b PWM_GEN_2.
//! \param ulConfig is the configuration for the PWM generator.
//!
//! This function is used to set the mode of operation for a PWM generator.
//! The counting mode, synchronization mode, and debug behavior are all
//! configured. After configuration, the generator is left in the disabled
//! state.
//!
//! A PWM generator can count in two different modes: count down mode or count
//! up/down mode. In count down mode, it will count from a value down to zero,
//! and then reset to the preset value. This will produce left-aligned PWM
//! signals (i.e. the rising edge of the two PWM signals produced by the
//! generator will occur at the same time). In count up/down mode, it will
//! count up from zero to the preset value, count back down to zero, and then
//! repeat the process. This will produce center-aligned PWM signals (i.e. the
//! middle of the high/low period of the PWM signals produced by the generator
//! will occur at the same time).
//!
//! When the PWM generator parameters (period and pulse width) are modified,
//! their affect on the output PWM signals can be delayed. In synchronous
//! mode, the parameter updates are not applied until a synchronization event
//! occurs. This allows multiple parameters to be modified and take affect
//! simultaneously, instead of one at a time. Additionally, parameters to
//! multiple PWM generators in synchronous mode can be updated simultaneously,
//! allowing them to be treated as if they were a unified generator. In
//! non-synchronous mode, the parameter updates are not delayed until a
//! synchronization event. In either mode, the parameter updates only occur
//! when the counter is at zero to help prevent oddly formed PWM signals during
//! the update (i.e. a PWM pulse that is too short or too long).
//!
//! The PWM generator can either pause or continue running when the processor
//! is stopped via the debugger. If configured to pause, it will continue to
//! count until it reaches zero, at which point it will pause until the
//! processor is restarted. If configured to continue running, it will keep
//! counting as if nothing had happened.
//!
//! The \b ulConfig parameter contains the desired configuration. It is the
//! logical OR of the following: \b PWM_GEN_MODE_DOWN or
//! \b PWM_GEN_MODE_UP_DOWN to specify the counting mode, \b PWM_GEN_MODE_SYNC
//! or \b PWM_GEN_MODE_NO_SYNC to specify the synchronization mode, and
//! \b PWM_GEN_MODE_DBG_RUN or \b PWM_GEN_MODE_DBG_STOP to specify the debug
//! behavior.
//!
//! \note Changes to the counter mode will affect the period of the PWM signals
//! produced. PWMGenPeriodSet() and PWMPulseWidthSet() should be called after
//! any changes to the counter mode of a generator.
//!
//! \return None.
//
//*****************************************************************************
void
PWMGenConfigure(unsigned long ulBase, unsigned long ulGen,
unsigned long ulConfig)
{
//
// Check the arguments.
//
ASSERT(ulBase == PWM_BASE);
ASSERT((ulGen == PWM_GEN_0) || (ulGen == PWM_GEN_1) ||
(ulGen == PWM_GEN_2));
//
// Compute the generator's base address.
//
ulGen = PWM_GEN_BADDR(ulBase, ulGen);
//
// Change the global configuration of the generator.
//
HWREG(ulGen + PWM_O_X_CTL) = ((HWREG(ulGen + PWM_O_X_CTL) &
~(PWM_X_CTL_MODE | PWM_X_CTL_DEBUG |
PWM_X_CTL_LOADUPD | PWM_X_CTL_CMPAUPD |
PWM_X_CTL_CMPBUPD)) | ulConfig);
//
// Set the individual PWM generator controls.
//
if(ulConfig & PWM_X_CTL_MODE)
{
//
// In up/down count mode, set the signal high on up count comparison
// and low on down count comparison (i.e. center align the signals).
//
HWREG(ulGen + PWM_O_X_GENA) = ((PWM_GEN_ACT_ONE <<
PWM_GEN_ACT_A_UP_SHIFT) |
(PWM_GEN_ACT_ZERO <<
PWM_GEN_ACT_A_DN_SHIFT));
HWREG(ulGen + PWM_O_X_GENB) = ((PWM_GEN_ACT_ONE <<
PWM_GEN_ACT_B_UP_SHIFT) |
(PWM_GEN_ACT_ZERO <<
PWM_GEN_ACT_B_DN_SHIFT));
}
else
{
//
// In down count mode, set the signal high on load and low on count
// comparison (i.e. left align the signals).
//
HWREG(ulGen + PWM_O_X_GENA) = ((PWM_GEN_ACT_ONE <<
PWM_GEN_ACT_LOAD_SHIFT) |
(PWM_GEN_ACT_ZERO <<
PWM_GEN_ACT_A_DN_SHIFT));
HWREG(ulGen + PWM_O_X_GENB) = ((PWM_GEN_ACT_ONE <<
PWM_GEN_ACT_LOAD_SHIFT) |
(PWM_GEN_ACT_ZERO <<
PWM_GEN_ACT_B_DN_SHIFT));
}
}
//*****************************************************************************
//
//! Set the period of a PWM generator.
//!
//! \param ulBase is the base address of the PWM module.
//! \param ulGen is the PWM generator to be modified. Must be one of
//! \b PWM_GEN_0, \b PWM_GEN_1, or \b PWM_GEN_2.
//! \param ulPeriod specifies the period of PWM generator output, measured
//! in clock ticks.
//!
//! This function sets the period of the specified PWM generator block, where
//! the period of the generator block is defined as the number of \b PWM
//! clock ticks between pulses on the generator block \b zero signal.
//!
//! \note Any subsequent calls made to this function before an update occurs
//! will cause the previous values to be overwritten.
//!
//! \return None.
//
//*****************************************************************************
void
PWMGenPeriodSet(unsigned long ulBase, unsigned long ulGen,
unsigned long ulPeriod)
{
//
// Check the arguments.
//
ASSERT(ulBase == PWM_BASE);
ASSERT((ulGen == PWM_GEN_0) || (ulGen == PWM_GEN_1) ||
(ulGen == PWM_GEN_2));
//
// Compute the generator's base address.
//
ulGen = PWM_GEN_BADDR(ulBase, ulGen);
//
// Set the reload register based on the mode.
//
if(HWREG(ulGen + PWM_O_X_CTL) & PWM_X_CTL_MODE)
{
//
// In up/down count mode, set the reload register to half the requested
// period.
//
ASSERT((ulPeriod / 2) < 65536);
HWREG(ulGen + PWM_O_X_LOAD) = ulPeriod / 2;
}
else
{
//
// In down count mode, set the reload register to the requested period
// minus one.
//
ASSERT((ulPeriod <= 65536) && (ulPeriod != 0));
HWREG(ulGen + PWM_O_X_LOAD) = ulPeriod - 1;
}
}
//*****************************************************************************
//
//! Gets the period of a PWM generator block.
//!
//! \param ulBase is the base address of the PWM module.
//! \param ulGen is the PWM generator to query. Must be one of
//! \b PWM_GEN_0, \b PWM_GEN_1, or \b PWM_GEN_2.
//!
//! This function gets the period of the specified PWM generator block. The
//! period of the generator block is defined as the number of \b PWM clock
//! ticks between pulses on the generator block \b zero signal.
//!
//! If the update of the counter for the specified PWM generator has yet
//! to be completed, the value returned may not be the active period. The
//! value returned is the programmed period, measured in \b PWM clock ticks.
//!
//! \return Returns the programmed period of the specified generator block
//! in \b PWM clock ticks.
//
//*****************************************************************************
unsigned long
PWMGenPeriodGet(unsigned long ulBase, unsigned long ulGen)
{
//
// Check the arguments.
//
ASSERT(ulBase == PWM_BASE);
ASSERT((ulGen == PWM_GEN_0) || (ulGen == PWM_GEN_1) ||
(ulGen == PWM_GEN_2));
//
// Compute the generator's base address.
//
ulGen = PWM_GEN_BADDR(ulBase, ulGen);
//
// Figure out the counter mode.
//
if(HWREG(ulGen + PWM_O_X_CTL) & PWM_X_CTL_MODE)
{
//
// The period is twice the reload register value.
//
return(HWREG(ulGen + PWM_O_X_LOAD) * 2);
}
else
{
//
// The period is the reload register value plus one.
//
return(HWREG(ulGen + PWM_O_X_LOAD) + 1);
}
}
//*****************************************************************************
//
//! Enables the timer/counter for a PWM generator block.
//!
//! \param ulBase is the base address of the PWM module.
//! \param ulGen is the PWM generator to be enabled. Must be one of
//! \b PWM_GEN_0, \b PWM_GEN_1, or \b PWM_GEN_2.
//!
//! This function allows the \b PWM clock to drive the timer/counter for the
//! specified generator block.
//!
//! \return None.
//
//*****************************************************************************
void
PWMGenEnable(unsigned long ulBase, unsigned long ulGen)
{
//
// Check the arguments.
//
ASSERT(ulBase == PWM_BASE);
ASSERT((ulGen == PWM_GEN_0) || (ulGen == PWM_GEN_1) ||
(ulGen == PWM_GEN_2));
//
// Enable the PWM generator.
//
HWREG(PWM_GEN_BADDR(ulBase, ulGen) + PWM_O_X_CTL) |= PWM_X_CTL_ENABLE;
}
//*****************************************************************************
//
//! Disables the timer/counter for a PWM generator block.
//!
//! \param ulBase is the base address of the PWM module.
//! \param ulGen is the PWM generator to be disabled. Must be one of
//! \b PWM_GEN_0, \b PWM_GEN_1, or \b PWM_GEN_2.
//!
//! This function blocks the \b PWM clock from driving the timer/counter for
//! the specified generator block.
//!
//! \return None.
//
//*****************************************************************************
void
PWMGenDisable(unsigned long ulBase, unsigned long ulGen)
{
//
// Check the arguments.
//
ASSERT(ulBase == PWM_BASE);
ASSERT((ulGen == PWM_GEN_0) || (ulGen == PWM_GEN_1) ||
(ulGen == PWM_GEN_2));
//
// Disable the PWM generator.
//
HWREG(PWM_GEN_BADDR(ulBase, + ulGen) + PWM_O_X_CTL) &= ~(PWM_X_CTL_ENABLE);
}
//*****************************************************************************
//
//! Sets the pulse width for the specified PWM output.
//!
//! \param ulBase is the base address of the PWM module.
//! \param ulPWMOut is the PWM output to modify. Must be one of \b PWM_OUT_0,
//! \b PWM_OUT_1, \b PWM_OUT_2, \b PWM_OUT_3, \b PWM_OUT_4, or \b PWM_OUT_5.
//! \param ulWidth specifies the width of the positive portion of the pulse.
//!
//! This function sets the pulse width for the specified PWM output, where the
//! pulse width is defined as the number of \b PWM clock ticks.
//!
//! \note Any subsequent calls made to this function before an update occurs
//! will cause the previous values to be overwritten.
//!
//! \return None.
//
//*****************************************************************************
void
PWMPulseWidthSet(unsigned long ulBase, unsigned long ulPWMOut,
unsigned long ulWidth)
{
unsigned long ulGenBase, ulReg;
//
// Check the arguments.
//
ASSERT(ulBase == PWM_BASE);
ASSERT((ulPWMOut == PWM_OUT_0) || (ulPWMOut == PWM_OUT_1) ||
(ulPWMOut == PWM_OUT_2) || (ulPWMOut == PWM_OUT_3) ||
(ulPWMOut == PWM_OUT_4) || (ulPWMOut == PWM_OUT_5));
//
// Compute the generator's base address.
//
ulGenBase = PWM_OUT_BADDR(ulBase, ulPWMOut);
//
// If the counter is in up/down count mode, divide the width by two.
//
if(HWREG(ulGenBase + PWM_O_X_CTL) & PWM_X_CTL_MODE)
{
ulWidth /= 2;
}
//
// Get the period.
//
ulReg = HWREG(ulGenBase + PWM_O_X_LOAD);
//
// Make sure the width is not too large.
//
ASSERT(ulWidth < ulReg);
//
// Compute the compare value.
//
ulReg = ulReg - ulWidth;
//
// Write to the appropriate registers.
//
if(PWM_IS_OUTPUT_ODD(ulPWMOut))
{
HWREG(ulGenBase + PWM_O_X_CMPB) = ulReg;
}
else
{
HWREG(ulGenBase + PWM_O_X_CMPA) = ulReg;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -