output compare waveform generation - MC9s12C32

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

output compare waveform generation - MC9s12C32

4,098 Views
pirate
Contributor I
Hi,

I am using a MC9s12C32 evaluation board. My timer is alreay configured for overflow inteerupt. I want to use the TImer OC3, 4, 5 and 6 channels to generate output waveform. This waveform geneartion is very time crictical so i am disabling the overflow interrupt but i couldnot reset the TCNT register to know exeactly where my waveform generation started and when it ended. Is there a way to do this. Has anybody done this before.
Any inputs will be very highly appreciated.

Thanks!!!
 
 
 
 
Added p/n to subject.


Message Edited by NLFSJ on 2008-02-27 06:10 PM
Labels (1)
0 Kudos
21 Replies

1,726 Views
pirate
Contributor I
I am not initilaising the OC3-6 interrupts anymore and have moved the acquire_data function outside the interrupt routine.
what is the increment in the while loop doing... I dont know what r u incrementing in the while loop.
can you please explain?

Thanks.
0 Kudos

1,726 Views
allawtterb
Contributor IV
It is testing the flag for each channel, if the flag is set (the compare has become true) it increments a variable.  All this shows is that the flags get set at different times as after the while loops complete Timer3 and 4 will have the same value but the others have different values.  The flags don't all become set at the same time, if they did Timer3,4,5 and 6 would all contain the same value at the end of the while loop.
0 Kudos

1,726 Views
pirate
Contributor I
attached is a document that describes the problem in more deatil.

Thanks!!!!


Message Edited by pirate on 2008-03-04 07:58 PM
0 Kudos

1,726 Views
colinh
Contributor I
Hi

Its a bit hard to see exactly whats going on - I would suggest setting a breakpoint on

    while(!(TFLG1 & 0x40))

and see what the contents of TFLG is the first time you hit this.  (BTW - It is good practice to clear pending interrupt flags during an init routine - you had this but have now commented it out)

I assume the register OC7M is all 0, or that OC7 is not being enabled somewhere else in your code?

Personally I dont like chopping and changing between output compare and direct control as some of the finer details of how this will work in all cases is not always clear in the documents. If you need to force an immediate value onto the pin then use the CFORC register. 

Out of curiousity, what triggers the call to acquire_data in the code you documented?

Regards
Colin
0 Kudos

1,726 Views
pirate
Contributor I
An Input switch press triggers the call to acquire_data......
0 Kudos

1,726 Views
kef
Specialist I
The problem is you disable OC pins by clearing TIOS register. When you enable TIOS again, OC triggers are in the state you left them after last waveform. To put OC pins in initial state, you should reconfigure output compares from set to clear logic and vice versa, then write to CFORC to force to state you just programmed. Suggested code:
 
Code:
// TCTL1/TCTL2 OM/OL bit defines#define COMPOFF   0#define COMPTOGG  1#define COMPCLEAR 2#define COMPSET   3// Somewhere you enable timer and configure TIOS register once//   // timer channels 6-3 are output compares//   TIOS |= (1<<6) | (1<<5) | (1<<4) | (1<<3);//void ForceInitialState(void){   // initial OC levels   TCTL12 = (COMPSET << 2*6) | (COMPCLR << 2*5) | (COMPSET << 2*4) | (COMPCLR << 2*3);   // force initial OC levels   CFORC = (1<<6) | (1<<5) | (1<<4) | (1<<3);}void StartWaveform(void){short usTCNT;   usTCNT = TCNT;   TC3 = usTCNT + 100;   TC4 = usTCNT + 105;   TC5 = usTCNT + 700;   TC6 = usTCNT + 1100;   // clear flags   TFLG1 = (1<<6) | (1<<5) | (1<<4) | (1<<3);   // switch to target OC levels   TCTL12 = (COMPCLR << 2*6) | (COMPSET << 2*5) | (COMPCLR << 2*4) | (COMPSET << 2*3);   // Since you aren't using interrupts, here you may wait for longest   // OC6 compare   while( !(TFLG1 & (1<<6)) );}

 
0 Kudos

1,726 Views
colinh
Contributor I
Not sure if I agree with this diagnosis - No more than a few instruction cycles before clearing TIOS to 0, TFLG1 is written with 0x78 thereby clearing the flags.  So hypothetically anyway we shouldn't be seeing these flags set when we come back into the routine next time around.

Nonetheless I agree with the approach in the suggested code.


0 Kudos

1,726 Views
kef
Specialist I
That should work once, maybe. I think pirate is calling OC3_Init periodically. After wait for OC6 flag is done, he exits to acquire_data, where he clears TIOS. Then the process repeats but noone clears output compare pin triggers. It's not enough to clear flags, something should be done around TCTL1/TCTL2.
0 Kudos

1,726 Views
colinh
Contributor I

We might be struggling against one thing Freescale do anywhere near as well as TI - they don't give us explicit logic diagrams showing the internal peripheral structures. 

Theoretically the compare event is 'gone' (it can have no further effect on logic) as soon as the TFLG bit is cleared, and pirate does seem to be doing that after each call to OC3_Init() in aquire_data(). This now cleared compare event should have no further effect on the output pin.  However if there is an internal flip-flop, preceding the output latch,  that the compare logic toggles, then this would not be effected by pirates direct control of the pin, and as soon as compare control is re-asserted the old flip-flop value takes effect on the pin again.

Just a theory :smileywink:


          

0 Kudos

1,726 Views
kef
Specialist I
I did test program that shows something similar to original problem. If you connect dual channel scope, one channel to PTT MARKPIN'th pin, another to PTT TESTPIN'th pin, you may note that 1st ouput compare seems to work, but further compares seem to not work, OC pin rises as soon as TIOS bit is set.
 
Code:
// TCTL1/TCTL2 OM/OL bit defines#define COMPOFF   0#define COMPTOGG  1#define COMPCLR   2#define COMPSET   3#define MARKPIN 3 // PT3 marks the setting bits in TIOS #define TESTPIN 2 // test OC2void main(void){   TSCR1 |= 0x80;   DDRT |= (1<<MARKPIN);      for(;;)   {   int i;      TFLG1 = (1<<TESTPIN); // clear flag      PTT |= (1<<MARKPIN);      TIOS |= (1<<TESTPIN); // change TCx config from IC to OC       PTT &= ~(1<<MARKPIN);      TFLG1 = (1<<TESTPIN);       // clear flag       //TCTL setup      TCTL12 = (COMPSET << 2*TESTPIN);            TFLG1 = (1<<TESTPIN);       // clear flag once more            *(&TC0 + TESTPIN) = TCNT + 3000;      TFLG1 = (1<<TESTPIN);        // and once more         for(i=0; i<5000; i++);  // delay            TIOS = 0;              // change all TCx config to IC   }}

 
 
 
0 Kudos

1,726 Views
pirate
Contributor I
I tried this in the simulator and i get same values for Timer3,Timer4 and different values for timer5 and timer 6.But still the waveforms on the GPIO line for these OC3-6 channels start at the same time.

Thanks.
0 Kudos

1,726 Views
pirate
Contributor I
Below is the code for what i am trying to acheive..The problem i am having is i see all the compare evnts happen to be at the same time. for example in OC3-init() if i am waiting for OC3 event all the other events happen at that time. and if i am waiting for OC6 event all the other events happen with OC6. Can you guys let me know what am i doing wrong?

void main(void)
{

 TOF_init();
 
  MODRR = 0x00;  //set port T as timer outputs
  DDRT = 0xFF;
  PTT = 0x50;
  EnableInterrupts;
  for(;:smileywink:{
           
                     
  }
}


void TOF_init(void)
{
  TSCR1 = 0x80;   // Enable TCNT, 4MHz in run mode
  TSCR2 = 0x80;   // TCNT prescale, TOI arm
 
/* Bottom three bits of TSCR2 (PR2,PR1,PR0) determine TCNT period
    divide  BootMode(24MHz)    Run Mode (4MHz)
000   1     42ns  TOF  2.73ms  250ns TOF 16.384ms
001   2     84ns  TOF  5.46ms  500ns TOF 32.768ms
010   4    167ns  TOF  10.9ms    1us TOF 65.536ms   
011   8    333ns  TOF  21.8ms      2us TOF 131.072ms
100  16    667ns  TOF  43.7ms      4us TOF 262.144ns
101  32   1.33us  TOF  87.4ms         8us TOF 524.288ms
110  64   2.67us  TOF 174.8ms   16us TOF 1.048576s
111 128   5.33us  TOF 349.5ms   32us TOF 2.097152s */
  TFLG2 = 0x80;   // initially clear TOF
  usTimer31to16 = 0;
}
__interrupt void TOF_Interrupt(void)
{
        usTimer31to16++;
    if (usTimer31to16 == 0xFFFF)
        {
           usTimer31to16 = 0;            
        }
     if (usTimer31to16 == 2)
       {      
              usTimer31to16 = 0;    
              acquire_data();
       }        
        
  TFLG2 = 0x80;          // acknowledge TOF
}
void OC3_Init(void)
{
    unsigned short      usTCNT;
    
    PTT = (PTT | 0x01);

    TFLG1 = 0x78;   // clear timer capture  interrupt register
    //  TSCR1 = 0x00;   //timer disable
    TIOS |= 0x78;   // activate TC6->3 as output compare
    TSCR2 = 0x00;   // TCNT prescale, Disable Timer overflow interrupt
    
    TIE  |= 0x78;

    //    C6        C5        C4        C3
    //   1 0       1 1       1 0       1 1
    //   LOW       HIGH      LOW       HIGH
    TCTL1 =   0x2E;  //change state  OC 6-4
    TCTL2 =   0xC0; //change state  OC 3
    //get the current TCNT
    usTCNT = TCNT;

    //setup the waveform to start sometime in the future
    TC3 = usTCNT + 100;
    TC4 = usTCNT + 105;
    TC5 = usTCNT + 700;
    TC6 = usTCNT + 1100;

    //  TSCR1 = 0x80; //timer enable

    while(!(TFLG1 & 0x40))
    {
    }

    TFLG1 = 0x78;    // clear timer capture  interrupt register
    TSCR2 = 0x80;   // enable Timer overflow interrupt

    PTT = (PTT & 0x01);
}
void acquire_data(void)
    {
   
        DisableInterrupts;
       
          
          
           OC3_Init(); //enables timer for output compare mode
          
          
           TIOS =0x00; //disable out put compare
            
            PTT = 0x50;
          
        EnableInterrupts;  
    }


Thanks!!!!!!!!!



0 Kudos

1,726 Views
allawtterb
Contributor IV
I don't know what you are trying to achieve with the posted code.  It seems that you are waiting for the timer overflow interrupt to occur twice then setting channels 3-6 to set/clear pins.  You wait for the last output compare to happen then exit and repeat the whole process again.  What exactly are you trying to do?
0 Kudos

1,726 Views
pirate
Contributor I
I want to generate the a waveform on the OC3-6 channels periodically....but my problem is that all the events OC3 to OC-6 happen at the sametime. Instead of happening at different times. My question is why is the output compare event for all the 4 channels happening at the samtime. if you look at the TC3-6 registers they should happen at different times. Right now i am waiting for the TC6 event to occur....so all the events happen at TC6 and i lieave the function after TC6 event. If i wait for TC3 event all the events happen at TC3 and the function is exited.

Again my question is why is not there is a time difference in the triggering of all the four channels?

Thanks!!!!!!
0 Kudos

1,726 Views
allawtterb
Contributor IV
How have you verified this? Running this through the simulator here they occur as they should, all at different times.
0 Kudos

1,726 Views
pirate
Contributor I
I am using the technological arts MC9S12C32 Evaluation Board. I am monitoring channels OC3-6 on an oscillloscope. I drive Port T line 0 high when i enter the routine and and drive it low when i exit to know when the OC3_Init() routine started and ended.

Can you please tell me how did you verify that its working?

Thanks.
0 Kudos

1,726 Views
kef
Specialist I
Do you have somewhere interrupt handlers for all OC3-OC6? In OC3_Init you are enabling OC3-OC6 interrupts:
 
TIE  |= 0x78;

, but I see no OC3-OC6 ISR's.
0 Kudos

1,726 Views
pirate
Contributor I
No i dont have any interrupt handlers for channels OC-3 to OC-6. I am enabling those channels as interrupt sources because i want the TFLG1 register bits for these channels to be set so that i can wait for these events in the same routine itself...

I have tried the same routine without enabling those interrupts but still the result was not different.

Thanks.
0 Kudos

1,726 Views
allawtterb
Contributor IV
You don't have to enable the interrupts for the flags in TFLG1 to be set when the compare happens.
 
All I did was change your while loop to:
Code:
    while(!(TFLG1 & 0x40))    {      if (TFLG1 & 0x08)         Timer3++;            if (TFLG1 & 0x10)         Timer4++;            if (TFLG1 & 0x20)         Timer5++;            if (TFLG1 & 0x40)         Timer6++;             }

 
Timer3-6 are volatile unsigned chars (volatile to make sure they were placed in RAM to be easy to monitor).  Timer4 flag and Timer3 flag will be the same value at the end of the while because the counts are very close (5 bus cycles different).
 
There are alot of unnecessary things in the code, you should only need to initialize many of the register once, you disable interrupts from within a function called by an ISR.
0 Kudos

1,726 Views
colinh
Contributor I
Hi

I am guessing that what you really want to do is control when the edges occur relative to "now" whatever that might be .  You dont need to reset the TCNT to do this.  You can set up your first edge to occur at a time relative to "now" by, for example, setting OCMPn = TCNT + T_EDGE_DELAY; (use the real register names), where T_EDGE_DELAY is the time from "now" to the first edge. If you want the following edges to be precise and relative to the preceding edge then you do something like OCMPn += T_EDGE2_DELAY; in the ISR for the output compare.

If "now" is an input signal that you have fed into an input capture then you can set your output compare time to be a defined time relative to the captured time stamp.

Is this the sort of thing you want to to? Hope this helps

Cheers
Colin

0 Kudos