1. Brief description
I am a student in school. This semester happens to be learning single-chip computer. I am also interested in it. There were no big problems in writing the programs of digital tube and clock, but I encountered some problems when I made the matrix keys, but I have solved them. I will write out the problems and solutions below, hoping to help you.
2. Development boards used: Puzhong Science and Technology HC6800-ES V2.0 (Other development boards can be modified according to the schematic diagram referring to this program, the core code is mostly the same, change the interface is OK)
PS: The design of this ghost development board is slightly odd. There is an interface in the matrix keys that is shared with the buzzer. As a result, I kept ringing when I started writing. Although the program could run, I later watched the official program to solve it (the solution is a thieves). Although it still sounds, the sound is negligible (there are still problems with the circuit design). I'll elaborate later.
3. Implementation Methods
The result of this program is that when you press the key, the corresponding number will be displayed on the tube, for example, when you press the S13 key, the tube will display 13.
There are two methods used in the program, which can be switched by modifying the function name. Let's start with a brief explanation of the principle of matrix keys:
As shown in the figure, this is the matrix key of the development board I have. It is not the same as the textbook (Pine Cedar, Tsinghua University Press), but it works in the same way. For example, the S1 key, which is controlled by P17 and P13 ports, we put P17 port 1 (high level), P13 port 0 (low level), when the key is pressed 0 & 1 = 0, then P17 port will become 0, we can judge if the key is pressed by detecting the state of P17 port.
The following describes the implementation:
First, flip scan: recommended to use this first, this code is relatively short, first all rows are placed in a column and all columns are set to 0 (0xF0, according to the specific interface of matrix keys). When a key is pressed, if S3 key is pressed, P17 port will become 0. We can detect which row is by switch statement, then 0x7F, we can make a two-dimensional array (I think it's more intuitive to use a two-dimensional array because it corresponds to the matrix keys) where the row is set to zero (the array starts from zero), and then flipped, i.e., the row is set to zero and column 1 (0x0F) to detect which column it is. If this is 0x0D, the column can be determined to be 2, and then the specific key is (0, 2) That is, the third S3 in the first line, and then it's displayed through the digital tube (I'll write this when I have time to see if anyone else can read it)
The second is column-by-column scanning: first set the first column to 0 and then all other 1 (0xF7), so that when the first row has keys pressed, you can directly determine which one is, then set the second column to 0 and all other 1, scan the second column, and so on, scan all keys four times to determine all keys. At the same time, add a statement to check if the keys are loose (while (P1!= 0xF7)). , when you go into a while cycle on a long timer, the program will stop here until you release it, otherwise the long timer program will continue to cycle and detect, and the buzzer will ring.
(Actually, there were some problems in the design of this development board, so we can only list them one by one. The problem is that the buzzer is also connected to the P1.5 port. If you use progressive scan, you will first set P1.5 to 1 and then set it to 0, forming a pulse signal, causing the buzzer to ring, so it can only be listed. I used the flip method in the initial program, and it is direct line. The result is that although the program is running normally, the buzzer keeps ringing because P1.5 has been set at 0 and 1, forming a pulse. Later, the official program was seen to solve the problem. The official method is a chicken thieves. First, he uses the if statement to detect if there is a key press (if (P1!= 0xF0)). When a key press is detected, execute the program mentioned above to determine the specific key, so P1.5 will only be flipped once, the buzzer will only sound once, and the sound can be ignored (the faster the frequency, the higher the pitch), so that he can avoid ringing all the time.)
The schematic diagram shows that the buzzer shares a P1.5 port with the matrix keyboard
IV. Specific Procedures
Here's the code. The program is a bit long because you have written two ways to flip directly to the scanner for understanding. If you are using Proteus analogue, you can connect the program to hardware, the display interface of the digital tube is connected to P 0, the interface is selected to connect to P 138 decoder, the ABC of the 138 decoder is connected to P 2.2 to P 2.4, the matrix keyboard is connected to P 1, and the Proteus is not connected to buzzer. There are not so many restrictions on the program.
/*-------------------------------------------- | Only applicable to general HC6800-ESV2.0 | | Other development boards can refer to this program according to the schematic | --------------------------------------------*/ #include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit a0 = P2^2; //Bit Address Statement, ABC three ports controlling 138 decoder of digital tube sbit a1 = P2^3; sbit a2 = P2^4; //Gongyin Digital Tube uchar code cattube[] = {0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F, 0x77,0x7C,0x39,0x5E,0x79,0x71}; //2-D Array Key Display uchar code out[4][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}}; //Delay Program 12MHz Crystal Vibration, Mode 1 n*0.1ms void delay(uint n) { TMOD = 0x02; TH0 = 0x9C; TL0 = 0x9C; TR0 = 1; while(n--) { while(TF0 == 0); TF0 = 0; } TR0 = 0; } uint s = 0; uint i = 0; //Matrix Row uint j = 0; //Matrix Column uchar out0 = 0; uchar out1 = 0; //Display program, dynamic display of two digital tubes void tube() { out0 = out[i][j] %10; //Extract Bits out1 = out[i][j] /10; //Extract Ten Bits P0 = 0x00; switch(s) //Bit by Bit Display { case 0:a2=0;a1=0;a0=0;s++;P0 = cattube[out0];break; case 1:a2=0;a1=0;a0=1;s=0;P0 = cattube[out1];break; default:break; } } /*-------------------------------------------------------------------------------------------------- | The following two methods will be used for scanning: | | 1,Flip Scan: Set all rows to 0 and all columns to 1 for row scan, and then flip to scan columns to determine specific keys. | | 2,Column by column scan: 0 in column, 1 in all the remaining 7 bits, one column of keys can be determined at a time, and four scans to determine specific keys. | | (Column scan is required here, line scan because interface sharing will cause buzzer pulse to sound abnormally)| --------------------------------------------------------------------------------------------------*/ //Flip Scan void key_scan_all() { P1 = 0x0F; //Row Assignment Initial Value if(P1 != 0x0F) //Key detection to detect if a key is pressed { delay(100); //Delayed dithering if(P1 != 0x0F) { P1 = 0xF0; //Line Scan switch(P1) { case 0x70: i = 0;break; case 0xB0: i = 1;break; case 0xD0: i = 2;break; case 0xE0: i = 3;break; } P1 = 0x0F; //Column Scan switch(P1) { case 0x07: j = 0;break; case 0x0B: j = 1;break; case 0x0D: j = 2;break; case 0x0E: j = 3;break; } while(P1 != 0x0F); //Wait for key to release } } } //Scan column by column void key_scan_once() { P1 = 0xF7; //First column assigns initial values if(P1 != 0xF7) //Key Detection to detect if the first column has a key press { delay(100); //Delayed dithering if(P1 != 0xF7) { j = 0; switch(P1) //Determine specific keys { case 0x77: i = 0;break; case 0xB7: i = 1;break; case 0xD7: i = 2;break; case 0xE7: i = 3;break; } while(P1 != 0xF7); //Wait for key to release } } P1 = 0xFB; //The second column assigns initial values if(P1 != 0xFB) //Key Detection to detect if the second column has a key press { delay(100); //Delayed dithering if(P1 != 0xFB) { j = 1; switch(P1) //Determine specific keys { case 0x7B: i = 0;break; case 0xBB: i = 1;break; case 0xDB: i = 2;break; case 0xEB: i = 3;break; } while(P1 != 0xFB); //Wait for key to release } } P1 = 0xFD; //Column 3 Assigning Initial Values if(P1 != 0xFD) //Key Detection to detect if the third column has a key press { delay(100); //Delayed dithering if(P1 != 0xFD) { j = 2; switch(P1) //Determine specific keys { case 0x7D: i = 0;break; case 0xBD: i = 1;break; case 0xDD: i = 2;break; case 0xED: i = 3;break; } while(P1 != 0xFD); //Wait for key to release } } P1 = 0xFE; //Fourth column assigns initial values if(P1 != 0xFE) //Key Detection to detect if the fourth column has a key press { delay(100); //Delayed dithering if(P1 != 0xFE) { j = 3; switch(P1) //Determine specific keys { case 0x7E: i = 0;break; case 0xBE: i = 1;break; case 0xDE: i = 2;break; case 0xEE: i = 3;break; } while(P1 != 0xFE); //Wait for key to release } } } void main() { while(1) { tube(); //display key_scan_once(); //Scan to switch between two modes by modifying the function name delay(30); //Digital tube refresh frequency } }