// 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&&vol STC 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
Previous article:MCU Self-study Notes: Flowing Light
Next article:nRF401 wireless module debugging work notes
- Popular Resources
- Popular amplifiers
Recommended Content
Latest Microcontroller Articles
He Limin Column
Microcontroller and Embedded Systems Bible
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
MoreSelected Circuit Diagrams
MorePopular Articles
- 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
MoreDaily News
- New breakthrough! Ultra-fast memory accelerates Intel Xeon 6-core processors
- New breakthrough! Ultra-fast memory accelerates Intel Xeon 6-core processors
- Consolidating vRAN sites onto a single server helps operators reduce total cost of ownership
- Consolidating vRAN sites onto a single server helps operators reduce total cost of ownership
- 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!
Guess you like
- ICE40LP1K CDONE pin is always low
- Is there a company where you can have breakfast until 10 o'clock, take a nap until 2 o'clock, and receive 18 months' salary per year?
- [Automatic clock-in and walking timing system based on face recognition] Maixbit/MaixPy pitfall! The audio playback function blocks the call
- A new high voltage charging method
- 1
- Wireless Earbud Battery Ultra-Low Standby Power Consumption Reference Design
- Fake news and exaggerated hype are hurting China's IC industry. Silence is not the solution (Reprinted)
- When MOS tubes are connected in parallel, do they have to be symmetrical?
- Looking for Bluetooth skype phone solution
- What are the 9 most important applications of the Internet of Things (IoT)?