📄 example_7_cpwm.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 + -