//This decoding program is suitable for decoding NEC's upd6121 and its compatible chips, and supports most remote control experimental boards using 11.0592MHZ crystal oscillators
#include
#include
sbit IR=P3^2; //Define the IR bit as the P3.2 pin
sbit RS=P2^0; //Register selection bit, define the RS bit as the P2.0 pin
sbit RW=P2^1; //Read and write selection bit, define the RW bit as the P2.1 pin
sbit E=P2^2; //Enable signal bit, define the E bit as the P2.2 pin
sbit BF=P0^7; //Busy flag bit, define the BF bit as the P0.7 pin
sbit BEEP = P3^6; //Buzzer control port P36
unsigned char flag;
unsigned char code string[ ]= {"1602IR-CODE TEST"};
unsigned char a[4]; //Store user code, user inverse code and key data code, key data inverse code
unsigned int LowTime,HighTime; //Store high and low level width
/********************************************************
Function: Delay 1ms
*******************************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*********************************************************
Function: Delay for several milliseconds
Entry parameter: n
*******************************************************/
void delay(unsigned char n)
{
unsigned char i;
for(i=0;i
}
/************************************************************/
void beep() //Buzzer beeps function
{
unsigned char i;
for (i=0;i<100;i++)
{
delay1ms();
BEEP=!BEEP; //BEEP negation
}
BEEP=1; //Turn off the buzzer
delay(250); //Delay
}
/********************************************************
Function: Determine the busy status of the LCD module
Return value: result. result=1, busy; result=0, not busy
***************************************************/
unsigned char BusyTest(void)
{
bit result;
RS=0; //According to the regulations, when RS is low and RW is high, the status can be read
RW=1;
E=1; //Read and write are allowed only when E=
1_nop_(); //No operation_nop_
();
_nop_();
_nop_(); //No operation for four machine cycles, giving the hardware reaction time
result=BF; //Assign the busy flag level to result
E=0;
return result;
}
/*********************************************************
Function: Write the mode setting instruction or display address to the LCD module
Entry parameter: dictate
*******************************************************/
void WriteInstruction (unsigned char dictate)
{
while(BusyTest()==1); //If busy, wait
RS=0; //According to the regulations, when RS and R/W are both low, you can write instructions
RW=0;
E=0; //Set E to low level (according to Table 8-6, when writing instructions, E is a high pulse,
// that is, to make E jump from 0 to 1, so it should be set to "0" first
_nop_();
_nop_(); //No operation for two machine cycles, giving the hardware time to react
P0=dictate; //Send data to port P0, that is, write instructions or addresses
_nop_();
_nop_();
_nop_();
_nop_(); //No operation for four machine cycles, giving the hardware time to react
E=1; //Set E to high level
_nop_();
_nop_();
_nop_();
_nop_(); //No operation for four machine cycles, giving the hardware time to react
E=0; //When E jumps from high level to low level, the LCD module starts to execute the command
}
/********************************************************
Function: specify the actual address of the character display
Entry parameter: x
******************************************************/
void WriteAddress(unsigned char x)
{
WriteInstruction(x|0x80); //The display position is determined as "80H+address code x"
}
/*********************************************************
Function: write data (standard ASCII code of the character) to the LCD module
Entry parameter: y (character constant)
*******************************************************/
void WriteData(unsigned char y)
{
while(BusyTest()==1);
RS=1; //When RS is high and RW is low, data can be written
RW=0;
E=0; //E is set to low level (according to Table 8-6, when writing instructions, E is a high pulse,
// that is, to make E jump from 0 to 1, so it should be set to "0" first
P0=y; //Send data to P0 port, that is, write data to LCD module_nop_
();
_nop_();
_nop_();
_nop_(); //No operation for four machine cycles, give hardware reaction time
E=1; //E set high level_nop_
();
_nop_();
_nop_();
_nop_(); //No operation for four machine cycles, give hardware reaction time
E=0; //When E jumps from high level to low level, LCD module starts to execute command
}
/********************************************************
Function: Initialize the LCD display mode
************************************************/
void LcdInitiate(void)
{
delay(15); //Delay 15ms. When writing instructions for the first time, the LCD should be given a longer reaction
timeWriteInstruction(0x38); //Display mode setting: 16×2 display, 5×7 dot matrix, 8-bit data interfacedelay
(5); //Delay 5ms
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x0C); //Display mode setting: display on, cursor on, cursor flashingdelay
(5);
WriteInstruction(0x06); //Display mode setting: cursor moves right, characters do not
movedelay(5);
WriteInstruction(0x01); //Clear screen instruction, clear the previous display contentdelay
(5);
}
/************************************************************
Function: Decode 4 bytes of user code and key data code
Description: If the decoding is correct, return 1, otherwise return 0
Export parameter: dat
*************************************************************/
bit DeCode(void)
{
unsigned char i,j;
unsigned char temp; //Store decoded data
for(i=0;i<4;i++) //Continuously read 4 user codes and key data codes
{
for(j=0;j<8;j++) //Each code has 8 digits
{
temp=temp>>1; //Each data bit in temp is shifted right by one bit, because the high-order data is read first
TH0=0; //Timer clear 0
TL0=0; //Timer clear 0
TR0=1; //Start timer T0
while(IR==0) //If it is low level, wait
; //Low level timing
TR0=0; //Close timer T0
LowTime=TH0*256+TL0; //Save low level width
TH0=0; //Clear the timer
TL0=0; //Clear the timer
TR0=1; //Turn on timer T0
while(IR==1) //If it is high level, wait
;
TR0=0; //Turn off timer T0
HighTime=TH0*256+TL0; //Save the high level widthif
((LowTime<370)||(LowTime>640))
return 0; //If the low level length is not within a reasonable range, it is considered an error and the decoding stopsif
((HighTime>420)&&(HighTime<620)) //If the high level time is around 560 microseconds, that is, count 560/1.085=516 timestemp
=temp&0x7f; //(520-100=420, 520+100=620), then this bit is 0
if((HighTime>1300)&&(HighTime<1800)) //If the high level time is around 1680 microseconds, that is, the count is 1680/1.085=1548 times
temp=temp|0x80; //(1550-250=1300,1550+250=1800), then the bit is 1
}
a[i]=temp; //Store the decoded byte value in a[i]
}
if(a[2]=~a[3]) //Verify whether the key data code and its inverse code are equal. Generally, there is no need to verify the user code
return 1; //Decoding is correct, return 1
}
/*------------------Convert binary code to compressed BCD code and display---------------*/
void two_2_bcd(unsigned char date)
{
unsigned char temp;
temp=date;
date&=0xf0;
date>>=4; //Shift right four bits to get the upper four bits
date&=0x0f; //AND with 0x0f to ensure the upper four bits are 0
if(date<=0x09)
{
WriteData(0x30+date); //lcd displays the upper four bits of the key value
}
else
{
date=date-0x09;
WriteData(0x40+date);
}
date=temp;
date&=0x0f;
if(date<=0x09)
{
WriteData(0x30+date); //lcd displays the lower four bits of the key value
}
else
{
date=date-0x09;
WriteData(0x40+date);
}
WriteData(0x48); //Display the character 'H'
}
/****************************************************************
Function: 1602LCD display
****************************************************************/
void Disp(void)
{
WriteAddress(0x40); // Set the display position to the first word of the first line
two_2_bcd(a[0]);
WriteData(0x20);
two_2_bcd(a[1]);
WriteData(0x20);
two_2_bcd(a[2]);
WriteData(0x20);
two_2_bcd(a[3]);
}
/****************************************************************
Function: Main function
************************************************************/
void main()
{
unsigned char i;
LcdInitiate(); //Call LCD initialization function
delay(10);
WriteInstruction(0x01);//Clear display: clear screen instruction
WriteAddress(0x00); // Set the display position to the first word of the first line
i = 0;
while(string[i] != '') //'' is the end of the array
{ // Display characters www.pcbsig.com
WriteData(string[i]);
i++;
}
EA=1; //Open general interrupt
EX0=1; //Open external interrupt 0
ET0=1; //Timer T0 interrupt enable
IT0=1; //Falling edge trigger of external interrupt
TMOD=0x01; //Use timer T0 mode 1
TR0=0; //Timer T0 off
while(1); //Wait for the interrupt generated by the infrared signal
}
/****************************************************************
Function: External interrupt processing function triggered by infrared
**************************************************************/
void Int0(void) interrupt 0
{
EX0=0; //Turn off external interrupt 0, no longer receive the interrupt of the secondary infrared signal, only decode the current infrared signal
TH0=0; //Clear the high 8 bits of timer T0
TL0=0; //Clear the low 8 bits of timer T0
TR0=1; //Turn on timer T0
while(IR==0); //If it is a low level, wait and time the low level of the boot code
TR0=0; //Turn off timer T0
LowTime=TH0*256+TL0; //Save the low level time
TH0=0; //Clear the high 8 bits of timer T0
TL0=0; //Clear the low 8 bits of timer T0
TR0=1; //Turn on timer T0
while(IR==1); //If it is a high level, wait and time the high level of the boot code
TR0=0; //Turn off timer T0
HighTime=TH0*256+TL0; //Save the high level length of the boot codeif
((LowTime>7800)&&(LowTime<8800)&&(HighTime>3600)&&(HighTime<4700))
{
//If it is a boot code, start decoding, otherwise give up, the low level timing of the boot code
//times=9000us/1.085=8294, judgment interval: 8300-500=7800, 8300+500=8800.
if(DeCode()==1) //Execute remote control decoding function
{
Disp();//Call 1602LCD display function
beep();//The buzzer sounds to prompt that the decoding is successful
}
}
EX0=1; //Turn on external interrupt EX0
}
Previous article:PCF8591 DA Driver
Next article:1602LCD display driver
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- Rambus Launches Industry's First HBM 4 Controller IP: What Are the Technical Details Behind It?
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- Communication system cannot do without filter series 2
- The difference between RETI and RET in MCU assembly instructions
- [Sipeed LicheeRV 86 Panel Review] 10. LVGL Timer
- Today at 10:00 AM, live broadcast with prizes: Protecting clean water sources - ADI water quality monitoring solutions
- [Ateli Development Board AT32F421 Review] + Unboxing and Learning Plan
- What are risc-v chips?
- sensortile box source code
- Lingdongwei MM32 download program error description solution
- Double 12 limited time offer | Tektronix year-end rewards, oscilloscope third-order upgrade!
- Driver chip in Type-c OTG mode - LDR6028S