IR Remote Controllers and receivers follow standard protocols for sending and receiving the data. Some of the standard protocols are NEC , JVC , SIRC (Sony Infrared Remote Control) etc. We will be discussing only the NEC protocol. After understanding the frame format of IR Remote, We will be interfacing a IR receiver with 8051 and decode the key pressed.

NEC Protocol

NEC IR protocol encodes the keys using a 32bit frame format as shown below.

NEC Frame Format
Address Complement of Address Command Complement of Command
LSB-MSB(0-7) LSB-MSB(8-15) LSB-MSB(16-23) LSB-MSB(24-31)

Each bit is transmitted using the pulse distance as shown in the image.
Logical '0': A 562.5µs pulse burst followed by a 562.5µs space, with a total transmit time of 1.125ms
Logical '0': A 562.5µs pulse burst followed by a 1.6875ms space, with a total transmit time of 2.25ms NecIrRemote 1.png

When a key is pressed on the remote controller, the message transmitted consists of the following, in order:

  1. A 9ms leading pulse burst (16 times the pulse burst length used for a logical data bit)
  2. A 4.5ms space
  3. The 8-bit address for the receiving device
  4. The 8-bit logical inverse of the address
  5. The 8-bit command
  6. The 8-bit logical inverse of the command
  7. A final 562.5µs pulse burst to signify the end of message transmission.

The four bytes of data bits are each sent least significant bit first. Below image illustrates the format of an NEC IR transmission frame, for an address of 00h (00000000b) and a command of ADh (10101101b).

A total of 67.5ms is required to transmit a message frame. It needs 27ms to transmit the 16 bits of address (address + inverse) and the 16 bits of command (command + inverse). NecIrRemote 0.png

IR Key Codes

Below table gives the complete list of Codes for NEC IR Remote.

Key Encoded Value
CH- 0xFFA25D
CH 0xFF629D
CH+ 0xFFE21D
PREV 0xFF22DD
NEXT 0xFF02FD
PLAY/PAUSE 0xFFC23D
VOL- 0xFFE01F
VOL+ 0xFFA857
EQ 0xFF906F
0 0xFF6897
100+ 0xFF9867
200+ 0xFFB04F
1 0xFF30CF
2 0xFF18E7
3 0xFF7A85
4 0xFF10EF
5 0xFF38C7
6 0xFF5AA5
7 0xFF42BD
8 0xFF4AB5
9 0xFF52AD


Sample Code

Below is the sample code to decode the key pressed on IR remote control and send on UART. We need an External interrupt to detect the pulses and timer to measure these pulse widths.

  • INT0(P2.2) will be configured as falling Edge interrupt to detect the pulses.
  • Timer0(Mode1) will be configured to generate a periodic interrupt of 1ms.

First two transitions will be ignored as they will mark SOF(Start of the frame). After this continuously 32-bit information will be captured in a variable. If the pulse width is greater than 2ms then it will be considered as LOGIC-1 else as LOGIC-0. If the pulse width is greater than 50ms then it will be considered as SOF(Start of the frame).

1ms Delay Calculation:

  • Clock Freq=11.0592 Mhz
  • Machine Cycle = 12
  • Delay=1ms

$$TimerValue= 65536 - ((Delay * ClockFreq)/Machine Cycle)=65536-((1ms * 11.0592Mhz)/12) = 65536 - 921= 0xFC67$$

