cancel
Showing results for 
Search instead for 
Did you mean: 

create a frequency, use CC1 as overflow

schulzm-free
Associate II
Posted on February 16, 2012 at 16:18

Hello, I want to create flanks with an Timer4 interrupt. I works if i use the interrupts from

 external flanks. Now I want to create the flanks with an internal frequency. Its a little

 complicated to describe all so I only describe the  problem.

Timer 4 CC3 and CC4 are used to create the outputsignal-flanks with an interrupt. For a

 new flank I have to load a new value in the CC3 or CC4. But if i have a frequency wich is

 less than 2^16/72MHz  => 918µs... I need a counter for the overflows. The counter is set

 to with the number of overflows and counts down with ever CC1-flag.

Every time if I load the interrupt CCs i also load the CC1 with the same value. Now I can

 check with the CC1 flag if the timer pass the 918µs after the last flank. But if the

 new CC1 is to close the old CC1 one CC1-flag is left. I tryed to correct this by checking

 the distance beween old CC1 and new CC1 and if the distance is to low (less than

 25000) I add 2^15 to the value of CC1. Oncurrent I decrease the overflowcounter

 because now it has to run on time more. Now it seems that the overflow is one to less if

 the distance is more than 19000. So I get 1 Flag to much. If the distance is more than

 5000 the outputsignal is correct. Is there a better way to do this or what is the bug in the

 program?   

       

//new frequency

     

if

(Test_lock == RESET)       

//if new flag is ready

      {

        n_Tim4_exte_CC1 = (n_Frequency >>

16

) +

1

//timerextension CC1

       

//if CC1 is set with + 2^15

       

if

(test_CC1 ==

1

)

        {

          n_Tim4_exte_CC1--;

          test_CC1 =

0

;

          TIM_ClearFlag(TIM4, TIM_FLAG_CC1);

        }

       Test_lock = SET;             

//lock this function

}

     

//32 bit extension

     

if

(TIM_GetFlagStatus(TIM4, TIM_FLAG_CC1) == SET   &&    

//if timer pass CC1 

         n_Tim4_exte_CC1 >

0

   )         

//if not all overflow completed

         

                 {

        n_Tim4_exte_CC1 --;

        TIM_ClearFlag(TIM4, TIM_FLAG_CC1);

      }

     

//free for next outputflank 

     

if

(n_Tim4_exte_CC1 ==

0

                      && 

//extension is 0

        

          Flag_pos_Flank_dumped== SET         &&  

//last flanks finshed

        

          Flag_neg_Flank_dumped== SET        )

      {

       Flag_High_Flank = SET;               

//function to set the new interrupts can be used 1 time

       n_Timer4_output_start_pos = (n_Timer4_Impulsestart + n_Frequency);

//new outputflank value

      

Test_lock = RESET;               

//enable first if-function again

       

//if the new CC1 is to close the the old CC1 

   

       

if

((n_Timer4_output_start_pos > n_Timer4_Impulsestart                             &&

        (n_Timer4_output_start_pos - n_Timer4_Impulsestart) <

25000

)                 ||

        (n_Timer4_output_start_pos < n_Timer4_Impulsestart                                 &&

        (

65535

- n_Timer4_Impulsestart + n_Timer4_output_start_pos) <

25000

))

        {

          TIM_SetCompare1(TIM4, (n_Timer4_output_start_pos +

32767

)); 

//set CC1 opposite

          test_CC1 =

1

;

          TIM_ClearFlag(TIM4, TIM_FLAG_CC1);

        }

       

else

        {

          TIM_SetCompare1(TIM4, n_Timer4_output_start_pos); 

//set CC1 at the same value like the new flank

        }

      }

0690X000006050FQAQ.png

I hope someon can help me.. thank you.

                     
4 REPLIES 4
Posted on February 16, 2012 at 17:30

Well, I'm confused.

If you want low frequencies, you might want to seriously consider increasing the prescaler, and getting courser granularity. What resolution/granularity do you need for you settings, what range of frequencies are you looking to support?

Are you toggling pins, is this under interrupt? If interrupting, you have to clear the CCx otherwise the routine will just tail-chain back into itself.

If you want a clean, more long term time base, look are the 32-bit core counter in the trace unit, this overflows at ~1 min.

Consider if you can use SysTick to create yourself a 1 ms time base (900 us or whatever),  and use that to program the ''phase'' for the CCR firing.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
schulzm-free
Associate II
Posted on February 16, 2012 at 17:53

