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

📄 f50x_pca0_9-10-11bit_pwm_output.c

📁 C8051F500开发编程:MCU全部资源应用实例
💻 C
字号:
//-----------------------------------------------------------------------------
// F50x_PCA0_9-10-11Bit_PWM_Output.c
//-----------------------------------------------------------------------------
// Copyright 2008 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// This program sends a PWM waveform out of an I/O pin, using the PCA's
// 9/10/11-bit PWM Output Mode.  The duty cycle of the waveform is modified
// periodically within the main loop.
//
// In this example, PCA Module 0 is used to generate the waveform, and the
// crossbar is configured to send the CEX0 pin out on P0.0.
//
// How To Test:
// 
// 1) Change the BIT_MODE global constant to choose the correct mode
// 2) Download code to a F50x device which has an oscilloscope monitoring P0.0
//    If running on a 'F500 target board, remove the shorting block from the 
//    J22 header (Side A) or J32 header (Side B).
// 3) Run the program - the waveform should be visible on the oscilloscope.
// 4) Verify that the duty cycle of the waveform varies smoothly between
//    minimum and maximum values.
//
//
// Target:         C8051F500
// Tool chain:     Keil C51 8.0 / Keil EVAL C51
// Command Line:   None
//
//
// Release 1.0
//    -Initial Revision (ADT)
//    -09 JUNE 2008
//

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include <compiler_defs.h>
#include <C8051F500_defs.h>            // SFR declarations

//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------

#define SYSCLK       24000000          // Internal oscillator frequency in Hz
//Defines the number of bits used in Pulse Width Modulation.
//9 = 9 bit, 10 = 10 bit, 11 = 11 bit
#define BIT_MODE 9

#if(BIT_MODE == 9)
   
   #define  PWM_MODE 0x81              //Enable 9-bit PWM
   #define  BIT_VALUE 512
   #define  DELAY 6000                 //Arbitrary delay so it's smooth	    
   
 #elif(BIT_MODE == 10)
   
   #define  PWM_MODE 0x82              //Enable 10-bit PWM
   #define  BIT_VALUE 1024
   #define  DELAY 4000
   
 #elif(BIT_MODE == 11)
   
   #define  PWM_MODE 0x83              //Enable 11-bit PWM 
   #define  BIT_VALUE 2048
   #define  DELAY 2000

#else

   #error "Invalid value for BIT_MODE."
 
#endif

//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void PORT_Init (void);
void PCA0_Init (void);
INTERRUPT_PROTO (PCA0_ISR, INTERRUPT_PCA0);

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

U16 CEX0_Compare_Value;                // Holds current PCA compare value

//-----------------------------------------------------------------------------
// main() Routine
//-----------------------------------------------------------------------------

void main (void)
{
   U16 delay_count;                    // Used to implement a delay
   bit duty_direction = 0;             // 0 = Decrease; 1 = Increase

   SFRPAGE = ACTIVE_PAGE;

   PCA0MD = 0x00;                      // Disable watchdog timer

   PORT_Init ();                       // Initialize crossbar and GPIO
   OSCILLATOR_Init ();                 // Initialize oscillator
   PCA0_Init ();                       // Initialize PCA0

   EA = 1;                             // Globally enable interrupts

   while (1)
   {
      // Wait a little while
      for (delay_count = DELAY; delay_count > 0; delay_count--);

      if (duty_direction == 1)         // Direction = Increase
      {
         // First, check the ECOM0 bit
         if ((PCA0CPM0 & 0x40) == 0x00)
         {
            PCA0CPM0 |= 0x40;          // Set ECOM0 if it is '0'
         }
         else                          // Increase duty cycle otherwise
         {
            CEX0_Compare_Value--;      // Increase duty cycle

            if (CEX0_Compare_Value == 0x0000)
            {
               duty_direction = 0;     // Change direction for next time
            }
         }
      }
      else                             // Direction = Decrease
      {
         if (CEX0_Compare_Value == (BIT_VALUE - 1)) //Check for overflow
         {
            PCA0CPM0 &= ~0x40;         // Clear ECOM0
            duty_direction = 1;        // Change direction for next time
         }
         else
         {
            CEX0_Compare_Value++;      // Decrease duty cycle
         }
      }

   }
}


