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

📄 example_7_cpwm.c

📁 CYGNAL单片机
💻 C
字号:
//-----------------------------------------------------------------------------
// Example 7
// Center-Aligned PWM with Dead-Time
//-----------------------------------------------------------------------------
// Copyright 2004 Silicon Laboratories Inc.
//
// AUTH: KAB
// DATE: 12MAR04
//
// This program reads the voltage at P0.6 and outputs center-aligned PWM
// with dead-time on P0.1 and P0.2.
//
// Target: C8051F30x
//
// Tool chain: KEIL Eval 'c'
//

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f300.h>                 // sfr declarations

typedef union                          // union used for writing to PCA0CPxx
    {
        struct
        {
            unsigned char hi;
            unsigned char lo;
        } b;
        unsigned int w;
    }udblbyte;
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------

#define SYSCLK       24500000          // SYSCLK frequency in Hz
#define PERIOD (SYSCLK/20000/2)
#define DEADTIME 25                    // desired dead-time in clocks
#define LATENCY 45                     // worst case latency in clocks
#define HTSPAN (PERIOD - 2*LATENCY)    // high-time span

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

unsigned int HiTime;                   // global PWM high-time
unsigned int nextEdge0;                // CEX0 next edge time
unsigned int nextEdge1;                // CEX1 next edge time
unsigned int nextEdge2;                // CEX2 next edge time

//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------

void SYSCLK_Init (void);
void PORT_Init (void);
void PCA0_Init (void);
void PCA0_ISR (void);
void ADC0_Init (void);
unsigned char readVin(void);
unsigned char avgVin(void);

//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------

void main (void)
{

   unsigned long x;
   unsigned int y;



   PCA0MD &= ~0x40;                    // Disable Watchdog Timer

   SYSCLK_Init ();                     // Initialize system clock to                                          // 24.5MHz internal oscillator
   PORT_Init ();                       // Initialize crossbar and GPIO
   PCA0_Init ();
   ADC0_Init();

   EA = 1;                             // enable global interrupts

   while (1)
   {
      x = avgVin();                    // get avg. ADC reading
      x *= HTSPAN;                     // multiply by span
      y = x>>8;                        // through away low byte
      y += LATENCY;                    // add minimum latency
      EIE1    &= ~0x08;                // disable interrupt while updating
      HiTime =  y;                     // coherent update of global hitime
      EIE1    |= 0x08;                 // re-enable interrupt
   }
}

//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------

