return (TH1 * 256 + TL1); //Return T1 count value
}
/*External interrupt 1 service, determine infrared and receive infrared NEC decoding*/
void EXINT1_ISP() interrupt 2 //EXINT1 interrupt number is 2
{
unsigned char byte = 0; //Receive decoded data
unsigned int time = 0; //Receive the pilot code and idle and carrier time
unsigned char i, j;
time = GetLowTimers(); //Carrier pilot code (9ms carrier + 4.5ms idle): range (8.5ms-9.5ms)
if ((time < 7833) || (time > 8755)) //Counting cycle = 12/11059200 Counting time = (TH1*256+TL1)*12/11059200
{
//Error code, clear interrupt flag and exit interrupt
IE1 = 0;
return;
}
time = GetHighTimers(); //4.5ms idle time: range: 4ms-5ms
if ((time < 3686) || (time > 4608)) // () must be added when judging
{
//incompatible
IE1 = 0; //External interrupt flag
return; //Exit interrupt function
}
//The boot code is correct, start looping to receive user code and key code
for (i = 0; i < 4; i++) //Receive 4 bytes of data
{
for (j = 0; j < 8; j++) //Receive 8 bits
{
time = GetLowTimers(); //Carrier: 560us carrier + 560us/1.68ms idle: 340us 760us
if ((time < 313) || (time > 700))
{
//Error code
IE1 = 0; // Clear external interrupt flag
return;
}
time = GetHighTimers(); //Idle
if ((time > 313) && (time < 700)) //560us idle, bit value '0' time greater than 340us and time < 780us
{
byte >>= 1; //Low bit first, receive bit by bit, shift the data bit right to the low bit
}
else if ((time > 1271) && (time < 1658)) //1.68ms idle: range: 1.38ms-1.8ms, bit value is '1'
{
byte >>= 1; // First shift right one bit and move this bit to the highest bit of byte
byte |= 0x80; //Set this position to 1
}
else
{
//The received code is an error
IE1 = 0; // Clear external interrupt 1 flag
return; //Exit the interrupt function
}
}
irdCode[i] = byte; //Receive code value
}
flagIrd = 1; //Receive completion flag set to 1
IE1 = 0; // Clear external interrupt flag
}
/**
************************************************************************
* @file : Keyboard.c
* @author : xr
* @date : April 21, 2014 22:23:12
* @version : V1.2.3
* @brief: Button bottom driver microcontroller STC89C52RC MCU crystal oscillator 11.0592MHZ
************************************************************************
*/
#include //KEY sbit KEY_IN_1 = P2^4; sbit KEY_IN_2 = P2^5; sbit KEY_IN_3 = P2^6; sbit KEY_IN_4 = P2^7; sbit KEY_OUT_1 = P2^3; sbit KEY_OUT_2 = P2^2; sbit KEY_OUT_3 = P2^1; sbit KEY_OUT_4 = P2^0; static unsigned char volatile keySta[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}}; //Current status of 16 buttons unsigned char pdata keyCodeMap[4][4] = { //Key code is encoded according to ASCII code {'1', '2', '3', 0x26}, //Number keys 1, 2, 3 and up key {'4', '5', '6', 0x25}, //Number keys 4, 5, 6 and left key {'7', '8', '9', 0x28}, //Number keys 7, 8, 9 and down key {'0', 0x1B, 0x0D, 0x27} //Number key 0 and ESC key, Enter key, Right key }; /*You need to use the structure variable timeBuf of type struct Time in the main.c file and need to redeclare it*/ struct Time { unsigned char year; unsigned char month; unsigned char day; unsigned char hour; unsigned char min; unsigned char sec; unsigned char week; }; extern struct Time timeBuf; extern unsigned char setTimeIndex; //external variable declaration void LcdCoursorRight(); void LcdCoursorLeft(); void SetTimeBcdByte(unsigned char keyNum); void KeyAction(unsigned char keycode); extern void LcdRefreshSetCoursor(); extern void LcdCloseCoursor(); extern void IncTimeBysetTimeIndex(); extern void DecTimeBySetTimeIndex(); extern GetTimeFromDS1302(struct Time * time); extern void SetTimeToDS1302(struct Time * time); extern void RefreshLcdShowTime(); /*Key driver, judge the key status, and pass the key code of the corresponding key to the key action function*/ void KeyDriver() { static unsigned char pdata keyBackup[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}}; //The backup of the key is the status value of the last key press unsigned char i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (keySta[i][j] != keyBackup[i][j]) { //Button has action if (keyBackup[i][j] != 0) //Determine the current key value based on the last backup value, that is, the key action { // Press the button to execute the action KeyAction(keyCodeMap[i][j]); // pass the corresponding key code } //Backup the value of this button keyBackup[i][j] = keySta[i][j]; } } } } /*Dynamic scanning of keys to debounce keys*/ void KeyScan() { static unsigned char keyout = 0; //Key row index, the last changed keyout value is used each time, so it is defined as a static variable static unsigned char keybuff[4][4] = {{0xFF, 0xFF, 0xFF, 0xFF},{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},{0xFF, 0xFF, 0xFF, 0xFF}}; //Key scan buffer unsigned char i = 0; /*Scan the key value and store the key status value in the keybuff buffer*/ keybuff[keyout][0] = (keybuff[keyout][0] << 1) | KEY_IN_1; //Store the scan value of the first key in the keyout row into the keybuff[keyout][0] buffer keybuff[keyout][1] = (keybuff[keyout][1] << 1) | KEY_IN_2; keybuff[keyout][2] = (keybuff[keyout][2] << 1) | KEY_IN_3; keybuff[keyout][3] = (keybuff[keyout][3] << 1) | KEY_IN_4; /*Update the status of the button after scanning and debounce*/ for (i = 0; i < 4; i++) // Each row has four buttons that need to be judged { if ((keybuff[keyout][i] & 0x1F) == 0x00) //The values of the 5 key scans are all 0, indicating that the key is pressed steadily { keySta[keyout][i] = 0; } else if ((keybuff[keyout][i] & 0x1F) == 0x1F) //The scan values of the 5 keys are all 1, indicating that the key is stable. { keySta[keyout][i] = 1; } } //row++ keyout++; keyout &= 0x03; //Return to zero at 4 /*Determine which row of keys to scan based on the value of keyout*/ switch (keyout) { case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break; // Scan line 1 case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break; // Scan line 2 case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break; // Scan line 3 case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break; // Scan line 4 default: break; } } /*Key action, perform corresponding operations according to the key code*/ void KeyAction(unsigned char keycode) { if (keycode >= '0' && keycode <= '9') { if (setTimeIndex != 0) // only respond when in the setting state SetTimeBcdByte(keycode - '0'); //Number keys to set time } else if (keycode == 0x26) //Use the up key to adjust the value at the cursor flashing position++ { IncTimeBysetTimeIndex(); //Increment the high or low digits of the BCD code } else if (keycode == 0x27) // Use the right key to move the cursor to the right { if (setTimeIndex != 0) // only respond when in the setting state LcdCoursorRight(); //Decrement the high or low digit of the BCD code } else if (keycode == 0x25) // Use the left key to move the cursor to the left { if (setTimeIndex != 0) LcdCoursorLeft(); } else if (keycode == 0x28) //Decrement the value at the flashing position of the down key cursor { DecTimeBySetTimeIndex(); } else if (keycode == 0x1B) //ESC key, cancel the current setting { setTimeIndex = 0; //Clock normal operation index = 0 LcdCloseCoursor(); //Close cursor flashing } else if (keycode == 0x0D) //Enter key, switch between setting time and restoring clock operation { if (setTimeIndex == 0) //Normal operation state, start switching to setting state { setTimeIndex = 1; LcdRefreshSetCoursor(); //Refresh the cursor flashing position and make the cursor flash } else { //Write the set time value and switch to normal operation SetTimeToDS1302(&timeBuf); GetTimeFromDS1302(&timeBuf); setTimeIndex = 0; LcdCloseCoursor(); //Close cursor flashing } } } /*setTimeIndex++, to set the cursor to move right when blinking*/ void LcdCoursorRight() { if (setTimeIndex < 12) setTimeIndex++; //Cursor setting index++ else setTimeIndex = 1; LcdRefreshSetCoursor(); } /*setTimeIndex--, set the cursor to blink left*/ void LcdCoursorLeft() { if (setTimeIndex > 1) setTimeIndex--; //Cursor setting index-- else setTimeIndex = 12; LcdRefreshSetCoursor(); } /*Set the high digit of the BCD code*/ unsigned char SetBCDHighByte(unsigned char bcd, unsigned char keyNum) { bcd &= 0x0F; // clear high bit bcd |= (keyNum << 4); //keyNum moves to a higher position return (bcd); } /*Set the low digit of the BCD code*/ unsigned char SetBCDLowByte(unsigned char bcd, unsigned char keyNum) { bcd &= 0xF0; //low bit clear bcd |= keyNum; //Put the keyNum number in the lower position return (bcd); //Return the changed bcd byte data } /*Set the time value by key value (set the high and low digits of the time value)*/ void SetTimeBcdByte(unsigned char keyNum) //Transfer the value of the key { switch (setTimeIndex) { case 1: timeBuf.year = SetBCDHighByte(timeBuf.year, keyNum); break; //Set the high BCD byte of the year case 2: timeBuf.year = SetBCDLowByte(timeBuf.year, keyNum); break; //Set the low BCD byte of the year case 3: timeBuf.month = SetBCDHighByte(timeBuf.month, keyNum); break; case 4: timeBuf.month = SetBCDLowByte(timeBuf.month, keyNum); break; case 5: timeBuf.day = SetBCDHighByte(timeBuf.day, keyNum); break; case 6: timeBuf.day = SetBCDLowByte(timeBuf.day, keyNum); break; case 7: timeBuf.hour = SetBCDHighByte(timeBuf.hour, keyNum); break; case 8: timeBuf.hour = SetBCDLowByte(timeBuf.hour, keyNum); break; case 9: timeBuf.min = SetBCDHighByte(timeBuf.min, keyNum); break; case 10: timeBuf.min = SetBCDLowByte(timeBuf.min, keyNum); break case 11: timeBuf.sec = SetBCDHighByte(timeBuf.sec, keyNum); break; case 12: timeBuf.sec = SetBCDLowByte(timeBuf.sec, keyNum); break } RefreshLcdShowTime(); //Refresh time value display LcdCoursorRight(); //Cursor flashes and moves right LcdRefreshSetCoursor(); //Refresh cursor flashing }
Previous article:Design of emergency power inverter circuit using single chip microcomputer SPWM
Next article:Circuit structure of P0 port of 51 single chip microcomputer
Recommended ReadingLatest update time:2024-11-16 19:52
- Popular Resources
- Popular amplifiers
- Principles and Applications of Single Chip Microcomputers 3rd Edition (Zhang Yigang)
- Signal Integrity and Power Integrity Analysis (Eric Bogatin)
- Traffic Light Control System Based on Fuzzy Control (Single-Chip Microcomputer Implementation)
- Principles and Applications of Single Chip Microcomputers (Second Edition) (Wanlong)
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!
- 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
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- I would like to ask if the 8255A chip can only select one port at a time. After defining the address for the port, such as Q8255A XBYTE...
- Power supplies with digital control
- Evaluation summary: Mil based on NXP's first NPU kit MYC-JX8MPQ
- How to choose a suitable water level sensor?
- Can someone help me think of a microcontroller project?
- Development of User Graphical Interface (GUI) for Digital Oscilloscope Based on DSP
- [Xianji HPM6750 Review] + Software simulation IIC reads the temperature and humidity sensor values
- In fact, Valentine's Day 20200214 was cancelled
- This problem occurs when setting up the stm8 environment. What is the reason? Thank you
- dsp28335 data space