cancel
Showing results for 
Search instead for 
Did you mean: 

Infrared Timer (IRTIM) in STM32F4

shara
Associate II
Posted on October 26, 2016 at 03:00

Hello, I trying to make IR transmitter with STM32F4DISCOVERY demoboard and found in

http://stmcufinder.com/wp-content/uploads/training/STM32L4-WDG_TIMERS-Infra-Red-Timer-%28IRTIM%29.swf

that it F4 MCU should have built-in periph for mixin PWM from two timers - one for carrier frequency and second for signal modulation.

0690X00000605SOQAY.png

0690X00000605HbQAI.png

But I can't find such thing in datasheet or reference manual. Is it there?

And what is the best way to make IR transmitter without this thing? I made two timers - carrier, which connected to GPIO and data modulator, which toggling carrier in interrupt, but I think it can be done better.

#stm32f4 #irtim
10 REPLIES 10
Posted on October 26, 2016 at 09:24

There is no uniform 'F4 family in this regard. If by F4DISCOVERY you mean the DISCO with 'F407 on board, or the other one with 'F429 (and a TFT LCD display), those are fairly old models which do not have this feature.

You can chain two timers, master providing modulation and slave the carrier, slave in gated mode. You then need to consider timing so that in the gaps the LED is not driven.

JW
Walid FTITI_O
Senior II
Posted on October 26, 2016 at 13:41

Hi name.shara, 

There is no RITIM modulator in STM32F4xx device. The IR transmitter and receiver can be used in the STM32F0, STM32F3 and STM32L4 series.

This is a wrong table, please refer to the online training on the official ST website at this

http://www.st.com/content/st_com/en/support/learning/stm32l4-online-training.html

<

After the reference manual as information source, I recommend the application note 

http://www.st.com/content/ccc/resource/technical/document/application_note/group0/36/b5/60/26/50/c7/46/4a/DM00271524/files/DM00271524.pdf/jcr:content/translations/en.DM00271524.pdf

 and the related firmware he X-CUBE-IRREMOTE.

Although STM32L4xx MCUs feature the IRTIM, the STM32L476G-EVAL board is not equipped with the necessary IR components. The X-CUBE-IRREMOTE therefore does not support this EVAL board.

-Hannibal-
shara
Associate II
Posted on October 27, 2016 at 23:48

Thanks all

shara
Associate II
Posted on October 28, 2016 at 03:00

I'm trying to make Gated Mode where TIM3 is master, TIM4 is slave (carrier) in PWM mode. But. When TIM3 pauses TIM4, GPIO pin can be in high mode and it stucks in this position until TIM4 unpaused.

Can I turn off GPIO pin when TIM3 disabled?

Posted on October 28, 2016 at 09:03

> I'm trying to make Gated Mode where TIM3 is master, TIM4 is slave (carrier) in PWM mode.

> But when TIM3 pauses TIM4, GPIO pin can be in high mode and it stucks in this position until TIM4 unpaused.

This is what I meant by

>> You then need to consider timing so that in the gaps the LED is not driven.

Usually, modulation is in integer multiples of carrier, so it should be possible to start both timers simultaneously (starting them after each other in software with disabled interrupts should result in only a few clocks of difference which might suffice), and set the modulation change (i.e. value of compare register of the modulation timer) to a point when the carrier timer's output is low. This should result in the desired behaviour provided the timers never stop and the modulation is achieved by only changing output compare mode of the modulation timer.

JW

shara
Associate II
Posted on October 28, 2016 at 09:43

Nope, i tried to make command sequence of

http://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol

with one timer at 38kHz in pwm mode and DMA, but it's not working. Signal periods is not divisible to carrier i think and i think that receiver counts time, not impulses.

Will try to test this theory with interrupts.

Posted on October 28, 2016 at 10:40

>Signal periods is not divisible to carrier

In that case, use the modulator timer to trigger a DMA which changes the carrier's compare mode.

JW

shara
Associate II
Posted on October 28, 2016 at 12:20

I was right, made first working sketch:

  • Timer input frequency 76 kHz
  • Carrier: Timer 4 channel 1 in PWM mode (Prescaler: 19, Counter Period: 99, Pulse: 50 â€�? result frequency: 38 kHz, duty cycle: 50%)
  • Data: Timer 3 with global interrupt (Prescaler: 75, Counter Period: 1)
  • In PWM_Data array periods between level change in µs {9000-1, 4500-1, 560-1, 565-1, ...}

In interrupt I set:

  • New Counter Period for Data Timer (TIM3)

    TIM3->ARR = PWM_Data[pwm_data_pos];
  • Toggle Carrier Timer (TIM4) and pins

    HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);

    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);

But this method so dirty. Can you explain your idea?

Posted on October 28, 2016 at 13:50

> Timer input frequency 76 kHz

You meant 76MHz, isnt't it?

Note that in that protocol all timing elements are multiple of  562.5us (let's call it T - let's denote T.1 a 562.5us burst of 38kHz pulses, and T.0 a 562.5us pause): 1 is 1xT.1 + 1xT.0, 0 is 1xT.1 + 3xT.0, the preamble is 16xT.1 + 8xT.0; and the entire repeat code is 16xT.1 + 4xT.0 + 1xT.1.

So, for your example of TIM4_CH1 and TIM3_CH1:

- set up TIM4_CH1 prescaler/ARR for the carrier as you've described, except setting TIM4_CCMR1.OC1M to 0b100 (force inactive), enable CC1 and enable timer

- set TIM3_CH1 prescaler/ARR to a 562.5us period, enable DMA upon update by setting TIM3_DIER.UDE,  enable timer

- decompose the required code into T.0 and T.1, e.g. the example http://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol (addr=0x00, cmd=0xAD) would be 11111111111111110000000010101010101010101000100010001000100010001000100010001010001010001000101000101000101000101010001010 (the final 0 is not in the protocol, but needed to end with the LED switched off)

- in SRAM, into an array uint32_t nec_data[122] store value of TIM4_CMMR1 setting .OC1M to any of the PWM for 1, and setting .OC1M to Force inactive for 0

- for the DMA stream/channel respective to TIM3_CH1, set non-cyclic, memory-to-peripheral, 122 transfers of word; memory increment and address to nec_data, peripheral nonicrement and address is TIM4_CCMR1

- enable DMA stream

You can test it without DMA, simply replacing the DMA by an interrupt which does nothing just

static uint_least8_t i;

TIM4->CMMR1 = nec[i];

i++;

if (i >= 122) {

  // disable this interrupt now

}

JW