Infrared learning remote control made of STC12C2052AD single chip microcomputer

Publisher:SparkleMagicLatest update time:2012-08-22 Source: 51heiKeywords:STC12C2052AD Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Click to browse the next page

// Interrupt function pays attention to develop the habit of specifying register groups
//Interrupt programs of different priorities must not use the same set of registers
/*****The solution to prevent interrupts from changing the data in registers during programming is to assign registers to interrupts.
       It is fine to use the same group for items of the same priority.
    1. When writing an interrupt program, you must use the using statement to specify the register group. Groups 1, 2, and 3 are all OK, but not 0.
    2. The interrupt of 51 MCU has two priorities. One interrupt will not interrupt another interrupt of the same priority.
       In this way, interrupts of the same level can use the same group. For example, low-priority interrupt functions are all
       Use using 1, and all high-priority interrupts use using 2. This way there will be no conflict.
    Here is a normal example:  
    C program: void int0() interrupt 0 using 1
 By default, the 5 interrupts are of the same level and will not conflict, but it is best to develop a good habit
 If the register to be used by the interrupt is not specified, the data must be pushed into the stack each time for protection, and the stack must be popped after the interrupt is completed, which will increase the code by 32 bytes.
 Complete code download: http://www.51hei.com/f/hwxx52.rar
*************************************************** ******************/
#include 
#include 
#define uchar unsigned char
#define uint unsigned int
//Shaozhanyu Production Welcome to Zhengding, Hebei Changsha Aviation Vocational and Technical College 2010 QQ: 41165643
//
//Define the Flash operation wait time and constants to allow IAP/ISP/EEPROM operations
//#define ENABLE_ISP 0x80 //When the system operating clock is <30MHz, set this value to the ISP_CONTR register
//#define ENABLE_ISP 0x81 //When the system operating clock is <24MHz, set this value to the ISP_CONTR register
#define ENABLE_ISP 0x82 //When the system operating clock is <20MHz, set this value to the ISP_CONTR register  
//#define ENABLE_ISP 0x83 //When the system operating clock is <12MHz, set this value to the ISP_CONTR register  
//#define ENABLE_ISP 0x84 //When the system operating clock is <6MHz, set this value to the ISP_CONTR register
//#define ENABLE_ISP 0x85 //When the system operating clock is <3MHz, set this value to the ISP_CONTR register  
//#define ENABLE_ISP 0x86 //When the system operating clock is <2MHz, set this value to the ISP_CONTR register  
//#define ENABLE_ISP 0x87 //When the system operating clock is <1MHz, set this value to the ISP_CONTR register  

union union_temp16
{
    uint un_temp16;
    uchar un_temp8[2];
}my_unTemp16;

uchar Byte_Read(uint add); //Read one byte, IAP function must be enabled before calling
void Byte_Program(uint add, uchar ch); //Byte programming, IAP function must be enabled before calling  
void Sector_Erase(uint add); //Erase sector
void IAP_Disable(); //Disable IAP function  

