1. Functional description
1. SCM and PC are connected by RS232, and an asynchronous serial port communication program is written to realize the communication between SCM and PC's serial port assistant. Specific functions are as follows:
(1) PC sends orders to MCU to turn on or off designated LED lights
(2) PC sends orders to MCU to start or stop buzzer playing music
(3) The PC sends characters to the MCU and displays them on the 1602 LCD. It can also issue commands to delete characters, change lines and clear the display.
At the end of the single chip computer, click on the matrix key and send the serial number of the key to the PC.
2. Circuit diagrams designed in PROTEUS
3. Source code
#include<reg52.h> #include<intrins.h> #include <stdio.h> sbit LCDEN=P3^4; sbit RS=P3^5; sbit RW=P3^6; sbit BF=P1^7; sbit FM=P3^2; unsigned char code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159, 212,212,106,126,159,169,190,119,119,126,159,142,159,0}; //Happy birthday, the beat meter, the beat determines the length of each note. unsigned char code SONG_LONG[]= {9,3,12,12,12,24,9,3,12,12,12,24,9,3,12,12,12,12,12,9,3,12,12,12,24,0}; unsigned char code keyval[]="0123456789ABCDEF"; //Key corresponding symbols unsigned char code keycode[]={ 0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f}; //Keystroke key coding void delay(unsigned int t) //Delay t milliseconds {int i,j; for(i=0;i<=t;i++) for(j=0;j<=110;j++); } void send(unsigned char s) //Sender function, the state of eight lights (0/1), in the form of a string sent to the upper computer, the first highest bit { unsigned char i,t; for(i=0;i<8;i++) { s<<=1; t=CY; SBUF='0'+ t; //Send lamp status to PC while(!TI);//Waiting to be sent TI=0;//Clear Send End Flag } } unsigned char DectectBusyBit(void)//State Judgment Function (Busy/idle?) { bit result; P1 = 0xff; //Pre-reading high level to prevent misjudgment RS = 0; delay(5); RW = 1; LCDEN = 1; delay(5); result=BF; //If LCM is busy, test again and again, step in place; when LCM is idle, continue. LCDEN = 0; return result; } void WrComLCD(unsigned char ComVal)//Write command functions { while(DectectBusyBit()==1); //First check if LCM is idle RS = 0; delay(1); RW = 0; LCDEN = 1; P1 = ComVal; delay(1); LCDEN = 0; } void WrDatLCD(unsigned char DatVal)//Write data functions { while(DectectBusyBit()==1); RS = 1; delay(1); RW = 0; LCDEN = 1; P1 = DatVal; delay(1); LCDEN = 0; } void LCD_Init(void)//1602 Initialization Function { WrComLCD(0x38); // Functional settings: 16*2 rows, 5*7 bits, 8 bits data interface WrComLCD(0x38); WrComLCD(0x38); //Repeat setting function instructions many times, because LCD does not know whether to use 4-bit data interface or 8-bit data interface after starting, so it always defaults to 4-bit at the beginning. WrComLCD(0x01); // Clean screen WrComLCD(0x06); // Cursor self-increasing, screen immovable delay(1); // Delay, wait for the above instructions to take effect, and then show below to prevent scrambling. WrComLCD(0x0e); // On display, on cursor, flashing } unsigned char keypad4_4()//Key Scanning Function: To de-jitter, if a key is pressed, the corresponding key value (0-15) is returned, and no key is pressed, 16 is returned. { unsigned char i,row,temp; unsigned char key=16;//Key number, initial value set to 16, the purpose is: no key press when returning 16; //If no initial value is set (default value is 0), when no key is pressed, 0 will be returned, and 0 will be mistaken for being pressed. row=0xef; //Start with the first column for(i=0;i<4;i++) { P2=0xff; P2=row; //Signals in column i, corresponding to low, all others high row=_crol_(row,1); //Generate the next sequence of signals temp=P2; //Read-in Scanning Signal temp=temp&0x0f; //Shield high 4-bit signal, only low 4-bit row signal if(temp!=0x0f)//If a key is pressed, one of the lower four bits is lower because a key is pressed in a row in column i. { delay(10); //Delay shaking temp=P2; temp=temp&0x0f; if(temp!=0x0f) //Make sure the key is pressed again { switch(temp) //Decide which button is pressed according to the low 4-bit line signal { case 0x0e:key=0+i;break; //Column i, row 1, button pressed case 0x0d:key=4+i;break; //The key in line 2 of column i is pressed case 0x0b:key=8+i;break; //The key in line 3 of column i is pressed case 0x07:key=12+i; //The key in line 4 of column i is pressed } do { temp=P2; //Scan the button again temp=temp&0x0f; }while(temp!=0x0f); //Waiting for key release } } } return(key);//Finish the scan and return the key value } void matrix(){ unsigned char y,i=0; //while(1){ y=keypad4_4(); if(y<16){ SBUF=keyval[y]; //Send lamp status to PC while(!TI);//Waiting to be sent TI=0;//Clear Send End Flag // i++; } // if(i==10) break; // } } //Playback function void PlayMusic() { unsigned int i=0,j,k; while(SONG_LONG[i]!=0||SONG_TONE[i]!=0) { //Play each note, SONG_LONG for beat length for(j=0;j<SONG_LONG[i]*20;j++) { FM=~FM; //The SONG_TONE delay vote determines the frequency of each note. for(k=0;k<SONG_TONE[i]/3;k++); } delay(50); i++; } } void main (void) { unsigned char t,led=0xff; //The initial state of the lamp is completely extinguished unsigned int a=1; FM=0; SCON=0x50;//Serial Port Mode 1 PCON=0x00;//T1 initialization, TMOD=0x20;//T1 is set as mode 2 TH1=0xFD;//Choose 9600, fosc=11.0592MHz TR1=1;//Start T1 P0=led; send(led); //Send the initial state to the host computer LCD_Init(); //Initialization 1602 WrComLCD(0x80); //Location is the first in the first line. while(1) { matrix(); if(RI)//Receiving Upper Computer Data { RI=0;//Clear Receiving Mark t=SBUF; //Receiving data from host computer if(t!='d' && t!='l' && t!='c') WrDatLCD(t); if(t=='s') //'s'is the synchronization requester of the host computer. send(led);//Direct sending display status to host computer if(t=='d'){ //'d'deletes a character for the 1602 display WrComLCD(0x10); WrDatLCD(' '); delay(5); WrComLCD(0x10); } if(t=='l'){ //'l'is a line change for 1602 display if(a==1){ WrComLCD(0xC0); a=0;} else {WrComLCD(0x80);a=1;} } if(t=='c'){ // 'c'clears the screen for 1602 display screen WrComLCD(0x01); //Clean screen WrComLCD(0x80); } if(t=='f'){ PlayMusic(); } if(t>='0' && t<='7'){ //Receiving the Upper Computer Key t=t-'0';// Get the key code of the host computer led=led^(1<<t);//Keyboard counterposition P0=led; //Updating SCM Display send(led); //Send Display Status to PC } } } }