cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 timer2 input capture

turboscrew
Senior III
Posted on March 10, 2017 at 15:46

I'm trying to use timer2 ch2 for input capture, but I don't seem to get it to work.

I wonder what am I doing wrong?

I don't use CMSIS or any other libraries.

Here's my set-up:

    nvic[NVIC_ICER_0] |= 0x10000000; // disable tim2 IRQ

    nvic[NVIC_ICPR_0] |= 0x10000000; // clear tim2 pending

    tim2[TIM_DIER] &= 0xffffa0a0; // disable timer interrupts

    tim2[TIM_CCER] = 0x000000000; // disable channels

    /* switch timer2 ch2 for input capture on falling edge */

    /* put input capture routine to 'interrupt vector' */

    dht_intvec = dht_irq_capt;

    /* T2 should be PA1 by default */

    tim2[TIM_CCMR1] = (tim2[TIM_CCMR1] & 0x00000000)

        | 0x00000100; // CC2S=T2, OC1M = 000, IC2F = 000

    tim2[TIM_CCER] = 0x00000030; // ch2 falling edge, capture enable    /* pin PA1 = tmr2_ch2 */

    /* Input pull-up/down: min. 30kOhm, typ. 40kOhm, max. 50kOhm */

    gpioa[GPIO_CRL] = (gpioa[GPIO_CRL] & 0xffffff0f)

            | 0x00000080;

    /* PA1 pull-up - line up to end the start pulse */

    gpioa[GPIO_ODR] |= 0x00000002;

    /* enable interrupts */

    tim2[TIM_SR] &= 0xffffe1a0; // clear flags

    tim2[TIM_DIER] = (tim2[TIM_DIER] & 0xffffa0a0)

        | 4; // CC2IE (enable capture 2 interrupt)

    nvic[NVIC_ICPR_0] |= 0x10000000; // clear tim2 pending

    nvic[NVIC_ISER_0] |= 0x10000000; // enable tim2 IRQ (28)

The time base runs fine - I've checked by reading the CNT-register, and

output compare seems to work.

#timer2 #input-capture #stm32f103
9 REPLIES 9
T J
Lead
Posted on March 10, 2017 at 22:32

this is a terrible way to program the most important parts of you code..

and I think your problem will be in these lines;

   tim2[TIM_DIER] &= 0xffffa0a0; // disable timer interrupts

   gpioa[GPIO_CRL] = (gpioa[GPIO_CRL] & 0xffffff0f)

   tim2[TIM_DIER] &= 0xffffa0a0; // disable timer interrupts

   tim2[TIM_SR] &= 0xffffe1a0; // clear flags

   tim2[TIM_DIER] = (tim2[TIM_DIER] & 0xffffa0a0)

the whole point of portability is to use the provided Constants,that's why we have CMSIS

My advice is don't hard code anything, otherwise you can't expect it to work anywhere else and it will be trouble to get working.

turboscrew
Senior III
Posted on March 11, 2017 at 00:54

For someone who remembers 'CAN_MCR_INRQ' or 'CAN_BTR_LBKM'.

Especially when writing the code.

(Psst... '2 << 20 | 3 << 16 | 5 << 0'.) 😉

Those are actually hard to remember, when you deal with, say, 3 or 4 different devices:

Raspberry Pi, PowerPC, TI C6000-series DSP, ...

And I have come across several others with my ~20 years career with embedded programming.

At the moment I'm only dealing with STM32F103 and Raspberry Pi 2B.

And maybe Atmel atMega 169. All hobby-stuff.

If you are interested, Some time ago I wrote 'rpi_stub' - a bare metal GDB agent for Raspberry Pi 2B that uses

serial line:

https://github.com/turboscrew/rpi_stub

.

That too without any libraries.

Posted on March 11, 2017 at 00:16

 ,

 ,

'the whole point of portability is to use the provided Constants' I thought the other way: constants being used for

achieving portability?

My point is rather, if there are some settings missing or in wrong order. Or if something else is clearly wrong.

I'd like to see a description about what should happen to the HW in correct initialization, not how to use a library

that I don't really have a clue of what it actually does, to achieve it.

I'd like to understand it, not just to get away with it.

Well, partly those weird constants came from misunderstanding of 'Reserved, must be kept at reset value'. :D

Should have realized that 'reset value' = 'zero', not the value it contained at reset.