sbit JIESHOU=P1^0; //Receive indicator light
sbit FASHE=P1^1; //Transmit indicator light
sbit KEY=P3^5;
sbit cin=P3^2; //receiving end
sbit contrl=P3^0; //transmit control terminal
sbit khz=P3^1; //38KHZ generated, set by T1
/****************************************************** ***************/
void delayms(uint);          
void ADC();
void InitADC();
void init1();
void init2();
void fashe();
void jieshou();
void delayus(uchar i);
void led(uchar x);
/****************************************************** *****/
uint voltage;
bit receive=0; //receive flag
bit flag=0; //Low level recording completion flag
bit end=0;
bit finish=1;
uchar a[43]={121,1,3,4,44,55,24,156,35};
//High 128 RAM for indirect addressing, high 128 RAM for internal 256 can only be addressed indirectly
uchar j=0;
uint zu=0,addr=0; //sector address
uchar k; //key code
uchar m=0; //Used to move the array when writing EEPROM
uchar b[6]; //Total number of bytes used to store each set of data
/****************************************************** *********************/
/****************************************************** ***************/
 void main()
{   
 delayus(5);
 delayms(1000);
 InitADC(); //This will affect other places where P1 port is used, so try to put it in front
 contrl=0; //Close 38K output
 KEY=1;
      Sector_Erase(0x0000); // Erase sector 1
  Sector_Erase(0x200);
  Sector_Erase(0x400);
  Sector_Erase(0x600);
  Sector_Erase(0x800);
  Sector_Erase(0xa00);
  Sector_Erase(0xc00); // Erase sector 7
 addr=0xc00;
 FASHE=0;
 JIESHOU=0;
  FASHE=1;
     delayms(4900);

  for(j=6;j>0;j--)//j is the total length of the data. In this way, no extra space will be stored.
   { Byte_Program(addr,a

??); //Start writing EEPROM from the first address of the sector corresponding to this group of data
        m++; //Move down the array
  addr++; //move down the address
  delayms(1);} //for end
    m=Byte_Read(0xc00);

 if(m==121)
    {
 JIESHOU=1;
 delayms(6000);
 }
 m=0; //It will be used later, so clear it to 0  
 addr=0;
 zu=0;
 
 FASHE=0;
 KEY=1;
 JIESHOU=0;
     delayms(1000);
      Sector_Erase(0x0000); // Erase sector 1
  Sector_Erase(0x200);
  Sector_Erase(0x400);
  Sector_Erase(0x600);
  Sector_Erase(0x800);
  Sector_Erase(0xa00);
  Sector_Erase(0xc00); // Erase sector 7
 EX1=1; //Open external interrupt 1
 IT1=1; //External interrupt 1 edge triggered, otherwise it will be interrupted when pressed
   EA=1;
 delayms(1);
   //Both lights go out while waiting for a key press
   while(1)
   {
  if(receive) //External key interrupt 1, officially enter the receiving function
  {
  FASHE=0; //Transmit indicator light
  JIESHOU=1; //Receive indicator light
  delayms(3000);
  JIESHOU=0;
  delayms(2);
  FASHE=1;
  delayms(3000);
  FASHE=0;
  jieshou(); //The receiving function is called when the count overflows after T0 timing starts
  }
    if(!KEY) //Enter the transmission mode when KEY is 0
  {
  JIESHOU=0;
   delayms(200);
  FASHE=1;
  delayms(200);
  KEY=1;
  fashe();
  }
   }  
}
/****************************************************** *******************/
// Initialize the receiving function
void init1()//Receive initialization
{
  finish=1;
  EA=0; //Because we need to write to EEPROM, we must turn off EA
  TMOD=0x01; //T0 mode 1
  TH0=0x00;
  TL0=0x00;
  TR0=0;
  EX0=1;
  EX1=0; //Turn off the external interrupt 1 button. Once the receiving function is entered, turn off the button to prevent interference
  ET0=1; //Open T0 interrupt
  IT0=1; //External interrupt edge trigger
  EA=0;
}
//
/****************************************************** *******************/
// Initialize the launch function
void init2()//Emit initialization
{
  contrl=0; //Turn off the transmitter. Since it is connected in parallel with the 38K output terminal, it will not output when pulled low.
  TMOD=0x21; //T0 mode 1, external INTO wake-up, T1 mode 2
  TH1=-(13/256); //Timed to flip once every 13us, i.e. 38KHZ (26us)
  TL1=-(13%256);
  ET1=1; //T1 interrupt
  TR1=1;
  EA=1;
}

/****************************************************** *************************/
// Infrared receiving subroutine
void jieshou()
{
 init1(); //Receive initialization
 delayms(3000);
   flag=0;
   finish=1;
   JIESHOU=1; //The receiver light will turn on before you can start pressing the remote control
   EA=1; //Open interrupt    
       EX0=1;
 //The receiving light is on and waiting for receiving
 while(finish) //Exit receiving loop detection
 {
   while(flag) //T0 has started the flag, remember to clear it after use, started by external interrupt 0, initial start detection
   {//The first low level width measurement has started
    while(!cin); //Wait for the high level to arrive, T0 interrupt will not occur here, because the low level width will not be as long as 65MS
     {
   TR0=0;   
      a[j]=TH0; //Low level width first stores high 8 bits of data
   j++;
   a[j]=TL0; // stores the low level width
      j++; // array down
  TH0=0; //Reinstall T0
      TL0=9; //Compensate for the previous time consumed
      TR0=1; //Restart T0, timing high level     
      }
     //High level width measurement starts
    while(cin&&flag);
//Wait for cin to reach a low level. T0 interrupt occurs while waiting here.
Because the last level must be high (no signal is high)
     //flag=1 means T0 has not been interrupted, and reception is still valid
  if(flag) //flag is 1 to indicate that the timing is valid, flag=0 indicates that the last high level is very long and has ended
  { //Add a flag to exit this waiting
      TR0=0;
   a[j]=TH0; //Store high 8 bits of data first
   j++;
   a[j]=TL0; // stores the low level segment
      j++; // array down
  TH0=0; //Reinstall T0
      TL0=0;
      TR0=1; //Restart T0, timing low level
  }
   }
    //Judge whether to exit receiving
     if(end)
  {

  receive=0; //clear the receive start flag to 0 after use
  flag=0;
  FASHE=1;
  delayms(122);
  JIESHOU=1; //Two lights on indicate successful reception
  j=0;
  finish=0;
  end=0;
  }
  }
  // After receiving, turn on two lights
      finish=1;
    EX1=1; //Open external button interrupt 1
  EA=1;
  }
/**********************************************/
// Infrared emission subroutine
void fashe() //No ejection operation is arranged in the launch program, so the only way to re-enter the selection mode is to restart
{
 
  while(1)
  {
  ADC();
  switch(k)
  {
  case 1:for(j=0
It is fine to use the same group for items of the same priority.
     1. When writing an interrupt program, you must use the using statement to specify the register group. Groups 1, 2, and 3 are all OK, but not 0.
    2. The interrupt of 51 MCU has two priorities. One interrupt will not interrupt another interrupt of the same priority.
 In this way, interrupts of the same level can use the same group. For example, low-priority interrupt functions all use using 1.
High priority interrupts are all using 2. This way there will be no conflict.
    Here is a normal example:  
    C program: void int0() interrupt 0 using 1
 By default, the 5 interrupts are of the same level and will not conflict, but it is best to develop a good habit
 If the register to be used by the interrupt is not specified, the data must be pushed into the stack each time for protection, and the stack must be popped after the interrupt is completed, which will increase the code by 32 bytes.
*************************************************** ******************/
//The interrupt function must specify which group of registers to use. Using the same group may destroy the data in the last register.   
//Interrupts of the same priority level can use the same set of registers
  void time0() interrupt 1 using 1 // Timer 0 interrupt
  {
   EA=0;
   EX0=0;
   EX1=0;
   ET0=0;
   FASHE=0;
   delayms(200);
   JIESHOU=0; //Receive indicator light
   delayms(1000);
   //More than 65MS, indicating that the reception is complete
   b[zu/0x200]=j; //j starts from 0, and after the last level is stored, j is incremented by 1, and the total length is exactly the current value
   addr=zu; //Because the zu value will be used below, so its data is transferred here
   //zu is the starting address of each storage space
   m=0;
   for(;j>0;j--)//j is the total length of the data. In this way, no extra space will be stored.
   { Byte_Program(addr,a

??); //Start writing EEPROM from the first address of the sector corresponding to this group of data
        m++; //Move down the array
  addr++; //move down the address
  delayms(1);} //for end

     i<(zu<0xa00)//After the first group of codes are completed, go to the second group, each group has 200 spaces
      zu+=0x200; //After testing a group, the sector address points to the next sector
      else
    { zu=0x000;} //More than 6 groups of code, memory redirected to the first group
  flag=0;
  receive=0; //clear the receive start flag to 0 after use
      end=1; //Exit the outermost loop of the receiving function

  }
/****************************************************** *****/
// The transmission frequency 38khz is generated by T1
  void time1() interrupt 3 using 1 //Timer 1 interrupt, because the default is the same priority,
So you can use the same set of registers
  {
   khz=!khz;
  }
/****************************************************** *****/
//External interrupt storage high level length
void interint0() interrupt 0 using 1 //external interrupt 0  
{
 
  if (flag==0) //flag=0 means the pulse is received for the first time
   {
     TH0=0;
 TL0=10; // Make up for the time consumed by the previous delay function
     TR0=1;
 EX0=0; //Disable external interrupt 0, all subsequent counts are in the receiving function
     flag=1; // indicates starting T0

    }

}
//
/****************************************************** *************/
/****************************************************** *****/
//External button interrupt 1
void interint1() interrupt 2 using 1 //external interrupt 1   
{
 receive=1;
 delayms(122); //wait for the jitter time to pass
 EA=0;
}

/****************************************************** *****/
//AD conversion initialization----turn on ADC power
void InitADC()
{
P1=0xff; //This has an impact on other places where P1 port is used
ADC_CONTR|=0x80;
delayms(30);
//These two registers are used to set the four states of P1 port. Each bit corresponds to a P1 pin and operates according to the state combination.

P1M0=0x08; //These two registers are used to set the four states of P1 port, each bit corresponds to a P1 pin, and the operation is performed according to the state combination
P1M1=0x08; //Set P1.3 to AD  

 }


 /****************************************************** *******************/
//AD conversion program
void ADC()
{
  

    ADC_DATA = 0; // Clear the result

    ADC_CONTR = 0x60; //Conversion speed setting 0x60 fastest speed

    ADC_CONTR = 0xE0; //1110,0000 clear ADC_FLAG,
ADC_START bit and lower 3 bits
    ADC_CONTR |= 0x03; //Select A/D current channel P1.3
    delayus(100); //Make the input voltage stable
    ADC_CONTR |= 0x08; //0000,1000 Set ADCS = 1 to start A/D conversion.

    while(!(ADC_CONTR & 0x10)); //! has a much higher priority than &
 /***************
 Here, while cannot be changed to while(ADC_CONTR & 0x10==0); it will be wrong because the priority == is higher than &.
So add brackets
  while( (ADC_CONTR & 0x10) ==0) or while(!(ADC_CONTR & 0x10));
//! has a much higher priority than &
    ******************************/
    ADC_CONTR &= 0xE7; //1111,0111 clear ADC_FLAG bit, turn off A/D conversion,
 
   voltage=ADC_DATA;

   if( vol=40&&vol=80&&vol=110&&vol=130&&vol=148&&volSTC International Limited ----------------
A complete EEPROM test program that can be tested directly using the Macrochip download board
STC12C52xxAD series MCU EEPROM/IAP functional test program demonstration
STC11xx series MCU EEPROM/IAP functional test program demonstration
STC10xx series MCU EEPROM/IAP functional test program demonstration
 --- STC International Limited ------------------
 --- Designed by Hongjing Technology 2009/1/12 V1.0 --------------
*************************************************/


//Read a byte. You need to turn on the IAP function before calling. Entry: DPTR = byte address. Return: A = read byte.
uchar Byte_Read(uint add)
{
    ISP_DATA = 0x00;
    ISP_CONTR = ENABLE_ISP; // Enable IAP function and set Flash operation waiting time
    ISP_CMD = 0x01; //IAP/ISP/EEPROM byte read command

    my_unTemp16.un_temp16 = add; //Assignment of union variables,
This is two bytes. Because it is a shared memory, the following array also has this content.
    ISP_ADDRH = my_unTemp16.un_temp8[0]; //Set the high 8 bits of the target unit address
    ISP_ADDRL = my_unTemp16.un_temp8[1]; //Set the lower 8 bits of the target unit address

    EA = 0;
    ISP_TRIG = 0x46; //First send 5Ah, then send A5h to the ISP/IAP trigger register, this needs to be done every time
    ISP_TRIG = 0xB9; //After sending A5h, the ISP/IAP command is triggered and started immediately
    _nop_();
    //EA = 1;
    IAP_Disable(); //Disable the IAP function, clear the relevant special function registers, and put the CPU in a safe state.
                    //After a continuous IAP operation is completed, it is recommended to turn off the IAP function. It is not necessary to turn it off every time.   
    return (ISP_DATA); //Data is in the ISP_DATA register
}

//Byte programming, IAP function must be turned on before calling, entry: DPTR = byte address, A = byte data to be programmed  
void Byte_Program(uint add, uchar ch)
{
    ISP_CONTR = ENABLE_ISP; // Enable IAP function and set Flash operation waiting time
    ISP_CMD = 0x02; //IAP/ISP/EEPROM byte programming command

    my_unTemp16.un_temp16 = add;  
//Assignment of union variables, here is two bytes, because of the shared memory, so the following array also has this content
    ISP_ADDRH = my_unTemp16.un_temp8[0]; //Set the high 8 bits of the target unit address
    ISP_ADDRL = my_unTemp16.un_temp8[1]; //Set the lower 8 bits of the target unit address

    ISP_DATA = ch; //The data to be programmed is first sent to the ISP_DATA register  
    EA = 0; //Interrupts must be disabled, otherwise it will not be possible to write
    ISP_TRIG = 0x46; //First send 46h, then send B9h to the ISP/IAP trigger register, this is required every time
    ISP_TRIG = 0xb9; //After sending B9h, the ISP/IAP command is triggered and started immediately    
    _nop_();
    //EA = 1;
    IAP_Disable(); //Disable the IAP function, clear the relevant special function registers, and put the CPU in a safe state.
                    //After a continuous IAP operation is completed, it is recommended to turn off the IAP function. It is not necessary to turn it off every time.   
}

// Erase sector, entry: DPTR = sector address
void Sector_Erase(uint add)
{
    ISP_CONTR = ENABLE_ISP; // Enable IAP function and set Flash operation waiting time
    ISP_CMD = 0x03; //IAP/ISP/EEPROM sector erase command

    my_unTemp16.un_temp16 = add;
    ISP_ADDRH = my_unTemp16.un_temp8[0]; //Set the high 8 bits of the target unit address
    ISP_ADDRL = my_unTemp16.un_temp8[1]; //Set the lower 8 bits of the target unit address

    EA = 0; //Interrupt must be disabled
    ISP_TRIG = 0x46; //First send 46h, then send B9h to the ISP/IAP trigger register, this is required every time  
    ISP_TRIG = 0xB9; //After sending B9h, the ISP/IAP command is triggered and started immediately   
    _nop_();
    //EA = 1;
    IAP_Disable(); //Disable the IAP function, clear the relevant special function registers, and put the CPU in a safe state.
                    //After a continuous IAP operation is completed, it is recommended to turn off the IAP function. It is not necessary to turn it off every time.
}

void IAP_Disable()
{
    //Disable the IAP function, clear the relevant special function registers, and put the CPU in a safe state.
    //After a continuous IAP operation is completed, it is recommended to turn off the IAP function. It is not necessary to turn it off every time.   
    ISP_CONTR = 0; //Disable IAP function
    ISP_CMD = 0; // Clear the command register so that there is no command in the command register. This sentence is not necessary.   
    ISP_TRIG = 0; // Clear the command trigger register to make the command trigger register non-triggered. This sentence is not required.  
    ISP_ADDRH = 0;
    ISP_ADDRL = 0;
}


//
void delayus(uchar i )
{

    while(i--);
}

//Delay function
void delayms(uint k)
{
uint data i,j;
for(i<0;i				   
Keywords:STC12C2052AD Reference address:Infrared learning remote control made of STC12C2052AD single chip microcomputer

Previous article:MCU Self-study Notes: Flowing Light
Next article:nRF401 wireless module debugging work notes

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号