[embedded Linux_ARM bare metal] - Implementation of serial port communication

1. three concepts of communication

The communication process can be divided into three steps: first, the sender encodes according to the fixed coding format; Secondly, the encoded information is sent to the transmission medium; Finally, the receiver decodes the received information to get valid information.

  • Serial communication concept 1
    Synchronous and asynchronous: the clock beats of the sender and receiver are the same, which is called synchronous. Otherwise, it is called asynchronous. As shown in the rain, the top line is the synchronization signal line, and the transmitter and receiver work at the same beat.

    Synchronization usage scenario: when the frequencies of the transmitter and receiver are fixed, the synchronization signal is used. You can imagine that the receiving end is always receiving messages from the sending end.
    Asynchronous scenario: asynchronous communication is used when the frequency of both sides of the communication is not fixed.
  • Level signal and differential signal

    Level signal: the level signal requires two signal lines, one is the reference line GND (0V), and the other is the signal line. The level signal value is the difference between the signal line and the reference battery line.
    **Differential signal: * * there is no reference line but two signal lines. Signal value of differential signal: voltage difference between the two signal lines.
    **Features of two signal lines: * * level signal is easy to be interfered and suitable for short distance transmission. The differential signal has strong anti-interference ability and is suitable for long-distance transmission.
    Level signal preparation: RS232 preparation: -3~-15 indicates 1, 3~15 indicates 0; TTL standard: +5 means 1, 0 means 0 The serial port at the back of our computer is the TTL standard level.
  • Parallel communication and serial communication
    Parallel and serial mainly refer to the number of communication lines, that is, the amount of information that can be transmitted by the sender and the receiver at the same time. For example, for level signals, two can transmit 1-bit binary, and three can transmit 2-bit binary; 9 pieces are required to transmit 8 bits.
    For differential signals, two lines can send one bit of binary at the same time, and 16 lines are required to transmit 8 bits.
    However, in fact, the most commonly used serial port is still serial communication, because it saves materials, and now the most commonly used serial port is to transmit debugging information. In daily life, network communication and USB communication pass through asynchronous, serial and differential modes.

2 basic principle of serial port communication

  • Three communication lines: RX TX GND
    In the actual serial communication, there are 9 lines, but only three are valid, namely RX TX GND.
  • Baud rate, data bit, parity bit, stop bit
    This is the setting for outputting debugging information from the SECURECRT link serial port.

    Baud rate: refers to the number of binary bits transmitted in one second. The common ones are 9600115200 If the baud rates of both sides are inconsistent, there will be problems in receiving and sending.
    Data bits: the sending end is cycle by cycle, and usually encodes the transmission information into ACSII code, so it sends 8 bits in a cycle.
    Start bit: the start bit is set to the high level and low level agreed by both parties. When the sender receives the binary stream, it will know where to start.
    Stop bit: the stop bit is specified by both sides of serial communication in advance and is reflected by the level change on the communication line. Common stop bits include 1 bit, 1.5 bit and 2 bits.
    Parity bit: add up the data bits one by one. If it is an even number, the parity bit is 1. If it is an odd number, the parity bit is 0 (see your definition).
  • Information is transmitted on the channel in the form of binary stream
  • DB9 interface introduction
    DB9 is a commonly used specification in the early days of serial communication. There are 9 lines in DB9, 3 of which are communication lines, and the remaining 6 are related to flow control (to control the speed of the sending stream). Flow control is generally disabled now, so 6 are useless.

3. working block diagram of serial port communication

As can be seen from the above figure, the whole serial port controller includes two parts: transmitter and receiver. The functions of the two parts are independent of each other. The transmitter is responsible for sending information to the outside and the receiver is responsible for receiving information from the outside.
The Transmitter consists of a transmit buffer and a transmit shifter. When we send information, we encode it into a binary stream, and then write a frame of data into the transmission buffer (the rest of the transmission is automatically completed by the hardware). The unit is shown in the above figure to illustrate the working process. Then, the transmission shifter will automatically read a frame of data from the transmission buffer and transmit it on the Tx communication line bit by bit.
The receive buffer consists of a receiver and a receive shifter. The binary stream enters my receiving shifter through the Rx communication line, and then the receiving shifter automatically shifts and stores the binary bit in the receiving buffer. After receiving a frame of data, an interrupt is generated to the CPU. After receiving the interrupt, the CPU can know that the receiver has received a full frame of data, and will process the frame data.
For our software engineers, the above process is to set the corresponding registers. We don't care about the specific hardware details at all. When setting the register, it should be noted that to set the baud rate generator of the serial port controller is to set the transmit / receive beat clock. The baud rate generator is actually a clock divider. Its work requires the source clock (from APB bus), and then internally divides the source clock (configured by software setting registers) to obtain the target clock, and then uses the target clock to generate the baud rate (hardware automatic).

4. specific implementation

Although you can directly set the value of the register, * (volatile unsigned int *) XXX address value XX = 0xXXXX, in order to make the code clear and tidy, it is written as follows.
First, define the register; Then, initialize the operation; Finally, define UART_ The putc function sends (that is, assigns a value to a register).

#define  GPAOCON 	 0XE02000000 / / see the data manual for setting the address,
#define  UCON0   	0XE2900004
#define  ULCON0  	0XE2900000
#define	 UMCON0  	0xE290000C
#define  UFCON0 	0xE2900008
#define  UBRDIV0 	0XE2900028
#define  UDIVSLOT0  0XE290002C

#define  UTRSTA0 	0XE2900010
#define  UTXH0 		0XE2900020
#define  URXH0 		0XE2900024
// Define access register macro
#define  rGPA0CON  (*(volatile unsigned int *)GPAOCON)
#define  rUCON0		(*(volatile unsigned int *)UCON0)
#define  rULCON0	(*(volatile unsigned int *)ULCON0)
#define  rUMCON0 	(*(volatile unsigned int *)UMCON0)
#define  rUFCON0 	(*(volatile unsigned int *)UFCON0)
#define  rUBRDIV0	(*(volatile unsigned int *)UBRDIV0)
#define  rUDIVSLOT0  (*(volatile unsigned int *)UDIVSLOT0)

#define  rUTRSTA0 	(*(volatile unsigned int *)UTRSTA0)
#define  rUTXH0	(*(volatile unsigned int *)UTXH0)
#define  rURXH0  (*(volatile unsigned int *)URXH0)

// Serial port initialization program
void uart_init(void)
		// Initialize the GPIO pin corresponding to Tx Rx
	rGPA0CON &= ~(0xff<<0);			// Clear all bit0 ~ 7 of the register
	rGPA0CON |= 0x00000022;			// 0b0010, Rx Tx
	// Setting of several key registers
	rULCON0 = 0x3;
	rUCON0 = 0x5;
	rUMCON0 = 0;
	rUFCON0 = 0;
	// Baud rate setting 	 DIV_VAL = (PCLK / (bps x 16))-1
	// PCLK_PSYS is calculated with 66MHz 		 Remainder 0.8
	//rUBRDIV0 = 34;	
	//rUDIVSLOT0 = 0xdfdd;
	// PCLK_PSYS is calculated with 66.7MHz 		 Remainder 0.18
	// DIV_VAL = (66700000/(115200*16)-1) = 35.18
	rUBRDIV0 = 35;
	// (number of 1 in rUDIVSLOT) /16= remainder calculated in the previous step =0.18
	// (number of 1 in rUDIVSLOT = 16*0.18= 2.88 = 3
	rUDIVSLOT0 = 0x0888;		// Three ones. Check the official recommendation form to get this number

// Serial port sending program, send a byte
void uart_putc(char c)
	// When the serial port sends a byte, it actually throws a byte into the sending buffer
	// Because the speed of one byte sent by the serial port controller is far lower than that of one byte, the CPU must confirm the serial port controller before sending one byte
	// The current buffer is empty (meaning that the serial port has sent out one)
	while(!(rUTRSTA0 & (1 << 1)))
	rUTXH0 = c;


The results are as follows: (under review, picture first)

Posted by zmola on Wed, 01 Jun 2022 18:33:07 +0530