📄 example_4_bldc.c
字号:
//-----------------------------------------------------------------------------
// Example 4
// BLDC Motor Control
//-----------------------------------------------------------------------------
// Copyright 2004 Silicon Laboratories Inc.
//
// AUTH: KAB
// DATE: 12MAR04
//
// This program provides Brushless DC motor 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 three outputs P1.0,
// P1.1, & P1.2 These three outputs are used to drive the lower transistors in
// an 3-Phase Bridge configuration. P0.4, P0.5, & P0.6 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.
//
// P0.0, P0.1, and P0.2 are used for hall effect sensor inputs. This pins are
// polled to determine the rotor position. The readHalls() function requires
// three identical samples and returns the hall code. The corresponding state
// of the motor is found from the HallPattern. This state is then used to
// commutate the motor.
//
// It is safe to single-step and use breakpoints ONLY with the motor wires
// disconnected. Do not single step through the code with the motor wires
// connected! The PWM outputs may remain active while the CPU is stopped.
// In particular do not single step past the lines that enable the PWM.
// These lines are marked with comments in ALL CAPS.
//
// Target: C8051F33x
//
// Tool chain: KEIL Eval 'c'
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f330.h> // SFR declarations
//-----------------------------------------------------------------------------
// MACROS
//-----------------------------------------------------------------------------
#define GSAMP 3
//-----------------------------------------------------------------------------
// Hall-effect and commutation patterns
//-----------------------------------------------------------------------------
const unsigned char code hallPattern[7]=
{ 0x00, 0x01, 0x03, 0x02, 0x06, 0x04, 0x05};
const unsigned char code skipPattern[7]=
{~0x01,~0x01,~0x01,~0x02,~0x02,~0x04,~0x04};
const unsigned char code P1Pattern[7]=
{~0x00,~0x20,~0x40,~0x40,~0x10,~0x10,~0x20};
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void SYSCLK_Init (void);
void PORT_Init (void);
void PCA0_Init (void);
void PCA0_ISR (void);
void ADC_Init (void);
unsigned char readVin(void);
unsigned char avgVin(void);
unsigned char readHalls(void);
unsigned char hallPosition(void);
void commutate(unsigned char);
void coast(void);
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void) {
unsigned char h,p;
bit start;
PCA0MD &= ~0x40; // Disable Watchdog Timer
SYSCLK_Init (); // initialize system clock
PORT_Init (); // initialize i/o
PCA0_Init (); // configure PCA0 to 8-bit PWM
ADC_Init(); // initialize i/o
EA = 1; // enable global interrupts
p = 0; // clear p
start = 1; // set start bit
while (1)
{
h = hallPosition(); // h equals hall position
if(h) // if good position
{
if ((h != p)||(start)) // if new position or start
{
p = h; // update p
// DO NOT SINGLE-STEP PAST THE NEXT
// LINE WITH MOTOR WIRES CONNECTED!!!
commutate(p); // commutate motor, enables PWM
start = 0;
}
PCA0CPH0 = avgVin(); // get avg reading and output to PWM
}
else
{
coast(); // coast until good reading
start = 1; // set start bit to restart motor
}
}
}
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
void SYSCLK_Init (void)
{
OSCICN = 0x83; // configure for 24.5 MHz
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports.
// P0.0 - HA
// P0.1 - HB
// P0.2 - HC
// P0.3 -
// P0.4 -
// P0.5 -
// P0.6 -
// P0.7 - Vin - analog input
//
// P1.0 - Abottom - push-pull output
// P1.1 - Bbot - push-pull output
// P1.2 - Cbot - push-pull output
// P1.3 -
// P1.4 - Atop - push-pull output
// P1.5 - Btop - push-pull output
// P1.6 - Ctop - push-pull output
// P1.7 -
//
void PORT_Init (void)
{
XBR0 = 0x00; // enable nothing on XBR0
XBR1 = 0x01; // enable PCA CEX0
P0SKIP = 0xFF; // skip all pins on P0
P0MDIN =~0x80; // P0.7 analog input
P1SKIP =~0x01; // skip all except P1.0
P1MDOUT = 0x77; // enable P1 outputs
XBR1 |= 0x40; // enable crossbar
P1 = 0xff; // P1 all high
}
//-----------------------------------------------------------------------------
// PCA0_Init
//-----------------------------------------------------------------------------
void PCA0_Init (void)
{
PCA0MD = 0x02; // PCA uses sysclk/4, no CF int
PCA0CPM0 = 0x00; // clear mode, pin high
PCA0L = 0x00; // reset the timer
PCA0H = 0x00;
PCA0CPH0 = 0x00; // initial to 0%
CR = 1; // START PCA0 timer
}
//-----------------------------------------------------------------------------
// coast function
//-----------------------------------------------------------------------------
void coast(void)
{
PCA0CPM0 = 0x00; // disable PWM
P1 = 0xff; // disable upper transistors
}
//-----------------------------------------------------------------------------
// readHalls function
//-----------------------------------------------------------------------------
// reads and debounces Hall-Sensor inputs
unsigned char readHalls(void)
{
unsigned char g,h,i;
g = 0;
h = 0;
while (g<GSAMP) // while less that 3 good samples
{
i = P0 & 0x07; // read halls
if (h == i) // if the same
g++; // one more good
else
g = 0; // else start over
h = i; // update h
}
return h; // return good hall code
}
//-----------------------------------------------------------------------------
// hallPosition function
//-----------------------------------------------------------------------------
unsigned char hallPosition (void)
{
unsigned char h,p;
h = readHalls(); // get debounced hall reading
// find corresponding pattern index
for (p=6;(h != hallPattern[p])&&(p!=0);p--);
return p;
}
//-----------------------------------------------------------------------------
// hallPosition function
//-----------------------------------------------------------------------------
void commutate (unsigned char i)
{
PCA0CPM0 = 0x00; // disable PWM
P1 = 0xFF;
XBR1 &= ~0x40; // disable crossbar
P1SKIP = skipPattern[i];
P1 = P1Pattern[i];
XBR1 |= 0x40; // enable crossbar
// DO NOT SINGLE-STEP PAST THE NEXT
// LINE WITH MOTOR WIRES CONNECTED!!!
PCA0CPM0 = 0x42; // enable 8-bit PWM mode
}
//-----------------------------------------------------------------------------
// ADC functions
//-----------------------------------------------------------------------------
void ADC_Init(void)
{
AMX0P = 0x07; // positive input P0.7
AMX0N = 0x11; // single ended mode
ADC0CF = 0xC4; // 1MHz clock, left justified
ADC0CN = 0x80; // configure ADC for polled mode
REF0CN = 0x08; // use Vdd as ADC full scale
}
unsigned char readVin(void)
{
AD0INT = 0; // clear ADC0 end-of-conversion
AD0BUSY = 1; // initiate conversion
while (!AD0INT); // wait for conversion to complete
return ADC0H;
}
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 + -