📄 brushed_dc_motor.c
字号:
/**********************************************************************
* *
* Software License Agreement *
* *
* The software supplied herewith by Microchip Technology *
* Incorporated (the "Company") for its dsPIC controller *
* is intended and supplied to you, the Company's customer, *
* for use solely and exclusively on Microchip dsPIC *
* products. The software is owned by the Company and/or its *
* supplier, and is protected under applicable copyright laws. All *
* rights are reserved. Any use in violation of the foregoing *
* restrictions may subject the user to criminal sanctions under *
* applicable laws, as well as to civil liability for the breach of *
* the terms and conditions of this license. *
* *
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO *
* WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, *
* BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND *
* FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE *
* COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, *
* INCIDENTAL OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. *
* *
**********************************************************************/
/**********************************************************************
* *
* Author: Steve Bowling *
* *
* Filename: Brush_DC_Motor.c *
* Date: 2/21/03 *
* File Version: 1.00 *
* *
* Tools used: MPLAB GL -> 6.12.02 *
* Compiler -> 1.10 beta *
* Assembler -> *
* Linker -> *
* *
* Linker File: p30f6010.gld *
* *
* *
***********************************************************************
* Code Description
*
* This file demonstrates simple open loop control of a brush-DC
* motor using the Microchip motor control demo hardware. Two of
* the three motor control power module phases are used as an H
* bridge to drive the motor bi-directional.
**********************************************************************/
#include "c:\pic30_tools\support\h\p30F6010.h"
/*********************** START OF DEFINITIONS *******************/
// These are the pushbutton pin connections for the motor control PCB.
#define BUTTON1 !PORTGbits.RG6
#define BUTTON2 !PORTGbits.RG7
#define BUTTON3 !PORTGbits.RG8
#define BUTTON4 !PORTGbits.RG9
// This is the control line for the driver IC on the
// motor control PCB. It must be low to activate
// the PWM drive signals to the power module.
#define PWM_OUTPUT_ENABLE PORTDbits.RD11
// PFC switch firing line
#define PFC_FIRE PORTDbits.RD5
// BRAKE circuit firing line
#define BRAKE_FIRE PORTDbits.RD4
// This is the fault reset line for the motor power module.
// The dsPIC must generate an active high pulse to clear any
// of the red fault LEDs on the power module.
#define FAULT_RESET PORTEbits.RE9
// This is the fault input line from the power module. This
// line is connected to the PWM Fault A input pin (RE8).
#define FAULT_INPUT PORTEbits.RE8
// This is the interrupt flag for the PWM Fault A input. It is
// renamed for convenience.
#define FLTA_FLAG IFS2bits.FLTAIF
// These are the LEDs
#define LED4 PORTAbits.RA15
#define LED3 PORTAbits.RA14
#define LED2 PORTAbits.RA10
#define LED1 PORTAbits.RA9
// These are the counting periods for the medium and slow speed events.
// Count variables are decremented at each PWM interrupt.
#define SLOW_EVENT_PERIOD 1600 // 100msec period for 16KHz PWM
#define MEDIUM_EVENT_PERIOD 72 // 5msec period for 16KHz PWM
//---------------------------------------------------------------------
// This bit structure provides status flags for the software
struct {
unsigned :1;
unsigned Reverse:1;
unsigned Button1:1;
unsigned Button2:1;
unsigned Button3:1;
unsigned Button4:1;
unsigned DirChange:1;
unsigned Accelerate:1;
unsigned PWMFault:1;
unsigned Restart:1;
unsigned :1;
unsigned :1;
unsigned :1;
unsigned PWMEvent:1;
unsigned MediumEvent:1;
unsigned SlowEvent:1;
} Flags;
// This is a software counter used to time slower system events, such as
// button polling, etc.
unsigned int SlowEventCount, MediumEventCount;
// This variable holds the A/D
unsigned int Speed, OldSpeed;
//----------------------------------------------------------------------
void Setup(void); // Initializes dsPIC and peripherals
int ReadADC(unsigned int channel);
void __attribute__((__interrupt__)) _PWMInterrupt(void);
void Delay(unsigned int count);
//---------------------------------------------------------------------
main ( void )
{
Setup();
while(1)
{
ClrWdt(); // Clear the watchdog timer
// This code is executed after each PWM interrupt occurs.
// The PWM ISR sets PWMflag to signal the interrupt.
if(Flags.PWMEvent)
{
// If no direction change or restart is happening,
// the motion profile is not executing, so just read the pot value
// to get the speed setting.
if((Flags.DirChange == 0) && (Flags.Restart == 0))
{
// Get the speed setting from the potentiometer
Speed = ReadADC(7);
// Limit the range of duty cycles.
if(Speed > 800) Speed = 800;
}
// Write the duty cycles to the PWM module.
if(Flags.Reverse)
{
PDC1 = PTPER - (Speed >> 2);
PDC2 = PTPER + (Speed >> 2);
}
else
{
PDC1 = PTPER + (Speed >> 2);
PDC2 = PTPER - (Speed >> 2);
}
Flags.PWMEvent = 0;
} // end if(PWMEvent)
//-----------------------------------------------------------------
// Medium speed event handler executes every 5msec
//-----------------------------------------------------------------
if(Flags.MediumEvent)
{
// This is the main loop code that responds to a fault event
// signalled by the fault ISR. Here, we just turn on a status
// LED to let the user know that the fault occurred.
// The fault condition is reset when Button 1 is pressed.
if(Flags.PWMFault)
{
LED1 = 1;
Flags.PWMFault = 0;
}
// This is the 'motion profile'. If a direction change is
// requested, this code will ramp down the speed setting,
// reverse the motor, then slowly ramp it back up.
if(Flags.DirChange)
{
if(Flags.Accelerate)
{
// If we're back to our old speed, we're done!
// Clear the DirChange flag
if(Speed == OldSpeed)
{
Flags.DirChange = 0;
LED4 = 0;
}
// Otherwise, speed up
else Speed++;
}
// Otherwise, slow down
else Speed--;
// Has the speed ramped down to 0?
// If so, set the acceleration flag and reverse the direction.
if(Speed == 0)
{
Flags.Accelerate = 1;
Flags.Reverse = ~Flags.Reverse;
}
}
if(Flags.Restart)
{
if(Speed == OldSpeed) Flags.Restart = 0;
else Speed++;
}
Flags.MediumEvent = 0;
} //end if(MediumEvent)
//-----------------------------------------------------------------
// Slow event handler executes every 100msec
//-----------------------------------------------------------------
if(Flags.SlowEvent)
{
// These statements check to see if any of the buttons are pressed.
// If so, a software flag is set so the button press can be debounced.
if(BUTTON1) Flags.Button1 = 1;
if(BUTTON2) Flags.Button2 = 1;
if(BUTTON3) Flags.Button3 = 1;
if(BUTTON4) Flags.Button4 = 1;
// If button #1 is pressed, a reset signal will be sent to the
// power module to clear any fault LEDs that are lit.
// The fault A interrupt flag is also cleared to reactivate
// the dsPIC MCPWM.
if(Flags.Button1)
{
// Wait until the button is released before doing anything.
if(!BUTTON1)
{
// Reset the speed variable. Save the old speed for use
// in the restart profile.
OldSpeed = Speed;
Speed = 0;
// Set the duty cycles back to 50% and set a restart flag.
PDC1 = PTPER;
PDC2 = PTPER;
Flags.Restart = 1;
// Turn the PWM output back on that was disabled in the FLTA ISR
OVDCON = 0x0F00;
// Turn off the status LED
LED1 = 0;
// Reset the power module.
FAULT_RESET = 1;
Nop();
Nop();
Nop();
FAULT_RESET = 0;
// Clear the button status flag.
Flags.Button1 = 0;
}
}
// Button2 doesn't do anything except light the LED
if(Flags.Button2)
{
LED2 = 1;
if(!BUTTON2)
{
LED2 = 0;
Flags.Button2 = 0;
}
}
// Button2 doesn't do anything except light the LED
if(Flags.Button3)
{
LED3 = 1;
if(!BUTTON3)
{
LED3 = 0;
Flags.Button3 = 0;
}
}
// Button #4 is used to set the direction of the motor.
if(Flags.Button4)
{
// Wait until the button is released before doing anything.
// Start a direction change if one is not already in progress.
if(!BUTTON4 && !Flags.DirChange)
{
LED4 = 1;
// Set the direction change flag.
Flags.DirChange = 1;
// Tell the motion profile to decelerate the motor
Flags.Accelerate = 0;
// Save the current Speed setting
OldSpeed = Speed;
// Clear the button status flag
Flags.Button4 = 0;
}
}
Flags.SlowEvent = 0;
} // end if(SlowEvent)
} // end while(1)
} // end main
//---------------------------------------------------------------------
void Setup(void)
{
// Initialize variables
Speed = 0;
OldSpeed = 0;
SlowEventCount = SLOW_EVENT_PERIOD;
MediumEventCount = MEDIUM_EVENT_PERIOD;
// Initialize PORTs
PORTA = 0;
PORTB = 0; // Initialize PORTs
PORTC = 0;
PORTD = 0;
PORTE = 0;
PORTG = 0;
TRISA = 0x39FF;
TRISB = 0xFFFF;
TRISC = 0xFFFF;
TRISD = 0xF7CF; // RD11 is output for PWM_OUTPUT_ENABLE line
// RD5 is PFC_FIRE line
// RD4 is BRAKE_FIRE line
TRISE = 0xFDFF; // RE9 is output for FAULT_RESET line
TRISG = 0xFFFF;
// Initialize PWM
PTPER = 230; // Value gives 16KHZ center aligned PWM at 7.38MIPS
PDC1 = PTPER;
PDC2 = PTPER;
PDC3 = 0;
PDC4 = 0;
PWMCON1 = 0x0033; // Enable PWM 1,2 pairs for complementary mode
DTCON1 = 0x000F; // Value provides 2us dead time at 7.38 MIPS
DTCON2 = 0;
FLTACON = 0x0003; // Fault A enabled for latched mode on PWM1, 2
FLTBCON = 0; // Fault B not used.
OVDCON = 0x0F00; // Enable PWM1H,1L, 2H, and 2L for PWM
PTCON = 0x8002; // Enable PWM for center aligned operation
IFS2bits.PWMIF = 0;
IEC2bits.PWMIE = 1; // Enable PWM interrupts.
IFS2bits.FLTAIF = 0;// Clear the fault A interrupt flag.
IEC2bits.FLTAIE = 1;// Enable interrupts for Fault A
// Initialize ADC
ADCON1 = 0;
ADCON2 = 0;
ADCON3 = 0;
ADPCFG = 0;
ADCHS = 0x0007;
ADCON1bits.ADON = 1;
// Reset any active faults on the motor control power module.
FAULT_RESET = 1;
// Initialize SPI1 for slave mode
SPI1CON = 0x0040; // Slave mode, CKP = 1
SPI1STAT = 0x8000; // Enable SPI
FAULT_RESET = 0;
// Enable the driver IC on the motor control PCB
PWM_OUTPUT_ENABLE = 0;
// Ensure PFC switch is off.
PFC_FIRE = 0;
// Turn brake off.
BRAKE_FIRE = 0;
// Ensure FLTA flag is cleared
FLTA_FLAG = 0;
}
//---------------------------------------------------------------------
int ReadADC(unsigned int channel)
{
int Delay;
if(channel > 0x000F) return(0);
ADCHS = channel;
ADCON1bits.SAMP = 1;
for(Delay = 0; Delay < 20; Delay++);
IFS0bits.ADIF = 0;
ADCON1bits.SAMP = 0;
while(!IFS0bits.ADIF);
return(ADCBUF0);
}
//---------------------------------------------------------------------
// The PWM ISR just sets a software flag to trigger SVM calculations
// in the main software loop.
void __attribute__((__interrupt__)) _PWMInterrupt(void)
{
SlowEventCount--;
if(SlowEventCount == 0)
{
Flags.SlowEvent = 1;
SlowEventCount = SLOW_EVENT_PERIOD;
}
MediumEventCount--;
if(MediumEventCount == 0)
{
Flags.MediumEvent = 1;
MediumEventCount = MEDIUM_EVENT_PERIOD;
}
Flags.PWMEvent = 1;
IFS2bits.PWMIF = 0;
}
//---------------------------------------------------------------------
// The FLTA ISR responds to events on the PWM fault pin.
// This ISR code just turns off all the PWM outputs via the OVDCON
// register and signals the main loop that a problem has occurred.
void __attribute__((__interrupt__)) _FLTAInterrupt(void)
{
// Keep all outputs disabled until we figure out what is going on!
OVDCON = 0;
// Signal a fault to the main loop.
Flags.PWMFault = 1;
// Clear the FLTA interrupt flag.
IFS2bits.FLTAIF = 0;
}
//---------------------------------------------------------------------
// This is a generic delay routine
void Delay(unsigned int count)
{
unsigned int j;
for(j=0;j<count;j++);
}
// end of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -