cancel
Showing results for 
Search instead for 
Did you mean: 

Could Anyone here please help me with RC5 Decoding in STM32F0

AKHIL VARGHESE
Associate II
Posted on March 14, 2017 at 08:35

I am beginner in STM32 Programming. I need to code the IR,RC5 Remote protocol in stm32f0 microcontroller. Please help me to do coding it.

 

 

https://community.st.com/tags♯/?tags=timer%20delay

 

‌

‌

Thanks and Regards

Akhil 

#timer-delay #stm32f0 #stm32f30f4 #rc5 #rc5_protocol
9 REPLIES 9
Posted on March 15, 2017 at 20:41

OK, so what do you have already done? What HW do you have? Did you successfully write and run a LED blinky?

JW

T J
Lead
Posted on March 15, 2017 at 22:36

did you see this link ?

http://www.sbprojects.com/knowledge/ir/rc5.php

you would use two timers for sure...

basically the bit shifter would be under the 1st timer interrupt control

run the 1st timer overflow at twice the frequency ie 72KHz so you have 2 phases

in the shifter, if its a one, shift zero in the first phase then the one in the second phase

if its a zero, shift a one first then a zero.

1st timer interrupt

stop the 2nd timer now

check the on phase/ off phase

to shift a zero phase, just exit the 1st timer interrupt

to shift a one phase, run a 2nd timer at the spike frequency and set the pulse length to a few counts.(probably best to use PWM output here)

after setting the 2nd phase move shifting pointer to next bit of the data

Posted on March 16, 2017 at 06:20

Hi,

Thanks for replying to my question.

I have done the coding for stm32f030f4p6 microcontroller. I have successfully done coding the led and PWM Output for led brightness control.

Now i have to do RC5 coding,for which i connected the IR Sensor in Pin PA4 and used Timer Input capture method. I am getting an output for the decoded value,but it is not in proper way. Output is coming only after pressing the remote key for long time.

I am posting the code i have done, kindly please go through it and help me to decode the command and address properly.

void init_timer()

{

TIM14->PSC = 47;

TIM14->ARR = 2220;

//TIM14->CR1 |= (1<<8);

TIM14->CR1 &= ~(3<<8); //Clock division tDTS = tCK_INT

TIM14->CR1 &= ~(1<<1); //UEV Enabled

TIM14->CR1 |= (1<<7); //TIMx_ARR register is buffered

TIM14->CR1 |= (1<<2); //Only counter overflow generates an UEV if enabled

TIM14->CCMR1 |= 1; //CC1S Input Capture mode 01

//TIM14->CCMR1 |= (1<<2); //ICIPSC Presacler value capture is done once every 2 events

// TIM14->CCMR1 |= TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1; //(3<<4); //IC1F Input digital filter

TIM14->CCER |= TIM_CCER_CC1E; //(1); //CC1E: Capture/Compare 1 enable.

TIM14->CCER |= (1<<1);//Falling edge CC1NP and CC1P Value

TIM14->DIER |= 2; //CC1 Capture interrupt enabled, Update Intrpt Disabled

TIM14->CR1 |= (1); //Counter enabled

NVIC_EnableIRQ(TIM14_IRQn);

}

void TIM14_IRQHandler(void)

{

int read;

if ((TIM14->SR & TIM_SR_CC1IF) != 0)

{

//if ((TIM14->SR & TIM_SR_CC1OF) != 0)

//{

TIM14->SR = 0X0000;

read = TIM14->CCR1; //read input capture value

cnt++;

if(read >=640 && read <= 1140 )

//if(read >=883 && read <= 895)

//if(read == 889)

{

data = data<<1;

}

else if(read >= 1340 && read <= 2220)

//else if(read == 1778)

//else if(read >= 1772 && read <= 1784)

{

data <<= 1;

data |= 1;

}

if(cnt>=13)

{

cnt=0;

data &= 0x7FF;

data >>= 6;

data &= 0x1F;

}

if(data == 0x19)   //Address = 0X19

{

GPIOA->BSRR |= (1<<7);   //LED ON

}

}

}
Posted on March 16, 2017 at 06:35

Hi,

Thanks for replying to my question.

I have tried using timer input capture method and got a partial output i can say. I used only one timer. Since i am not much familiar with the timer function i couldn't able run 2 timer together as you said. Kindly go through the code i have pasted here and help me any suggestion son this.

Thanks and Regards

Akhil

void init_timer()