//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function initializes the system clock to use the internal oscillator
// at 24 MHz.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
   U8 SFRPAGE_save = SFRPAGE;
   SFRPAGE = CONFIG_PAGE;

   OSCICN = 0x87;                      // Set internal oscillator to run
                                       // at its maximum frequency
   SFRPAGE = SFRPAGE_save;
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function configures the crossbar and GPIO ports.
//
// P0.0   digital   push-pull     PCA0 CEX0
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
   U8 SFRPAGE_save = SFRPAGE;
   SFRPAGE = CONFIG_PAGE;

   P0MDOUT |= 0x01;                    // Set CEX0 (P0.0) to push-pull

   XBR1    = 0x04;                     // Enable CEX0 on crossbar
   XBR2    = 0x40;                     // Enable crossbar and weak pull-ups

   SFRPAGE = SFRPAGE_save;
}

//-----------------------------------------------------------------------------
// PCA0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
// This function configures the PCA time base, and sets up 9/10/11-bit PWM 
// output mode for Module 0 (CEX0 pin).
//
// The frequency of the PWM signal generated at the CEX0 pin is equal to the
// PCA main timebase frequency divided by 512/1024/2048 respectively.
//
// The PCA time base in this example is configured to use SYSCLK, and SYSCLK
// is set up to use the internal oscillator running at 24.5 MHz.  Therefore,
// the frequency of the PWM signal will be:

// 9  bits => 24.5 MHz / 512  = 47.851 KHz
// 10 bits => 24.5 MHz / 1024 = 23.926 KHz
// 11 bits => 24.5 MHz / 2048 = 11.963 KHz

// Using different PCA clock sources or a different processor clock will
// result in a different frequency for the PWM signal.
//
//    -------------------------------------------------------------------------
//    How "9/10/11-Bit PWM Mode" Works:
//
//       The PCA's 9/10/11-bit PWM Mode works by setting an output pin low 
//    every time the main n-bits in the PCA counter (PCA0H) overflows, and 
//    then setting the pin high whenever a specific match condition is met.
//
//    Upon a PCA0 nth-bit overflow (PCA0 incrementing from 0x01FF to 0x0000),
//    the CEXn pin will be set low.
//
//    When the PCA0 register increments and matches the PCA0CPn register for
//    the selected module, the CEXn pin will be set high, except when the
//    ECOMn bit in PCA0CPMn is cleared to '0'.  By varying the value of the
//    PCA0CPn register, the duty cycle of the waveform can also be varied.
//
//    When ECOMn = '1', the duty cycle of the PWM waveform is:
//
//       9-bit PWM Duty Cycle = ( 512 - PCA0CPn) / 512
//      10-bit PWM Duty Cycle = (1024 - PCA0CPn) / 1024
//      11-bit PWM Duty Cycle = (2048 - PCA0CPn) / 2048
//
//    To set the duty cycle to 100%, a value of 0x0000 should be loaded into
//    the PCA0CPn register for the module being used (with ECOMn set to '1').
//    When the value of PCA0CPn is equal to 0x0000, the pin will never be
//    set low.
//
//    To set the duty cycle to 0%, the ECOMn bit in the PCA0CPMn register
//    should be cleared to 0.  This prevents the PCA0CPn match from occuring,
//    which results in the pin never being set high.
//
// The duty cycle of the PWM output signal in 9/10/11-bit PWM mode should be 
// varied by writing to an "Auto-Reload" Register, which is dual-mapped into 
// the PCA0CPHn and PCA0CPLn register locations. The data written to define 
// the duty cycle should be right-justified in the registers. The auto-reload 
// registers are accessed (read or written) when the bit ARSEL in PCA0PWM is 
// set to 

⌨️ 快捷键说明

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