Jump to content
43oh

Interrupt routines


Recommended Posts

Hi!

 

First of all, I'm very new to the TI Stellaris boards. I'm trying to read out a produced PWM signal. I am using a EK-LM3S9B90 eva Board.

 

So, here is my code. As you can see, I have no idea how to get to the width of the PWM signal peak. I expect a peak of about 1ms width (which should be calculated in the code) and a period of 20ms const.

 

Is there a possibility to read out the point where the interrupts on both edges are called and write them into variables? So it should be easy to get the pulse width, as I think... This may sound dumb, but my programming skills are in their infant stadium.

 

Help is much appreciated!

void
SetPins(void) // I/O Pins Konfigurieren
{
    // GPIO Port D aktivieren
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    // GPIO Port D, Pin 4 als CCP (Capture Compare PWM) genutzt
    GPIOPinConfigure(GPIO_PD4_CCP3);
    // GPIO Port D, Pin 3 als CCP für PWM-Auslesen mittel Capture
    GPIOPinConfigure(GPIO_PE3_CCP1);

    // Settings für CCP Pins. Nötig für Timer/PWM
    GPIOPinTypeTimer(GPIO_PORTD_BASE, GPIO_PIN_4);
    GPIOPinTypeTimer(GPIO_PORTE_BASE, GPIO_PIN_3);

    // USR_LED ausschalten
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0);
}


void
InitConsole(void) // UART Initialisieren
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    UARTStdioInit(0);
}

/*
void
Timer0BIntHandler(void) // Timer0B Handler für Capture INTs
{
	// Timer INT Flag löschen
	TimerIntClear(TIMER0_BASE, TIMER_TIMB_TIMEOUT);

	//if()

	IntDisable(INT_TIMER0B); // INT deaktivieren
	TimerIntDisable(TIMER0_BASE, TIMER_TIMB_TIMEOUT); // INT verbieten
	TimerIntClear(TIMER0_BASE, TIMER_TIMB_TIMEOUT); // offene Flags löschen
}
*/

int
main(void)
{
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
    			   SYSCTL_XTAL_16MHZ);

    // Aktivierung Timer
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);

    SetPins();
    InitConsole();

    // Timerkonfigurierung
    TimerConfigure(TIMER0_BASE, TIMER_CFG_B_CAP_COUNT_UP);
    TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR |
    			   TIMER_CFG_B_PWM);

    // 5% Duty Cycle für PWM
    TimerLoadSet(TIMER1_BASE, TIMER_B, 64000);
    TimerMatchSet(TIMER1_BASE, TIMER_B, TimerLoadGet(TIMER1_BASE, TIMER_ - 3200);

    // bei Peak an CCP1 INT auslösen
    TimerControlEvent(TIMER0_BASE, TIMER_B, TIMER_EVENT_BOTH_EDGES);

    // Timer einschalten
    TimerEnable(TIMER0_BASE, TIMER_;
    TimerEnable(TIMER1_BASE, TIMER_;

    // Clearen und Erlauben des TimerINT
    TimerIntClear(TIMER0_BASE, TIMER_CAPA_EVENT | TIMER_CAPB_EVENT);
    TimerIntEnable(TIMER0_BASE, TIMER_CAPA_EVENT | TIMER_CAPB_EVENT);

    // INTs erlauben (vgl. sei())
    IntMasterEnable();

    PeakTime = ???;
    UARTprintf("Breite Peak: %d\n", PeakTime); // Breite Peak als Zählerstand Timer
    PeakTime = 0;

    while(1)
    {

    }
}

Link to post
Share on other sites

Hi,


First, you cross-posted on e2e tiva-arm site - and I prefer to highlight you here some problems:


1) According to the user manual, page 560:


 


In Edge-Time mode, the timer is configured as a 16-bit down-counter. In this mode, the timer is initialized to the value loaded in the GPTMTnILRregister. The timer is capable of capturing three types of events: rising edge, falling edge, or both.


So your configuration of Timer 0 must be changed, two timers, split configuration. On 9B90 there are no alternative to that - this is Stellaris. One timer will be enough. With two timers you will have problems - there is no guarantee there are only one free timer inside nor they will be in sync. 


 


You should also realize the generated PWM signal and the capture are two un-related events, so you don't know when one start or stop or takes more than usual (period and/or duty). So there is the possibility that an edge to come when the counter is at count=5, goes to 0 (over-roll) and reloads with 0xFFFF and the next edge is at 0xFFE0 - so you must make some math. But if either the duration or the period is longer than 0xFFFF maximum capacity, some more over-rolls may be present. You did not specified any boundary-limitations-parmeters of your pulse to be measured - so we must ask or signal the problem. Keep in mind this is important - any omision will force you to return to this problem and find out patches - so thinking from the beginning at the whole problem will be your benefit (not ours).


 


Now about the measurement itself:


Of coarse should be done only in interrupt - and you have some solutions:


2) Start as you already done, with detecting both edges. But this means when in interrupt you must detect what was the edge - rising or falling. You may use a separate GPIO pin configured as input and to read its value, hi or low and then to make further calculations.


 


3)Start with the capture for the positive edge and when interrupt is fired, change the settings for the negative edge.


Your interrupt must respond also to overtime (over-roll) - and must be counted and taken into account. You must clean up the over-roll count at every edge change.


 


Take care in this configuration the prescalers are not available - seems you already read about and choose to lower the system clock - but this is not a solution since some applications may need higher/highest system clock (USB, Ethernet, etc).


L


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...