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.

TM4C123GXL High and Low Output Logic

I am currently confused on how to make one pin of the microcontroller output a high and another pin output a low.  The dual h-bridge motor driver uses 2 logic pins to drive the motor in both directions depending on the logic.  On an Arduino, DigitalWrite() with 1 or 0 made the pin high or low.  I am stuck on doing this on the TM4C123GXL.

I tried using GPIOPinWrite with the 3rd parameter as 0x0 for low and the GPIO_PIN_(X) for high, but it did not work.

Any help would be greatly appreciated!

  • Hello Hak

    How is the GPIO being configured for output mode? A sample code post of the configuration and the API calls would be useful.

    Also when you stop the debugger, does the execution flow show that it is a FaultISR?
  • Here is the code. I managed to get my PWM signal working.


    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/pwm.h"
    #include "utils/uartstdio.h"

    #define STEERING_RIGHT GPIO_PIN_4
    #define STEERING_LEFT GPIO_PIN_7

    void delayMS(int delay)
    {
    SysCtlDelay((SysCtlClockGet()/(3*1000))*delay);
    }

    void ConfigureUART(void)
    {
    // Set the clock
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    // Enable the GPIO Peripheral used by the UART.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    // Enable UART0
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);

    // Configure GPIO Pins for UART mode.
    ROM_GPIOPinConfigure(GPIO_PB0_U1RX);
    ROM_GPIOPinConfigure(GPIO_PB1_U1TX);
    ROM_GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    // Use the internal 16MHz oscillator as the UART clock source.
    UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);

    // Initialize the UART for console I/O.
    UARTStdioConfig(1, 115200, 16000000);
    }

    void ConfigurePWM(void)
    {
    uint32_t period = 4000; // 20ms (16Mhz / 64pwm_divider / 50)
    uint32_t dutyCycle = 250; // 1.5ms pulse width

    // Set the clock
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    // Configure PWM Clock divide system clock by 64
    SysCtlPWMClockSet(SYSCTL_PWMDIV_64);

    // Enable the peripherals used by this program.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);

    // Configure PF1,PF2,PF3 Pins as PWM
    GPIOPinConfigure(GPIO_PF2_M1PWM6);
    GPIOPinConfigure(GPIO_PF3_M1PWM7);
    GPIOPinTypePWM(GPIO_PORTF_BASE,GPIO_PIN_2 | GPIO_PIN_3);

    // Configure PWM Options
    // PWM_GEN_2 Covers M1PWM4 and M1PWM5
    // PWM_GEN_3 Covers M1PWM6 and M1PWM7
    PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);

    // Set the Period
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, period);
    PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, period);

    // Set PWM duty
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,dutyCycle);
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7,dutyCycle);

    // Enable the PWM generator
    PWMGenEnable(PWM1_BASE, PWM_GEN_2);
    PWMGenEnable(PWM1_BASE, PWM_GEN_3);

    // Turn on the output pins
    PWMOutputState(PWM1_BASE,PWM_OUT_6_BIT | PWM_OUT_7_BIT, true);
    }

    void ConfigureSteering(void)
    {
    // Set the clock
    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

    // Enable and wait for the port to be ready for access
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB))
    {
    }

    // Configure the GPIO port for the steering operation
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, STEERING_LEFT | STEERING_RIGHT);
    }

    int main(void)
    {
    uint32_t period = 40000;
    uint32_t dutyCycle = 20000;
    double i = 2;

    ConfigureUART();
    ConfigurePWM();
    ConfigureSteering();

    while(1)
    {
    UARTprintf("Press 'w' to speed up and 's' to slow down.\n");
    char direction = UARTCharGet(UART1_BASE);
    dutyCycle = period/i;

    if(direction == 'd' | direction == 'D')
    {
    GPIOPinWrite(GPIO_PORTB_BASE, STEERING_RIGHT, STEERING_RIGHT);
    GPIOPinWrite(GPIO_PORTB_BASE, STEERING_LEFT, 0x0);
    }
    else
    {
    GPIOPinWrite(GPIO_PORTB_BASE, STEERING_RIGHT, 0x0);
    GPIOPinWrite(GPIO_PORTB_BASE, STEERING_LEFT, 0x0);
    }
    if(direction == 'a' | direction == 'A')
    {
    GPIOPinWrite(GPIO_PORTB_BASE, STEERING_LEFT, STEERING_LEFT);
    GPIOPinRead(GPIO_PORTB_BASE, STEERING_RIGHT);
    }
    else
    {
    GPIOPinWrite(GPIO_PORTB_BASE, STEERING_RIGHT, 0x0);
    GPIOPinWrite(GPIO_PORTB_BASE, STEERING_LEFT, 0x0);
    }
    if(direction == 'w' | direction == 'W')
    {
    i++;
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7, dutyCycle);
    }
    if(direction == 's' | direction == 'S')
    {
    i--;
    PWMPulseWidthSet(PWM1_BASE, PWM_OUT_7, dutyCycle);
    }
    }
  • Hello Hak,

    First, there is a logic problem with the code. For direction, it will only work for the command A, as it is processed right after the command D without conditional.

    Second, there is PinRead on the A direction if that makes no sense.

    Then, on the next iteration, your direction variable is overwritten by something new from the buffer and any command different than A will turn off your direction motors.

    The GPIO configuration itself appears correct. Just relax and think your logic a bit more. After you get it working, try to learn a way to avoid the blocking read of the serial input, as your CPU is stuck doing nothing while you don't send a char.

    By the way, did you confirm you are getting a valid byte via serial port? Are the electric signals all good?

    Bruno

  • Hello Hak,

    Put a breakpoint on the line "dutyCycle = period/i;". Then step through the execution flow to see where the program flow goes. This will tell if the character is being received correctly or not and hence executing the correct GPIOPinWrite function.