?? bldc.c
字號:
GPIOPinIntClear(HALL_PORT, HALL_A | HALL_B | HALL_C); // // Perform commutation if the motor is running. // if(g_iRunning == MOTOR_RUNNING) { // // Get the current Hall effect sensor state. // ulHall = (GPIOPinRead(HALL_PORT, HALL_A | HALL_B | HALL_C) >> HALL_SHIFT); // // Get the set of PWM signals to be driven. // ulPWM = g_pulHallToPhase[ulHall]; // // If drive direction is reversed, then invert the PWM signals. This // will reverse the current direction through the motor. // if(g_bReverse) { if(ulPWM & PHASE_A) { ulPWM ^= PHASE_A; } if(ulPWM & PHASE_B) { ulPWM ^= PHASE_B; } if(ulPWM & PHASE_C) { ulPWM ^= PHASE_C; } } // // Set the PWM signals to be driven. // PWMOutputState(PWM_BASE, ulPWM ^ (PHASE_A | PHASE_B | PHASE_C), false); PWMOutputState(PWM_BASE, ulPWM, true); }}//*****************************************************************************////! Configure the GPIO block to read from the Hall effect sensors.//!//! This function performs the setup on the GPIO block in order to properly//! interface with the Hall effect sensors on the motor. The GPIO pins are//! configured as inputs with both edge interrupt generation, and an interrupt//! handler is installed to handle the interrupts caused by a change in the//! Hall effect sensor state.//!//! \return None.////*****************************************************************************static voidSetupGPIO(void){ // // Configure the Hall effect GPIO pins as inputs with interrupt generation // on both rising and falling edges. // GPIODirModeSet(HALL_PORT, HALL_A | HALL_B | HALL_C, GPIO_DIR_MODE_IN); GPIOIntTypeSet(HALL_PORT, HALL_A | HALL_B | HALL_C, GPIO_BOTH_EDGES); // // Enable the Hall effect GPIO pin interrupts. // GPIOPinIntEnable(HALL_PORT, HALL_A | HALL_B | HALL_C); IntEnable(HALL_INT); // // Changes in the hall effect sensors are the highest priority, so set the // interrupt priority to the highest. // IntPrioritySet(HALL_INT, 0x00);}//*****************************************************************************////! Configure the PWM block to drive the motor.//!//! This function performs the setup on the PWM block in order to properly//! driver the windings of the motor. The three generators are configured to//! run at the same rate and are synchronized. All six outputs are disabled,//! non-inverted, and set to disable on fault conditions.//!//! \return None.////*****************************************************************************static voidSetupPWM(void){ // // Enable the PWM peripheral. // SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM); // // Set the PWM clock divider. // SysCtlPWMClockSet(PWMDIV); // // Make the appropriate GPIO pins be PWM outputs instead of GPIO. // GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_HW); GPIODirModeSet(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_HW); GPIODirModeSet(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_HW); // // Set the PWM outputs to a non-inverted state with the signal disabled // during fault conditions. // PWMOutputInvert(PWM_BASE, PHASE_A | PHASE_B | PHASE_C, false); PWMOutputFault(PWM_BASE, PHASE_A | PHASE_B | PHASE_C, true); // // Disable the PWM outputs. // PWMOutputState(PWM_BASE, PHASE_A | PHASE_B | PHASE_C, false); // // Configure and enable the generators. // PWMGenConfigure(PWM_BASE, PWM_GEN_0, (PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_DBG_STOP)); PWMGenConfigure(PWM_BASE, PWM_GEN_1, (PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_DBG_STOP)); PWMGenConfigure(PWM_BASE, PWM_GEN_2, (PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_DBG_STOP)); PWMGenEnable(PWM_BASE, PWM_GEN_0); PWMGenEnable(PWM_BASE, PWM_GEN_1); PWMGenEnable(PWM_BASE, PWM_GEN_2); // // Set the period of each generator timer. // PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, g_ulPwmPeriod); PWMGenPeriodSet(PWM_BASE, PWM_GEN_1, g_ulPwmPeriod); PWMGenPeriodSet(PWM_BASE, PWM_GEN_2, g_ulPwmPeriod); // // Set the initial pulse width of the PWM signals to zero. // PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, 0); PWMPulseWidthSet(PWM_BASE, PWM_OUT_1, 0); PWMPulseWidthSet(PWM_BASE, PWM_OUT_2, 0); PWMPulseWidthSet(PWM_BASE, PWM_OUT_3, 0); PWMPulseWidthSet(PWM_BASE, PWM_OUT_4, 0); PWMPulseWidthSet(PWM_BASE, PWM_OUT_5, 0); // // Synchronize the timers. // PWMSyncUpdate(PWM_BASE, PWM_GEN_0_BIT | PWM_GEN_1_BIT | PWM_GEN_2_BIT); PWMSyncTimeBase(PWM_BASE, PWM_GEN_0_BIT | PWM_GEN_1_BIT | PWM_GEN_2_BIT);}//*****************************************************************************////! Sets the duty cycle of the PWM outputs.//!//! \param ulDutyCycle is the duty cycle for the outputs, specified in clocks.//!//! This function will synchronously update the duty cycle of the PWM outputs//! to the specified value.//!//! \return None.////*****************************************************************************static voidSetPWMDutyCycle(unsigned long ulDutyCycle){ // // Set the PWM duty cycle for each of the PWM outputs. // PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, ulDutyCycle); PWMPulseWidthSet(PWM_BASE, PWM_OUT_1, ulDutyCycle); PWMPulseWidthSet(PWM_BASE, PWM_OUT_2, ulDutyCycle); PWMPulseWidthSet(PWM_BASE, PWM_OUT_3, ulDutyCycle); PWMPulseWidthSet(PWM_BASE, PWM_OUT_4, ulDutyCycle); PWMPulseWidthSet(PWM_BASE, PWM_OUT_5, ulDutyCycle); // // Synchronously update them all now. // PWMSyncUpdate(PWM_BASE, PWM_GEN_0_BIT | PWM_GEN_1_BIT | PWM_GEN_2_BIT);}//*****************************************************************************////! Interrupt handler for the QEI edge interrupt.//!//! This function is called whenever an edge is seen on the GPIO connected to//! the optical encoder. It simply counts the number of edges seen.//!//! \return None.////*****************************************************************************voidEdgeIntHandler(void){ // // Clear the GPIO interrupt. // GPIOPinIntClear(GPIO_PORTC_BASE, GPIO_PIN_4); // // Increment the count of edges. // g_ulVelCount++;}//*****************************************************************************////! Interrupt handler for the QEI interrupt.//!//! This function is called whenever the QEI interrupt occurs. In open-loop//! operation, it takes care of spinning down the motor when a stop has been//! requested. In closed-loop operation, it adjusts the PWM duty cycle based//! on the measured speed of the motor by appyling a PID control algorithm. In//! either mode, it takes care of reversing the direction of rotation when//! requested by the user.//!//! \return None.////*****************************************************************************voidQEIIntHandler(void){ char pcBuffer[6]; long lDelta; // // Clear the QEI interrupt. // if(g_bSoftwareQEI) { TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } else { QEIIntClear(QEI_BASE, QEI_INTTIMER); } // // Capture the encoder edge count. // if(g_bSoftwareQEI) { lDelta = g_ulVelCount * 4; g_ulVelCount = 0; } else { lDelta = QEIVelocityGet(QEI_BASE); } // // Increment the count of QEI interrupts. // g_ulSpeedCount++; // // Get the speed of the motor and convert it from pulses per 1/100th of a // second into rpm. // g_ulSpeed = lDelta = (lDelta * 100 * 60) / (ENCODER_LINES * 4); // // Check the motor running state. // if(g_iRunning == MOTOR_STOPPING) { // // The motor is stopping, and the high side switches have been turned // off. A delay time has expired, so move to the next state. // g_iRunning = MOTOR_STOP_DELAY; // // There is nothing further to do. // return; } else if(g_iRunning == MOTOR_STOP_DELAY) { // // The motor is stopping, and the delay time has expired, so the motor // is now stopped. // g_iRunning = MOTOR_STOPPED; // // Turn on the low side switches. This will cause the motor to brake. // PWMOutputInvert(PWM_BASE, PWM_OUT_1_BIT | PWM_OUT_3_BIT | PWM_OUT_5_BIT, true); // // There is nothing further to do. // return; } // // Update the PWM duty cycle if the motor is being driven closed-loop. // if(!g_bOpenLoop) { // // Compute a new duty cycle delta. // lDelta = PIDUpdate(&g_sPID, lDelta, g_ulTarget - lDelta); // // Update the PWM duty cycle. // lDelta = g_ulBaseDutyCycle + (lDelta / 10000); if(lDelta < 5) { lDelta = 5; } if(lDelta > (g_ulPwmPeriod - 5)) { lDelta = g_ulPwmPeriod - 5; } SetPWMDutyCycle(lDelta); } // // See if debug mode is enabled. // if(g_bDebug) { // // Print the current speed measurement to the user interface. // lDelta = g_ulSpeed; pcBuffer[0] = '0' + ((lDelta / 1000) % 10); pcBuffer[1] = '0' + ((lDelta / 100) % 10); pcBuffer[2] = '0' + ((lDelta / 10) % 10); pcBuffer[3] = '0' + (lDelta % 10); pcBuffer[4] = ' '; pcBuffer[5] = '\0'; UIDisplay(pcBuffer); }}//*****************************************************************************////! Configure the QEI block to read the motor speed.//!//! This function performs the setup on the QEI block in order to measure the//! speed of the motor. The positional information from the QEI block is not//! used, only the speed.//!//! \return None.////*****************************************************************************static voidSetupQEI(void){ // // See if this part has a QEI peripheral. // if(SysCtlPeripheralPresent(SYSCTL_PERIPH_QEI)) { // // Disable software QEI. // g_bSoftwareQEI = false; // // Enable the QEI peripheral. // SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI); // // Make the appropriate GPIO pins be QEI inputs instead of GPIO. // GPIODirModeSet(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_6, GPIO_DIR_MODE_HW); GPIODirModeSet(GPIO_PORTD_BASE, GPIO_PIN_7, GPIO_DIR_MODE_HW); // // Configure the QEI block to capture on both edges, use quadrature // signals, and to capture the speed. // QEIConfigure(QEI_BASE, (QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET | QEI_CONFIG_QUADRATURE | QEI_CONFIG_NO_SWAP), 0); QEIVelocityConfigure(QEI_BASE, QEI_VELDIV_1, SysCtlClockGet() / 100); // // Enable velocity timer expiration interrupt. // QEIIntEnable(QEI_BASE, QEI_INTTIMER); IntEnable(INT_QEI); // // Enable the QEI block. // QEIEnable(QEI_BASE); QEIVelocityEnable(QEI_BASE); // // Set the QEI interrupt to the second highest priority. It shouldn't // be as high as the hall effect sensors (i.e. it shouldn't interfere // with commutation of the motor) but it should be handled ahead of the // other interrupts. // IntPrioritySet(INT_QEI, 0x40); } else { // // Enable software QEI. // g_bSoftwareQEI = true; // // Enable the timer that will be used to provide the timer period // interrupt. // SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); // // Configure and enable a timer to provide interrupt every 1/100th of a // second. // TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER); TimerLoadSet(TIMER0_BASE, TIMER_A, (SysCtlClockGet() / 100) - 1); TimerEnable(TIMER0_BASE, TIMER_A); // // Enable the interrupt handler for the timer. // TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); IntEnable(INT_TIMER0A); // // Configure the optical encoder GPIO pin as an input with interrupt // generation on the rising edge. // GPIODirModeSet(GPIO_PORTC_BASE, GPIO_PIN_4, GPIO_DIR_MODE_IN); GPIOIntTypeSet(GPIO_PORTC_BASE, GPIO_PIN_4, GPIO_RISING_EDGE); // // Enable the optical encoder GPIO pin interrupt. // GPIOPinIntEnable(GPIO_PORTC_BASE, GPIO_PIN_4); IntEnable(INT_GPIOC); // // Set the QEI interrupts to the second highest priority. It shouldn't // be as high as the hall effect sensors (i.e. it shouldn't interfere // with commutation of the motor) but it should be handled ahead of the // other interrupts. Both interrupts are set to the same priority as a // form of mutual exclusion between the two interrupt handlers (it is // guaranteed that one handler will not interrupt the other, so they // can share global variables without special consideration of being // interrupted by the other). // IntPrioritySet(INT_GPIOC, 0x40); IntPrioritySet(INT_TIMER0A, 0x40); }}//*****************************************************************************////! Debug command callback function.//!//! \param ulValue is ignored.//!//! This function is called when the debug command is entered by the user. It//! toggles closed-loop debug mode, in which the measured motor speed is//! printed periodically in order to evaluate the performance of the PID gain//! factors.//!//! \return None.////*****************************************************************************static voidDebugHandler(unsigned long ulValue)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -