Description of program design objectives and program operation effects
Program design goal: by pressing the key key1 to control the music playback and the lyrics display of the nixie tube.
Description of program operation effect: press the key key1 to play the music I can say ABC and display the lyrics; Press key1 again to pause playing music.
Program related circuit and principle description
1. Principle description
This experimental board adopts a passive buzzer. Compared with the active buzzer, the advantage of the passive buzzer is that it is cheap and can change the sound by controlling its vibration frequency. Therefore, the passive buzzer can be used for music playing. The advantage of active buzzer is that it is simple to use and does not need to write "music score". The passive buzzer used in this experimental board is an electromagnetic buzzer, which is composed of oscillator, electromagnetic coil, magnet, vibrating diaphragm and shell. After the power is turned on, the received audio signal current passes through the solenoid to generate a magnetic field. The vibrating diaphragm vibrates and sounds periodically under the interaction of electromagnetic coil and magnet.
In this program, the array music [] is the music to be played. The format is note, beat, note, beat, and so on. The note is the tone to be emitted, and the beat is the duration of the sound. As shown in the figure, in the array music [], the format of note representation is: ten bits represent low octave, medium octave or high octave, 1 represents high octave, 2 represents medium octave, 3 represents high octave, and one bit represents simple music notes. For example, 0x15 represents S0 of low octave, 5S0 of low octave as shown in the figure, and 0x21 represents DO of medium octave, d0 of medium octave as shown in the figure. Among the notes, 0x00 represents the ending symbol, which means that the whole song has been sung, while 0xff represents the stop symbol, which means to stop for 100ms. In both cases, you should re execute the first step in the loop. The rest is played normally. After the program is burned into the MCU, you need to press the key key1 to play. Compared with the basic article, the lyrics nixie tube synchronous display function is added.
Note: because the use of nixie tube to display lyrics is really reluctant, some letters are difficult to display on the nixie tube, such as "M", The main learning focus of this experiment is on the synchronous display of lyrics and the digital arrangement of songs (i.e. from simplified music to music code). The corresponding symbol table (A-Z) of ABC English song letter nixie tube display has been made into another document. See the document "ABC English song letter nixie tube display corresponding symbol table (A-Z)".
2. Program related circuits
(1) Circuit schematic diagram of passive buzzer
(2) Key control circuit
Chip related pins: Beep -- P3^4;
The code is as follows:
#include "STC15F2K60S2.H" #define uint unsigned int // Macro definition #define uchar unsigned char sbit led_sel=P2^3; //Nixie tube and led strobe pin sbit sel0=P2^0; //SEL0, SEL1 and SEL2 are combined as bit selection information, 0-7 sbit sel1=P2^1; sbit sel2=P2^2; sbit beep=P3^4; //Buzzer pin sbit key1=P3^2; //Define key 1 sbit key2=P3^3; //Define key 2 uchar timeh,timel; //Defines the reload value of the timer uchar flag; //Selected lit nixie tube 0-7 flag bits bit zanting; //Play or pause flag bit uchar jindu=0; //The position pointed to in the music array uchar geci[]={0x77,0x7f,0x39,0x00,0x6f,0x7b}; //Display the nixie tube segment code of the startup screen uchar geci1[]={0x77,0x7f,0x39,0x3f,0x79,0x71,0x3d,0x40}; //Display the digital segment code ABCDEFG of A-G- uchar geci2[]={0x76,0x06,0x1e,0xf6,0x38,0x4f,0x37,0x40}; //Display H-N nixie tube segment code HIJKLMN- uchar geci3[]={0x3f,0x73,0xbf,0x40,0xf7,0x6d,0x07,0x40}; //Display the digital segment code OPQ-RST of O-T- uchar geci4[]={0x62,0x3e,0xf9,0x40,0xf6,0xe6,0xdb,0x40}; //Displays the U-Z segment code UVW-XYZ- uchar geci5[]={0xf6,0xe6,0xdb,0x80,0x37,0x3f,0xf9,0x00}; //XYZ,Now uchar geci51[]={0xe6,0x3f,0x62,0x00,0x6d,0x79,0x79,0x00}; //you see uchar geci6[]={0x0f,0x39,0x77,0x37,0x00,0x6d,0x77,0xe6}; //I can say uchar geci61[]={0x77,0x7f,0x39,0x00,0x00,0x00,0x00,0x00}; // ABC uchar weixuan[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; //Bit selection code uchar code music[] ={ //Music code, the song is "I can say ABC", the format is: note, beat, note, beat, 0x11,0x10,0x21,0x10, //The ten digits of notes represent low octave, medium octave or high octave, 1 represents low octave, 2 represents medium octave and 3 represents high octave 0x25,0x10,0x25,0x10, //A bit represents a note of simplified music. For example, 0x15 represents S0 of low octave and 0x21 represents DO of medium octave. 0x26,0x10,0x26,0x10, //The beat represents the sound length, for example, 0x10 represents one beat, 0x20 represents two beats, and 0x05 represents 1 / 2 beat 0x25,0x10,0x25,0x10, //16 0x24,0x10,0x14,0x10, 0x23,0x10,0x13,0x10, 0x22,0x10,0x22,0x10, 0x21,0x10,0x21,0x10, //32 0x25,0x10,0x25,0x10, 0x24,0x10,0x24,0x20, 0x23,0x10,0x23,0x10, 0x22,0x10,0x22,0x10, //48 0x25,0x10,0x25,0x10, 0x24,0x10,0x24,0x20, 0x23,0x10,0x23,0x10, 0x22,0x10,0x22,0x10, //64 0x21,0x10,0x21,0x10, 0x25,0x10,0x25,0x10, //72 0x26,0x10,0x26,0x10, 0x25,0x10,0x25,0x10, //80 0x24,0x10,0x24,0x10, 0x23,0x10,0x23,0x10, //88 0x22,0x10,0x22,0x10, 0x21,0x10,0x21,0x20, //96 0x00,0x00 }; uchar code quzi[] ={ //This array data is the reload value of each note in the timer. The first column is high and the second column is low 0xf8,0x8c, //Low octave, low 1 0xf9,0x5b, 0xfa,0x15, //Low 3 0xfa,0x67, 0xfb,0x04, //Low 5 0xfb,0x90, 0xfc,0x0c, //Low 7 0xfc,0x44, //Central C key 0xfc,0xac, //Medium 2 0xfd,0x09, 0xfd,0x34, //Medium 4 0xfd,0x82, 0xfd,0xc8, //Medium 6 0xfe,0x06, 0xfe,0x22, //High octave, high 1 0xfe,0x56, 0xfe,0x6e, //High 3 0xfe,0x9a, 0xfe,0xc1, //High 5 0xfe,0xe4, 0xff,0x03 //High 7 }; void delay(unsigned int xms) { uint i,j; for(i=xms;i>0;i--) for(j=124;j>0;j--); } //Function Description: in the quzi array, find the reload value of the simplified musical note defined by the music array, and return its position in the quzi array //Entry parameter: simplified musical notes defined in tem: music array //Exit parameter: returns the position value of tem note in quzi array uchar quyin(uchar tem) { uchar qudiao,jp,weizhi; //Define tunes, notes and positions qudiao=tem/16; //The upper 4 digits are the tune value jp=tem%16; //The lower four are notes if(qudiao==1) //When the tune value is 1, it is the low octave, and the base address of the low octave in the quzi array is 0 qudiao=0; else if(qudiao==2) //When the tune value is 2, it is the middle octave, and the base address of the middle octave in the quzi array is 14 qudiao=14; else if(qudiao==3) //When the tune value is 3, it is the high octave. The high octave is in the quzi array, and the base address is 28 qudiao=28; weizhi=qudiao+(jp-1)*2; //By adding a note to the base address as an offset, the position of the note in the quzi array can be located return weizhi; //Returns this location value } void playmusic()//Play music { uchar p,m,tem; //m is the beat while(1) { if(zanting==1) //Play or pause control { p=music[jindu]; if(p==0x00) //If you encounter an end character, delay 1 second, return to the beginning and do it again { jindu=0; delay(1000); break; } else if(p==0xff) //If you encounter a pause, delay 100ms and continue to take the next note { jindu++; delay(100); TR0=0; //Off timer 0 break; } else //Normally take notes and beats { tem=quyin(music[jindu]); //Gets the position value of the current note in the quzi array timeh=quzi[tem]; //Reload the timer corresponding to the note to timeh and timel timel=quzi[tem+1]; jindu++; TH0=timeh; //Assign timeh and timer to the timer TL0=timel; m=music[jindu]; //Get beat jindu++; } TR0=1; //On timer 0 delay(m*180); //Wait for the beat to complete and output audio through port P3^4 TR0=0; //Off timer 0 beep=0; //Set beep to 0 to protect the buzzer } } } //The function of system initialization is to configure the IO port void init_sys() { P0M0=0xff; //Set push-pull mode P0M1=0x00; P2M0=0x08; P2M1=0x00; P3M0=0x10; P3M1=0x00; } //timer initiated void init() { TMOD=0x01; //Set timer 0, working mode 1, 16 bit manual reset initial value; Set timer 1, working mode 0, 16 bit automatic reset initial value TH0=0xD8; //Set initial value of timer 0 TL0=0xEF; TH1=(65536-1000)/256; //Set initial value of timer 1 TL1=(65536-1000)%256; EA=1; //Open total interrupt ET0=1; //Open timer 0 interrupt ET1=1; //Open timer 1 interrupt TR0=0; //Timer 0 is not started temporarily TR1=1; //Start timer 1 EX0=1; //Start external interrupt 0 zanting=0; //Initial value of play or pause flag bit beep=0; //Set beep to 0 to protect the buzzer } void main() { init_sys(); //System initialization init(); P0=0x00; key1=1; flag=0; while(1) playmusic(); //Enter play music function } //Timer 0 interrupts processing, reloads the value, reverses the beep value, and generates a square wave void tim1()interrupt 1 //Timer control frequency { TH0=timeh; //Reset initial value after interruption TL0=timel; beep=~beep; //Interrupt beep flip to generate square wave, making the buzzer sound } //Press the external interrupt of key 1, reverse the flag bit, and the function is to pause and play music void exint0()interrupt 0 { if(key1==0) { delay(10); if(key1==0) zanting=~zanting; } } //Timer 1 interrupt processing, used as nixie tube to display lyrics. void timer1()interrupt 3 //Refer the display program to timer 1 interrupt service program { flag++; if(flag==8) flag=0; P0=0; P2=weixuan[flag]; if(jindu==0) //By judging the jindu during playback, the lyrics display at this time can be controlled { //When this is zero, "ABC ge" is displayed switch(flag) { case 0:P0=geci[0];break; case 1:P0=geci[1];break; case 2:P0=geci[2];break; case 4:P0=geci[4];break; case 5:P0=geci[5];break; default:P0=geci[3];break; } } else if(jindu<16) { //At this time, the progress is between 0-15, and "ABCDEFG -" is displayed switch(flag) { case 0:P0=geci1[0];break; case 1:P0=geci1[1];break; case 2:P0=geci1[2];break; case 3:P0=geci1[3];break; case 4:P0=geci1[4];break; case 5:P0=geci1[5];break; case 6:P0=geci1[6];break; default:P0=geci1[7];break; } } else if(jindu<32) { //At this time, the progress is between 16-31, and "HIJKLMN -" is displayed switch(flag) { case 0:P0=geci2[0];break; case 1:P0=geci2[1];break; case 2:P0=geci2[2];break; case 3:P0=geci2[3];break; case 4:P0=geci2[4];break; case 5:P0=geci2[5];break; case 6:P0=geci2[6];break; default:P0=geci2[7];break; } } else if(jindu<48) { //At this time, the progress is between 32-47, and "OPQ- RST -" is displayed switch(flag) { case 0:P0=geci3[0];break; case 1:P0=geci3[1];break; case 2:P0=geci3[2];break; case 3:P0=geci3[3];break; case 4:P0=geci3[4];break; case 5:P0=geci3[5];break; case 6:P0=geci3[6];break; default:P0=geci3[7];break; } } else if(jindu<64) { //At this time, the progress is between 48-63, and "UVW- XYZ -" is displayed switch(flag) { case 0:P0=geci4[0];break; case 1:P0=geci4[1];break; case 2:P0=geci4[2];break; case 3:P0=geci4[3];break; case 4:P0=geci4[4];break; case 5:P0=geci4[5];break; case 6:P0=geci4[6];break; default:P0=geci4[7];break; } } else if(jindu<72) { //At this time, the progress is between 64-71, and "XYZ- NOW" is displayed switch(flag) { case 0:P0=geci5[0];break; case 1:P0=geci5[1];break; case 2:P0=geci5[2];break; case 3:P0=geci5[3];break; case 4:P0=geci5[4];break; case 5:P0=geci5[5];break; case 6:P0=geci5[6];break; default:P0=geci5[7];break; } } else if(jindu<80) { //At this time, the progress is between 72-79, and "YOU SEE" is displayed switch(flag) { case 0:P0=geci51[0];break; case 1:P0=geci51[1];break; case 2:P0=geci51[2];break; case 3:P0=geci51[3];break; case 4:P0=geci51[4];break; case 5:P0=geci51[5];break; case 6:P0=geci51[6];break; default:P0=geci51[7];break; } } else if(jindu<88) { //At this time, the progress is between 80-87, and "ICAN SAY" is displayed switch(flag) { case 0:P0=geci6[0];break; case 1:P0=geci6[1];break; case 2:P0=geci6[2];break; case 3:P0=geci6[3];break; case 4:P0=geci6[4];break; case 5:P0=geci6[5];break; case 6:P0=geci6[6];break; default:P0=geci6[7];break; } } else if(jindu<96) { //At this time, the progress is between 88-95, and "ABC" is displayed switch(flag) { case 0:P0=geci61[0];break; case 1:P0=geci61[1];break; case 2:P0=geci61[2];break; case 3:P0=geci61[3];break; case 4:P0=geci61[4];break; case 5:P0=geci61[5];break; case 6:P0=geci61[6];break; default:P0=geci61[7];break; } } }