//***************************************************************************** // //! Sets the motor to be driven at the requested duty cycle. //! //! \param ucMotor determines which motor's duty cycle is to be set. Valid //! values are \e LEFT_SIDE or \e RIGHT_SIDE. //! \param usPercent Percent of the maximum speed to drive the motor in //! 8.8 fixed point format. This value must be less than (100 << 8). //! //! This function can be called to set the duty cycle of one or other of the //! motors. //! //! \return None. //! //! \note The duty cycle and motor speed are not the same thing, although there //! is a relation. // //***************************************************************************** void MotorSpeed(tSide ucMotor, unsigned short usPercent) { unsigned long ulPWMOut, ulPWMOutBit; // // Check for invalid parameters. // ASSERT((ucMotor == LEFT_SIDE) || (ucMotor == RIGHT_SIDE)); ASSERT(usPercent < (100 << 8)); // // Which PWM output are we controlling? // if(ucMotor == LEFT_SIDE) { ulPWMOut = PWM_OUT_2; ulPWMOutBit = PWM_OUT_2_BIT; } else { ulPWMOut = PWM_OUT_0; ulPWMOutBit = PWM_OUT_0_BIT; } // // First, enable the PWM output in case it was disabled by the // previously requested speed being greater than 95% // PWMOutputState(PWM0_BASE, ulPWMOutBit, true); // // Make sure that output is not inverted. // PWMOutputInvert(PWM0_BASE, ulPWMOutBit, false); // // Set the pulse width to the requested value. Divide by two since // we are using 6V motors with 12V power rail. // PWMPulseWidthSet(PWM0_BASE, ulPWMOut, ((PWM_PERIOD * usPercent) / (100 << 8))); }
//***************************************************************************** // // Configure PWM0 for a 25% duty cycle signal running at 250Hz. This example // also shows how to invert the PWM signal every 5 seconds for 5 seconds. // //***************************************************************************** int main(void) { // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal on your board. // SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Set the PWM clock to the system clock. // SysCtlPWMClockSet(SYSCTL_PWMDIV_1); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for Timer operation. // InitConsole(); // // Display the setup on the console. // UARTprintf("PWM ->\n"); UARTprintf(" Module: PWM0\n"); UARTprintf(" Pin: PD0\n"); UARTprintf(" Configured Duty Cycle: 25%%\n"); UARTprintf(" Inverted Duty Cycle: 75%%\n"); UARTprintf(" Features: PWM output inversion every 5 seconds.\n\n"); UARTprintf("Generating PWM on PWM0 (PD0) -> State = "); // // The PWM peripheral must be enabled for use. // SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); // // For this example PWM0 is used with PortB Pin6. The actual port and // pins used may be different on your part, consult the data sheet for // more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using. // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the GPIO pin muxing to select PWM00 functions for these pins. // This step selects which alternate function is available for these pins. // This is necessary if your part supports GPIO pin function muxing. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using. // GPIOPinConfigure(GPIO_PB6_M0PWM0); // // Configure the PWM function for this pin. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using. // GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_6); // // Configure the PWM0 to count up/down without synchronization. // PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); // // Set the PWM period to 250Hz. To calculate the appropriate parameter // use the following equation: N = (1 / f) * SysClk. Where N is the // function parameter, f is the desired frequency, and SysClk is the // system clock frequency. // In this case you get: (1 / 250Hz) * 16MHz = 64000 cycles. Note that // the maximum period you can set is 2^16. // TODO: modify this calculation to use the clock frequency that you are // using. // PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 64000); // // Set PWM0 to a duty cycle of 25%. You set the duty cycle as a function // of the period. Since the period was set above, you can use the // PWMGenPeriodGet() function. For this example the PWM will be high for // 25% of the time or 16000 clock ticks (64000 / 4). // PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, PWMGenPeriodGet(PWM0_BASE, PWM_OUT_0) / 4); // // Enable the PWM0 Bit0 (PD0) output signal. // PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT, true); // // Enable the PWM generator block. // PWMGenEnable(PWM0_BASE, PWM_GEN_0); // // Loop forever while the PWM signals are generated. // while(1) { // // Print out that the level of PWM is normal. // UARTprintf("Normal \b\b\b\b\b\b\b\b"); // // This function provides a means of generating a constant length // delay. The function delay (in cycles) = 3 * parameter. Delay // 5 seconds arbitrarily. // SysCtlDelay((SysCtlClockGet() * 5) / 3); // // Invert PWM0 signal. // PWMOutputInvert(PWM0_BASE, PWM_OUT_0_BIT, true); // // Print out that the level of PWM is inverted. // UARTprintf("Inverted\b\b\b\b\b\b\b\b"); // // This function provides a means of generating a constant length // delay. The function delay (in cycles) = 3 * parameter. Delay // 5 seconds arbitrarily. // SysCtlDelay((SysCtlClockGet() * 5) / 3); // // Switch PWM0 signal back to regular operation. // PWMOutputInvert(PWM0_BASE, PWM_OUT_0_BIT, false); } }
/* ---- Private Function Prototypes -------------------------------------- */ void A3906Init() { SysCtlPWMClockSet(SYSCTL_PWMDIV_1); // // Enable the peripherals used by this device. (PWM0,1,2,3) // SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM); SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // PWM 0,1 ROLL_MOTOR SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // PWM 2,3 PITCH_MOTOR SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // FL1 + FL2 GPIOPinConfigure(GPIO_PB6_M0PWM0); GPIOPinConfigure(GPIO_PB7_M0PWM1); GPIOPinConfigure(GPIO_PA6_M1PWM2); GPIOPinConfigure(GPIO_PA7_M1PWM3); // // Set GPIO PWM pins. They are used to output the PWM0-3 signals // GPIOPinTypePWM(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7); //pwm1 2-3 GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_6 | GPIO_PIN_7); //pwm0 2-3 // Set the PWM period to 20KHz. // N = (1 / F) * SysClk. // Where N is the function parameter // F is the desired frequency // SysClk is the system clock frequency. // In this case you get: (1 / 20KHz) * 80MHz = 4000 cycles. Note that ulPeriod = 4000;// SysCtlClockGet() / PWMRATE; //ulPeriod = SysCtlClockGet() / 50000;//PWMRATE; // // Set the PWM period to chosen rate. // PWMGenConfigure(PWM_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, ulPeriod); //PWMGenConfigure(PWM_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); //PWMGenPeriodSet(PWM_BASE, PWM_GEN_1, ulPeriod); PWMOutputInvert(PWM_BASE,PWM_OUT_0_BIT | PWM_OUT_1_BIT, true); // // Enable the PWM0 and PWM1 output signals. // PWMOutputState(PWM_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT, true); // // Enable the PWM generators. // PWMGenEnable(PWM_BASE, PWM_GEN_0); //PWMGenEnable(PWM_BASE, PWM_GEN_1); // // Set the PWM period to chosen rate. // //PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); //PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, ulPeriod); PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, ulPeriod); PWMOutputInvert(PWM1_BASE,PWM_OUT_2_BIT | PWM_OUT_3_BIT, true); // // Enable the PWM0 and PWM1 output signals. // PWMOutputState(PWM1_BASE, PWM_OUT_2_BIT | PWM_OUT_3_BIT, true); // // Enable the PWM generators. // //PWMGenEnable(PWM1_BASE, PWM_GEN_0); PWMGenEnable(PWM1_BASE, PWM_GEN_1); #if 0 // setup interrupt handlers for overcurrent GPIOPinInit(A3906_OC1_INTERRUPT_PORT,A3906_OC1_INTERRUPT_PIN,true,true); GPIOPinInit(A3906_OC2_INTERRUPT_PORT,A3906_OC2_INTERRUPT_PIN,true,true); #endif desiredencoder[0] = -1; // means not active desiredencoder[1] = -1; dcycle[0] = PITCH_MINIMUM_DUTYCYCLE; // recommended initial values dcycle[1] = ROLL_MINIMUM_DUTYCYCLE; brakeOnChange = true; }
/* * ======== PWMTiva_open ======== * @pre Function assumes that the handle is not NULL */ PWM_Handle PWMTiva_open(PWM_Handle handle, PWM_Params *params) { unsigned int key; uint8_t cyclesPerMicroSec; uint8_t prescalar; uint16_t pwmGenerator; uint16_t *pwmGenPeriod; uint32_t pwmGenOptions; uint32_t prescalarRegVal; uint32_t tempPeriod; Types_FreqHz freq; PWMTiva_Object *object = handle->object; PWMTiva_HWAttrs const *hwAttrs = handle->hwAttrs; BIOS_getCpuFreq(&freq); cyclesPerMicroSec = freq.lo / 1000000; if(params == NULL) { params = (PWM_Params *) &PWM_defaultParams; } /* Assert if period is too large for peripheral */ tempPeriod = params->period * cyclesPerMicroSec; Assert_isTrue(tempPeriod <= (PWMTiva_MAX_MATCH_VALUE * PWMTiva_MAX_PRESCALAR), NULL); PWMTiva_calculatePrescalar(tempPeriod, &prescalarRegVal, &prescalar); /* Get the PWM generator and it's period */ pwmGenerator = hwAttrs->pwmOutput & PWM_GEN_MASK; pwmGenPeriod = (object->pwmStatus)->genPeriods + ((hwAttrs->pwmOutput / PWM_OUT_0) - 1); key = Hwi_disable(); /* Verify if PWM peripheral has been initialized by another PWM instance */ if ((object->pwmStatus)->cyclesPerMicroSec) { /* * The PWM peripheral has already been initialized. * * Ensure the instance has not been opened and the peripheral prescalar * is >= the prescalar required for new instance. */ if (((object->pwmStatus)->activeOutputs & object->pwmOutputBit) || ((object->pwmStatus)->prescalar < prescalar)) { Hwi_restore(key); return (NULL); } /* Check if the other output on the generator is active */ if (*pwmGenPeriod) { /* Ensure period are the same */ if (params->period != *pwmGenPeriod) { Hwi_restore(key); return (NULL); } /* Get PWM generator options & ensure options are the same */ pwmGenOptions = (HWREG(hwAttrs->baseAddr + pwmGenerator) & ~PWM_X_CTL_ENABLE); if (hwAttrs->pwmGenOpts != pwmGenOptions) { Hwi_restore(key); return (NULL); } } } else { /* PWM has not been initialized by another instance */ (object->pwmStatus)->prescalar = prescalar; (object->pwmStatus)->cyclesPerMicroSec = cyclesPerMicroSec; PWMTiva_setPrescalar(hwAttrs->baseAddr, prescalarRegVal); } /* PWM can be opened safely, mark as being used */ (object->pwmStatus)->activeOutputs |= object->pwmOutputBit; if (!(*pwmGenPeriod)) { /* Initialize PWM signal generator */ *pwmGenPeriod = params->period; PWMGenConfigure(hwAttrs->baseAddr, pwmGenerator, hwAttrs->pwmGenOpts); PWMGenPeriodSet(hwAttrs->baseAddr, pwmGenerator, (tempPeriod / prescalar)); } Hwi_restore(key); /* * Set PWM duty to initial value (not 0 or period) - required when * inverting output polarity to generate a duty equal to 0 or * period. See comments in PWMTiva_setDuty for more information. */ object->pwmDuty = 1; object->dutyMode = params->dutyMode; /* Set PWM generator outputs to 0 initially */ PWMOutputInvert(hwAttrs->baseAddr, object->pwmOutputBit, params->polarity); PWMTiva_setDuty(handle, 0); PWMOutputState(hwAttrs->baseAddr, object->pwmOutputBit, true); PWMGenEnable(hwAttrs->baseAddr, pwmGenerator); Log_print2(Diags_USER1, "PWM:(%p) opened; period set to: %d", (UArg) handle, params->period); return (handle); }
//***************************************************************************** // //! Initializes the PWM control routines. //! //! This function initializes the PWM module and the control routines, //! preparing them to produce PWM waveforms to drive the power module. //! //! \return None. // //***************************************************************************** void PWMInit(void) { // // Make the PWM pins be peripheral function. // GPIOPinTypePWM(PIN_PHASEA_LOW_PORT, PIN_PHASEA_LOW_PIN | PIN_PHASEA_HIGH_PIN); GPIOPinTypePWM(PIN_PHASEB_LOW_PORT, PIN_PHASEB_LOW_PIN | PIN_PHASEB_HIGH_PIN); GPIOPinTypePWM(PIN_PHASEC_LOW_PORT, PIN_PHASEC_LOW_PIN | PIN_PHASEC_HIGH_PIN); // // Configure the three PWM generators for up/down counting mode, // synchronous updates, and to stop at zero on debug events. // PWMGenConfigure(PWM0_BASE, PWM_GEN_0, (PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_DBG_STOP)); PWMGenConfigure(PWM0_BASE, PWM_GEN_1, (PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_DBG_STOP)); PWMGenConfigure(PWM0_BASE, PWM_GEN_2, (PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_DBG_STOP)); // // Set the initial duty cycles to 50%. // g_ulPWMDutyCycleA = 32768; g_ulPWMDutyCycleB = 32768; g_ulPWMDutyCycleC = 32768; // // Configure the PWM period, duty cycle, and dead band. The initial period // is 1 KHz (for triggering the ADC), which will be increased when the // motor starts running. // PWMClearDeadBand(); PWMSetFrequency(); PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, PWM_CLOCK / 1000); PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, PWM_CLOCK / 1000); PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, PWM_CLOCK / 1000); PWMUpdateDutyCycle(); // // Enable the PWM generators. // PWMGenEnable(PWM0_BASE, PWM_GEN_0); PWMGenEnable(PWM0_BASE, PWM_GEN_1); PWMGenEnable(PWM0_BASE, PWM_GEN_2); // // Synchronize the time base of the generators. // PWMSyncTimeBase(PWM0_BASE, PWM_GEN_0_BIT | PWM_GEN_1_BIT | PWM_GEN_2_BIT); // // Configure an interrupt on the zero event of the first generator, and an // ADC trigger on the load event of the first generator. // PWMGenIntClear(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO); PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO | PWM_TR_CNT_LOAD); PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_1, 0); PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_2, 0); PWMIntEnable(PWM0_BASE, PWM_INT_GEN_0); IntEnable(INT_PWM0_0); IntEnable(INT_PWM0_1); IntEnable(INT_PWM0_2); // // Set all six PWM outputs to go to the inactive state when a fault event // occurs (which includes debug events). // PWMOutputFault(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT | PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT), true); // // Disable all six PWM outputs. // PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT | PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT), false); // // Ensure that all outputs are not-inverted. // PWMOutputInvert(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT | PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT), false); }