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.

Generating high frequency signal with MSP430

Hi,

I need to generate a very fast signal (40 KHZ) (which consists of an array of 0s and 1s) and this signal is sent to one of the GPIO pins on ez430-rf2500 board. This array is generated based on the values of the other array that is read from the memory (I declared  this other array as a const array at the begining of the code).
I use 16MHz DCO and a TimerB to generate the fast interrupts that will trigger reading of const array values and generate an output signal at the GPIO. Also, I use IAR Workbench 4.11b.

So, my code looks something like this:

main()
{

...    //  some code goes here

  TimerB0_Init();

  do
  {
     __bis_SR_register(LPM0_bits + GIE);
     ReadCoeff();

  }while(TimerControl==0);

  ...    //  some code goes here

}


void ReadCoeff()
{

   if (aCounter >= COEFFICIENT_LENGTH-1)
   {

     TimerControl = 1;

     aCounter = 0;
     cCounter = 0;
    }


   if (cCounter == 0)   //read new coeff
   {
     m_coeff = coeffs[aCounter];
     aCounter++;
   }
  
   if (m_coeff != 0)       
   {
     switch (cCounter)     
     {
     
      case 0:
        P2OUT &= ~(BIT1);  
        break;
   
      case 3:   
        P2OUT &= ~(BIT1); 
        break;  
   
      default:     
        P2OUT |= (BIT1);  
        break;
 
     }
 
     switch (m_coeff)   
     {
      case 1:
       P2OUT |= (BIT2);  
       break;
      
      case 2:
       P2OUT &= ~(BIT2);
       break;
    
      default:
       break;
     }
  
   }
   
}



void TimerB0_Init()
{
 TBCCTL0 = CCIE;                           // TBCCR0 interrupt enabled
 TBCCR0 = TIMER_PERIOD;                           // TIMER_PERIOD = 100;
 TBCTL = TBSSEL_2 + MC_1;                  // SMCLK, upmode
}


#pragma vector=TIMERB0_VECTOR
__interrupt void Timer_B (void)
{
 switch (TimerControl)
 {

 case 1:
     ...  //  some code goes here
  break;
 
 default:
   __bic_SR_register_on_exit(LPM0_bits);
  break;
  
 }
}


However, it seems that I cannot generate the output signal at the GPIO so fast: by looking on the output at the oscilloscope, I see that some signal samples on the GPIO are missing -- like it takes too much time to go through the ReadCoeff() and an interrupt occurs before the end of this function. But, the TIMER_PERIOD, that controls the number of cycles before an interrupt occurs is set to 100 -- by  looking into the number of instructions called during the ReadCoeff() on IAR it seems that  100 cycles is enough for the MSP430 to go  through the ReadCOeff() function.

So, my question is why I cannot generate the fast signal by using my code?
Is there a better routine that I should use in order to generate a high frequency signal at the GPIO?

Any input is  really appreciated, thanks!

  • You can set TIMER_PERIOD to 1000 to test if you get the correct waveform correctly (but 10 slowly).

    The code shown does not make sense to me. Maybe you have introduced typos or omitted relevant  lines.

  • I have tried with TIMER_PERIOD = 200 and I'm pretty sure that I'm getting the correct waveform. But when I decrease the TIMER_PERIOD, I'm not getting the same signal anymore.

    Yes, I haven't put the whole code, I thought this piece of code is enough to get the feeling of what the code is doing. Main() function actually contains more code, but here I put only the relevant part:

     

    main()
    {

    ...

    TimerControl = 0;

    TimerB0_Init();

    do
    {
       __bis_SR_register(LPM0_bits + GIE);
       ReadCoeff();

    }while(TimerControl==0);


    ...

    }

    Could you please tell me why do you think that the code doesn't make sense?

    Thanks!

     

  • If it works with TIMER_PERIOD = 200 but not 100, then you know that the do{...}while (...); takes between 100 and 200 SMCLKs to finish.

    You get 60 k-bit/second but not 120 k-bit/second. Correct? How fast do you want?

    ---

    To speed it up with your current scheme, you need to simplify and optimize ReadCoeff().

    There are details in your current code that I do not understand. For example:

    If cCounter is not 0, aCounter will not change and TimerControl will remain to be 0 so the do {..} whlie (...); loop will be forever.  Every time, you will use the same old m_coeff, you will do the same operation on P2OUT BIT1 and BIT2, this will not produce anything new.

    On the other hand, if cCounter is 0, you will always clear BIT1 of P2OUT which will not produce anything new either,

    If m_coeff is 0, you do not do anything. If it is not 0, the switch(M_coeff) default also says you do not do anything. Why test for !=0 and not rely on the default? I thought you want to either clear or set a bit. Why do you want to do nothing?

    ---

    If you can use the USCI (instead of the Timer and GPIO) to generate a bit pattern, I think you can get a few Meg-bit/second. You can use either A0 or B0 in the SPI master mode and only put SIMO on a pin. SOMI and CLK are generated but not using any pin.

    ---

    Is there any other interrupt while you are doing this? If so, it may need to be disabled.

  • Hi old_cow_yellow,

    Thanks for the input. Sorry, I have omitted the piece of code at the beginning of  ReadCoeff() function:

    void ReadCoeff()
    {

        cCounter++;
        if (cCounter == 4)
        {
         cCounter = 0;
        }

    ...
    }


    So, what I'm trying to do is the following:

    read the one coefficient from coeffs
    m_coeff = coeffs[aCounter];

    and if m_coeff is different than 0, then for each m_coeff generate 4 samples (this is why I need cCounter, which counts from 0 to 3).

    Also, I generate two signals. The first signal that goes to  P2.1 depends on the cCounter (this corresponds to the first switch loop).
    The other signal that goes to P2.2 depends on the value of m_coeff (which can be 0,1,2), so that when m_coeff == 1 or m_coeff ==2 P2.2 is either 0 or 1 (this corresponds to the second switch loop).
    The condition that these two signals at P2.1 and P2.2 need to meet is that these two signals cannot change at the same edge.  

    In switch(m_coeff) you are right,  I should use default instead of having two cases.    

    So I hope that this explains what I'm doing. I don't have any other interrupts going on.

    So, when the interrupts are generated every 100 cycles, the signal at P2.1 should have frequency of 40KHz. However, I get around 31.1KHz. Interestinlgly, if I comment out the condition

    if (m_coeff != 0)


    and leave everything within this "if" condition unchanged, the frequency of the signal at P2.1 is around 39.3KHz, but still not 40KHz.


    Is it possible that IAR compiler adds some overhead, which causes the additional delays/cycles?

     

    Thanks!

     

  • What P2.1 frequency do you get when you set TIMER_PERIOD = 200?

    (The current code does not work correctly at TIMER_PERIOD = 100, thus the frequencies you stated in your previous posting are meaningless.)

    Can you show me the contents of the entire constant array coeffs[]?

    (The frequency of P2.1 depends on the contents of coeffs[] as well as TIMER_PERIOD.)

     

     

**Attention** This is a public forum