This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Pin discrepancies between documentation for Tiva Launchpad, SensorHub BoosterPack, and Tivaware software

Other Parts Discussed in Thread: TM4C123GH6PM

Hi, 

I am configuring PWM to play a tone through a speaker based on data received from the MPU9150 on the SensorHub Boosterpack.  I am attempting to combine two examples taken from Tivaware 1.0:

TivaWare_C_Series-1.0\examples\boards\ek-tm4c123gxl-boostxl-senshub\compdcm_mpu9150

TivaWare_C_Series-1.0\examples\peripherals\pwm\dead_band 

Originally, I attempted to use PE4 to output the PWM signal but detected no signal once I got everything to compile and run.  I then tried to follow the dead_band.c example even more closely and tried to use PD0 as the output of the PWM signal (I have gotten this example to successfully run on my launchpad*).  I tried to combine the compdcm and dead_band code and saw that PD0 and PD1 are being used by I2C so the MPU9150 can talk to the MCU.  However, when I looked up which pins I can use that the SensorHub BoosterPack isn't using, I ran into some discrepancies between user's guide for the BoosterPack and the software written for it: 

http://www.ti.com/lit/ug/spmu290/spmu290.pdf shows that J2.6 and J2.7 are the pins used for the Sensor I2C. However, based on the MCU's family user's guide schematic: http://datasheet.octopart.com/EK-TM4C123GXL-Texas-Instruments-datasheet-15542121.pdf  J2.6 and J2.7 are PB6 and PB7 (also pins I can use as PWM output signal*).  

Can someone please clear up which pins are being used for which functions, and make clear which pins I can in fact use to output a PWM signal without disrupting the communication from MPU9150 to MCU? 