{

TIM14->PSC = 47;

TIM14->ARR = 2220;

//TIM14->CR1 |= (1<<8);

TIM14->CR1 &= ~(3<<8); //Clock division tDTS = tCK_INT

TIM14->CR1 &= ~(1<<1); //UEV Enabled

TIM14->CR1 |= (1<<7); //TIMx_ARR register is buffered

TIM14->CR1 |= (1<<2); //Only counter overflow generates an UEV if enabled

TIM14->CCMR1 |= 1; //CC1S Input Capture mode 01

//TIM14->CCMR1 |= (1<<2); //ICIPSC Presacler value capture is done once every 2 events

// TIM14->CCMR1 |= TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1; //(3<<4); //IC1F Input digital filter

TIM14->CCER |= TIM_CCER_CC1E; //(1); //CC1E: Capture/Compare 1 enable.

TIM14->CCER |= (1<<1);//Falling edge CC1NP and CC1P Value

TIM14->DIER |= 2; //CC1 Capture interrupt enabled, Update Intrpt Disabled

TIM14->CR1 |= (1); //Counter enabled

NVIC_EnableIRQ(TIM14_IRQn);

}

void TIM14_IRQHandler(void)

{

int read;

if ((TIM14->SR & TIM_SR_CC1IF) != 0)

{

//if ((TIM14->SR & TIM_SR_CC1OF) != 0)

//{

TIM14->SR = 0X0000;

read = TIM14->CCR1; //read input capture value

cnt++;

if(read >=640 && read <= 1140 )

//if(read >=883 && read <= 895)

//if(read == 889)

{

data = data<<1;

}

else if(read >= 1340 && read <= 2220)

//else if(read == 1778)

//else if(read >= 1772 && read <= 1784)

{

data <<= 1;

data |= 1;

}

if(cnt>=13)

{

cnt=0;

data &= 0x7FF;

data >>= 6;

data &= 0x1F;

}

if(data == 0x19)   //Address = 0X19

{

GPIOA->BSRR |= (1<<7);   //LED ON

}

}

}
Posted on March 16, 2017 at 08:10

I cannot go through your code.

you only need to transmit, correct ?

initialize:

I suggested using the 1st timer overflow interrupt at 72KHz, did you start there ? check it on a cro. (Oscilloscope)

then you set a 2nd timer set to 256KHz roughly, (does the spec say ?)  with PWM mode with approx, 5% duty cycle. 

in 1st timer interrupt:

when you need to send pulses, enable the 2nd timer pwm,

when you need to send low signal, disable the 2nd timer pwm.

this is your work to do... please don't ask me to do your work.

I am happy to guide you.

Posted on March 16, 2017 at 08:30

Hi

I think you have misunderstood my question.

I have to decode the RC5 Code received in the IR Sensor.

Sorry if i confused You.

Regards 

Akhil

Nazim Nuriev
Associate II
Posted on March 16, 2017 at 10:02

Look ar AN3174 - Implementing an RC5 infrared remote control receiver

Posted on March 16, 2017 at 10:36

OK so you want to measure time between successive trailing edges and make received-0-or-1 decision based on that time in the ISR.

First, you don't rely on any fixed period. That means, you cannot simply read out the captured time from TIM14->CCR1. You need to calculate the time *elapsed since the last edge*, i.e. remember the last readout from the previous time the interrupt fired, in a global variable, and subtract the it from the current readout. For this to work, you need to take into account counter overflows, so better set ARR to maximum value (0xFFFF) and do time_difference = (new_readout - old_readout) & 0xFFFF;.

You might need also to count the counter overflows (i.e. enable interrupts also on update events and input capture events; and in  the interrupt routine distinguish whether it was update or capture (or both)) - in case of multiple overflows between capture events it's a long intercharacter gap which needs a restart (see below).

Next, decide what to do if the measured time falls outside the intervals you determined (and you might to fine tune further) for 0 and 1.

  • If it's below the shortest time, it's probably some noise around the edges; you might decide to either restart (see below) or ignore it, but in the latter case then you can't advance the counter and you can't modify the 'last edge's readout' so that the time counts up toward the next edge properly.
  • if it's in between the intervals for 0 and 1, then it's some error in decoding and you have to restart (see below). Some prefer not to have this interval gap between 0 and 1 - this increases false positives and decreases false negatives, it's questionable which is more desirable in the target application
  • if it's above the longest time,  it's an intercharacter gap, which needs a restart

Restart is, when you zero your cnt.

JW

Posted on March 16, 2017 at 10:52

Thank You so much for Your Reply.

I will try to do in this method.

Regards 

Akhil