about Timer on s12xDP512

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

about Timer on s12xDP512

3,338 Views
vinay
Contributor I
hi,
      I am working on s12xdp512 16 bit controller on codewarrioer 4,5 version. in my program i am using ECT timer as measuring a pulses in normal manner ie i am not using capture mode.just i wait for pulse and start timer and next pulse i get timer count from TCNT reg. my code like this
main()
{
 TSCR2=0x06; //  prescaler /32 3200 nsec
 TCNT=0;
 TSCR1_TEN=0;// timer off  
for(;:smileywink:
   {
              
             while(PTP_PTP1==0); // wait for pulse going to be rise
                if(TSCR1_TEN== 0) // timer off
                     {TSCR1_TEN=1;  }// timer on
                 else
                {
                      Timercount=TCNT;
                      TCNT=0;                          //reset timer count
                       PORTB_PB3=1;        // on LED
                      do
                      {
                       Check_Time=TCNT;
                      }
                      while(Check_Time<1562); // LED on till 5 msec count
                      PORTB_PB3=0;                   //off LED
                }
}        
 }                    
                    
 i am using 4 mhz   crystal and using PLL i make it 20 Mhz.
everthing is fine working in Debug mode ie i am running this program in debug mode LED on 5 mesc at every pulse . but when i am going to dump the .s19 file of this project on controller and after power on my controller the progrm not working.i am using demo board of softec HCS12S STARTER KIT.  kindly help me in this reguard.
                  but insted of main timer if i am using modulus counter above,the program works fine both in debug and normal running mode.
 
plz waiting for help
 
vinay
              
Labels (1)
0 Kudos
6 Replies

736 Views
kef
Specialist I
Hm, I thought you didn't read docs carefully, necause from HC11 times HC11 timer and all further HC12, S12 and S12X TIM and ECT modules didn't allow to reset or write TCNT in normal modes. XDP512 datasheet is bit confusing, maybe. For example in chapter 7.3.2.5 Timer Count Register (TCNT), it's written
 
Read: Anytime
Write: Has no meaning or effect
All bits reset to zero.
 
I beliebe it should be write has no meaning or effect in normal modes and write makes all bits reset to zero in special modes.
 

Here's what you may find in earlier S12D family ECT block guide

Write has no meaning or effect in the normal mode; only writable in special modes (test_mode = 1).

 

We usually debug with BDM pod in special mode, that's why TCNT=0; works. Of course it won't work in normal mode, write to TCNT , TCNT=0; will be always ignored.

You may fix your code easily. Instead of clearing TCNT you may just note the TCNT count, and later subtract it from new TCNT value. Modified code should work in both modes:

for(;:smileywink:
   {
              
             while(PTP_PTP1==0); // wait for pulse going to be rise
                if(TSCR1_TEN== 0) // timer off
                     {TSCR1_TEN=1;  }// timer on
                 else
                {
                      Timercount=TCNT;
                       PORTB_PB3=1;        // on LED
                      do
                      {
                       Check_Time=TCNT;
                       Check_Time -= Timercount;
                      }
                      while(Check_Time<1562); // LED on till 5 msec count
                      PORTB_PB3=0;                   //off LED
                }
}        
0 Kudos

736 Views
vinay
Contributor I
Thanks kef....
 
              there is no any way to reset the TCNT??? i just want to reset TCNT and resume agin from 0x0000. please give some anather hint! because in some cases my TCNT may get overflow then my calculations may get rong isn't it???
 
vinay
0 Kudos

736 Views
kef
Specialist I
TCNT is normally not writeable or resettable to zero. Except see TSCR2 register TCRE bit description. You may use this bit to clear TCNT on TC7 output compare.
 
Calculations won't get wrong on TCNT overflow. Example:
 
you detect rising edge on t1=TCNT=0xE000
...
some tousands ticks later TCNT overflows from 0xFFFF  to 0
...
few ticks later you detect another pulse edge, say at t2=TCNT=0x3000
 
 
Unsigned difference t2-t1=0x3000-0xE000=0x5000. Isn't it correct? Use windows calculator, scientific view->Hex, switch from QWord word size to Word and verify.
From t1=0xE000 to overflow it takes 0x1,0000-0xE000=0x2000 ticks, then from TCNT=0 to t2=0x3000 it takes 0x3000. 0x3000+0x2000=0x5000. Overflow won't hurt you while your pulse width is shorter than 0x1,0000 timer tickes. It absolutely makes no difference if you reset TCNT or remember starting TCNT value and then remove this bias later.
 
I know you want to make it simplier for now, you may not like S12X  timer. But IMO one free running and not writeable timer counter plus 8 input captures / output compares (IC/OC) is definitely way better than say 7 timers and 7 IC/OC. For me, having single free running timer and 8 IC/OC is the same like having 8 independent timers. Show me other MCU that has so many timers. I used PIC18Fx48 as lower end CAN enabled MCU. It had 2 IC/OC, 2 16bit timers and 2 8bit timers, IIRC. All it is a lot less flexible than single timer and 8 IC/OC.
 
0 Kudos

736 Views
kef
Specialist I
I want to add a bit. You wanted to use just timer counter hardware to implement single software timer, right?
 
- Resitting TCNT to zero you won't be able to use TCNT for anything  else than this single software timer.
- Not resetting TCNT to zero you could have as many software timers as you wish. Something like this:
 
unsigned short t0_0;             // timer 0 initial value
unsigned short t0_duration;  // timer 0 period duration
 
unsigned short t1_0;             // timer 1 initial value
unsigned short t1_duration;  // timer 1 period duration
 
...
 
unsigned short tN_0;             // timer N initial value
unsigned short tN_duration;  // timer N period duration
 
 
 
// start measuring something using timer 0
//    remember initial TCNT
t0_0 = TCNT;
 
....
 
 
// something happened, calculate duration, timer 0
t0_duration = TCNT - t0_0;
 
 
 
0 Kudos

736 Views
vinay
Contributor I
very very Thanks kef
           
   As per Your suggesition i calculate the differerence between two conjegative rising edges. i am able to calculate my RPM uptill 200RPM as per my prescalar setting. but i cant go below that RPM. after viewing i came to conclusion that my TCNT overfolws there so cant calculate RPM properly. plz check my code 
 
main()
{
  TSCR2=0x06; //  prescaler /32 3200 nsec  one tick
  TSCR1=0x00;// timer off
 for(;:smileywink:
   {
                      
                while(PTP_PTP1==0);
                if(TSCR1==0x00) // timer off
                {TSCR1=0x80;
                }// timer on
                else
                {
               
                      
                      New_Count=TCNT;
                      if(New_Count>Old_count)
                      {
                        Timercount=New_Count-Old_count;
                     
                      }
                      else
                      {
                        Timercount=((0xffff+New_Count)-Old_count);
                      }
                      
                      Old_count=New_Count;      // store old conut here
                      Rpm=Max_count_P/Timercount;
}
}
 
                    Now as i am getting correct RPM uptill 208 RPM, why i am not getting below that?? why not my overflow count not added to calculation? where i am going to be rong??
                   also i check with interrupt overflow but cant work!
 
plz help me
 
 
vinay
 
0 Kudos

736 Views
kef
Specialist I
Hi
 
1) I don't know your bus frequency, but I see in the code :
 
  TSCR2=0x06; //  prescaler /32 3200 nsec  one tick
 
 
First of all 0x06 stands for prescaler bus_clock_frequency/64, not bus_clock_frequency/32.  But if you are sure that timer tick is 3200nsec, then it's normal that your code doesn't work below 208RPM. Pulse edges should come more often than every 2^16=65536 timer ticks. That's 1/(3200nsec*65536)=4.77Hz or 286RPM.
 
 
2) Your code assumes that pulses are very short. Your while loop doesn't wait for pulse edge but loops while pulse is low. These two things are the same only if pulse width is shorter than it takes to execute the rest of your code in the for(;:smileywink: loop. You should fix it. Maybe try to use PTP interrupt flag?
 
 
3) You are complicating the things with this code.
 
                      if(New_Count>Old_count)
                      {
                        Timercount=New_Count-Old_count;
                      }
                      else
                      {
                        Timercount=((0xffff+New_Count)-Old_count);
                      }
No matter is New_count higher than Old_count or not, It should be just
 
                        Timercount=New_Count-Old_count;
                     
If your Timercount is 32-bits wide, then it should be
 
                        Timercount=(New_Count-Old_count) & 0xFFFF;
 
or this
 
                        Timercount=(unsigned short)(New_Count-Old_count);
 
 
4) Regarding making your code working below 200RPM. i would use input capture interrupt and timer overflow interrupt. But since you want no interrupts, then I'm suggesting to extend 16-bit hardware timer counter to software 32-bit timer counter. it could be done loading your wait for PTP==1 loop with this code;
 
 
               while(PTP_PTP1==0)
               {
                  // Sample TCNT
                  NewTCNT = TCNT;
 
                  // Maintain overflow counter.
                  // Detect TCNT overflow not using timer overflow flag.
                  // It will work while this code is executed at least once, every time
                  // TCNT overflows to 0 and before MSB of TCNT will set, in other words
                  // every time TCNT falls into 0..0x7FFF interval.
                  // NewTCNT and OldTCNT must of type signed short
                  if( NewTCNT>=0 && OldTCNT<0) OvfCount++;

                  // save current NewTCNT to be able to detect further timer overflows
                  OldTCNT=NewTCNT;
 
                  // combine NewTCNT and OvfCount into 32 bits mylongTCNT
                  mylongTCNT = ((unsigned long)OvfCount << 16) | NewTCNT; 
               };
 
 
 
// Here are veriable types and.

unsigned

long mylongTCNT;
unsigned short OvfCount;
signed short NewTCNT;
signed short OldTCNT;

unsigned long New_Count;
unsigned long Old_count;

unsigned long Timercount;
   // the rest of the code is almost the same, just change TCNT to mylongTCNT and verify Rpm formula
...
   else
   {
      New_Count = mylongTCNT;
      Timercount=New_Count - Old_count;
       Old_count = New_Count;
 
      Rpm = ... ;
   }
 
 
I hope it will work, I didn't test it
0 Kudos