*Throughout dead_band.c, the code is commented saying PB6 and PB7 are being used to generate PWM output. However, at the very end, when PWMOutputState is called, it uses PWM_OUT_1_BIT | PWM_OUT_0_BIT as the pins to turn on.  For PWM Module 0, this corresponds to PB6 and PB7 (according to the family user's guide). However, in the comments it says the output pins are PD0 and PD1.  Like, what? 

Thanks for the help! 

  • Hello Jedi,

    The example code in peripherals is more of a basic code that has can be used as reference. The user needs to check if the Board and Software need to be updated. As an example the code is OK for both TM4C123 and TM4C129 but for minor SW changes for PWM and Pin Out being different.

    Similarly there are more than 2 PWM outputs possible. It is not possible for us to put out code for each and every feature and mapping.

    I would suggest studying the schematics and the data sheet signal description before using any code in the peripheral section of TIVAWare.

    Regards

    Amit

  • You should note too the presence of (famed) 0-ohm resistors on your board - which "join" PB6 & PB7 to PD0 & PD1. 

    It may not be possible to cleanly, "exit" each/every pin of that 4 pin cluster - w/out some hardware "hack."

    As Amit states - multiple other pins - carrying your required signal functionality - should be available on that board...

  • Thank you for the quick response! 

    As noted previously, I attempted to use pins that the Tiva C LaunchPad user's manual indicates should be able to output the pwm signal.  I edited the pwm configuration in dead_band.c to use PE4, PE5, PA6, and PA7, and was unsuccessful in observing a pwm signal when probing the pin with an oscilloscope.  

    More specifically, I edited SYSCTL_PERIPH_PWM0 to SYSCTL_PERIPH_PWM1 to change to pwm module 1 (instead of 0), SYSCTL_PERIPH_GPIOB to SYSCTL_PERIPH_GPIOE / SYSCTL_PERIPH_GPIOA to switch which pins to output on, GPIO_PB6_M0PWM0 to GPIO_PE4_M0PWM4 / GPIO_PE4_M1PWM2, GPIO_PA6_M1PWM2, etc. for different pins.  I only attempted to output on one pin at a time, unlike the dead_band.c example.  

    Although I am successful in getting dead_band.c to output a pwm signal on PD0/PD1/PB6/PB7, I am unsuccessful in outputting a pwm signal on any of the other pins allocated for this functionality.  I am unsure why this is the case, any ideas? 

    Thank you! 

  • Hello Jedi

    A code post of the non-working code and which device (full part number) with version register would be useful

    Regards

    Amit

  • This is the adapted dead_band.c code to have the pwm output on PE4.  The interesting part is ConfigureSpeaker().  I am running it in the same CCS Project I associated with compdcm_mpu9150.c, which is why I need the mpu related functions to build the project; I did the same when using deadband.c code to output pwm on PB6/7 (PD0/1) and was able to observe the pwm signal on these pins.  This program compiles and runs, but I am unable to observe the pwm signal when probing pin 5 on J1 with an oscilloscope. 




    //***************************************************************************** // // compdcm_mpu9150.c - Example use of the SensorLib with the MPU9150 // // Copyright (c) 2013 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // 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. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 1.0 of the EK-TM4C123GXL Firmware Package. // //****************** //*********************************************************** #include <stdlib.h> #include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_ints.h" #include "driverlib/debug.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/pwm.h" #include "driverlib/rom.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" #include "sensorlib/hw_mpu9150.h" #include "sensorlib/hw_ak8975.h" #include "sensorlib/i2cm_drv.h" #include "sensorlib/ak8975.h" #include "sensorlib/mpu9150.h" #include "sensorlib/comp_dcm.h" #include "drivers/rgb.h" #define memSize 350 #define buffSize 20 //***************************************************************************** // // Define MPU9150 I2C Address. // //***************************************************************************** #define MPU9150_I2C_ADDRESS 0x68 //***************************************************************************** // //! \addtogroup example_list //! <h1>Nine Axis Sensor Fusion with the MPU9150 and Complimentary-Filtered //! DCM (compdcm_mpu9150)</h1> //! //! This example demonstrates the basic use of the Sensor Library, TM4C123G //! LaunchPad and SensHub BoosterPack to obtain nine axis motion measurements //! from the MPU9150. The example fuses the nine axis measurements into a set //! of Euler angles: roll, pitch and yaw. It also produces the rotation //! quaternions. The fusion mechanism demonstrated is complimentary-filtered //! direct cosine matrix (DCM) algorithm is provided as part of the Sensor //! Library. //! //! Connect a serial terminal program to the LaunchPad's ICDI virtual serial //! port at 115,200 baud. Use eight bits per byte, no parity and one stop bit. //! The raw sensor measurements, Euler angles and quaternions are printed to //! the terminal. The RGB LED begins to blink at 1Hz after initialization is //! completed and the example application is running. // //***************************************************************************** //***************************************************************************** // // Global array for holding the color values for the RGB. // //***************************************************************************** uint32_t red[3]; uint32_t green[3]; uint32_t purple[3]; //***************************************************************************** // // Global instance structure for the I2C master driver. // //***************************************************************************** tI2CMInstance g_sI2CInst; //***************************************************************************** // // Global instance structure for the ISL29023 sensor driver. // //***************************************************************************** tMPU9150 g_sMPU9150Inst; //***************************************************************************** // // Global Instance structure to manage the DCM state. // //***************************************************************************** tCompDCM g_sCompDCMInst; //***************************************************************************** // // Global flags to alert main that MPU9150 I2C transaction is complete // //***************************************************************************** volatile uint_fast8_t g_vui8I2CDoneFlag; //***************************************************************************** // // Global flags to alert main that MPU9150 I2C transaction error has occurred. // //***************************************************************************** volatile uint_fast8_t g_vui8ErrorFlag; //***************************************************************************** // // Global flags to alert main that MPU9150 data is ready to be retrieved. // //***************************************************************************** volatile uint_fast8_t g_vui8DataFlag; //***************************************************************************** // // Global counter to control and slow down the rate of data to the terminal. // //***************************************************************************** #define PRINT_SKIP_COUNT 10 uint32_t g_ui32PrintSkipCounter; //***************************************************************************** // // The error routine that is called if the driver library encounters an error. // //***************************************************************************** #ifdef DEBUG void __error__(char *pcFilename, uint32_t ui32Line) { } #endif //***************************************************************************** // // MPU9150 Sensor callback function. Called at the end of MPU9150 sensor // driver transactions. This is called from I2C interrupt context. Therefore, // we just set a flag and let main do the bulk of the computations and display. // //***************************************************************************** void MPU9150AppCallback(void *pvCallbackData, uint_fast8_t ui8Status) { // // If the transaction succeeded set the data flag to indicate to // application that this transaction is complete and data may be ready. // if(ui8Status == I2CM_STATUS_SUCCESS) { g_vui8I2CDoneFlag = 1; } // // Store the most recent status in case it was an error condition // g_vui8ErrorFlag = ui8Status; } //***************************************************************************** // // Called by the NVIC as a result of GPIO port B interrupt event. For this // application GPIO port B pin 2 is the interrupt line for the MPU9150 // //***************************************************************************** void IntGPIOb(void) { unsigned long ulStatus; ulStatus = GPIOIntStatus(GPIO_PORTB_BASE, true); // // Clear all the pin interrupts that are set // GPIOIntClear(GPIO_PORTB_BASE, ulStatus); if(ulStatus & GPIO_PIN_2) { // // MPU9150 Data is ready for retrieval and processing. // MPU9150DataRead(&g_sMPU9150Inst, MPU9150AppCallback, &g_sMPU9150Inst); } } //***************************************************************************** // // Called by the NVIC as a result of I2C3 Interrupt. I2C3 is the I2C connection // to the MPU9150. // //***************************************************************************** void MPU9150I2CIntHandler(void) { // // Pass through to the I2CM interrupt handler provided by sensor library. // This is required to be at application level so that I2CMIntHandler can // receive the instance structure pointer as an argument. // I2CMIntHandler(&g_sI2CInst); } //***************************************************************************** // // MPU9150 Application error handler. Show the user if we have encountered an // I2C error. // //***************************************************************************** void MPU9150AppErrorHandler(char *pcFilename, uint_fast32_t ui32Line) { // // Set terminal color to red and print error status and locations // UARTprintf("\033[31;1m"); UARTprintf("Error: %d, File: %s, Line: %d\n" "See I2C status definitions in sensorlib\\i2cm_drv.h\n", g_vui8ErrorFlag, pcFilename, ui32Line); // // Return terminal color to normal // UARTprintf("\033[0m"); // // Set RGB Color to RED // red[0] = 0xFFFF; red[1] = 0; red[2] = 0; RGBColorSet(red); // // Increase blink rate to get attention // RGBBlinkRateSet(10.0f); // // Go to sleep wait for interventions. A more robust application could // attempt corrective actions here. // while(1) { // // Do Nothing // } } //***************************************************************************** // // Function to wait for the MPU9150 transactions to complete. Use this to spin // wait on the I2C bus. // //***************************************************************************** void MPU9150AppI2CWait(char *pcFilename, uint_fast32_t ui32Line) { // // Put the processor to sleep while we wait for the I2C driver to // indicate that the transaction is complete. // while((g_vui8I2CDoneFlag == 0) && (g_vui8ErrorFlag == 0)) { // // Do Nothing // } // // If an error occurred call the error handler immediately. // if(g_vui8ErrorFlag) { MPU9150AppErrorHandler(pcFilename, ui32Line); } // // clear the data flag for next use. // g_vui8I2CDoneFlag = 0; } //***************************************************************************** // // Configure the UART and its pins. This must be called before UARTprintf(). // //***************************************************************************** void ConfigureUART(void) { // // Enable the GPIO Peripheral used by the UART. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // // Enable UART0 // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); // // Configure GPIO Pins for UART mode. // ROM_GPIOPinConfigure(GPIO_PA0_U0RX); ROM_GPIOPinConfigure(GPIO_PA1_U0TX); ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // Use the internal 16MHz oscillator as the UART clock source. // UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC); // // Initialize the UART for console I/O. // UARTStdioConfig(0, 115200, 16000000); } //***************************************************************************** // // Configure the vibrator and its gpio pins(PC4/6). This must be called before FB. // //***************************************************************************** void ConfigureVibration(void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); } //***************************************************************************** // // Configure the Speaker output and its gpio/pwm pins(PC4/6). // //***************************************************************************** void ConfigureSpeaker(void) { uint32_t PWMperiod, PulseWidth; /* Set PWM Clock */ SysCtlPWMClockSet(SYSCTL_PWMDIV_1); /* Enable Periphals */ SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); /* Configure the GPIO pin muxing to select PWM functions */ GPIOPinConfigure(GPIO_PE4_M0PWM4); /* Configure the GPIO pad for PWM function on pins PE4 */ GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_4); /* 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 440Hz */ PWMperiod = 80000000/440; // N = (1 / f) * SysClk PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, PWMperiod); /* Set PWM Pulse width */ PulseWidth = PWMGenPeriodGet(PWM0_BASE, PWM_OUT_0) / 2; PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, PulseWidth); /* Enable the dead-band generation on the PWM0 output signal */ PWMDeadBandEnable(PWM0_BASE, PWM_GEN_0, 160, 160); /* Set output state */ PWMOutputState(PWM0_BASE, PWM_OUT_4_BIT, true); } //***************************************************************************** // // Main application entry point. // //***************************************************************************** int main(void) { ConfigureSpeaker(); PWMGenEnable(PWM0_BASE, PWM_GEN_0); while(1){ /*Let PWM run */ } }

    We are using the Tiva C LaunchPad with TM4C123GH6PM processor and the SensorHub BoosterPack (not used in this code example).  I am unsure what you mean by version register; is that the version of the software we are using?

    Thanks so much!  

  • Hello Jedi,

    The generator and Pins are mapped together. M0PWM4 and M0PWM5 map to Generator-2 and not to Generator-0.

    GEN-0: PWM0 and PWM1

    GEN-1: PWM2 and PWM3

    GEN-2: PWM4 and PWM5

    GEN-3: PWM6 and PWM7

    Regards

    Amit

  • Amit, 

    Thank you so much! This clears everything up! However, after I set the clock using SysCtlPWMClockSet(), I need to enable the PWM peripheral, using SysCtlPeripheralEnable().  Currently, the input variable is SYSCTL_PERIPH_PWM0.  When I open declaration, I can't find SYSCTL_PERIPH_PWM2, or SYSCTL_PERIPH_PWM3.  Are the modules split further into generators, meaning SYSCTL_PERIPH_PWM0 corresponds to GEN-0 and GEN-1, and SYSCTL_PERIPH_PWM1 corresponds to GEN-2 and GEN-3? 

    Thank you so much for such quick responses! 

  • //*****************************************************************************
    //
    // Configure the Speaker output and its gpio/pwm pins(PC4/6).
    //
    //*****************************************************************************
    void
    ConfigureSpeaker(void)
    {
        uint32_t PWMperiod, PulseWidth;
    
        /* Set PWM Clock */
        SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
    
        /* Enable Periphals */
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
        /* Configure the GPIO pin muxing to select PWM functions */
        GPIOPinConfigure(GPIO_PE4_M0PWM4);
    
        /* Configure the GPIO pad for PWM function on pins PE4 */
        GPIOPinTypePWM(GPIO_PORTE_BASE, GPIO_PIN_4);
    
        /* Configure the PWM0 to count up/down without synchronization */
        PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    
        /* Set the PWM period to 440Hz */
        PWMperiod = 80000000/440; // N = (1 / f) * SysClk
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, PWMperiod);
    
        /* Set PWM Pulse width */
        PulseWidth = PWMGenPeriodGet(PWM1_BASE, PWM_OUT_4) / 2;
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4, PulseWidth);
    
        /* Enable the dead-band generation on the PWM0 output signal */
        PWMDeadBandEnable(PWM1_BASE, PWM_GEN_2, 160, 160);
    
        /* Set output state */
        PWMOutputState(PWM1_BASE, PWM_OUT_4_BIT, true);
    }
    
    //*****************************************************************************
    //
    // Main application entry point.
    //
    //*****************************************************************************
    int
    main(void)
     {
        ConfigureSpeaker();
        PWMGenEnable(PWM1_BASE, PWM_GEN_2);
        while(1){
        	/*Let PWM run */
        }
     }
    

    In other words, does the above code look correct in terms of using the correct pwm modules and generators? 

  • Hello Jedi,

    Each PWM Instance has 4 generators. Each Generator controls 2 pins. Hence to use GEN0 to GEN3 of PWM0 you need to enable PWM0 module. Similarly to use GEN0 to GEN3 of PWM1 you have to enable PWM1 module

    In the above code I would replace PWM1 with PWM0. A key to use is the GPIO Configuration. The Pin name is M0PWM4. Here M0 would represent PWM-0

    Regards

    Amit

  • Amit, Thanks so much! We got it up and working!