1. Program Function
Use the serial port debugging assistant to send a character X on the host computer. After receiving the character, the microcontroller returns "I get X" to the host computer. The serial port baud rate is set to 9600bps.
2. Program source code
//Interrupt enable register IE, byte address 0xA8
//When the MCU is reset, all bits in IE are cleared to 0
sfr IE = 0xA8;
//EA is the global interrupt enable bit
//When EA = 1, the global interrupt control is turned on. Under this condition, each interrupt control bit turns on or off the corresponding interrupt
// Disable all interrupts when EA = 0
sbit EA = IE^7;
//ET2 is the interrupt enable bit for timer/counter 2
//When ET2 = 1, turn on T2 interrupt, and when ET2 = 0, turn off T2 interrupt
sbit ET2 = IE^5; //8052 only
//ES is the serial port interrupt enable bit
//When ES = 1, the serial port interrupt is turned on; when ES = 0, the serial port interrupt is turned off
sbit ES = IE^4;
//ET1 is the timer/counter 1 interrupt enable bit
//When ET1 = 1, turn on T1 interrupt, and when ET1 = 0, turn off T1 interrupt
sbit ET1 = IE^3;
//EX1 is the external interrupt 1 interrupt enable bit
//EX1 = 1 to turn on external interrupt 1, EX1 = 0 to turn off external interrupt 1
sbit EX1 = IE^2;
//ET0 is the interrupt enable bit for timer/counter 0
//When ET0 = 1, turn on T0 interrupt, and when ET0 = 1, turn off T0 interrupt
sbit ET0 = IE^1;
//EX0 is the external interrupt 0 interrupt enable bit
//EX0 = 1 turns on external interrupt 0, EX0 = 0 turns off external interrupt 0
sbit EX0 = IE^0;
//SBUF is the serial data buffer register
//51 MCU contains two SBUFs, one is the send buffer register and the other is the receive buffer register
//These two registers share the same address 0x99, but they are physically two independent registers. There is an instruction operation to determine which register to access
//When executing a write instruction, access the serial transmit register, and when executing a read instruction, access the serial receive register
//The receiver has a double buffer structure, that is, it can receive the second byte before reading the previous received byte from the receive register
//If the second byte has been received and the first byte has not been read, one of the bytes will be lost
//For the transmitter, the data is controlled and sent by the CPU, so there is no need to consider
sfr SBUF = 0x99;
//SCON is the serial port control register
//SCON is bit-addressable, that is, you can access a specific bit of it
//SCON is used to set the serial port working mode, receive/send control and set status flags
//When the MCU is reset, all SCONs are cleared to 0
sfr SCON = 0x98;
//SM0, SM1 are the working mode selection bits. The serial port has 4 working modes, which are set by SM0 and SM1.
//SM0=0, SM1=0 is mode 0, i.e. synchronous shift register mode, used to expand I/O ports
//SM0=0, SM1=1 is mode 1, i.e. 10-bit asynchronous transmission, including 8-bit data, variable baud rate, and controlled by the overflow rate of timer 1
//SM0=1, SM1=0 is mode 2, i.e. 11-bit asynchronous transmission, including 9-bit data, fixed baud rate
//SM0=1, SM1=1 is mode 3, i.e. 11-bit asynchronous transmission, including 9-bit data, variable baud rate, and controlled by the overflow rate of timer 1
sbit SM0 = SCON^7;
sbit SM1 = SCON^6;
//SM2 is the multi-machine communication control bit, mainly used for mode 2 and mode 3
//When the receiver's SM2=1, the received RB8 can be used to control whether to activate RI, that is, when RB8=0, RI is not activated and the received information is discarded
//When RB8=1, the received data enters SBUF, and activates RI, and then reads the data from SBUF in the interrupt service.
//When SM0=0, no matter whether the received RB8 is 0 or 1, the received data can be entered into SBUF and RI can be activated. That is, RB8 does not have the function of controlling RI activation.
//By controlling SM2, multi-machine communication can be achieved.
//In mode 0, SM2 must be 0
//In mode 1, if SM2=1, RI is set to 1 only when a valid stop bit is received.
sbit SM2 = SCON^5;
//REN is the serial reception enable bit
//REN=1 allows the serial port to receive data
//When REN=0, the serial port is prohibited from receiving data
sbit REN = SCON^4;
//TB8 is the 9th bit of the data sent in mode 2 and 3
//In mode 2 or mode 3, the 9th bit of the data is sent, and its function can be defined by software, and can be used as the parity bit of the data
//Or in multi-machine communication, as the flag bit of the address frame/data frame
// In mode 0 and mode 1, this bit is not used
sbit TB8 = SCON^3;
//RB8 is the 9th bit of the received data in mode 2 and 3
//In mode 2 or mode 3, it is the 9th bit of the received data, which can be used as a parity bit or a flag bit of the address frame/data frame
//In mode 1, if SM2=0, RB8 is the received stop bit
sbit RB8 = SCON^2;
//TI is the send interrupt flag
// In mode 0, when the serial transmission of the 8th bit of data ends, or in other modes, when the serial transmission of the stop bit begins,
//The internal hardware sets TI to 1 and sends an interrupt request to the CPU. In the interrupt service routine, it must be cleared to 0 by software to cancel the interrupt request
sbit TI = SCON^1;
//RI is the receive interrupt flag
// In mode 0, when the serial reception of the 8th bit of data ends, or in other modes, in the middle of the serial reception stop bit,
// Set RI to 1 by internal mail, send an interrupt request to CPU, and clear it to 0 by software in the interrupt service routine to cancel the interrupt request
sbit RI = SCON^0;
//TMOD is the timer/counter working mode register
//Byte address bit 0x89, cannot be bit-addressed
//When the MCU is reset, all TMODs are cleared to 0
//The high 4 bits of TMOD are used to set timer 1, and the low 4 bits are used to set timer 0.
//The high and low 4 bits are composed of GATE, C/T, M1, M0
//GATE is the gate control bit
//GATE=0, the start and stop of the timer/counter are only controlled by TRX (X=0,1) in the TCON register
//GATE=1, the start and stop of the timer/counter are controlled by the level of TRX (X=0,1) in the TCON register and the external interrupt pin (INT0 or INT1)
//C/T is the timer mode and counter mode selection bit
//C/T=1 is counter mode, C/T=0 is timer mode
//M1M0 is the working mode selection bit
//M1=0,M0=0 is mode 0, 13-bit timer/counter
//M1=0,M0=1 is mode 1, 16-bit timer/counter
//M1=1,M0=0 is mode 2, 8-bit output value automatically reloaded 8-bit timer/counter
//M1=1, M1=0 is mode 3, only applicable to T0, divided into two 8-bit counters, T1 stops counting
sfr TMOD = 0x89;
//TCON is the timer/counter control register
//TCON byte address is 88H, bit addressable
//The TCON register is used to control the start and stop of the timer, and to mark timer overflow and interrupt
//When the MCU is reset, all TCONs are cleared to 0
//TCON contains TF1,TR1,TF0,TR0 for timer/counter
//IE1, IT1, IE0, IT0 contained in TCON are used for external interrupts
sfr TCON = 0x88;
//TF1 is the overflow flag of timer 1
//When counter 1 overflows, the hardware sets TF1 to 1 and requests an interrupt. After entering the interrupt service routine, the hardware automatically clears it to 0
//If the timer interrupt is used, this bit does not need to be operated manually
//If you use software query, after checking that this bit is 1, you need to clear it to 0 using software
sbit TF1 = TCON^7;
//TR1 is the timer 1 running control bit
//Clear by software to turn off timer 1, when GATE=1 and INT1 is high, set TR1 to start timer 1
//When GATE=0, set TR1 to 1 to start timer 1
sbit TR1 = TCON^6;
//TF0 is the overflow flag of timer 0, its function and operation method are the same as TF1
sbit TF0 = TCON^5;
//TR0 is the timer 0 operation control bit, its function and operation mode are the same as TR1
sbit TR0 = TCON^4;
//IE1 is the external interrupt 1 request flag
//When IT1=0, it is level triggered, S5P2 samples INT1 pin in each machine cycle,
//If INT1 is low, set it to 1, otherwise clear IE1 to 0
//When IT1=1, INT1 bit jump edge trigger mode, when the first machine cycle samples INT1 as low level, IE1 is set to 1
//When IE1=1, it means that external interrupt 1 is requesting an interrupt from the CPU. When the CPU responds to the interrupt and turns to the interrupt service routine, this bit is cleared by hardware
sbit IE1 = TCON^3;
//IT1 is the external interrupt 1 trigger mode selection bit
//IT1=0, level trigger mode, low level on pin INT1 is valid
//IT1=1, jump edge trigger mode, the negative jump from high to low on the pin INT1 is valid
sbit IT1 = TCON^2;
//IE0 is the external interrupt 0 request flag, the function and operation are the same as IE1
sbit IE0 = TCON^1;
//IT0 is the external interrupt 0 trigger mode selection bit, the function and operation are the same as IT1
sbit IT0 = TCON^0;
//Timer 1 initial value high 8 bits
sfr TH1 = 0x8D;
//Timer 1 initial value low 8 bits
sfr TL1 = 0x8B;
#define uchar unsigned char
#define uint unsigned int
uchar flag, a, i;
uchar code table[] = "I get "; //Define a character type encoding array
void init();
void main()
{
init(); //initialization
while (1)
{
//If the flag is detected as 1, it means that the program has executed the serial port interrupt service program, that is, the data has been received.
if (flag == 1)
{
//Manually clear the flag to 0 to facilitate flag detection
flag = 0;
//After detecting that the flag is 1, that is, the serial port interrupt occurs, clear ES to 0 first, because data will be sent next. If the serial port interrupt is not closed, after sending the data,
//The MCU will also apply for a serial port interrupt, enter the interrupt service routine again, the flag is 1 again, and send data again, repeating
//Therefore, we turn off the serial port interrupt before sending data, and turn on the serial port interrupt after sending the data, so that the data can be sent safely
ES = 0;
//Send the characters in the previous array one by one through the for loop
//Since there are 6 characters in the array table, the loop ends with 6
for (i = 0; i < 6; i++)
{
//Send characters
SBUF = table[i];
//After writing a data to SBUF, use while(!TI) to wait for the transmission to be completed, because after the transmission is completed, TI will be
//Hardware set to 1, then exit while(!TI)
while (!TI);
// Then manually clear TI to 0
TI = 0;
}
//Write the data read from the interrupt service routine into SBUF
SBUF = a;
while (!TI); //same as above
TI = 0; //same as above
ES = 1; //Newly enable serial port interrupt
}
}
}
void init()
{
TMOD = 0x20; //Set timer 1 to work mode 2: 8-bit timer with 8-bit initial value and automatic reload (the purpose of setting timer 1 is that its overflow rate determines the serial port baud rate)
TH1 = 0xfd; //Initial value of timer 1 (baud rate is 9600)
TL1 = 0xfd; // Initial value of timer 1 (baud rate is 9600), note: TH1 and TL1 initial values must be the same
//ET1 = 1; //There is no need to enable the timer 1 interrupt here, because timer 1 works in mode 2, which is 8-bit automatic reload mode, and there is nothing to do when entering the interrupt
REN = 1; // Allow the serial port to receive data
SM0 = 0; //Set the serial port working mode 1
SM1 = 1; //Set the serial port working mode 1 (10-bit asynchronous transmission and reception, variable baud rate, and determined by the overflow rate of timer 1)
EA = 1; // Enable general interrupt
ES = 1; //Open serial port interrupt
TR1 = 1; //Start timer 1
}
//Serial port interrupt service routine
void ser() interrupt 4
{
//RI is the receive interrupt flag. In mode 0, when the serial reception of the 8th bit of data ends, or in other modes, the serial reception stop bit
//In the middle, the internal hardware sets RI to 1 and sends an interrupt request to the CPU. It must also be cleared to 0 by software in the interrupt service routine to cancel the interrupt.
//This interrupt application is to facilitate the next interrupt application detection, that is, to generate the next interrupt.
// Here RI is cleared to 0, because since the program has generated a serial port interrupt, it must have received or sent data. No data was sent at the beginning
//It must be that data has been received. At this time, RI will be set to 1 by hardware, so it must be cleared to 0 by software after entering the serial port interrupt service routine.
//Generate the next interrupt.
RI = 0;
//Read the data in SBUF to a, this is the most important purpose of this interrupt service program
a = SBUF;
//Set the flag to 1 to facilitate querying in the main program to determine whether data has been received
flag = 1;
}
3. Summary of the program
1) Before operating the serial port, you need to initialize some special function registers of the microcontroller related to the serial port, mainly to set the baud rate.
a. Determine the working mode of T1 (become TMOD register)
b. Calculate the initial value of T1, load TH1, TL1
c. Start T1 (program the TR1 bit in TCON)
d. Determine the serial port working mode (program the SCON register)
e. When the serial port works in interrupt mode, interrupt settings must be performed (change to IE, IP registers)
2) The 51 MCU can access the serial receive or serial transmit register through the special function register SBUF. The two registers share the same address.
99H, but physically they are two independent registers. Which register is accessed is determined by the instruction operation. When executing a write instruction, the serial transmit register is accessed, and when executing a read instruction, the serial receive register is accessed. The receiver has a double buffer structure, that is, the previously received data is read from the receive register.
The second byte can be received before the first byte is read. If the second byte has been received but the first byte has not been read, the first byte is lost.
One byte. For the transmitter, since the data is controlled and sent by the CPU, it does not need to be considered.
a=SBUF; means the MCU automatically takes the data in the serial port receiving register to a.
SBUF=a; represents that the microcontroller sends the data in the serial port send register bit by bit from the serial port.
3) This program can be used to display the data received by the serial port.
a. In the while of the main function main, ES=0 can be replaced with EA=0, and ES=1 can be replaced with EA=1 (that is, the temporary control of the serial port interruption can be changed to the control of the global interruption)
b. ET1=1 in the initialization function init cannot be opened, even if there is a sub-function of counter 1 outside the main function (the function is empty)
c. TR1=1 in the initialization function init needs to be turned on (including TMOD=0x20), because the overflow rate of timer 1 is needed to determine the serial port baud rate.
d. REN=1 in the initialization function init needs to be turned on, otherwise the serial port will not receive data
e. The initialization function SM1=1 needs to be turned on, otherwise the serial port will receive garbled characters
f. The initialization function ES=1 needs to be turned on, otherwise the serial port will not receive data
5) In method 2, the address of TH1 is 0x8D, which is the same as the address of TF0 in TCON. Doesn’t assigning a value to TH1 affect TF0?