Input Capture on MC9S08QG8

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

Input Capture on MC9S08QG8

跳至解决方案
2,940 次查看
mnemonic
Contributor III

Hello!

 

I failed trying initialize input capture mode for a couple of days on this device. I am little frustrated at this moment.

 

I am not so new to freescale controllers, working on different HC08/ HCS08 and HCS12 types. I started two years ago from zero, never done coding before. But at this time I can say that these controllers are very "cool" and I like the work with them.

 

To my setup/problem:

 

I have a windsensor wich sending pulses to my QG8 Demoboard. The windsensor is driven by two fans wich I can control in speed. I have also a debouncing circuit between my sensor and the QG8. I want in the end configuration measuring the windspeed. Input capture seems to be the best solution for me. I also have to say, I never worked with the TPM Module before.

 

I have two variables

 

TPMCH0VAL_RISE: DS.B   2
TPMCH0VAL_FALL: DS.B   2

 

and reading/store the channel register by

 

ldhx TPMC0VH+TPMC0VL

sthx TPMCH0VAL_RISE

 

I can also do another way

 

mov TPMC0VH,TPMCH0VAL_RISE

mov TPMC0VL,TPMCH0VAL_RISE+1

 

Wich is the better way?

 

In Debug mode I can see that the variable TPMCH0VAL_RISE do not change when I let the fans blowing faster or slower. (This is my problem)

 

Here is my code:

 

In this code I trying to understand the basics of the input capture function. This means that this code is not the "last word". I only trying here to capture a rising edge and store it to my variable in the first step. If this works I will try to switch to falling edge cause I have to measure one period. One period consists falling and rising edge.

 

TPMCH0VAL_RISE: DS.B   2
TPMCH0VAL_FALL: DS.B   2
TPMCH0VAL:      DS.B   2
;
; code section
;
            ORG    ROMStart

_Startup:
            LDHX   #RAMEnd+1                   ;initialize the stack pointer
            TXS
            lda #%00000011                      ;ResetPin enable
            sta SOPT1
            lda #%10010111                      ;OSC Trimm ~8MHz
            sta ICSTRM
            mov #%11000111,ICSC1           ;int. Osc. on
            mov #%00000000,ICSC2           ;ext. Osc. off
            CLI                                       ;enable interrupts
            jsr init_timer                           ;initialize the timer
mainLoop:
           
           
           
           
            BRA    mainLoop

init_timer:
                                    
            mov #%00000000,TPMMODH   ;I am not sure what should stand here for input capture
            mov #%00000001,TPMMODL    ;But I know I should write a value in it for normal counter operation
            mov #%01000100,TPMC0SC    ;Timer 1 Channel 0,Input capture only, rising edges only
            mov #%00001000,TPMSC        ;Interrupt disabled, work as input capture, busclock = sourceclock, Divided by 1
            rts

;**************************************************************
;* spurious - Spurious Interrupt Service Routine.             *
;*             (unwanted interrupt)                           *
;**************************************************************
spurious:                                          ; placed here so that security value
            NOP                                    ; does not change all the time.
            RTI

 

TPMOVF_ISR:                                   ;I will never come here with this timersetup
            sei
            nop                      
            cli
            rti

TPMCH0_ISR:                                    ;Start of Timer 1 Channel 0 ISR

RISING_EDGE:
            ;pshh                                  ;save H:X
            sei                                      ;disable (whole) interrupts
            ldhx TPMC0VH+TPMC0VL        ;Load 16 Bit value to Index Register
            sthx TPMCH0VAL_RISE           ;save content to "my defined Ram variable"
            lda TPMC0SC
            bclr 7,TPMC0SC                    ;clear Channel 0 Flag
            ;mov #%01011000,TPM1C0SC ;setup Channel 0 for falling edge (i also should
                                                     ;measure the other side of one period)
FALLING_EDGE:
           
            ;brclr 7,TPM1C0SC,FALLING_EDGE  ;wait here for the falling edge
            ;ldhx TPM1C0VH+TPM1C0VL          ;Load 16 Bit value to Index Register
            ;sthx TPM1CH0VAL_FALL              ;save content to "my defined Ram variable"
            ;lda TPM1C0SC
            ;bclr 7,TPM1C0SC                       ;clear Channel 0 Flag
            ;mov #%00001000,TPM1SC          ;Interrupts enabled, work as input capture,
                                                           ;busclock = sourceclock, Divided by 1,
                                                           ;this stand here cause I do only

                                                           ;once a timer initialisation after reset and 
                                                           ;this should be enought
           
            ;pulh                           ;restore H:X
            cli                            ;enable (whole) interrupts
            rti                            ;End of interrupt

;**************************************************************
;*                 Interrupt Vectors                          *
;**************************************************************
            ORG   Vrti
           
            DC.W  spurious        ; RTI  
            DC.W  spurious        ; RESERVED2
            DC.W  spurious        ; RESERVED3
            DC.W  spurious        ; ACMP
            DC.W  spurious        ; ADC
            DC.W  spurious        ; KEYBOARD
            DC.W  spurious        ; IIC
            DC.W  spurious        ; SCITX
            DC.W  spurious        ; SCIRX
            DC.W  spurious        ; SCIERR
            DC.W  spurious        ; SPI
            DC.W  spurious        ; MTIM
            DC.W  spurious        ; RESERVED 13
            DC.W  spurious        ; RESERVED 14
            DC.W  spurious        ; RESERVED 15
            DC.W  spurious        ; RESERVED 16
            DC.W  spurious        ; TPMOVF
            DC.W  spurious        ; TPMCH1
            DC.W  TPMCH0_ISR      ; TPMCH0
            DC.W  spurious        ; RESERVED
            DC.W  spurious        ; LVD
            DC.W  spurious        ; IRQ 
            DC.W  spurious        ; SWI
            DC.W  _Startup        ; RESET
END

 

 

Can anyone tell me please am I on the right way?

 

Wich way is better to save the content of the Timerregister mov or ldhx?

 

 How I can see "more" in Debug mode?

 cause this? 

***When background mode is active, the timer counter and the coherency mechanism are frozen such that the

buffer latches remain in the state they were in when the background mode became active even if one or

both bytes of the counter are read while background mode is active.***

 

 

In the Datasheet stands:

 

When either byte of the 16-bit capture register is read, both bytes are latched into a buffer to support

coherent 16-bit accesses regardless of order.

 

WHere is this buffer? 

 

 

 

 

Please give me somone some input wich I can capture!:smileyhappy:

 

Best regards

 

Ingo Kauf

 

 

   

 

Message Edited by mnemonic on 2009-08-09 08:52 PM
标签 (1)
0 项奖励
回复
1 解答
714 次查看
mnemonic
Contributor III

Hello Peg!

 

Thank you for those Documents! Very nice!

 

I found also a online training video about the TPM Module.

 

Best regards,

 

Ingo Kauf

 

 

在原帖中查看解决方案

0 项奖励
回复
5 回复数
714 次查看
bigmac
Specialist III

Hello Ingo,

 

In addition to the problem mentioned by Tony P, I see that you have a modulo setting of $0001.  This would mean that the 16-bit counter would toggle between $0000 and $0001 values, not what you require.  The modulo setting should be either zero (free running) or $FFFF to maximize the TPM overflow period.  I suspect there may be some misunderstanding of the input capture process.

 

If the period you are trying to measure should exceed the TPM overflow period, you will also need to take into account the number of overflows that occurs, which is a much more complicated process.  If you choose not to count the overflows, there will be a minimum wind speed that can be measured.  In this case, you will still need to monitor the overflows so that the period reading may be rejected if two overflow events should occur without at least one intervening input capture event.

 

Another possibility for increasing the range of the period measurement, and maintain accuracy at higher speeds, would be to dynamically change the prescale setting to increase the overflow period for low wind speeds, and reduce the overflow period for higher speeds.

 

If the wind velocity sensor generates a number of pulses for each revolution of the anemometer, it should only be necessary to calculate the total period between pulses, say between the occurrence of each positive edge.  It shouldn't be necessary to handle the timing of the opposite edge.

 

The way I would handle the period calculation would be to maintain RAM storage for the previous capture value TPREV, and the current period value PERIOD, and also the prescale value associated with the reading, if this is variable.

 

So within the TPM channel ISR,

   ; PERIOD = TPMC0V - TPREV  16-bit modulo calculation

   lda  TPMC0VL

   tax

   sub  TPREV+1

   sta  PERIOD+1

   lda  TPMC0VH

   psha

   pulh

   sbc  TPREV

   sta  PERIOD

 

   ; Update TPREV ready for next event

   sthx TPREV
 

The 16-bit PERIOD value will then need to be processed to calculate the wind speed, preferably using integer arithmetic, and presumably a wind speed display is then updated. 

 

Regards,

Mac

 

0 项奖励
回复
714 次查看
mnemonic
Contributor III

Hello Mac, Hello tonyp! 

 

Mac, you´re right. I am not (really) clear in the functions of the TPM module. I also never worked with the TPM module before. But I want to learn more about the functions of the TPM. For my basic understanding I wrote two programs. The first one starts the counter, counting up to a value and switches a LED on if the value is reached. The second uses the external clock source which comes from my anemometer, counting the pulses and after reaching the value in Modulo Register a LED starts to light. 

 

Then I was trying to undestand the input capture function. The code in my first post, you can call it V 1.0, was my first experiment with the input capture function. After a my Post I ported the code to my MC9S08AW60 Demoboard cause there is one whole Port connected to a 8 Bit LED Band on PortF. So I can see more as on the QG8 Demoboard which have only two LED´s on it.

 

After reading the post from tonyp i modified the Timer ISR. I know that normally the H Register should be saved. But in this case i was not sure. It is a so small code only two interrupts and no hard 16 Bit instructions to Index Register. Now I am just reading the TPM1C0VL by lda and store it to my variable. In my MainLoop I load the variable and put it on PortF. I am able now to see what the timer do in input capture mode. The value in my variable change so fast and differs from my understanding. I thought that if the speed from my anemometer does not change, then the variable should be the same value since the last interrupt. That´s not the case! So I was trying to Stop and clear the timer in my ISR to get a new count. That´s also not working. I am talking about a ~8Mhz busclock and pulse about 20ms. I do not undestand why the value in my variable change so hard. It should be a linear value. 

 

After this I modify the ISR to compare the TPM1CNTL and the TMP1C0VL Registers. These Registers have never the same value but I think there should be the same value in it. Confusing! 

 

I have asked some questions about the input capture function which i am interrested in.

 

Could you please tell me: 

 

In the Datasheet stands: When either byte of the 16-bit capture register is read, both bytes are latched into a buffer to supportcoherent 16-bit accesses regardless of order. 

Where is this buffer? Do you have an address? $xxxx 

 

How I can see "more" in Debug mode? cause this?  ***When background mode is active, the timer counter and the coherency mechanism are frozen such that thebuffer latches remain in the state they were in when the background mode became active even if one orboth bytes of the counter are read while background mode is active.***(Is it general a problem to debug Interrupt routines?) 

 

Wich way is better to save the content of the Timerregister mov or ldhx?(This is clear and allready explained by tonyp.) 

 

Do you know a application note which handles the Timer?  

 

Please correct me if i am wrong, 

 

The counter starts counting up from zero in free running mode if all 16 Bit in the modulo register are set to zero.  

 

In input capture mode, the counter is working continuously and writes the value of the current status in the channel value register immediately after an input capture event occurs.

 

Normally, measuring pulses (one pulse period) is done by adding the rising and the falling edge.

 

 

I really understand what you are telling me in your answer. Also the way you are going in your code. I think the most problem I have is handling and understanding the TPM Module. That can not work in a few days, that must have time. Three days for complete undestanding a HCS08 Timer is too short and without helpful experts like you and tonyp it´s allmost unpossible. 

 

May if you are not so busy it would be nice to get an answer on my questions.

 

Thank you very much,  

 

Best regards, 

 

Ingo Kauf

0 项奖励
回复
714 次查看
peg
Senior Contributor IV

Hello Ingo,

 

This document should help you. It is for the predecessor of the TPM, but it is essentially the same to use.

The coherency buffer is invisible to the user, it is at the same address.

The counter counts up from zero UNTIL it reaches the value in the modulo register, where it changes to zero.

 

Here  is another document that may assist with your understanding of the TPM.

 

0 项奖励
回复
715 次查看
mnemonic
Contributor III

Hello Peg!

 

Thank you for those Documents! Very nice!

 

I found also a online training video about the TPM Module.

 

Best regards,

 

Ingo Kauf

 

 

0 项奖励
回复
714 次查看
tonyp
Senior Contributor II

One obvious error is the use of TPMC0VH+TPMC0VL (addition of two consecutive addresses) as the target address for loading HX.  You only need to supply the TPMC0VH (the address of the MSB of the 16-bit location) to the LDHX instruction.  What you do ends up reading from a completely different memory address which is not related to the TPM.  Anyway, having seen that, I didn't bother checking for any further mistakes.  Correct this and let us know if you're still having trouble.

 

And you DO need the PSHH/PULH in the ISR but not the CLI before the RTI.

Message Edited by tonyp on 2009-08-09 11:24 PM
0 项奖励
回复