Skip to content

Commit efd45a7

Browse files
committed
upload Tutorial-4 UART HAHAHAHAHAHA
1 parent e4f3428 commit efd45a7

File tree

5 files changed

+517
-0
lines changed

5 files changed

+517
-0
lines changed

tutorial-4-uart/01-uart.md

+284
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
# UART
2+
[Back to Main](README.md)
3+
4+
> How your robot send and receive data from sensors and controller
5+
6+
<details>
7+
8+
<summary>Authors</summary>
9+
10+
Danny Lau, Chalex, Samuel Chee, Vivian Chan, Dicaprio Cheung
11+
12+
</details>
13+
14+
## Introduction
15+
16+
Imagine you want to transfer 8-bit data to another board, one way is to connect 8 wires to another board:
17+
18+
![](https://cdn.sparkfun.com/r/700-700/assets/c/a/c/3/a/50e1cca6ce395fbc27000000.png)
19+
20+
However, this is terrible. What if we want to transfer 32-bit data? We would need a lot of wires.
21+
22+
This calls for communication protocols, which aims to allow devices to communicate with each other using as few wires as possible.
23+
24+
![](https://cdn.sparkfun.com/r/700-700/assets/e/5/4/2/a/50e1ccf1ce395f962b000000.png)
25+
26+
## Universal Asynchronous Receiver-Transmitter (UART)
27+
28+
UART is a protocol used for serial communication and is used when the rate of transmission is not a concern. For example, UART could be used to send control commands but it isn't suitable to send high resolution images.
29+
30+
In our embedded system, UART is commonly used between two different boards or when trying to send data from an mobile/desktop application to your board using bluetooth.
31+
32+
### Sending and Receiving Data with UART
33+
34+
UART sends your data in serial, **asynchronous** mode.
35+
36+
![](https://www.circuitbasics.com/wp-content/uploads/2016/01/Introduction-to-UART-Basic-Connection-Diagram-768x376.png)
37+
38+
Serial communication is the process of sending data one bit at a time. For example, if we want to transmit data from UART1 to UART2, data will be sent bit by bit from the **TX pins** and received by the **RX pins**.
39+
40+
Asynchronous means that there is no common clock signal between the sender and receivers. In other words, the clocks of the STM32 and the bluetooth device may be different. As there is no way for the receiving side to determine the transmission speed dynamically, we need to predefine the same **baud rate** on both sides for the communication.
41+
42+
### Configuring UART Ports
43+
44+
![](https://i.imgur.com/F6AvURr.png)
45+
46+
To check which serial ports can be used as UART, you need to take a look on the main board, there should be small text `UART X` (Should be UART 1 and 3).
47+
48+
**1. Word Length, Parity and Start/Stop Bits**
49+
50+
During transformation, data is sent in **a packet**. According to the standard of uart, it sends 1 start bit (must), 5/6/7/8 bits of data (not 9), 1 bit of parity check (optional),1/1.5/2 bit of stop bit.
51+
52+
![](https://www.circuitbasics.com/wp-content/uploads/2016/01/Introduction-to-UART-Packet-Frame-and-Bits-2.png)
53+
54+
You do not need to modify these parameters for now, just use the default values and make sure the config on both sides of communication is the same. _The two extra bit of start bit and stop bit are **handled automatically** by stm32 and coolterm(later discussed) and you don't have to worry about them._
55+
56+
**2. Baud rate**
57+
58+
Baud rate is the number of bits of the signal sent per second and have predefined standards.
59+
60+
**Possible baud rate values**: 9600, 14400, 19200, 38400, 57600, **115200**, 128000, 230400, 256000, 460800 ...
61+
62+
`115200` is the most common and quickest speed that works on most devices without any problem, therefore, recommended in this tutorial. For example, standard windows (or, .net) utilities does not support anything above 115200. Our setting uses 1 start bit, 8 data bits, 0 parity bit and 1 stop bit, which means that 8 bit = 1 byte out of 10 bits sent are data, with a baud rate of 115200, effectively 11520 bytes of data could be sent in one second.
63+
64+
> **Note** Make sure the baud rates on both sides of the communication are the **same**.
65+
66+
### Initialization of UART Pins
67+
68+
Like most board/pin controls you have learnt so far, a UART port needs to be initialised before it is available for use. The init functions should already be called in main.c based on your board configuration.
69+
70+
**From main.c:**
71+
72+
```c
73+
MX_USART1_UART_Init();
74+
MX_USART3_UART_Init();
75+
```
76+
77+
### Transmitting and Receiving Data
78+
79+
After the initialization, you can start sending and receiving data by calling functions from the HAL Library.
80+
81+
#### Transmit function
82+
83+
```c
84+
HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
85+
```
86+
87+
`HAL_UART_Transmit()` transmits the given data within the time limit.
88+
89+
`huart`: UART handler. HAL Library needs to know what UART port should be used for data transfer. \&huart1 and \&huart3 are the possible values.
90+
91+
`pData`: Data array. Here it means the sequence of data that you want to transmit.
92+
93+
`Size`: The length of data array.
94+
95+
`Timeout`: Time limit for transmitting data. If huart is busy for some reasons (for example, sending other data), the program will stay for at most Timeout millisecond to wait until the sending operation is completed. if the program reaches time limit, it will give up to transmit data.
96+
97+
**TX Example:**
98+
99+
```c
100+
while (1)
101+
{
102+
/* Sending */
103+
static const char dat[] = "Hello, Word!";
104+
HAL_UART_Transmit(&huart1, (uint8_t*)&dat, sizeof(dat), 0xFFFF);
105+
HAL_Delay(200);
106+
}
107+
```
108+
109+
#### Receive function
110+
111+
```c
112+
HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
113+
```
114+
115+
`HAL_UART_Receive()` receives the given data within the time limit.
116+
117+
`huart`: UART handler. HAL Library needs to know what UART port should be used for data receive. \&huart1 and \&huart3 are the possible values.
118+
119+
`pData`: Data array. Here it means the array that you want to store received data in.
120+
121+
`Size`: The length of data array.
122+
123+
`Timeout`: Time limit for receiving data. If huart is busy for some reasons (for example, not receiving any data), the program will stay for at most Timeout millisecond to wait until the receiving operation is completed. if the program reaches time limit, it will give up to receive data.
124+
125+
**RX Example:**
126+
127+
```c
128+
while (1)
129+
{
130+
/* Receiving */
131+
static char dat[99];
132+
HAL_UART_Receive(&huart1, (uint8_t*)&dat, sizeof(dat), 0xFFFF);
133+
}
134+
```
135+
136+
#### Blocking vs Non-Blocking:**
137+
138+
When calling HAL\_UART\_Transmit() / HAL\_UART\_Receive(), your code will pause at the function call until data is successfully transmitted / received.
139+
140+
In some situations this is problematic, for example:
141+
142+
```c
143+
uint8_t rx_buff[99];
144+
uint8_t tx_buff[99];
145+
146+
int main(void)
147+
{
148+
uint16_t timeout = 0xFFFF; // Long timeout.
149+
150+
while (1)
151+
{
152+
//Code will stop here if nothing is received
153+
HAL_UART_Receive(&huart1, rx_buff, sizeof(rx_buff), timeout);
154+
155+
//Unable to transmit while waiting for data to be received
156+
HAL_UART_Transmit(&huart1, tx_buff, sizeof(tx_buff), timeout);
157+
}
158+
}
159+
160+
```
161+
162+
163+
#### Transmit function (Non-blocking)
164+
165+
```c
166+
HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
167+
```
168+
169+
`HAL_UART_Transmit_IT()` transmits the given data in the background using Interrupt mode.
170+
171+
`huart`: UART handler. HAL Library needs to know what UART port should be used for data transfer. \&huart1 and \&huart3 are the possible values.
172+
173+
`pData`: Data array. Here it means the sequence of data that you want to transmit.
174+
175+
`Size`: The length of data array.
176+
177+
When it finish transmitting the data, the UART transmit interrupt will be triggered.
178+
tehn the `HAL_UART_TxCpltCallback` function is called, which allows you to perform any necessary post-transmission actions.
179+
180+
`HAL_UART_TxCpltCallback()` (HAL library UART Transmit Complete Callback) This will be called whenever it finishes transmitting something on UART(no matter which UART port). You don't need to call this function in your code, but you need to define it.
181+
182+
`huart`: UART handler. HAL Library will tell you which UART port finished data transfer. \&huart1 and \&huart3 are the possible values.
183+
184+
**TX Example:**
185+
186+
```c
187+
const char data[] = "Hello, Word!";
188+
189+
// you need to write this function yourself, it won't auto-generate
190+
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
191+
{
192+
// Check if there is more data to be transmitted
193+
if (moreDataToTransmit)
194+
{
195+
// Transmit the next data buffer
196+
HAL_UART_Transmit_IT(huart, nextDataBuffer, nextDataSize);
197+
/* actually this is some kind of recursion. It calls itself after it finishes */
198+
}
199+
else
200+
{
201+
// Notify other parts of the application that the transmission is complete
202+
transmissionCompleteFlag = 1;
203+
}
204+
}
205+
206+
int main(void)
207+
{
208+
// Initialize the UART peripheral
209+
// ...
210+
211+
// Start transmiting data
212+
HAL_UART_Transmit_IT(&huart1, data, 1);
213+
214+
// Main loop
215+
while (1)
216+
{
217+
// Do other tasks
218+
}
219+
}
220+
```
221+
222+
#### Receive function (Non-blocking)
223+
224+
```c
225+
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
226+
```
227+
228+
`HAL_UART_Receive_IT()` receives the given data in the background using Interrupt mode.
229+
230+
`huart`: UART handler. HAL Library needs to know what UART port should be used for data transfer. \&huart1 and \&huart3 are the possible values.
231+
232+
`pData`: Data array. Here it means the sequence of data that you want to transmit.
233+
234+
`Size`: The length of data array you want to receive.
235+
236+
When it finish receving the whole length of data, the UART receive interrupt will be triggered.
237+
then the `HAL_UART_RxCpltCallback` function is called, which allows you to perform any necessary post-receive actions.
238+
239+
`HAL_UART_RxCpltCallback()` (HAL library UART Receive Complete Callback) This will be called whenever it finishes receiving the required length of data on UART(no matter which UART port). You don't need to call this function in your code, but you need to define it.
240+
241+
`huart`: UART handler. HAL Library will tell you which UART port finished data transfer. \&huart1 and \&huart3 are the possible values.
242+
243+
**RX Example:**
244+
245+
```c
246+
uint8_t rxBuffer[1]; //idk why but it has a high chance to fail when it is >1
247+
UART_HandleTypeDef huart1;
248+
249+
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
250+
{
251+
if (huart == &huart1)
252+
{
253+
// Process the received data
254+
if(rxBuffer[0] == 'a'){
255+
//do something
256+
}else if(rxBuffer[0] == 'b'){
257+
//do some other thing
258+
}else{
259+
...
260+
}
261+
262+
// Start receiving the next data
263+
HAL_UART_Receive_IT(&huart1, rxBuffer, sizeof(rxBuffer));
264+
/* actually this is some kind of recursion. It calls itself after it finishes */
265+
}
266+
}
267+
268+
int main(void)
269+
{
270+
// Initialize the UART peripheral
271+
// ...
272+
273+
// Start receiving data
274+
HAL_UART_Receive_IT(&huart1, rxBuffer, 1);
275+
276+
// Main loop
277+
while (1)
278+
{
279+
// Do other tasks
280+
}
281+
}
282+
```
283+
284+
[Continue to The Next Page](./02-bluetooth.md)

0 commit comments

Comments
 (0)