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

📄 example_3_dc.c

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