Posted on February 16, 2012 at 19:07

You should be able to attach bitmaps like other files, and then check the address in the attachment view, and edit/paste it directly into the post.

Anyway, consider computing the CC placement in units of 13.88 ns (1/72MHz), as a 32-bit or 64-bit variable. Use CC2 to trigger a mid point interrupt (0x8000, 405.11 us), and use the Update interrupt (0x10000, 910.22 us), if the event occurs within the next 910us you set the appropriate CCR values. You do this by decrementing 0x8000 from the time to placement variable at each interrupt, and then check if the value is less than 0x10000. Then offset that value by 0 or 0x8000, modulo 0x10000 depending if you are in the first or second half of the count.

The reason to do it twice per period is that you can then deal with 455 us of latency, and will avoid missing tight placements. ie you are placing the CC some 455-910 us early.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
schulzm-free
Associate II
Posted on February 17, 2012 at 16:13

I am not sure that I understand all. I tryed it in this way but it dint worke. I think there is a bug in the if where I add the 0x8000

//

first run

if

(Flag_first_ready==

RESET

)

{

Flag_first_ready=

SET

;

n_Tim4_extension_CC1 = n_Frequency + n_Timer4_Impulsestart;

TIM_SetCompare1(TIM4, 0x8000);

ADC1_Konv_Wert = 5000;

TIM_ClearFlag(TIM4, TIM_FLAG_CC1);

TIM_ClearFlag(TIM4, TIM_FLAG_Update);

}

//

new frequency

if

(Test_lock ==

RESET

)

{

n_Tim4_output_Startvalue_pos = n_Timer4_output_ Startvalue _pos_new;

// value for CC3, CC4 Interrupt

Test_lock =

SET

;

//

locked

}

//32 Bit

extension

if

((TIM_GetFlagStatus(TIM4, TIM_FLAG_CC1) ==

SET

||

TIM_GetFlagStatus(TIM4, TIM_FLAG_Update) ==

SET

) &&

n_Tim4_

extension

_CC1 > 0x8000 )

{

n_Tim4_extension _CC1 = n_Tim4_

extension

_CC1 - 0x8000;

TIM_ClearFlag(TIM4, TIM_FLAG_CC1);

TIM_ClearFlag(TIM4, TIM_FLAG_Update);

}

//

enable next protocol

if

(n_Tim4_Erweiterung_CC1 < 0x10000 &&

//

extension ans outputs ready

         

n_counter_protocoldata > (Protocollength - 1) &&

Flag_pos_Flank_output ==

SET

&&

Flag_neg_Flank_output ==

SET

)

{

Flag_High_Flanke =

SET

;

//

enable function to create a new protocol

n_Tim4_cnt_act = TIM_GetCounter(TIM4);

n_Tim4_extension_CC1 = n_Frequency + n_Timer4_output_Startvalue_pos;

n_Timer4_output_Startvalue_pos_neu = n_Tim4_extension_CC1;

if

(((n_Timer4_output_ Startvalue _pos_neu < n_Tim4_cnt_akt) && (n_Tim4_cnt_act > 0x8000) && (n_Timer4_ output _ Startvalue_pos_neu < 0x8000)) ||

((n_Timer4_output_ Startvalue_pos_neu > n_Tim4_cnt_akt) && (n_Tim4_cnt_act < 0x8000) && (n_Timer4_ output _ Startvalue_pos_neu > 0x8000)) ||

((n_Timer4_output_ Startvalue_pos_neu < n_Tim4_cnt_akt) && (n_Tim4_cnt_act < 0x8000) && (n_Timer4_ output _ Startvalue_pos_neu < 0x8000)) ||

((n_Timer4_output_ Startvalue_pos_neu < n_Tim4_cnt_akt) && (n_Tim4_cnt_act > 0x8000) && (n_Timer4_ output _ Startvalue_pos_neu > 0x8000)))

{

n_Tim4_extension_CC1 = n_Tim4_extension_CC1 + 0x8000;

}

TIM_ClearFlag(TIM4, TIM_FLAG_CC1);

TIM_ClearFlag(TIM4, TIM_FLAG_Update);

Test_lock =

RESET

;

//

enable 2. if

  

}

I forget someting to say:

''

n_Timer4_Impulsestart'' has the ''n_Tim4_output_Startvalue_pos'' value. The transfere happens in the function will be activated with ''Flag_High_Flanke =

SET''.