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.

Pulse Capture on stellaris LM4F120H5QR

Following is the code.. Kindly look at it

Doesn't seem to be working 

#define PART_LM4F120H5QR

#include "inc/hw_ints.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/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/timer.h"
#include "driverlib/pwm.h"
#include "utils/uartstdio.h"

int pulse_time_1;
int a,b,c;

void TIMER_Initialize(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

GPIOPinConfigure(GPIO_PB5_T1CCP1);
GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_5);
TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR |TIMER_CFG_B_CAP_COUNT);
TimerControlEvent(TIMER1_BASE,TIMER_B,TIMER_EVENT_BOTH_EDGES);
IntEnable(INT_TIMER1B);
TimerIntEnable(TIMER1_BASE, TIMER_CAPA_EVENT);
IntMasterEnable();
TimerEnable(TIMER1_BASE, TIMER_B);
}

void UART_Initialize()
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3|GPIO_PIN_2);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
}

int main(void)
{
SysCtlClockSet(SYSCTL_SYSDIV_64 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
TIMER_Initialize();
UART_Initialize();

while(1)
{
pulse_time_1=TimerLoadGet(TIMER1_BASE, TIMER_B);
TimerEnable(TIMER1_BASE, TIMER_B);
UARTprintf("%d",pulse_time_1);
//UARTCharPut(UART0_BASE,'$');
}
}

void Timer1IntHandler(void)
{
TimerIntClear(TIMER1_BASE, TIMER_CAPA_EVENT);
b=TimerValueGet(TIMER1_BASE, TIMER_B);
if (b<a) c=65535+a-b;
else c=a-b;
pulse_time_1=c/3125;

a= TimerValueGet(TIMER1_BASE, TIMER_B);
}

  • Hi Piyush

    Code post is good but what is the issue. Is the code hanging somewhere or it is not capturing Pulse. You need to be more clear on that.

    Secondly, in the Interrupt Handler, global variable "a" is being used before it is updated. Are you relying that it be initialized to a value as 0 in the beginning, then please make sure that the code initialize before using a global variable "a".

    Amit

  • Hi Piyush

    A second run through the code indicates that while TIMERB is being used TIMERA is being configured for Interrupts.

    TimerIntEnable(TIMER1_BASE, TIMER_CAPA_EVENT);

    instead of

    TimerIntEnable(TIMER1_BASE, TIMER_CAPB_EVENT);

    Also in the Interrupt Handler TIMER_CAPA_EVENT is being cleared whereas it should be TIMER_CAPB_EVENT.


    Amit

  • Hi,

    Please specify what do you try to do: a) counting edges or b) measuring pulse duration/period. Seems to be a mix between the two options.

    Petrei

  • I need the pulse length. The time the pulse is high or low.

  • Hi Piyush,

    Did you update the code with the recommendations and check if it solves your issue.

    Amit

  • Its not pulse capturing. I made the changes that you suggested.

    Thank You

    Amit

  • Hello Piyush,

    You are running the system at 3.125MHz looking at the SysCtlClockSet function and what is the pulse width you are expecting to capture?

    Amit

  • @Piyush,

    First of all, if you need to measure pulse length (either low or high or both) you need to configure your timer B for  TIMER_CFG_B_CAP_EVENT, TIMER_CFG_B_CAP_TIME  since this is the event which transfer the timer value into a register to be later read. Also, you need to configure the timer for overflow interrupt, since there are no means to synchronize the timer with the external pulse, nor the pulse satisfy the capacity of the register. 

    So you have to configure for two interrupts and take the necessary steps with each one. If overflow, then increase a static variable to take into account the number of overflows.

    If capture, then read the timer into a variable and make the difference between this time and the preceding one. After that, this variable must be transferred to another static one, namely the "preceding" one. Add the number of overflows times the overflow capacity to get a result. Use a flag to inform the main about.

    Note everything runs from interrupt. One more step to add here: how to determine the "high" or the "low" of the pulse. This can be done in several modes: a) try/check if you can read the capture pin with GPIOPinRead() - some reported to work, some not. If not then b) start with capturing rising edge and at the interrupt configure for falling edge.  Or c) use an input pin connected to the capture pin to determine the level.

    As you can observe, the best idea to manage all these is to design a small state machine. Do not forget the initializations/updates at each measurement cycle.

    Petrei

  • May I add 2 comments?

    a) brevity is not your friend in resolving this matter.  "Helpers" are forced to expend extra time/effort to "tease out" a more meaningful & detailed response.  This is not in your best interest...

    b) ARM MCUs have a large number of timers.  Often you can simplify the task by, "divide & conquer" (i.e. dedicating one timer to capture the signal's "high time" and a second timer to capture signal's "low time."  Later - once that dual timer method is proven - knowledge gleaned often enhances your odds of success w/single timer.  (but so often - who really cares? ...  and "optimization" too often plagues/retards mission accomplishment...KISS lives/breathes and works!)  You would route the signal of interest to 2 timer pins - rather than just 1 - should you adopt this simpler method...

    And...you've earlier ticked, "Verify Answer" - yet you indicate your issue remains unresolved...  That "verify" tick will likely chase away many - and indicates that, "attention to detail" may require some review...

  • I performed certain fixes and wrote the following code that works

    #define PART_LM4F120H5QR

    #include "inc/hw_ints.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/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/timer.h"
    #include "driverlib/pwm.h"
    #include "utils/uartstdio.h"
    //#include "ST7735.h"
    //#include "PLL.h"
    //#include "SysTick.h"
    //#include<string.h>

    unsigned long a=0;
    unsigned long b1=0,b2=0,b3=0,b4=0;
    unsigned long c1=0,c2=0,c3=0;
    float time_period,freq;
    char buffer[8];

    void ftoa(float f,char *buf)
    {
    int pos=0,ix,dp,num;
    if (f<0)
    {
    buf[pos++]='-';
    f = -f;
    }
    dp=0;
    while (f>=10.0)
    {
    f=f/10.0;
    dp++;
    }
    for (ix=1;ix<8;ix++)
    {
    num = (int)f;
    f=f-num;
    if (num>9)
    buf[pos++]='#';
    else
    buf[pos++]='0'+num;
    if (dp==0) buf[pos++]='.';
    f=f*10.0;
    dp--;
    }
    }

    void InitConsole(void)
    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTStdioInit(0);
    }


    int main(void)
    {
    InitConsole();
    SysCtlClockSet(SYSCTL_SYSDIV_64 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    GPIOPinConfigure(GPIO_PB1_T2CCP1);
    GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_1);
    TimerConfigure(TIMER2_BASE, TIMER_CFG_16_BIT_PAIR |TIMER_CFG_B_CAP_TIME);
    TimerControlEvent(TIMER2_BASE, TIMER_B,TIMER_EVENT_BOTH_EDGES);
    IntEnable(INT_TIMER2B);
    TimerIntEnable(TIMER2_BASE, TIMER_CAPB_EVENT);
    IntMasterEnable();
    TimerEnable(TIMER2_BASE, TIMER_B);


    }


    void Timer2IntHandler(void)
    {
    TimerIntClear(TIMER2_BASE, TIMER_CAPB_EVENT);
    b2=TimerValueGet(TIMER2_BASE, TIMER_B);
    if(b2>b1)
    {
    c2=b2-b1;
    }
    else
    {
    c2=65535-b1+b2;
    }
    if(c2>10000)
    {
    c2=c1;
    }
    UARTprintf("%d \n\r",c2);
    b1=b2;
    c1=c2;
    }