/***************************************************************************************************
ExploreEmbedded Copyright Notice
****************************************************************************************************
* File: necIrRemoteExample1.c
* Version: 16.0
* Author: ExploreEmbedded
* Website: http://www.exploreembedded.com/wiki
* Description: Sample program to decode NEC IR Remote pulses and display on LCD using 8051 controller.
This code has been developed and tested on ExploreEmbedded boards.
We strongly believe that the library works on any of development boards for respective controllers.
Check this link http://www.exploreembedded.com/wiki for awesome tutorials on 8051,PIC,AVR,ARM,Robotics,RTOS,IOT.
ExploreEmbedded invests substantial time and effort developing open source HW and SW tools, to support consider
buying the ExploreEmbedded boards.
The ExploreEmbedded libraries and examples are licensed under the terms of the new-bsd license(two-clause bsd license).
See also: http://www.opensource.org/licenses/bsd-license.php
EXPLOREEMBEDDED DISCLAIMS ANY KIND OF HARDWARE FAILURE RESULTING OUT OF USAGE OF LIBRARIES, DIRECTLY OR
INDIRECTLY. FILES MAY BE SUBJECT TO CHANGE WITHOUT PRIOR NOTICE. THE REVISION HISTORY CONTAINS THE INFORMATION
RELATED TO UPDATES.
Permission to use, copy, modify, and distribute this software and its documentation for any purpose
and without fee is hereby granted, provided that this copyright notices appear in all copies
and that both those copyright notices and this permission notice appear in supporting documentation.
**************************************************************************************************/
/*************************
NEC IR Remote Codes
**************************
0xFFA25D: CH-
0xFF629D: CH
0xFFE21D: CH+
0xFF22DD: PREV
0xFF02FD: NEXT
0xFFC23D: PLAY/PAUSE
0xFFE01F: VOL-
0xFFA857: VOL+
0xFF906F: EQ
0xFF6897: 0
0xFF9867: 100+
0xFFB04F: 200+
0xFF30CF: 1
0xFF18E7: 2
0xFF7A85: 3
0xFF10EF: 4
0xFF38C7: 5
0xFF5AA5: 6
0xFF42BD: 7
0xFF4AB5: 8
0xFF52AD: 9
**************************/
#include <reg51.h>
#include "lcd.h"
#include "stdutils.h"
uint32_t bitPattern=0,newKey=0;
uint8_t timerValue;
uint8_t msCount=0;
char pulseCount=0;
void timer0_isr() interrupt 1
{
if(msCount<50)
msCount++;
TH0 = 0xFC; // Reload the timer value for 1ms Delay
TL0 = 0x67;
}
void externalIntr0_ISR() interrupt 0
{
timerValue = msCount;
msCount = 0;
TH0 = 0xFC; // Reload the timer value for 1ms Delay
TL0 = 0x67;
pulseCount++;
if((timerValue>=50)) // If the pulse width is greater than 50ms, this will mark the SOF
{
pulseCount = -2; // First 2 counts needs to be skipped hence pulse count is set to -2
bitPattern = 0;
}
else if((pulseCount>=0) && (pulseCount<32)) //Accumulate the bit values between 0-31.
{
if(timerValue>=2) //pulse width greater than 2ms is considered as LOGIC1
{
bitPattern |=(uint32_t)1<<(31-pulseCount);
}
else
{
}
}
else if(pulseCount>=32) //This will mark the End of frame as 32 pulses are received
{
newKey = bitPattern; // Copy the newKey(patter) and set the pulse count to 0;
pulseCount = 0;
}
}
void main()
{
/*Connect RS->P0.0, RW->P0.1, EN->P0.2 and data bus to P0.4 to P0.7*/
LCD_SetUp(P0_0,P0_1,P0_2,P_NC,P_NC,P_NC,P_NC,P0_4,P0_5,P0_6,P0_7);
LCD_Init(2,16);
TMOD |= 0x01; // Timer0 MODE1(16-bit timer)
TH0 = 0xFC; //Timer value for 1ms at 11.0592Mhz clock
TL0 = 0x67;
TR0 = 1; // Start the Timer
ET0 = 1; // Enable the Timer0 Interrupt
IT0 = 1; // Configure INT0 falling edge interrupt
EX0 = 1; // Enable the INT0 External Interrupt
EA = 1; // Enable the Global Interrupt bit
LCD_DisplayString("Init Done");
while(1)
{
if(newKey!=0) //Wait till newKey press is detected
{
LCD_Clear(); //Clear the LCD and Display the new Key Code
LCD_Printf("newKey:%X",newKey);
newKey = 0; //CLear the newKey value for next cycle
}
}
}

Using IR Remote Library

/***************************************************************************************************
ExploreEmbedded Copyright Notice
****************************************************************************************************
* File: necIrRemoteExample1.c
* Version: 16.0
* Author: ExploreEmbedded
* Website: http://www.exploreembedded.com/wiki
* Description: Sample program to decode NEC IR Remote and turn ON/OFF the bulb.
This code has been developed and tested on ExploreEmbedded boards.
We strongly believe that the library works on any of development boards for respective controllers.
Check this link http://www.exploreembedded.com/wiki for awesome tutorials on 8051,PIC,AVR,ARM,Robotics,RTOS,IOT.
ExploreEmbedded invests substantial time and effort developing open source HW and SW tools, to support consider
buying the ExploreEmbedded boards.
The ExploreEmbedded libraries and examples are licensed under the terms of the new-bsd license(two-clause bsd license).
See also: http://www.opensource.org/licenses/bsd-license.php
EXPLOREEMBEDDED DISCLAIMS ANY KIND OF HARDWARE FAILURE RESULTING OUT OF USAGE OF LIBRARIES, DIRECTLY OR
INDIRECTLY. FILES MAY BE SUBJECT TO CHANGE WITHOUT PRIOR NOTICE. THE REVISION HISTORY CONTAINS THE INFORMATION
RELATED TO UPDATES.
Permission to use, copy, modify, and distribute this software and its documentation for any purpose
and without fee is hereby granted, provided that this copyright notices appear in all copies
and that both those copyright notices and this permission notice appear in supporting documentation.
**************************************************************************************************/
#include <reg51.h>
#include "stdutils.h"
#include "nec_ir.h"
sbit RELAY_PIN = P3^4;
void main()
{
uint32_t key;
RELAY_PIN = 0; // Turn OFF the relay during Init
IR_RemoteInit(); // Initialtile the INTO and Timer0 for decoding the IR pulses
while(1)
{
key = IR_RemoteGetKey(); // Read the key press, it returns key code if key press is detected, else it returns 0
switch(key)
{
case IR_CODE_1: RELAY_PIN = 1; break; /* Turn On Relay(Bulb) if 1 is pressed*/
case IR_CODE_0: RELAY_PIN = 0; break; /* Turn OFF Relay(Bulb) if 0 is pressed*/
default: break;
}
}
}

Downloads

Download the complete project folder from this link: Examples and Code Library


Have an opinion, suggestion , question or feedback about the article let it out here!