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

📄 example_4_bldc.c

📁 CYGNAL单片机
💻 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 + -