Serial Communication Explained: UART, I2C & SPI(原声文稿)
Today, we'll look at UR communication, the most basic form of serial communication.
We'll actually get a PC and a microcontroller communicating with each other.
The character we're sending to the PC is uppercase A.
To us, it's just A, but how does the MCU transmit this character?
In the ASCII table, uppercase A has a hexadecimal value of 0x41.
In binary, we write 0x41 as 8 bits, like this.
Ultimately, from a hardware perspective, what we need to do is transmit these 8 bits to another device. So how can we transfer these 8 bits?
The simplest way is to use one wire for each bit.
We use 8 data lines, each outputting 0 or 1 at the same time.
That's parallel communication.
The advantage is that we can send several bits at once. But 8 bits need 8 data lines.
That means using more of the MCU's pins and the number of traces we have to route on the PCB keeps growing. So this time we'll use just one wire.
Instead of sending 8 bits simultaneously, we'll send them one by one on a single line.
You send the first bit, then the next bit, and so on.
The data goes out in sequence.
This is the basic concept of serial communication. There are various types of serial communication like UART, I2C, SPI, and CAN.
In this session, I'll explain you ART, which is the most basic and commonly used among them.
UART stands for Universal Asynchronous Receiver Transmitter.
Here, the transmitters decide that sends data, and the receiver is the side that receives data.
And one of the most important terms here is asynchronous. Let's assume two MCUs are communicating.
For MCUA to send data, you must connect AS, TX to MCUB's RX.
To send data the other way, from MCUV to A, connect B's TX to A's RX.
So in your R communication, you have to cross -connect the T, X, and RX lines.
And since the two devices must have the same voltage reference, you also need to connect their grounds together.
But there's one strange thing here, there's no clock line.
So how can the MCU tell when the data begins and when it should read each individual bit?
To understand this, let's first look at the frame structure of UART communication.
UART doesn't simply transmit the 8 data bits we want to send.
It adds information before and after them, then sends everything as one frame.
Looking at a basic UART frame, there's a start bit, followed by the actual data bits, then optionally a parity bit depending on the settings, and finally a stop bit.
For this example, we'll use the most common settings.
We will configure it with 8 data bits, no parity bit, and a single stop bit.
UART holds the TX lying high when no data is being sent. This is called the idle state.
To send new data, the TX signal is pulled from high to low. This low interval is the start bit.
When the receiver sees the signal suddenly drop low after staying high, it can tell new data is starting to come in.
After the start bit, we have the actual data we want to send.
In this configuration, it's 8 bits, so a total of 8 data bits are sent.
After all 8 data bits are sent, a stop bit is appended.
The stop bit is high again.
If there's no new data after it, the line stays high and goes back to the idle state.
So we've sent a single character using a total of 10 bits.
Alright, let's go back to the letter A we saw at the beginning.
Uppercase A was 0x41.
And if we write this in binary, we get 8 bits, as shown here.
One thing to note about data transmission order is that UART typically sends the LSB first.
It transmits data bits, 0, 1, 2, and so on, starting from the far right. So the actual order of the data bits is like this.
But there's still one more problem.
We know that the start bit signals the beginning of data. So when should the receiver read data bit zero? And when should it read data bit one?
To solve this problem, we set the transmitter and receiver to the same speed beforehand. This value is the baud rate.
For this example, I'll set the baud rate to 9600.
The baud rate refers to the number of symbols transmitted per second.
So, you can think of it as transmitting 9600 bits per second.
To find how long one bit lasts, divide one second by 9600.
That's roughly 104 microseconds, so one bit lasts 104 microseconds.
Since the transmitter and receiver know this time in advance, they can figure out how long each bit takes without a separate clock line.
Okay, let's go back to the waveform.
At first, the UART line is idle, so it stays high.
Then, when data transmission begins, it drops from high to low.
The receiver detects this change and determines that a start bit has begun.
And this point becomes the reference for timing the subsequent data bits.
As I mentioned, the length of one bit is about 104 microseconds.
So you might think we could read the data right at 104 microseconds after the start bit begins.
But this point is near the boundary where the start bit ends and data bit zero begins.
So at this specific point, the signal might actually be in the middle of transitioning from one state to another.
So these bit boundaries are not a good place to read data.
It's more reliable to read near the center of the bit where the signal is sufficiently settled.
So to get reliable data, we read it at the center of the bit.
Since one bit is about 104 microseconds, the center of data bit, 0, is roughly 156 microseconds after the start bit begins.
From then on, we can read the next data bits at the set bit time intervals.
And finally, once we checked that the stop bit is high as expected, we've received one complete UART frame.
Now let's check whether the actual hardware really produces this waveform. But there's one problem here.
The STM32 has TX and RX pins for UART communication, but the PC we're using doesn't expose UART pins like these. It mainly uses USB ports.
So, for UART, communication between the STM32 and PC, we need a converter module like this.
This chip acts as a bridge, connecting the microcontroller's UART with the PC's USB. Now, let's run a serial terminal on the PC.
Since the STM32 is continuously sending the letter A, you can see A being repeatedly received in the terminal.
Now, let's check the communication waveform within a oscilloscope.
The STM32 is still continuously transmitting the letter A.
This waveform shows one UART frame carrying the character A.
The signal goes from high to low here. This is the start bit.
On the actual hardware, we can see the signal go from high to low as the start bit begins, just as we drew earlier.
The receiver uses this very change to determine that a new UART frame has started. Next come the actual data bits.
Let's check the sequence step by step on the oscilloscope.
You can see that the actual waveform matches the data we drew in the diagram earlier.
And finally comes the stop bit, with the signal high again. Let's also check the time axis.
We calculated earlier that at 9600B, one bit was about 104 microseconds long.
If we measure one bit interval, each grid division here is 200 microseconds, and you can see that one bit takes up about half a division.
In other words, it matches the result we calculated using the BOD rate.
So that's all for today's video. I'll be back with more helpful content next time.
If you have any questions, please leave them in the comments.
Thank you. SPI communication is frequently used by microcontrollers to interface with peripherals like sensors or memory.
Its structure is more complex than the UART communication we covered last time, making it confusing for beginners.
I've packed a lot of key information throughout this video, so please watch until the end and don't forget to subscribe.
One of SPI's most important features is synchronous communication.
In synchronous communication, data is sent and received in sync with the clock.
Therefore devices transmitting and receiving data operate based on this clock signal.
In SPI, the master generates and sends the clock signal to the slave.
So the slave can use this clock to tell when to read the data.
So we call the device that controls communication the master and the device that follows the master's clock, the slave. An SPI has another key feature. It supports full duplex communication.
Simply put, it means that you are able to send and receive data at the same time.
We'll see how this is possible in a moment when we look at how the data actually moves.
First, let's try connecting just one MCU and one sensor.
Excluding power and ground, there are four main signals used in SPI communication.
First is the clock. This This is the clock signal that the master generates and sends to the slave.
Next is MOSI, which stands for master out slave in. It's the line that carries data from the master to the slave.
In the other direction, there's MIASOL, short for master in slave out. It carries data from the slave to the master. Finally, there's the CS or chip select signal.
This signal is used by the master to select which slave device it wants to communicate with.
CS is generally used as an active low signal, so it's held high when not communicating then pulled low to select a device when communicating with that slave.
Right now, with only one slave, it may not be obvious why we need CS.
But later, when we connect several sensors, you will see right away why we need this signal.
Now for the most important part, I'll explain data transmission using a shift register, which is the core of SPI communication.
Let's assume the master has data from M0 through M7 in its shift register, and the slave has data from S0 through S7 in its shift register.
Here M7 and S7 are each the MSB, and M0 and S0 are each the LSB.
A shift register, as its name implies, is one where internal data moves one position at a time with the clock.
data exiting the master enters the slave through the MOSI and data exiting the slave enters the master through the MISO line.
Now let's have the master generate a clock signal.
With each clock cycle you can see one bit pass from the master shift register to the slave through the MOSI line but at that exact same moment one bit also comes out of the slave. This bit enters the master through the MISO line.
So, with each clock pulse, one bit moves from master to slave, and simultaneously, one bit moves from slave to master.
The data in the shift register shifts one position.
If another clock pulse is generated, the subsequent bits are exchanged.
Generate another clock pulse, and the next bit moves.
Let's keep repeating this process. What happens after a total of 8 clock pulses?
All 8 bits the master started with have moved over to the slave, and all 8 bits the slave started with have moved over to the master.
That's how we send and receive data in SPI communication.
And as I mentioned earlier, SPI supports full duplex communication.
Because we're using two data lines here, MOSI and MISO, the master can receive data from the slave even while it's sending data.
But there's one thing I didn't cover in detail just now.
I said data is exchanged in sync with the clock, but exactly when in the clock cycle should we read it.
A clock signal has both a rising edge and a falling edge, so data can be read either on the rising edge or on the falling edge.
And before the communication begins, the clock might be either in a low state or a high state.
So in SPI communication, combining these two settings gives us a total of four different modes. These are modes 0, 1, 2, and 3.
The values that determine this are C pull and C phase. C pull defines clock polarity.
It determines that the clock is low or high in its idle state when no communication occurs. C phase stands for clock phase.
It determines whether we read the data on the first clock edge or on the second clock edge.
So when these two are combined, they create the following four modes.
STM32 also provides a timing diagram like this.
Explaining all four modes one by one here could make things more complicated, so this time I'll explain how it works using just the most basic one, mode zero.
In mode zero, since C pull is zero, the clock remains in a low state when communication is not active.
And because the clock face is zero, data is read on the first clock edge.
The first clock edge is a rising edge.
edge, so the first data bit must already be output on Mozi and Miso before the rising edge.
And when a rising edge occurs, the master and slave read each other's data.
Then on the next falling edge, the shift register ships one position and outputs the next bit on Mozi and Miso.
Then when the next rising edge occurs, the data is read again.
By repeating this process, data is exchanged one bit at a time.
I explained earlier that the shift register moves one step at a time with the clock.
On the actual pins, data is read and sent based on these clock edges.
The basic principle is the same for mode 1, mode 2, and mode 3.
What changes is whether the clock idles low or high, and whether data is read on the first or second clock edge.
So when you use a sensor that communicates over SPI, you must always check its datasheet to confirm which SPI mode it uses.
If the master and slave are set to different modes, you won't be able to receive the data correctly.
So far, we've only connected one MCU and one sensor.
But in real systems, it's common to use multiple sensors. Let's try connecting three sensors.
The clock signal can be shared among all three sensors.
The MOSI line can also be connected from the master to each slave and shared.
The MESA line can also be shared, connecting to a single master input.
The important signal here is CS, which I briefly explained earlier.
I'll connect CS1 to S1, CS2 to S2, and CS3 to S3.
At this point, if the master wants to communicate with S2, it only needs to pull CS2 low, keeping CS1 and CS3 in a high state.
Then S2 is selected and can communicate with the master over SPI.
If you want to communicate with S1 instead, pull CS1 low.
This way you can connect multiple slave devices to an SPI peripheral but let's keep increasing the number of sensors.
On a PCB you have to route these signals to each sensors location so as the number of sensors grows the overall wiring structure gets more complex.
So some SPI devices support daisy chaining to reduce the number of these connections. Let's first look at the structure.
In a In a data chain, the structure is a bit different.
The master's mosey connects to the data input of the first slave.
Then the first slave's data output connects to the data input of the second slave.
Subsequently, the second slave's output connects to the third slave's input.
And finally, the last slave's output returns to the master's miso line.
Then the entire structure becomes connected like one long shift register.
For instance, let's suppose we have three 8 -bit devices.
When the master transmits the initial 8 bits, this data first goes into the shift register of the first device.
Then, as the next 8 bits are transmitted, the data previously in the first device shifts to the second, and new data from the master enters the first device.
If you send another 8 clock pulses, the existing data shifts to the next device again.
So if you have 3 8 -bit devices connected, you can think of the whole thing as 1 24 -bit shift register.
In this setup, multiple devices can share the same clock and chip select signals. This reduces the need to add a CS pin for each device.
The trade -off is that more devices mean more data to shift each time.
And all devices connected must support the Daisy Chain method too. That's all for today's video.
Next, I'll explain iSquared C, another commonly used protocol like SPI.
I'll start with how it works and explain it step by step so even beginners can follow easily.
If you subscribe, you can watch the video as soon as it's up. If you have any questions, please leave them in the comments. I'll see you in the next video. Thank you.
Are you glossing over I2C concepts because they seem difficult and just copying and pasting example code?
For now, the sensor readings look fine, so nothing seems wrong.
But once communication goes wrong, finding the cause gets quite difficult. I2C isn't that hard if you just get its structure.
In this video, I'll explain how data is actually exchanged, and at the end, show you the process of reading a value from a real temperature sensor. master at once, and debugging time halves.
Last time, we covered SPI, a clock -based synchronous serial interface.
i2c also exchanges data in sync with a clock.
With SPI, both sides could send data at the same time over MOSI and MISO.
ChipSelect shows the slave to communicate with.
Today's topic, i2c, uses two communication lines, SCL and SDA. S .C .L.
is the clock line that sets the timing for reading data and S .D .A. carries data in both directions.
Of course, power and common ground must be connected separately, since there's only one data line, the MCU and the Slave take turns using it.
So it's half duplex communication alternating between sending and receiving.
The MCU that starts communication and creates the clock is the master, and the device it communicates with is the Slave.
You can connect multiple slaves to a single master like this. Each slave has an address.
In I2C, the slave's address is sent when communication begins.
Here, let's say slave1's address is 0x48.
When the MCU sends an address on the data line, each slave checks it, and the one with the matching address responds.
Okay, but notice how multiple sensors are connected to a single data line.
But is it okay to just tie multiple output pins to the same line like this?
If one side outputs a high and the other outputs a low, the two outputs could conflict. That's why an open drain structure is used here.
When the switch is on, it pulls the data line towards ground, making it low.
When the switch is turned off again, the data line goes high through the pull -up resistor.
If even one connected device pulls the line low, the line is low. This is a very important point, so we'll come back to it later.
The clock line needs a pull -up resistor too, not just the data line.
The pull -up voltage must be compatible with both the connected master and slave.
We'll look at how the waveform changes depending on the resistance value after we go over the communication sequence.
First, let's see when communication starts and when it ends.
When no communication is happening, both the data line and the clock line are in a high state.
Here, if the data line falls from high to low while the clock is high, that's start. This is the condition to start communication.
Conversely, if the data line goes from low to high, while the clock is high, that's a stop signal. That's the condition to end communication.
The actual data transfer takes place in between, but this diagram is simplified to illustrate the start and stop conditions clearly. So how do we send data in between?
The data is drawn this way here to show that each bit can be either 0 or 1.
When sending data, prepare the next value while the clock is low.
While the clock is high, the data value must stay the same.
One byte is 8 bits, and the data is sent from the most significant bit, the NSB, to the least significant bit, the LSB.
After these 8 bits, a 9th clock pulse is generated.
This is when the receiving side sends a response. If the receiver pulls the data line low, it's an act. That means successful reception. If the line stays high instead, that's knack.
A knack can indicate no slave responded to the address or that a read has finished.
Now let's apply this rule to the entire communication sequence.
Let's assume the slave's address is set to 0x48.
First there's a start signal followed by the slave address and a bit that determines read or write.
Set the bit to 1 for a read and 0 for a write.
To try write operation first, I'll set the bit to 0.
Then, after confirming the slave's ACK response, the data is sent.
Finally, you confirm the slave's response one more time and end the communication with a stop signal. Alright, let's analyze this step by step.
First, the initial 8 bits consist of the slave's 7 -bit address and a single bit determining whether it's a read or write operation.
The master determines if it's a read or write.
Right. Address 0x48 in 7 bits is 1 0 0 1 0 0, as shown.
Adding the right bit, 0, gives 0x90.
Adding the read bit, 1, gives 0x91. First let's look at an MCU right.
The MCU generates start and sends 0x90.
The slave, with that address, returns ack.
Now the MCU sends the actual value to be written. For this example, let's send 0xA5.
The slave that received this data sends an act signal.
Since we're sending just one byte, the MCU concludes communication with a stop signal.
Now let's do the opposite and read a value from the slave.
Let's assume the slave sends 8 bits of data upon a read request.
Just like before, the MCU generates a start signal, then sends 0x91 with the read bit set to 1.
After the slave sends an act, it starts sending the data 0x3c.
This time, the MCU is the one receiving the value, so it must send the response.
If more data remains, the MCU sends an act.
But in this example, we're only receiving 8 bits, so the MCU sends a NAC.
Here, NAC isn't an error, but means all necessary data was received. Then communication ends with stop.
Now let's apply this to an actual temperature sensor, the TMP102.
With its address pin grounded, this sensor's address is 0x48.
And inside the sensor, there are registers that hold the current temperature, settings, and so on. 0x48 selects the sensor to communicate with.
The addresses in this table select registers inside that sensor.
Let's assume the sensor has measured the temperature to be 25 degrees.
Let's set its upper temperature limit to 85 degrees.
This upper limit is the reference temperature the sensor uses for a high temperature alert.
It's a feature where the sensor generates an alert if the current temperature exceeds this upper limit. The 85 degree upper limit is 0x5500.
We send this value in two parts, first 0x55, then 0x00.
With the TMP102, the most significant byte is sent first.
Now look at the sensor's actual write sequence.
The data portion is longer than in the basic example we saw earlier. The MCU sends the address in right direction.
Its first data byte selects the register.
The next two bytes are the temperature value to store there. First the MCU creates a start and sends 0x90.
When the sensor sends an act, the MCU then sends 0x03 to select the upper limit register. The sensor sends an act for this byte too.
Now the MCU sends the actual value to store.
From 0x5500 we send the leading high byte 0x55 first.
On receipt the sensor sends an acknowledge, then we send the low byte 0x00.
After checking the sensors acknowledge again, the MCU ends communication with a stop.
Now let's read the current temperature.
First the MCU sends 0x90 for a write.
After the sensor acknowledges, we send 0x00 to select the temperature register.
We can create another start condition without a stop in between.
This is called a repeated start.
It's the same start condition as before, but communication continues without ending.
After selecting the register, we send the address again to request a read.
Now we send the same address with ReBit1 appended 0x91. Then the sensor sends data.
Let's assume the two bytes representing the current temperature are 0x19 and 0x00.
The sensor first sends the high byte, 0x19.
We still need one more byte, so this time the MCU acknowledges.
Following that, the sensor transmits the remaining lower byte, 0x00. Now we've received both bytes we need. The MCU sends NAC in the final response slot.
Here the NAC means we don't need to receive any more data. data.
A stop then ends this communication. The two bytes combines a 0x1900.
So we also need to know what temperature this number represents.
The sensor we use today expresses temperature using the upper 12 bits.
Here, that value is 400.
Multiplying by 0 .0625 degrees per step gives 25 degrees.
The data sheet specifies the data's bit count and how to convert it to its actual value.
So far I've said that the clock is generated by the master, the MCU.
However, some slaves can hold the clock low if they need more time to prepare.
Once it's ready, the clock goes high again, and communication continues. This is called clock stretching.
It uses the open drain principle we discussed earlier.
If even one device pulls low, the entire line is low.
However, as not all sensors use this feature you must verify it before use. Now let's look at pull -up resistor values.
Common I2C modes are standard mode, up to 100 kilobits per second, fast mode, 400 kilobits per second, and fast mode plus, 1 megabit per second.
We've drawn square waveforms for clarity so far, but in practice the voltage doesn't go high instantly.
The wiring and pins have capacitance, so as the charge builds up through the pull -up resistor, the voltage rises, causing the rising edge to appear as a curve.
In a pull -up circuit, rise time can be approximated by the on -screen formula, multiply pull -up resistance by line capacitance, then by about 0 .85.
As an example, let's assume the capacitance of one line is 100 picofarads.
At 4 .7 kOhms, rise time is about 398 ns.
At 2 .2 kOhms, it's about 186 nanoseconds.
This refers to the rise time from 30 % to 70 % of the pull -up voltage.
The rise time limit in fast mode is 300 nanoseconds.
Under these conditions, 2 .2kms meets the rise time limit.
But that doesn't mean you should always choose a small resistor.
You also need to check how much current the pin pulling load can handle and the actual voltage.
So today we covered I2C communication, very common in embedded systems.
If you found today's video helpful, Please subscribe and click the like button.
I'll be back with even better content in the next video. Thank you