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

📄 brushed_dc_motor.c

📁 一个单片机控制有刷电机的C代码
💻 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 + -