📄 example_6_pwm.c
字号:
//-----------------------------------------------------------------------------
// Example 6
// PWM using PCA High Speed Output Mode
//-----------------------------------------------------------------------------
// Copyright 2004 Silicon Laboratories Inc.
//
// AUTH: KAB
// DATE: 12MAR04
//
// This example demonstrates using the High Speed Output (HSO) mode to
// generate a PWM signal.
//
// The program reads the value of a potentiometer connected to P0.6 and uses
// this value to set the duty Cycle of the PWM. This example could be used
// to drive a dc motor.
//
// Target: C8051F30x
//
// Tool chain: KEIL Eval 'c'
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f300.h> // SFR declarations
//-----------------------------------------------------------------------------
// typedefs
//-----------------------------------------------------------------------------
typedef union // union used for writing to TL0 & TH0
{
struct
{
unsigned char hi;
unsigned char lo;
} b;
unsigned int w;
}udblbyte;
//-----------------------------------------------------------------------------
// MACROS (all caps)
//-----------------------------------------------------------------------------
#define SYSCLK 24500000 // SYSCLK frequency in Hz
#define PERIOD (SYSCLK/20000)
#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;
unsigned int NextEdge;
bit Cycle;
//-----------------------------------------------------------------------------
// 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 PCA interrupt
HiTime = y; // coherent update of global hitime
EIE1 |= 0x08; // enable PCA interrupt
}
}
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
void SYSCLK_Init (void)
{
OSCICN = 0x07; // configure for 24.5 MHz
RSTSRC = 0x04; // enable missing clock detector
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports.
// P0.0 - PWM - CEX0 - push-pull output
// P0.1 -
// P0.2 -
// P0.3 -
// P0.4 -
// P0.5 -
// P0.6 - Analog Input
// P0.7 -
//
void PORT_Init (void)
{
XBR0 = 0x00; // skip nothing
XBR1 = 0x40; // Enable CEX0 on P0.0
P0MDOUT = 0x01; // enable CEX0 as a push-pull output
P0MDIN = ~0x40; // enable ADC input on P0.6
XBR2 |= 0x40; // enable crossbar
}
//-----------------------------------------------------------------------------
// PCA0_Init
//-----------------------------------------------------------------------------
void PCA0_Init (void)
{
udblbyte output;
PCA0MD = 0x08; // PCA uses sysclk, no CF int
PCA0CPM0 = 0x4D; // High Speed Output Mode, enable ECCF0
PCA0L = 0x00; // reset the timer
PCA0H = 0x00;
output.w = PERIOD/2; // schedule first interrupt
PCA0CPL0 = output.b.lo;
PCA0CPH0 = output.b.hi;
NextEdge = PERIOD; // initialize NextEdge
EIE1 |= 0x08; // enable PCA0 interrupts
EIP1 |= 0x08; // set PCA to high priority
CR = 1; // start PCA0 timer
}
//-----------------------------------------------------------------------------
// PCA0_ISR
//-----------------------------------------------------------------------------
void PCA0_ISR (void) interrupt 9 using 1
{
static bit cycle = 0;
udblbyte output;
output.w = NextEdge;
PCA0CPL0 = output.b.lo; // write lo byte first
PCA0CPH0 = output.b.hi; // write hi byte second
PCA0CN &= ~0x87; // clear all PCA flags
if (cycle)
{
NextEdge += PERIOD;
NextEdge -= HiTime;
}
else
{
NextEdge += HiTime;
}
cycle = !cycle;
}
//-----------------------------------------------------------------------------
// ADC functions
//-----------------------------------------------------------------------------
void ADC0_Init (void)
{
ADC0CN = 0x00; // normal tracking mode;
// ADC0 conversions are initiated
// on writes to AD0BUSY;
AMX0SL = 0xf6; // select P0.6
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;
}
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 + -