(And I'm not the only one that has misunderstood that initially, I heard.)

Now I know that 'tim2[TIM_DIER] &,= 0xffffa0a0,' could have been written as 'tim2[TIM_DIER] = 0,'.

The first four 'f's come from writing 16-bit entity as 32-bit word. The a0a0-part comes from the fact that

bits 15, 13, 7 and 5 are 'Reserved, must be kept at reset value'.

The GPIO_CRL-setting if fine - that I know, and the e1a0-part of SR-value: bits 15, 14, 13, 8, 7 and 5

are 'Reserved, must be kept at reset value'. That could also be written as 'tim2[TIM_SR] = 0'.

(BTW some of what you picked were not whole logical lines.)

I think the comments help too:

 ,/* Input pull-up/down: min. 30kOhm, typ. 40kOhm, max. 50kOhm */

 ,

 , ,  ,gpioa[GPIO_CRL] = (gpioa[GPIO_CRL] &, 0xffffff0f)

 ,

 , ,  , , ,  , , ,  ,| 0x00000080,

 ,tim2[TIM_DIER] = (tim2[TIM_DIER] &, 0xffffa0a0)

 ,

 , ,  , , ,  ,| 4, // CC2IE (enable capture 2 interrupt)

Like I mentioned, I don't use CMSIS or any other library - not even C standard library (except stdint.h).

This is a hobby/learning project. The professional stuff I do very differently.

I don't like to have textual definition for 'millions' of individual bits. I'll never remember them.

Web-programming comes to mind. You can't get even a small calculator program working without

downloading and installing tons of libraries first, some of which have version conflicts... :D

This close to HW isn't portable anyway. Even CMSIS has different code for different chips - ♯ ifdef'd in the files.

In most other contexts I would use named constants.

Posted on March 11, 2017 at 00:27

I used HAL for portability; eg.

        CAN->MCR |= CAN_MCR_INRQ;                                                             // (1)

        

        while ((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)             // (2)

        {

        // add time out here for a robust application

        }

        

        CAN->MCR &=~ CAN_MCR_SLEEP;                                                         // (3)

        CAN->BTR |= CAN_BTR_LBKM | 2 << 20 | 3 << 16 | 5 << 0;                     // (4)

        CAN->MCR &=~ CAN_MCR_INRQ;                                                            // (5)

        

        while ((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)             // (6)

        {

        // add time out here for a robust application

        }

this is much easier to read and bug free after you fix it.

turboscrew
Senior III
Posted on March 11, 2017 at 15:07

Forget it. I found the problem.

It was kinda rude, to give someone the finger as the first answer.

T J
Lead
Posted on March 11, 2017 at 22:49

huh ? are you referring to me ?

I was not rude, just pointing out how your coding style is inadequate for portability and debugging.

what was the fix ?

0xffffc1a0  not  0xffffe1a0 ?

ST processors have very good pin matching across many different processors, that's why it is imperative to use the portability constants.

We are all learning here, with some exceptions it seems.

Posted on March 11, 2017 at 23:38

>>

It was kinda rude, to give someone the finger as the first answer.

The question did lean towards 'what's wrong with my unique and unnecessarily awkward code', and doesn't look to be compilable by anyone else but yourself. When you do that you tend to limit the subset of people who might want to dig into it, and have to expect to rescue yourself when you inevitably fall over.

The use of 32-bit arrays and defines does seem awfully prone to causing issues. Using the C structs provided would seem to involve less work and less potential for issues, and makes the compiler do a lot of the work using code that has a thousand eyes on it.

I don't think any offence was meant, rather a 'what-the-heck are you doing, your head's going to hurt when you hit the pavement' kind of thing between colleagues.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
turboscrew
Senior III
Posted on March 12, 2017 at 03:59

Do you see my earlier response that's 'Currently being moderated.'?

Or is it visible only to me?

'...and doesn't look to be compilable by anyone else but yourself'

Well nobody's piece of code taken from the middle of everything else usually is,

except that I don't even use any libraries, so there are no library dependencies. 😉

In that sense it should be even more generally compilable than the ones that use

specific libraries... 😉

I have my reasons to do it that way this time.

Usually I'm writing more like this (also a hobby project):

https://github.com/turboscrew/rpi_stub

 

(Feel free if you have some use for it.)

At work a bit more 'high-level' way (when portability and maintainability by others is needed).

There are sometimes need to do things differently...

turboscrew
Senior III
Posted on March 12, 2017 at 13:16

And the problem was a wrong index value of the TIM_CCMR1. I somehow missed the TIM_RCR

(that only exist in advanced timers).