📄 example_3_dc.c
字号:
//-----------------------------------------------------------------------------
// Example 3
// DC Motor Control with Soft Reversing
//-----------------------------------------------------------------------------
// Copyright 2004 Silicon Laboratories Inc.
//
// AUTH: KAB
// DATE: 12MAR04
//
// This program provides dc motor control with reversing control using the PCA
// 8-bit PWM Mode. A single PCA module is used to generate an 8-bit PWM. The
// pin skip register XBR0 is used to multiplex the PWM between two outputs
// P0.0 and P0.1. These two outputs are used to drive the lower transistors in
// an H-Bridge configuration. P0.2 and P0.3 are used to drive the upper
// transistors.
//
// The ADC is used to read the potentiometer voltage on P0.6. The ADC uses
// polled mode and 64 sample averaging.
//
// The ADC is also used to sense the motor voltage during reversal. When the
// Reverse pushbutton is pressed, the PWM duty will be set to zero. The
// differential voltage across the motor is measured. The once this voltage
// drops below a limit, the upper transistors are reversed and the PWM will be
// applied to the other phase.
//
// Target: C8051F30x
//
// Tool chain: KEIL Eval 'c'
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f300.h> // SFR declarations
//-----------------------------------------------------------------------------
// Typdefs
//-----------------------------------------------------------------------------
typedef union // union used for writing to TL0 & TH0
{
struct
{
unsigned char hi;
unsigned char lo;
} b;
unsigned int w;
}udblbyte;
//-----------------------------------------------------------------------------
// MACROS
//-----------------------------------------------------------------------------
#define VWINDOW (5*256/100) // set window to +/- 5%
#define DTIME (245000/48) // set delay time to 10 ms per sample
#define GSAMP 10 // stop for 10 good samples (100ms)
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void SYSCLK_Init (void); // Initialize SYSCLK
void PORT_Init (void); // Initialize XBR and Port Pins
void PCA0_Init (void); // Initialize PCA0
void ADC0_Init (void); // Initialize ADC
void Timer_Init (void);
unsigned char readVin(void); // read ADC using polling
unsigned char avgVin(void); // returns avg ADC reading
void coast (void); // disable PWM and outputs
void detectStop(void); // wait for motor to stop
void reverse (void);
void delay(unsigned int);
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
bit Fwd;
sbit SW1 = P0^7;
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void)
{
PCA0MD &= ~0x40; // Disable Watchdog Timer
SYSCLK_Init (); // Initialize system clock
PORT_Init (); // Initialize crossbar and GPIO
ADC0_Init(); // Initialize ADC for polled mode
PCA0_Init (); // PCA0 for 8-bit PWM
Timer_Init();
Fwd = 1;
EA = 1; // enable global interrupts
while (1)
{
if(SW1)
{
PCA0CPH0 = avgVin(); // get avg reading and output to PWM
}
else
{
coast();
while(!SW1); // wait for button
detectStop();
reverse();
}
}
}
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
void SYSCLK_Init (void)
{
OSCICN = 0x07; // configure internal oscillator for
RSTSRC = 0x06; // enable missing clock detector
// and VDD Monitor.
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports.
// P0.0 - /Abot - active low PWM signal drives bottom transistor
// P0.1 - /Bbot - active low PWM signal drives bottom transistor
// P0.2 - /Atop - active low signal drives top transistor
// P0.3 - /Abot - active low signal drives top transistor
// P0.4 - VA
// P0.5 - VB
// P0.6 - Vin
// P0.7 - Switch
//
void PORT_Init (void)
{
XBR0 = 0x70; // skip P0.4, P0.5, & P0.6
XBR1 = 0x40; // Enable CEX0 on P0.0
P0MDOUT = 0x0f; // P0.0 - P0.4 are push-pull outputs
P0MDIN = ~0x70; // Configure P0.6 for analog input
XBR2 = 0x40; // Enable crossbar
P0 = ~0x08; // P0.3 low
}
//-----------------------------------------------------------------------------
// PCA0_Init
//-----------------------------------------------------------------------------
void PCA0_Init (void)
{
PCA0MD = 0x02; // PCA uses sysclk/4, no interrupt
PCA0CPM0 = 0x42; // Module 0, 8-bit PWM Mode
PCA0L = 0x00; // reset the timer
PCA0H = 0x00;
PCA0CPL0 = 0x00;
PCA0CPH0 = 0x00; // Initialize to minimum duty
CR = 1; // Start PCA0 timer
}
//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
void ADC0_Init (void)
{
ADC0CN = 0x40; // Low-power tracking mode;
// ADC0 conversions are initiated
// on writes to AD0BUSY;
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
}
//-----------------------------------------------------------------------------
// Timer_Init
//-----------------------------------------------------------------------------
void Timer_Init (void)
{
CKCON = 0x02; // T0 uses sysclk/48
TMOD = 0x01; // T0 mode 1, 16-bit counter
}
//-----------------------------------------------------------------------------
// read_Vin()
//-----------------------------------------------------------------------------
unsigned char readVin(void)
{
AD0INT = 0; // clear ADC0 end-of-conversion
AD0BUSY = 1; // initiate conversion
while (!AD0INT); // wait for conversion to complete
return ADC0;
}
//-----------------------------------------------------------------------------
// detectStop()
//-----------------------------------------------------------------------------
void detectStop(void)
{
unsigned char g;
AMX0SL = 0x54; // select P0.4 - P0.5
g = 0;
while (g < GSAMP) // wait for GSAMP good samples
{
AD0INT = 0; // clear ADC0 end-of-conversion
AD0WINT = 0; // clear window detector
AD0BUSY = 1; // initiate conversion
while (!AD0INT); // wait for conversion to complete
if(AD0WINT)
g++; // count number of good samples
else
g=0; // start over if outside window
delay(DTIME); // wait 10 ms
}
AMX0SL = 0xf6; // select P0.6, single ended
}
//-----------------------------------------------------------------------------
// avgVin()
//-----------------------------------------------------------------------------
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
}
//-----------------------------------------------------------------------------
// coast()
//-----------------------------------------------------------------------------
void coast(void)
{
PCA0CPH0 = 0; // disable PWM
P0 = 0xff; // force all outputs high
}
//-----------------------------------------------------------------------------
// reverse()
//-----------------------------------------------------------------------------
void reverse (void)
{
Fwd=!Fwd;
CR = 0; // Stop PCA0 timer
PCA0CPH0 = 0; // clear duty cycle
PCA0CPM0 = 0; // disable PWM
P0 = 0xff; // all high
XBR2 &= ~0x40; // disable Crossbar
if (Fwd)
{
XBR0 = ~0x01; // don't skip P0.0
P0 = ~0x08; // P0.3 low
}
else
{
XBR0 = ~0x02; // don't skip P0.1
P0 = ~0x04; // P0.2 low
}
XBR2 |= 0x40; // enable Crossbar
PCA0CPM0 = 0x42; // Module 0, 8-bit PWM Mode
CR = 1; // restart PCA0 timer
}
//-----------------------------------------------------------------------------
// delay()
//-----------------------------------------------------------------------------
void delay(unsigned int d)
{
udblbyte t;
TR0 = 0; // stop Timer0
t.w = -d; // take 2's complement
TL0 = t.b.lo; // write lo byte first
TH0 = t.b.hi; // write hi byte second
TF0 = 0; // clear overflow flag
TR0 = 1; // start Timer0
while(!TF0); // wait for overflow
TR0 = 0; // stop timer
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -