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.

No PWM Output on selected Timer Pin

Other Parts Discussed in Thread: TM4C129XNCZAD, LM4819

Hi again! I'm still using the TM4C129XNCZAD on the DK-TM4C129X connected Development Board. This board has an on-board speaker plus LM4819 amplifier for it.

The pin connected to the input of the amplifier on this board is PB2. PD4 also has to be configured as a GPIO output to pull the chip out of shutdown mode. However, for my testing, I have my scope hooked up to the output of PB2 directly, not after the amp (so the state of PD4 doesn't matter).

Because the designer of this board (for some unknown reason) connected the amp to the T5CCP0 pin instead of a PWM module pin, I have to generate the PWM using the timer module instead. I'm pretty sure my code is correct but I'm still not getting any output. The output on this pin is triggered by the comparator interrupt. This interrupt is working perfectly -- the LED comes on every time it trips. But still no noise.

Again, I'm sure I'm making an elementary mistake. All assistance is greatly appreciated! See my code below:

#include <stdint.h>
#include <stdbool.h>
#include "utils/ustdlib.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/debug.h"
#include "driverlib/adc.h"
#include "driverlib/comp.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/hibernate.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
//#include "drivers/pinout.h"
//#include "drivers/sound.h"



void makeSomeNoise(uint32_t ui32currentTone) {

	ROM_TimerDisable(TIMER5_BASE, TIMER_A); // make sure timer is off

	if(ui32currentTone == 1)
	{
		// if you're with me!
		ROM_TimerLoadSet(TIMER5_BASE, TIMER_A, 6000);
		ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, 0);
		ROM_TimerEnable(TIMER5_BASE, TIMER_A);
		ROM_SysCtlDelay(40000000);
	}
	if(ui32currentTone == 2)
	{

	}
	if(ui32currentTone == 3)
	{
		// do nothing, because the sound has been cut
	}

}

void PWMInitialize(void)
{
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_4); // pin for enabling LM4819

	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5); // enable timer5

	ROM_GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_2);
	ROM_GPIOPinConfigure(GPIO_PB2_T5CCP0); // set PB2 as Timer5 output CCP0
	ROM_TimerClockSourceSet(TIMER5_BASE, TIMER_CLOCK_SYSTEM);
	// ROM_TimerPrescaleSet(TIMER5_BASE, TIMER_A, ) // value between 0 and 255 to act as prescaler of timer
	ROM_TimerConfigure(TIMER5_BASE, TIMER_CFG_A_PWM|TIMER_CFG_PERIODIC); // configure timer for half-width PWM

	ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_4, 0x10); // PD4 goes high to activate LM4819 amp
}

void Comp0IntHandler(void)
{
	ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_7, 0x80); // turn led on

	ROM_SysCtlDelay(40000000);
	makeSomeNoise(1); // play tone 1
	//ROM_SysCtlDelay(40000000);
	//makeSomeNoise(2); // play tone 2
	//ROM_SysCtlDelay(40000000);
	//makeSomeNoise(3); // shut off sounds

	ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_7, 0x00); // turn led off
	ROM_ComparatorIntClear(COMP_BASE, 0);
}

int main(void) {

	ROM_SysCtlClockFreqSet(SYSCTL_OSC_INT|SYSCTL_USE_PLL|SYSCTL_CFG_VCO_480, 120000000); // set system clock to 120MHz

	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); // enable port D
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); // enable port Q
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); // enable port C
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // enable port B
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_COMP0); // enable analog comparator 0

	PWMInitialize(); // initalize PWM system

	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_4); // set PQ4 to output (Blue LED)
	ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_7, 0x00); // ensure blue LED is off

	ROM_GPIOPinTypeComparator(GPIO_PORTC_BASE, GPIO_PIN_7);
	ROM_GPIOPinTypeComparator(GPIO_PORTC_BASE, GPIO_PIN_6);

	ROM_ComparatorRefSet(COMP_BASE, COMP_REF_2_0625V); // set reference to 2.0625V
	ROM_ComparatorConfigure(COMP_BASE, 0, (COMP_TRIG_NONE|COMP_INT_BOTH|COMP_ASRCP_REF|COMP_OUTPUT_NORMAL)); // configure COMP0
	ComparatorIntRegister(COMP_BASE, 0, Comp0IntHandler);
	ROM_ComparatorIntEnable(COMP_BASE, 0);

	while(1)
	{
		// twiddle thumbs
	}
}

  • Hi Aurelius,

    Couple of quick points.

    1. PWM works in 16 bit mode so you need to set    

    TimerConfigure(TIMER5_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM);

    2. Secondly, the LOAD value is 0x6000 and Match value is 0. So it will count to 0 with PWM output as 0 and at match it will generate a single clock cycle of high pulse which may not be able to start the buzzer. I would suggest making it as 0x3000 so that PWM gets generated

    Regards

    Amit

    Regards

    Amit

  • Awesome, that helped a lot.

    I also have been trying to play around with the values of the LoadSet and MatchSet. I was able to get a nice square wave a minute ago by putting the Match at half the Load, but now I can't seem to replicate that. I just keep getting skinny little pulses that are inaudible.

    I'm pretty sure I understand how the timer system works -- you take the clock speed of the microcontroller and divide that by however many clock ticks you want the timer to run for and you work out the frequency that way. Then you take half of that value and load it into the MatchSet to create duty cycle. Of course 16-bit numbers only go to 32 768 so there's a limit to the frequencies available but it makes sense.

    I don't know what I changed to make it stop producing nice square waves! Argh.

    With the Load at 12000 (decimal) and the Match at 6000 I'm now getting pulses 48uS wide, 8mS apart.

  • Hi Aurelius,

    Probably a code post would be useful.

    Regards

    Amit

  • As you can see, the only changes I've really made are to the numbers and also adding the split pair as you recommended.

    #include <stdint.h>
    #include <stdbool.h>
    #include "utils/ustdlib.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/debug.h"
    #include "driverlib/comp.h"
    #include "driverlib/gpio.h"
    #include "driverlib/timer.h"
    #include "driverlib/hibernate.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    
    void makeSomeNoise(uint32_t ui32currentTone) {
    
    	ROM_TimerDisable(TIMER5_BASE, TIMER_A); // make sure timer is off
    
    	if(ui32currentTone == 1)
    	{
    		// if you're with me!
    		//ROM_TimerPrescaleSet(TIMER5_BASE, TIMER_A, 0x15);
    		ROM_TimerLoadSet(TIMER5_BASE, TIMER_A, 8000);
    		ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, 500);
    
    		ROM_TimerEnable(TIMER5_BASE, TIMER_A);
    		ROM_SysCtlDelay(40000000);
    		ROM_TimerDisable(TIMER5_BASE, TIMER_A);
    	}
    	if(ui32currentTone == 2)
    	{
    		//ROM_TimerPrescaleSet(TIMER5_BASE, TIMER_A, 0x10);
    		ROM_TimerLoadSet(TIMER5_BASE, TIMER_A, 8000);
    		ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, 1000);
    
    		ROM_TimerEnable(TIMER5_BASE, TIMER_A);
    		ROM_SysCtlDelay(40000000);
    		ROM_TimerDisable(TIMER5_BASE, TIMER_A);
    	}
    	if(ui32currentTone == 3)
    	{
    		// do nothing, because the sound has been cut
    	}
    
    }
    
    void PWMInitialize(void)
    {
    	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_4); // pin for enabling LM4819
    
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5); // enable timer5
    
    	ROM_GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_2);
    	ROM_GPIOPinConfigure(GPIO_PB2_T5CCP0); // set PB2 as Timer5 output CCP0
    	ROM_TimerClockSourceSet(TIMER5_BASE, TIMER_CLOCK_SYSTEM);
    	//ROM_TimerPrescaleSet(TIMER5_BASE, TIMER_A, 0x10);
    	ROM_TimerConfigure(TIMER5_BASE, TIMER_CFG_A_PWM|TIMER_CFG_SPLIT_PAIR); // configure timer for half-width PWM
    
    	ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_4, 0x05); // PD4 goes high to activate LM4819 amp
    }
    
    void Comp0IntHandler(void)
    {
    	ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_7, 0x80); // turn led on
    
    	ROM_SysCtlDelay(40000000);
    	makeSomeNoise(1); // play tone 1
    	//ROM_SysCtlDelay(4000000);
    	//makeSomeNoise(2); // play tone 2
    	//ROM_SysCtlDelay(40000000);
    	//makeSomeNoise(3); // shut off sounds
    
    	ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_7, 0x00); // turn led off
    	ROM_ComparatorIntClear(COMP_BASE, 0);
    }
    
    int main(void) {
    
    	ROM_SysCtlClockFreqSet(SYSCTL_OSC_INT|SYSCTL_USE_PLL|SYSCTL_CFG_VCO_480, 120000000); // set system clock to 120MHz
    
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); // enable port D
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); // enable port Q
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); // enable port C
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // enable port B
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_COMP0); // enable analog comparator 0
    
    	PWMInitialize(); // initalize PWM system
    
    	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_7); // set PQ4 to output (Blue LED)
    	ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_7, 0x00); // ensure blue LED is off
    
    	ROM_GPIOPinTypeComparator(GPIO_PORTC_BASE, GPIO_PIN_7);
    	ROM_GPIOPinTypeComparator(GPIO_PORTC_BASE, GPIO_PIN_6);
    
    	ROM_ComparatorRefSet(COMP_BASE, COMP_REF_2_0625V); // set reference to 2.0625V
    	ROM_ComparatorConfigure(COMP_BASE, 0, (COMP_TRIG_NONE|COMP_INT_BOTH|COMP_ASRCP_REF|COMP_OUTPUT_NORMAL)); // configure COMP0
    	ComparatorIntRegister(COMP_BASE, 0, Comp0IntHandler);
    	ROM_ComparatorIntEnable(COMP_BASE, 0);
    
    	while(1)
    	{
    		// twiddle thumbs
    	}
    }
    

  • Hello Aurelius,

    Looks like the disabling of the timer in the if-else statement in the makeSomeNoise function. I assume removing that will help. Also with the load and match of 8000 and 500, you would get pulses of 6.25% Duty Cycle.

    Regards

    Amit

  • Yeah but even when I play with the numbers and use 8000 and 4000 I'm still getting tiny little pulses.

    I'll try cutting the TimerDisable and see if that helps.

    EDIT: I remembered that for some reason variables stay in the memory unless you do a full reset. So if you reprogram the chip and didn't clear the prescaler before, it stays on the new program. Talk about a huge bug!!! so a full reset and reprogram fixed it...

  • Hi Aurelius.

    You mean to say the prescaler configured in the timer?

    Regards

    Amit