void SYSCLK_Init (void)
{
   OSCICN = 0x07;                      // 24.5MHz internal oscillator
   RSTSRC = 0x04;                      // enable missing clock detector
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports.
// P0.0 - CEX0
// P0.1 - CEX1
// P0.2 - CEX2
// P0.3 -
// P0.4 -
// P0.5 -
// P0.6 - Analog Input
// P0.7 - C2D
//

void PORT_Init (void)
{
   XBR0     =  0x00;                   // skip nothing
   XBR1     =  0xC0;                   // Enable CEX0-2 on P0.0-2
   P0MDOUT |=  0x07;                   // enable CEX0-2 as a push-pull output
   P0MDIN   = ~0x40;                   // configure P0.6 for analog input
   XBR2     =  0x40;                   // Enable crossbar

}

//-----------------------------------------------------------------------------
// PCA0_Init
//-----------------------------------------------------------------------------

void PCA0_Init (void)
{
   udblbyte output;                    // used to write to PCA0CPxx

   PCA0MD = 0x08;                      // use system clock
   PCA0CN = 0x00;                      // clear PCA control register

   //Module 0
   PCA0CPM0 = 0x4D;                    // HSO mode, enable interrupts
   output.w = PERIOD;                  // schedule first low-high transition
   PCA0CPL0 = output.b.lo;             // for one full period
   PCA0CPH0 = output.b.hi;

   //Module 1
   PCA0CPM1 = 0x4C;                    // HSO mode, disable interrupts
   output.w = (PERIOD/2+DEADTIME);     // schedule first low-high transition
   PCA0CPL1 = output.b.lo;             // before CEX0 sets polarity to
   PCA0CPH1 = output.b.hi;             // low on CEX0 H-L transition

   //Module 2
   PCA0CPM2 = 0x4C;                    // HSO mode, disable interrupts
   output.w = (2*PERIOD);              // schedule first low-high transition
   PCA0CPL2 = output.b.lo;             // after CEX0 sets polarity to
   PCA0CPH2 = output.b.hi;             // high on CEX0 H-L transition


   HiTime = PERIOD/2;                  // init HighTime to 50%
   nextEdge0 = (2*PERIOD);             // init next CEX0 to 50
   nextEdge1 = (3*PERIOD/2-DEADTIME);  // init next CEX1 and subtract DT
   nextEdge2 = (3*PERIOD/2+DEADTIME);  // init next CEX1 and add DT

   PCA0L  = 0x00;                      // clear PCA Low Byte
   PCA0H  = 0x00;                      // clear PCA High Byte

   EIP1 |= 0x08;                       // set PCA to high priority
   EIE1 |= 0x08;                       // Enable PCA0, interrupts

   CR = 1;                             // start PCA0 timer
}

//-----------------------------------------------------------------------------
// PCA0_ISR
//-----------------------------------------------------------------------------

void PCA0_ISR (void) interrupt 9 using 1
{
   static bit cycle = 0;

   udblbyte output;
   unsigned int t ;

   output.w = nextEdge1;               // output next edge on CEX1
   PCA0CPL1 = output.b.lo;
   PCA0CPH1 = output.b.hi;
   output.w = nextEdge2;               // output next edge on CEX2
   PCA0CPL2 = output.b.lo;
   PCA0CPH2 = output.b.hi;
   output.w = nextEdge0;               // output next edge on CEX0
   PCA0CPL0 = output.b.lo;
   PCA0CPH0 = output.b.hi;
   PCA0CN &= ~0x87;                    // clear all PCA flags

   cycle = !cycle;                     // toggle Cycle
   if (cycle)
   {
      nextEdge0 += PERIOD;             // pre-increment nextEdge0
      t = nextEdge0 - HiTime;          // calculate next edges
      nextEdge1 = t + (LATENCY/2 + DEADTIME);
      nextEdge2 = t + (LATENCY/2 - DEADTIME);
   }
   else
   {
      t = nextEdge0 + HiTime;          // calculate next edges
      nextEdge1 = t + (LATENCY/2 - DEADTIME);
      nextEdge2 = t + (LATENCY/2 + DEADTIME);
      nextEdge0 += PERIOD;             // post increment nextEdge0
   }
}

//-----------------------------------------------------------------------------
// ADC functions
//-----------------------------------------------------------------------------

void ADC0_Init (void)
{
   ADC0CN = 0x00;                      // use polled mode
   AMX0SL = 0xf6;                      // select P0.6, single ended
   ADC0CF = 0x81 ;                     // AD0SC=4, gain =1
   REF0CN = 0x0a;                      // ADC uses Vdd for full scale
   EIE1 &= ~0x04;                      // disable ADC0 EOC interrupt
   AD0EN = 1;                          // enable ADC
}

unsigned char readVin(void)
{
   AD0INT = 0;                         // clear ADC0 end-of-conversion
   AD0BUSY = 1;                        // initiate conversion
   while (!AD0INT);                    // wait for conversion to complete
   return ADC0;                        // return reading
}

unsigned char avgVin(void)
{
   unsigned char i, result;
   unsigned int sum;

   sum = 0;
   for (i = 64; i != 0; i--)           // repeat 64 times
   {
      sum += readVin();                // read ADC and add to sum
   }
   result = (unsigned char)(sum>>6);   // divide by 64 and cast to uchar
   return result;                      // return average reading
}

⌨️ 快捷键说明

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