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.

A little question regarding Timer interrupt on TMS320F2812

Hi,

I'm facing a little issue with the F2812 considering the Timer interrupt. I'm using the following code as shown below. The thing is, that I want to increment a counter value, every time a interrupt occures. Right now, the value is only incrementing when giving a interrupt from high [1] to low [0]. But can't make it interrupt everytime, no matter if the value incomming is low og high. I've tried with a simple if else statement (out-commented in the code), by changing the polarity, but no luck. Hope you can help me.

 

 

#include "DSP281x_Device.h"     // DSP281x Headerfile Include File
#include "DSP281x_Examples.h"   // DSP281x Examples Include File

// Prototype statements for functions found within this file.

interrupt void cpu_timer0_isr(void);

void main(void)

{

 

// Step 1. Initialize System Control:

// PLL, WatchDog, enable Peripheral Clocks

// This example function is found in the DSP281x_SysCtrl.c file.

   InitSysCtrl();
   DINT;
   InitPieCtrl();

 

// Disable CPU interrupts and clear all CPU interrupt flags:

   IER = 0x0000;
   IFR = 0x0000;

   InitPieVectTable();

// Interrupts that are used in this example are re-mapped to

// ISR functions found within this file.  

   EALLOW;  // This is needed to write to EALLOW protected registers

   GpioMuxRegs.GPADIR.all = 0xFFFF;            // All pins are outputs
   GpioDataRegs.GPADAT.all = 0x0000;           // All I/O pins are driven low
   GpioMuxRegs.GPADIR.bit.GPIOA0 = 1;       // Sets A0 to output | 1 = output | 0 = input
   GpioDataRegs.GPADAT.bit.GPIOA0 = 0;     // If 1 = high else 0 = low.

   GpioMuxRegs.GPEMUX.bit.XINT1_XBIO_GPIOE0 = 1;   // GPIOE0 is XINT1 pin
   PieVectTable.XINT1 = &cpu_timer0_isr;

   EDIS;    // This is needed to disable write to EALLOW protected registers

   XIntruptRegs.XINT1CR.bit.ENABLE = 1;            // Enable XINT1 pin
   //XIntruptRegs.XINT1CR.bit.POLARITY = 1;          // Interrupt triggers on rising edge

 

   /*while(1){

   if (GpioDataRegs.GPADAT.bit.GPIOA0 == 0){
   XIntruptRegs.XINT1CR.bit.POLARITY = 1;
   break;

   }else
   XIntruptRegs.XINT1CR.bit.POLARITY = 0; 

   break;
   }*/

 

// Enable CPU INT1 which is connected to CPU-Timer 0:

   IER |= M_INT1;

 

// Enable TINT0 in the PIE: Group 1 interrupt 7

   PieCtrlRegs.PIEIER1.bit.INTx4 = 1;

 

// Enable global Interrupts and higher priority real-time debug events:

   EINT;   // Enable Global interrupt INTM
   ERTM;   // Enable Global realtime interrupt DBGM

 

// Step 6. IDLE loop. Just sit and loop forever (optional):

   for(;;);

interrupt void cpu_timer0_isr(void)

{

   CpuTimer0.InterruptCount++;

   // Acknowledge this interrupt to receive more interrupts from group 1

   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

}

Best Regards
Dado

 

  • there is standard cpu timer interrupt example code under /tidcs. why just use that code? Your PieCtrlRegs configuration might also have some problems. check this example code.

    // TI File $Revision: /main/3 $
    // Checkin $Date: July 2, 2007   11:33:22 $
    //###########################################################################
    //
    // FILE:    Example_281xCpuTimer.c
    //
    // TITLE:   DSP281x Device Getting Started Program.
    //
    // ASSUMPTIONS:
    //
    //          This program requires the DSP281x V1.00 header files. 
    //          As supplied, this project is configured for "boot to H0" operation.
    //
    //          Other then boot mode configuration, no other hardware configuration
    //          is required.  
    //
    // DESCRIPTION:
    //
    //          This example configures CPU Timer0 and increments
    //          a counter each time the timer asserts an interrupt.
    //     
    //          Watch Variables:
    //                 CpuTimer0.InterruptCount
    //
    //###########################################################################
    // $TI Release: DSP281x C/C++ Header Files V1.20 $
    // $Release Date: July 27, 2009 $
    //###########################################################################


    #include "DSP281x_Device.h"     // DSP281x Headerfile Include File
    #include "DSP281x_Examples.h"   // DSP281x Examples Include File

    // Prototype statements for functions found within this file.
    interrupt void cpu_timer0_isr(void);

    void main(void)
    {

    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP281x_SysCtrl.c file.
       InitSysCtrl();

    // Step 2. Initalize GPIO:
    // This example function is found in the DSP281x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    // InitGpio();  // Skipped for this example 


    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
       DINT;

    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared. 
    // This function is found in the DSP281x_PieCtrl.c file.
       InitPieCtrl();
      
    // Disable CPU interrupts and clear all CPU interrupt flags:
       IER = 0x0000;
       IFR = 0x0000;

    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR). 
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in DSP281x_DefaultIsr.c.
    // This function is found in DSP281x_PieVect.c.
       InitPieVectTable();

    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file. 
       EALLOW;  // This is needed to write to EALLOW protected registers
       PieVectTable.TINT0 = &cpu_timer0_isr;
       EDIS;    // This is needed to disable write to EALLOW protected registers

    // Step 4. Initialize all the Device Peripherals:
    // This function is found in DSP281x_InitPeripherals.c
    // InitPeripherals(); // Not required for this example
       InitCpuTimers();   // For this example, only initialize the Cpu Timers

    // Configure CPU-Timer 0 to interrupt every second:
    // 100MHz CPU Freq, 1 second Period (in uSeconds)
       ConfigCpuTimer(&CpuTimer0, 100, 1000000);
       StartCpuTimer0();

    // Step 5. User specific code, enable interrupts:


    // Enable CPU INT1 which is connected to CPU-Timer 0:
       IER |= M_INT1;

    // Enable TINT0 in the PIE: Group 1 interrupt 7
       PieCtrlRegs.PIEIER1.bit.INTx7 = 1;

    // Enable global Interrupts and higher priority real-time debug events:
       EINT;   // Enable Global interrupt INTM
       ERTM;   // Enable Global realtime interrupt DBGM

    // Step 6. IDLE loop. Just sit and loop forever (optional):
       for(;;);

    }


    interrupt void cpu_timer0_isr(void)
    {
       CpuTimer0.InterruptCount++;

       // Acknowledge this interrupt to receive more interrupts from group 1
       PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }

  • If you compare the things I'm writting, you will see that I'm actually using the same example :)

    Please read my problem in the beginning igen, and then read the description of what the example does.

  • Actually I read it and it was very confusing. I am not sure if you want to generate an internal timer interrupt or want to use external source to generate an hardware interrupt XINT1. They are totally different stories. Looks like you want to use external clock source to generate hardware interrupt XINT1. But what you refer is timer interrupt example code. hmm...

  • Yu Cai,

     

    I'm very sorry that I'm not such an expert at DSP 32-bit Real-time MCU's, as you are!

    But I will try to make it more clear now:

    I have an accelerometer, which gives the DSP the inputs. And I would like to read the values incomming from the accelerometer (Real time). So no matter if the accelerometer gives me a low voltage input < 1.5V, the interrupt should trigger and the value should be read by the DSP. The same by higher voltage input > 1.5V. And right now I was just trying to read a 0 value if the voltage was < 1.5V, and the same with reading 1 if the voltage was > 1.5V. That's the thing. 

    Please don't hesitate to ask if you still don't understand!

    Best regards

    Dado

  • Thanks Dado. Now I understand. If you want to read sensor data for accelerometer sensor to DSP. The way that you are using is not recommended since looks like your sensor's analog output directly goes to digital input pin of DSP (XINT1). This is unacceptable in circuit design. 

    And I am not sure if you are using on-chip ADC or off-chip ADC? If using on-chip ADC then you can use event manager to generate the sampling clock by using internal PWM waveform. If you want to use on-chip ADC and XINT1. You have to put an voltage buffer (voltage follower) between your sensor and the rest of the circuit. And if you want to judge if it is higher or lower than certain threshold, you need to use an comparator or schmitter trigger (74HC14) to generate TTL compatible digital interrupt source.

    If you try to use off-chip ADC, then it's easier then above. The off-chip ADC normally has its own data_ready signal which can be used as XINT1 source.

    By the way, it is not recommended using on-chip ADC of C2000 DSP if you want to get very high precision data.

    Thanks

    Yu Cai 

  • Thanks for the fast reply!

    The sensors output is digital. Should I still use som of the things you mention above?

  • what kinda digital interface that sensor use?

  • Edit:  Looks like your question was answered while I was typing.

     

  • Actually, to make sure if you code is running properly. Use a signal generator as clock source to check if your XINT1 ISR is working fine. And make sure to clear XINT1CR when leaving the ISR.

    for ur sensor part, make sure it's output is 3.3V logic if it's digital interface.

  • Thanks for all the answers. I'm very thankfull for the help! The accelerometer we are using is this one: http://www.parallax.com/Portals/0/Downloads/docs/prod/acc/MXD2125G&M.pdf

    Now it works :) We will now try to include the accelerometer. I hope it's okay to return to this post if other issues shows up. :)

  • Cong!

    Since the accelerometer sensor you are using is PWM waveform output. The easiest solution is using low pass filter (as suggested in the data sheet) to get the analog output and fed into the on-chip ADC of F2812. Using internal clock to sample it. Don't forget to put the voltage buffer between the accelerometer sensor and the analog input of ADC.

  • Hi!

     

    I am working together with Dado on this project, and we have a new question. We are not using DSP on-chip ADC, instead we are using the XINT1 and XINT2 pins in combination with interrupts for reading the pulses directly coming from the accelerometer. The way we are thinking of doing it is by connecting the X-axis and Y-axis outputs of the accelerometer to the XINT1 and XINT2 pins respectively. We have tried to modify our program (part shown below) to do this, but without succes. We are hoping to be able to read changes in the input values when tilting the accelerometer. Any ideas for changes?

     

    void main(void)

    {

    (... other code ...)

       GpioMuxRegs.GPEMUX.bit.XINT1_XBIO_GPIOE0 = 1;   // Input X Read from Acc | GPIOE0 is XINT1 pin

       GpioMuxRegs.GPEMUX.bit.XINT2_ADCSOC_GPIOE1 = 1;   // Input Y Read from Acc

     

       PieVectTable.XINT1 = &cpu_timer0_isr;

       PieVectTable.XINT2 = &cpu_timer1_isr;

     

       XIntruptRegs.XINT1CR.bit.ENABLE = 1;            // Enable XINT1 pin

       XIntruptRegs.XINT2CR.bit.ENABLE = 1; 

     

    // Enable CPU  is connected to CPU-Timer 0:

       IER |= M_INT1;

       IER |= M_INT2;

     

    // Enable TINT0 in the PIE: Group 1 interrupt 7

       PieCtrlRegs.PIEIER1.bit.INTx4 = 1;

       PieCtrlRegs.PIEIER1.bit.INTx5 = 1;

     

    // Enable global Interrupts and higher priority real-time debug events:

       EINT;   // Enable Global interrupt INTM

       ERTM;   // Enable Global realtime interrupt DBGM

     

    // Step 6. IDLE loop. Just sit and loop forever (optional):

       for(;;);

     

     

    interrupt void cpu_timer0_isr(void)

    {

       while(1){

       if (GpioDataRegs.GPADAT.bit.GPIOA0 == 0){

       XIntruptRegs.XINT1CR.bit.POLARITY = 1; // Triggers on rising edge

       }else 

       XIntruptRegs.XINT1CR.bit.POLARITY = 0; // Triggers on faling edge

       break;

       }

     

       Xout = CpuTimer0.InterruptCount++;

     

       // Acknowledge this interrupt to receive more interrupts from group 1

       PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

    }

     

    interrupt void cpu_timer1_isr(void)

    {

       while(1){

       if (GpioDataRegs.GPADAT.bit.GPIOA0 == 0){

       XIntruptRegs.XINT2CR.bit.POLARITY = 1; // Triggers on rising edge

       }else 

       XIntruptRegs.XINT2CR.bit.POLARITY = 0; // Triggers on faling edge

       break;

       }

     

       Yout = CpuTimer1.InterruptCount++;

     

       // Acknowledge this interrupt to receive more interrupts from group 1

       PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

    }

  • I think you guys want to use internal timer to count the duty cycle of the PWM output of the accelerometer sensors? Am I right? I don't think this is a good way to collect the Accelerometer sensor. F2812 has eCAP module to do this.

    If I were you, I will put two RC filter (or active low pass filter) in XOUT and YOUT of the accelerometer sensor and use ADCINA0 and ADCINA1 to collect these two channel signal. And /tidcs has example code and you don't need to do anything.

    Calculating duty cycle of PWM waveform by using two external interrupt is not a good (correct) way to do it.

  • Hi Yu Cai,

    Thanks for the reply!
    We have a few questions now, since you posted your last post. Just to make it clear, the outputs of the accelerometer are digital, so why convert them to analog by using the RC filter (or active low pass filter), and then back to digital again through the ADC?

    In your previous post you wrote:
    "By the way, it is not recommended using on-chip ADC of C2000 DSP if you want to get very high precision data."

    So we are a bit confused now?

    The example you are refering to from /tidfsc, is this one: Example_281xAdcSoc.c ? Please correct me if I'm wrong.

    I was wondering if it was possible to use the ADC peripherals as input pins, by setting them to input, and then use the same code with few changes, and store the positions in the end?

     

    Best
    Regards

    Dado & Jonas 

  • On chip ADC is normally not so accurate compared to off-chip ADC. I have bad experience of using F2812 on-chip ADC. But if you don't need very high accuracy, then it's OK.

    Converting the PWM output from XOUT and YOUT is recommended by the datasheet of accelerometer sensor and it's a popular way of converting PWM duty cycle information to useful information (PWM actually is a cheaper version of DAC). If you need to capture the duty cycle information from PWM waveform, it is recommended by using eCAP functionality of F2812. Which is not straightforward compared to on-chip ADC solution. And its real-time performance is not as good as on-chip ADC solution which I believe.

    The sample code is under /tidcs, i think it is adc_soc which I don't remember exactly. You can test it and don't need to change too much from the example code to get what u need.

    The on-chip ADC peripheral already has analog input. So before hooking up with you analog output from LPF, make sure its range is between 0 and 3V since that on-chip ADC range is 0~3V. If your output is not under this range, u need to add some external circuit (not that complicated) to convert it.  

    Do the real-time conversion you will get real-time accelerometer sensor data.

    Good Luck!

  • Hi again,

    Now we have tried to do what you suggested, using on-chip ADC with the Example_281xAdcSoc.c example file. We didn't change anything else than setting a Vcc pin for the accelerometer so that we could enable and disable it. We are monitoring LoopCount, Conversioncount and Voltage1[ConversionCount] as it says in the example, and LoopCount is just giving us different values which has a wide range, and Conversiontcount is giving different values between 0 and 9. Voltage1[ConversionCount] doesn't change value at all, it's just 0 all the time.

    We didn't change anything in the code. We made the RC circuit for the accelerometer, as suggested in the datasheet and now we are stuck again. Is it the code it's wrong with or? ?

  • 2 steps:

    1. I think you need to change a little bit of the Example_281xAdcSoc if you want to use ADCINA0 and ADCINA1 since the example's default setting is ADCINA3 and ADCINA2. If you have F2812 ezDSP evaluation kit, connecting the ADCINA0 or ADCINA1 to a power supply or voltage reference (if you have). Adjust the DC value of the power supply, to make sure the example code is working properly.

    2. Use mulitimeter or oscilliscope to check the output of RC filter for the accelerometer. making sure it has change when you tilt the accelerometer sensor. If it doesn't have any change, means something wrong with the analog front end. If it's working, then you can hook up to the DSP board.

     

  • Hello,
    I also have problem on timer0. I try to use it to interrupt my main program, but I can .I have followed the program you proposed, this programe here does not allow me to interrupt my main program could you help me please to intorrupt my main program. I thank you

    cordially