Home | Projects | Notes > MCU Peripheral Drivers > USART Driver (stm32f407xx_usart_driver.h/.c
)
stm32f407xx_usart_driver.h/.c
)
USART initialization / Peripheral clock control
USART Tx
USART Rx
USART interrupt configuration & handling
Other USART management APIs
USART_Mode
Transmitter mode
Receiver mode
Transmitter/receiver mode
USART_Baud
Baudrate
USART_NumOfStopBits
USART_WordLength
8-bit
9-bit
USART_ParityControl
No parity
Even parity
Odd parity
USART_HWFlowControl
Create stm32f407xx_usart_driver.c
and stm32f407xx_usart_driver.h
Complete USART register definition structure and other macros (e.g., peripheral base addresses, device definition, clock enable, clock disable, etc.) in the MCU specific header file.
Add USART register bit definition macros in the MCU specific header file.
ADD USART configuration structure and USART handle structure in USART header file.
stm32f407xx_usart_driver.h
Path: Project/Drivers/Inc/
xxxxxxxxxx
1711/*******************************************************************************
2 * File : stm32f407xx_usart_driver.h
3 * Brief : STM32F407xx MCU specific USART driver header file
4 * Author ; Kyungjae Lee
5 * Date : Jun 20, 2023
6 *
7 * Note : This code includes only the features that are necessary for my
8 * personal projects.
9 * ****************************************************************************/
10
11
12
13
14
15
16/*******************************************************************************
17 * APIs supported by the USART driver
18 * (See function definitions for more information)
19 ******************************************************************************/
20
21/* USARTx peripheral configuration structure */
22typedef struct
23{
24 uint8_t USART_Mode; /* Available values @USART_Mode */
25 uint32_t USART_Baud; /* Available values @USART_Baud */
26 uint8_t USART_NumOfStopBits; /* Available values @USART_NumOfStopBits */
27 uint8_t USART_WordLength; /* Available values @USART_WordLength */
28 uint8_t USART_ParityControl; /* Available values @USART_ParityControl */
29 uint8_t USART_HWFlowControl; /* Available values @USART_HWFlowControl */
30} USART_Config_TypeDef;
31
32/* USARTx peripheral handle structure */
33typedef struct
34{
35 USART_TypeDef *pUSARTx; /* Base address of USARTx(x:1,2,3) */
36 USART_Config_TypeDef USART_Config;
37 uint8_t *pTxBuffer; /* Application Tx buffer address */
38 uint8_t *pRxBuffer; /* Application Rx buffer address */
39 uint32_t TxLen; /* Number of bytes left to transmit */
40 uint32_t RxLen; /* Number of bytes left to receive */
41 uint8_t TxBusyState;/* Available values @TxRxBusyState */
42 uint8_t RxBusyState;/* Available values @TxRxBusyState */
43} USART_Handle_TypeDef;
44
45/**
46 * @USART_Mode
47 * Note: Check TE and RE bits in USART_CR1 register.
48 */
49/* (CR1) TE=1, RE=0 */
50/* (CR1) TE=0, RE=1 */
51/* (CR1) TE=1, RE=1 */
52
53/**
54 * @USART_Baud
55 * Note: Baudrates are in 'bits per second (bps)' and can be found in the
56 * MCU reference manual.
57 * Check USART_BRR register.
58 */
59
60
61
62
63
64
65
66
67
68
69
70
71
72/**
73 * @USART_NumOfStopBits
74 * Note: Check STOP bit field in USART_CR2 register.
75 */
76
77
78
79
80
81/**
82 * @USART_WordLength
83 * Note: Check M bit in USART_CR1 register.
84 */
85
86
87
88/**
89 * @USART_ParityControl
90 * Note: Check PCE and PS bits in USART_CR1 register.
91 */
92
93
94
95
96/**
97 * @USART_HWFlowControl
98 * Note: Check CTSE and RTSE bits in USART_CR3 register.
99 */
100
101
102
103
104
105/**
106 * TxRxState (Application communication state)
107 */
108
109
110
111
112/**
113 * I2C application event macros
114 */
115
116
117
118
119
120
121
122
123
124
125/*******************************************************************************
126 * APIs supported by the USART driver
127 * (See function definitions for more information)
128 ******************************************************************************/
129
130/* Peripheral clock setup */
131void USART_PeriClockControl(USART_TypeDef *pUSARTx, uint8_t state);
132
133/**
134 * Init and De-init
135 */
136void USART_Init(USART_Handle_TypeDef *pUSARTHandle);
137void USART_DeInit(USART_TypeDef *pUSARTx);
138
139
140/**
141 * Data send and receive
142 */
143void USART_TxBlocking(USART_Handle_TypeDef *pUSARTHandle, uint8_t *pTxBuffer, uint32_t len);
144void USART_RxBlocking(USART_Handle_TypeDef *pUSARTHandle, uint8_t *pRxBuffer, uint32_t len);
145uint8_t USART_TxInterrupt(USART_Handle_TypeDef *pUSARTHandle, uint8_t *pTxBuffer, uint32_t len);
146uint8_t USART_RxInterrupt(USART_Handle_TypeDef *pUSARTHandle, uint8_t *pRxBuffer, uint32_t len);
147
148
149/**
150 * IRQ configuration and ISR handling
151 */
152void USART_IRQInterruptConfig(uint8_t irqNumber, uint8_t state);
153void USART_IRQPriorityConfig(uint8_t irqNumber, uint32_t irqPriority);
154void USART_IRQHandling(USART_Handle_TypeDef *pUSARTHandle);
155
156
157/**
158 * Other peripheral control APIs
159 */
160void USART_PeriControl(USART_TypeDef *pUSARTx, uint8_t state);
161void USART_SetBaudRate(USART_TypeDef *pUSARTx, uint32_t baudrate);
162
163/**
164 * Application callback functions (Must be implemented by application)
165 * Note: Since the driver does not know in which application this function will
166 * be implemented, it is good idea to give a weak function definition.
167 */
168void USART_ApplicationEventCallback(USART_Handle_TypeDef *pUSARTHandle, uint8_t appEvent);
169
170
171/* STM32F407XX_USART_DRIVER_H */
stm32f407xx_usart_driver.c
Path: Project/Drivers/Src/
xxxxxxxxxx
7941/*******************************************************************************
2 * File : stm32f407xx_usart_driver.c
3 * Brief : STM32F407xx MCU specific USART driver source file
4 * Author ; Kyungjae Lee
5 * Date : Jun 20, 2023
6 *
7 * Note : This code includes only the features that are necessary for my
8 * personal projects.
9 * ****************************************************************************/
10
11
12
13/*******************************************************************************
14 * APIs supported by the I2C driver
15 * (See function definitions for more information)
16 ******************************************************************************/
17
18/**
19 * USART_PeriClockControl()
20 * Brief : Enables or disables USART peripheral clock
21 * Param : @pUSARTx - base address of USARTx peripheral
22 * @state - ENABLE or DISABLE macro
23 * Retval : None
24 * Note : N/A
25 */
26void USART_PeriClockControl(USART_TypeDef *pUSARTx, uint8_t state)
27{
28 if (state == ENABLE)
29 {
30 if (pUSARTx == USART1)
31 USART1_PCLK_EN();
32 else if (pUSARTx == USART2)
33 USART2_PCLK_EN();
34 else if (pUSARTx == USART3)
35 USART3_PCLK_EN();
36 else if (pUSARTx == UART4)
37 UART4_PCLK_EN();
38 else if (pUSARTx == UART5)
39 UART5_PCLK_EN();
40 else if (pUSARTx == USART6)
41 USART6_PCLK_EN();
42 }
43 else
44 {
45 if (pUSARTx == USART1)
46 USART1_PCLK_DI();
47 else if (pUSARTx == USART2)
48 USART2_PCLK_DI();
49 else if (pUSARTx == USART3)
50 USART3_PCLK_DI();
51 else if (pUSARTx == UART4)
52 UART4_PCLK_DI();
53 else if (pUSARTx == UART5)
54 UART5_PCLK_DI();
55 else if (pUSARTx == USART6)
56 USART6_PCLK_DI();
57 }
58} /* End of USART_PeriClockControl */
59
60/**
61 * USART_Init()
62 * Brief : Initializes USART peripheral
63 * Param : @pUSARTHandle - pointer to USART handle structure
64 * Retval : None
65 * Note : N/A
66 */
67void USART_Init(USART_Handle_TypeDef *pUSARTHandle)
68{
69 /* Temporary variable */
70 uint32_t temp = 0;
71
72 /* Configure USART_CR1 ---------------------------------------------------*/
73
74 /* Enable USART peripheral clock */
75 USART_PeriClockControl(pUSARTHandle->pUSARTx, ENABLE);
76
77 /* Enable USART Tx and Rx engines */
78 if (pUSARTHandle->USART_Config.USART_Mode == USART_MODE_RX)
79 {
80 /* Enable receiver (RE=1) */
81 temp |= (0x1 << USART_CR1_RE);
82 }
83 else if (pUSARTHandle->USART_Config.USART_Mode == USART_MODE_TX)
84 {
85 /* Enable transmitter (TE=1) */
86 temp |= (0x1 << USART_CR1_TE);
87 }
88 else if (pUSARTHandle->USART_Config.USART_Mode == USART_MODE_TXRX)
89 {
90 /* Enable both the receiver and transmitter (RE=1, TE=1) */
91 temp |= ((0x1 << USART_CR1_RE) | (0x1 << USART_CR1_TE));
92 }
93
94 /* Configure the word length */
95 temp |= pUSARTHandle->USART_Config.USART_WordLength << USART_CR1_M;
96
97 /* Configure parity */
98 if (pUSARTHandle->USART_Config.USART_ParityControl == USART_PARITY_EVEN)
99 {
100 /* Enable parity */
101 temp |= (0x1 << USART_CR1_PCE);
102
103 /* Select even parity (optional since even parity is selected by
104 * default when parity is enabled
105 */
106 temp &= ~(0x1 << USART_CR1_PS);
107 }
108 else if (pUSARTHandle->USART_Config.USART_ParityControl == USART_PARITY_ODD)
109 {
110 /* Enable parity */
111 temp |= (0x1 << USART_CR1_PCE);
112
113 /* Select odd parity (optional since even parity is selected by
114 * default when parity is enabled
115 */
116 temp |= (0x1 << USART_CR1_PS);
117 }
118
119 /* Write to USART_CR1 register */
120 pUSARTHandle->pUSARTx->CR1 = temp;
121
122 /* Configure USART_CR2 ---------------------------------------------------*/
123
124 temp = 0;
125
126 /* Configure the number of stop bits */
127 temp |= pUSARTHandle->USART_Config.USART_NumOfStopBits << USART_CR2_STOP;
128
129 /* Write to USART_CR2 register */
130 pUSARTHandle->pUSARTx->CR2 = temp;
131
132 /* Configure USART_CR3 ---------------------------------------------------*/
133
134 temp = 0;
135
136 /* Configure USART hardware flow control */
137 if (pUSARTHandle->USART_Config.USART_HWFlowControl == USART_HW_FLOW_CTRL_CTS)
138 {
139 /* Enable CTS flow control */
140 temp |= (0x1 << USART_CR3_CTSE);
141 }
142 else if (pUSARTHandle->USART_Config.USART_HWFlowControl == USART_HW_FLOW_CTRL_RTS)
143 {
144 /* Enable RTS flow control */
145 temp |= (0x1 << USART_CR3_RTSE);
146 }
147 else if (pUSARTHandle->USART_Config.USART_HWFlowControl == USART_HW_FLOW_CTRL_CTS_RTS)
148 {
149 /* Enable both the CTS and RTS flow control */
150 temp |= (0x1 << USART_CR3_CTSE);
151 temp |= (0x1 << USART_CR3_RTSE);
152 }
153
154 /* Write to USART_CR3 register */
155 pUSARTHandle->pUSARTx->CR3 = temp;
156
157 /* Configure USART_BRR (Baud rate register) ------------------------------*/
158
159 /* Configure baudrate */
160 USART_SetBaudRate(pUSARTHandle->pUSARTx, pUSARTHandle->USART_Config.USART_Baud);
161
162} /* End of USART_Init() */
163
164/**
165 * USART_DeInit()
166 * Brief : Deinitializes USART peripheral
167 * Param : @pUSARTx - base address of USARTx peripheral
168 * Retval : None
169 * Note : N/A
170 */
171void USART_DeInit(USART_TypeDef *pUSARTx)
172{
173
174} /* End of USART_DeInit */
175
176/**
177 * USART_TxBlocking()
178 * Brief : Handles blocking-based USART transmission
179 * Param : @pUSARTHandle - pointer to USART handle structure
180 * @pTxBuffer - pointer to Tx buffer
181 * @len -
182 * Retval : None
183 * Note : N/A
184 */
185void USART_TxBlocking(USART_Handle_TypeDef *pUSARTHandle, uint8_t *pTxBuffer, uint32_t len)
186{
187 uint16_t *pData;
188
189 /* Repeat until @len number of bytes are transmitted */
190 for (uint32_t i = 0; i < len; i++)
191 {
192 /* Wait until USART_SR_TXE flag is set.
193 * Wait until Transmit Data Register (TDR) is empty.
194 */
195 while (!(pUSARTHandle->pUSARTx->SR & (0x1 << USART_SR_TXE)));
196
197 /* Check word length configuration */
198 if (pUSARTHandle->USART_Config.USART_WordLength == USART_WORDLEN_9BITS)
199 {
200 /* If 9-bit, load DR with 2 bytes with all bits other than the
201 * first 9 bits masked.
202 */
203 pData = (uint16_t *)pTxBuffer;
204 pUSARTHandle->pUSARTx->DR = (*pData & (uint16_t)0x01FF);
205
206 /* Check parity bit configuration */
207 if (pUSARTHandle->USART_Config.USART_ParityControl == USART_PARITY_DISABLE)
208 {
209 /* No parity bit is is used in this transfer. So, 9-bit user
210 * data will be sent. (Need 2 bytes to transfer 9 bits)
211 */
212 pTxBuffer++;
213 pTxBuffer++;
214 }
215 else
216 {
217 /* Parity bit is used in this transfer. So, 8-bit of user data
218 * will be sent.
219 * The 9th bit will be replaced by parity bit by the hardware.
220 */
221 pTxBuffer++;
222 }
223 }
224 else
225 {
226 /* 8-bit data transfer */
227 pUSARTHandle->pUSARTx->DR = (*pTxBuffer & (uint8_t)0xFF);
228
229 /* Increment the Tx buffer address */
230 pTxBuffer++;
231 }
232 }
233
234 /* Wait till USART_SR_TC flag is set */
235 while (!(pUSARTHandle->pUSARTx->SR & (0x1 << USART_SR_TC)));
236
237} /* End of USART_TxBlocking */
238
239/**
240 * USART_RxBlocking()
241 * Brief : Handles blocking-based USART reception
242 * Param : @pUSARTHandle - pointer to USART handle structure
243 * @pRxBuffer - pointer to Rx buffer
244 * @len -
245 * Retval : None
246 * Note : N/A
247 */
248void USART_RxBlocking(USART_Handle_TypeDef *pUSARTHandle, uint8_t *pRxBuffer, uint32_t len)
249{
250 /* Repeat until @len number of bytes are received */
251 for (uint32_t i = 0; i < len; i++)
252 {
253 /* Wait until USART_SR_RXNE flag is set */
254 while (!(pUSARTHandle->pUSARTx->SR & (0x1 << USART_SR_RXNE)));
255
256 /* Check the word length configuration */
257 if (pUSARTHandle->USART_Config.USART_WordLength == USART_WORDLEN_9BITS)
258 {
259 /* Expected to receive 9-bit data in a frame */
260
261 /* Check the parity bit configuration */
262 if (pUSARTHandle->USART_Config.USART_ParityControl == USART_PARITY_DISABLE)
263 {
264 /* No parity bit is is used in this transfer. So, read only the
265 * first 9 bits.
266 */
267 *((uint16_t *)pRxBuffer) = (pUSARTHandle->pUSARTx->DR & (uint16_t)0x01FF);
268
269 /* Increment the Rx buffer address two times */
270 pRxBuffer++;
271 pRxBuffer++;
272 }
273 else
274 {
275 /* Parity bit is used in this transfer. So, 8-bit of user data
276 * will be received.
277 * The 9th bit will be replaced by parity bit by the hardware.
278 */
279 *pRxBuffer = (pUSARTHandle->pUSARTx->DR & (uint8_t)0xFF);
280 pRxBuffer++;
281 }
282 }
283 else
284 {
285 /* 8-bit data transfer */
286 pUSARTHandle->pUSARTx->DR = (*pRxBuffer & (uint8_t)0xFF);
287
288 /* Increment the Tx buffer address */
289 pRxBuffer++;
290 }
291 }
292} /* End of USART_RxBlocking */
293
294/**
295 * USART_TxInterrupt()
296 * Brief : Handles interrupt-based USART transmission
297 * Param : @pUSARTHandle - pointer to USART handle structure
298 * @pTxBuffer - pointer to Tx buffer
299 * @len -
300 * Retval : None
301 * Note : N/A
302 */
303uint8_t USART_TxInterrupt(USART_Handle_TypeDef *pUSARTHandle, uint8_t *pTxBuffer, uint32_t len)
304{
305 uint8_t txState = pUSARTHandle->TxBusyState;
306
307 if (txState != USART_BUSY_IN_TX)
308 {
309 pUSARTHandle->TxLen = len;
310 pUSARTHandle->pTxBuffer = pTxBuffer;
311 pUSARTHandle->TxBusyState = USART_BUSY_IN_TX;
312
313 /* Enable interrupt for TXE */
314 pUSARTHandle->pUSARTx->CR1 |= (0x1 << USART_CR1_TXEIE);
315
316 /* Enable interrupt for TC */
317 pUSARTHandle->pUSARTx->CR1 |= (0x1 << USART_CR1_TCIE);
318 }
319
320 return txState;
321} /* End of USART_TxInterrupt */
322
323/**
324 * USART_RxInterrupt()
325 * Brief : Handles interrupt-based USART reception
326 * Param : @pUSARTHandle - pointer to USART handle structure
327 * @pTxBuffer - pointer to Tx buffer
328 * @len -
329 * Retval : None
330 * Note : N/A
331 */
332uint8_t USART_RxInterrupt(USART_Handle_TypeDef *pUSARTHandle, uint8_t *pRxBuffer, uint32_t len)
333{
334 uint8_t rxState = pUSARTHandle->RxBusyState;
335
336 if (rxState != USART_BUSY_IN_RX)
337 {
338 pUSARTHandle->RxLen = len;
339 pUSARTHandle->pRxBuffer = pRxBuffer;
340 pUSARTHandle->RxBusyState = USART_BUSY_IN_RX;
341
342 (void)pUSARTHandle->pUSARTx->DR;
343
344 /* Enable interrupt for RXNE */
345 pUSARTHandle->pUSARTx->CR1 |= (0x1 << USART_CR1_RXNEIE);
346 }
347
348 return rxState;
349} /* End of USART_RxInterrupt */
350
351/**
352 * USART_IRQInterruptConfig()
353 * Brief : Enables or disables USART interrupts
354 * Param : @irqNumber - IRQ number
355 * @state - ENABLE or DISABLE macro
356 * Retval : None
357 * Note : N/A
358 */
359void USART_IRQInterruptConfig(uint8_t irqNumber, uint8_t state)
360{
361 if (state == ENABLE)
362 {
363 /* Configure NVIC_ISERx register */
364 if (irqNumber <= 31)
365 *NVIC_ISER0 |= (0x1 << irqNumber);
366 else if (32 <= irqNumber && irqNumber <= 63)
367 *NVIC_ISER1 |= (0x1 << irqNumber % 32);
368 else if (64 <= irqNumber && irqNumber <= 95)
369 *NVIC_ISER2 |= (0x1 << irqNumber % 32);
370 }
371 else
372 {
373 /* Configure NVIC_ICERx register */
374 if (irqNumber <= 31)
375 *NVIC_ICER0 |= (0x1 << irqNumber);
376 else if (32 <= irqNumber && irqNumber <= 63)
377 *NVIC_ICER1 |= (0x1 << irqNumber % 32);
378 else if (64 <= irqNumber && irqNumber <= 95)
379 *NVIC_ICER2 |= (0x1 << irqNumber % 32);
380 }
381} /* End of USART_IRQInterruptConfig */
382
383/**
384 * USART_IRQPriorityConfig()
385 * Brief : Configures USART IRQ interrupt priorities
386 * Param : @irqNumber - IRQ number
387 * @irqPriotity - IRQ priority (Make sure this parameter is of
388 * type uint32_t. Due to the number of bits it
389 * needs to be shifted during the calculation,
390 * declaring it as uint8_t did not do its job.
391 * Retval : None
392 * Note : N/A
393 */
394void USART_IRQPriorityConfig(uint8_t irqNumber, uint32_t irqPriority)
395{
396 /* Find out the IPR register */
397 uint8_t iprNumber = irqNumber / 4;
398 uint8_t iprSection = irqNumber % 4;
399 uint8_t bitOffset = (iprSection * 8) + (8 - NUM_PRI_BITS_USED);
400 *(NVIC_IPR_BASE + iprNumber) |= (irqPriority << bitOffset);
401} /* End of USART_IRQPriorityConfig */
402
403/**
404 * USART_IRQHandling()
405 * Brief : Handles USART event IRQ
406 * Param : @pUSARTHandle - pointer to USART handle structure
407 * Retval : None
408 * Note : This function will first decode the event that occurred, and
409 * handle the event accordingly.
410 * The compiler will generate unused variable for 'temp3'. (In
411 * general, it is a good practice to check if an interrupt is
412 * enabled, along with its status bit. Currently, to generalize
413 * the code for all UARTs, we are not checking the CTSIE bit.)
414 */
415void USART_IRQHandling(USART_Handle_TypeDef *pUSARTHandle)
416{
417 uint32_t temp1, temp2, temp3;
418 uint16_t *pData;
419
420 /* Check for TC (Transmission Complete) flag -----------------------------*/
421
422 /* Check the state of TC bit in SR */
423 temp1 = pUSARTHandle->pUSARTx->SR & (0x1 << USART_SR_TC);
424
425 /* Check the state of TCEIE bit */
426 temp2 = pUSARTHandle->pUSARTx->CR1 & (0x1 << USART_CR1_TCIE);
427
428 if (temp1 && temp2)
429 {
430 /* Handle interrupt triggered by TC flag */
431
432 /* Close transmission and call application callback if TxLen is zero */
433 if (pUSARTHandle->TxBusyState == USART_BUSY_IN_TX)
434 {
435 /* If TxLen = 0, close the data transmission */
436 if (! pUSARTHandle->TxLen)
437 {
438 /* Clear TC flag */
439 pUSARTHandle->pUSARTx->SR &= ~(0x1 << USART_SR_TC);
440
441 /* Clear TCIE control bit */
442
443 /* Reset the application status */
444 pUSARTHandle->TxBusyState = USART_READY;
445
446 /* Reset Tx buffer address to NULL */
447 pUSARTHandle->pTxBuffer = NULL;
448
449 /* Reset TxLen to zero */
450 pUSARTHandle->TxLen = 0;
451
452 /* Notify the application of the event USART_EV_TX_CMPLT */
453 USART_ApplicationEventCallback(pUSARTHandle, USART_EV_TX_CMPLT);
454 }
455 }
456 }
457
458 /* Check for TXE (Transmit data register Empty) flag ---------------------*/
459
460 /* Check the state of TXE bit in SR */
461 temp1 = pUSARTHandle->pUSARTx->SR & (0x1 << USART_SR_TXE);
462
463 /* Check the state of TXIEIE bit in CR1 */
464 temp2 = pUSARTHandle->pUSARTx->CR1 & (0x1 << USART_CR1_TXEIE);
465
466 if (temp1 && temp2)
467 {
468 /* Handle interrupt triggered by TXE flag */
469
470 if (pUSARTHandle->TxBusyState == USART_BUSY_IN_TX)
471 {
472 /* Keep transmitting data until TxLen reaches to zero */
473 if (pUSARTHandle->TxLen > 0)
474 {
475 /* Check whether the word length is 8-bit or 9-bit in a frame */
476 if (pUSARTHandle->USART_Config.USART_WordLength == USART_WORDLEN_9BITS)
477 {
478 /* If 9-bit, load DR with 2 bytes with all bits other than the
479 * first 9 bits masked.
480 */
481 pData = (uint16_t *)pUSARTHandle->pTxBuffer;
482 pUSARTHandle->pUSARTx->DR = (*pData & (uint16_t)0x01FF);
483
484 /* Check parity bit configuration */
485 if (pUSARTHandle->USART_Config.USART_ParityControl == USART_PARITY_DISABLE)
486 {
487 /* Parity bit is not used, so 9-bit user data will be sent.
488 * Increment the Tx buffer address twice. */
489 pUSARTHandle->pTxBuffer++;
490 pUSARTHandle->pTxBuffer++;
491 pUSARTHandle->TxLen -= 2;
492 }
493 else
494 {
495 /* Parity bit is used, so 8-bit user data will be sent.
496 * The 9th bit will be replaced by the parity bit by the hardware.
497 */
498 }
499 }
500 else
501 {
502 /* 8-bit data transmission */
503 pUSARTHandle->pUSARTx->DR = (*pUSARTHandle->pTxBuffer & (uint8_t)0xFF);
504
505 /* Increment the Tx buffer address */
506 pUSARTHandle->pTxBuffer++;
507 pUSARTHandle->TxLen -= 1;
508 }
509 }
510
511 if (pUSARTHandle->TxLen == 0)
512 {
513 /* Clear TXEIE bit (disable interrupt triggered by TXE flag */
514 pUSARTHandle->pUSARTx->CR1 &= ~(0x1 << USART_CR1_TXEIE);
515 }
516 }
517 }
518
519 /* Check for RXNE flag ---------------------------------------------------*/
520
521 temp1 = pUSARTHandle->pUSARTx->SR & (0x1 << USART_SR_RXNE);
522 temp2 = pUSARTHandle->pUSARTx->CR1 & (0x1 << USART_CR1_RXNEIE);
523
524 if (temp1 && temp2)
525 {
526 /* Handle interrupt triggered by RXNE flag */
527
528 if (pUSARTHandle->RxBusyState == USART_BUSY_IN_RX)
529 {
530 if (pUSARTHandle-> RxLen > 0)
531 {
532 /* Check whether the word length is 8-bit or 9-bit in a frame */
533 if (pUSARTHandle->USART_Config.USART_WordLength == USART_WORDLEN_9BITS)
534 {
535 /* Receiving 9-bit data in a frame */
536
537 /* Check parity bit configuration */
538 if (pUSARTHandle->USART_Config.USART_ParityControl == USART_PARITY_DISABLE)
539 {
540 /* Parity is not used, so all 9 bits will be user data */
541
542 /* Read only the least significant 9 bits */
543 *((uint16_t *)pUSARTHandle->pRxBuffer) = (pUSARTHandle->pUSARTx->DR & (uint16_t)0x01FF);
544
545 /* Increment the Rx buffer address two times */
546 pUSARTHandle->pRxBuffer++;
547 pUSARTHandle->pRxBuffer++;
548 pUSARTHandle->RxLen -= 2;
549 }
550 else
551 {
552 /* Parity is used, so 8-bit will be user data and 1 bit parity */
553 *pUSARTHandle->pRxBuffer = (pUSARTHandle->pUSARTx->DR & (uint8_t)0xFF);
554 pUSARTHandle->pRxBuffer++;
555 pUSARTHandle->RxLen -= 1;
556 }
557 }
558 else
559 {
560 /* Receiving 8-bit data in a frame */
561
562 /* Check parity bit configuration */
563 if (pUSARTHandle->USART_Config.USART_ParityControl == USART_PARITY_DISABLE)
564 {
565 /* Parity is not used, so all 8-bit will be user data */
566
567 /* Read 8 bits from DR */
568 *pUSARTHandle->pRxBuffer = (uint8_t)(pUSARTHandle->pUSARTx->DR & (uint8_t)0xFF);
569 }
570 else
571 {
572 /* Parity is used, so 7-bit will be user data and 1 bit parity */
573
574 /* Read only the least significant 7 bits */
575 *pUSARTHandle->pRxBuffer = (uint8_t)(pUSARTHandle->pUSARTx->DR & (uint8_t)0x7F);
576 }
577
578 /* Increment the Rx buffer address */
579 pUSARTHandle->pRxBuffer++;
580 pUSARTHandle->RxLen -= 1;
581 }
582 } /* End of if (pUSARTHandle-> RxLen > 0) */
583
584 if (pUSARTHandle->RxLen == 0)
585 {
586 /* Clear RXNEIE bit (disable interrupt triggered by RXNE flag */
587 pUSARTHandle->pUSARTx->CR1 &= ~(0x1 << USART_CR1_RXNEIE);
588 pUSARTHandle->RxBusyState = USART_READY;
589
590 /* Notify the application of the event USART_EV_RX_CMPLT */
591 USART_ApplicationEventCallback(pUSARTHandle, USART_EV_RX_CMPLT);
592 }
593 }
594 }
595
596 /* Check for CTS flag ----------------------------------------------------*/
597 /* Note: CTS feature is not applicable for UART4 and UART5 */
598
599 /* Check the state of CTS bit in SR */
600 temp1 = pUSARTHandle->pUSARTx->SR & (0x1 << USART_SR_CTS);
601
602 /* Check the state of CTSE bit in CR3 */
603 temp2 = pUSARTHandle->pUSARTx->CR3 & (0x1 << USART_CR3_CTSE);
604
605 /* Check the state of CTSIE bit in CR3 */
606 temp3 = pUSARTHandle->pUSARTx->CR3 & (0x1 << USART_CR3_CTSIE);
607
608 if (temp1 && temp2)
609 {
610 /* Clear CTS flag in SR */
611 pUSARTHandle->pUSARTx->SR &= ~(0x1 << USART_SR_CTS);
612
613 /* Notify the application of the event USART_EV_CTS */
614 USART_ApplicationEventCallback(pUSARTHandle, USART_EV_CTS);
615 }
616
617 /* Check for IDLE detection flag -----------------------------------------*/
618
619 /* Check the state of IDLE bit in SR */
620 temp1 = pUSARTHandle->pUSARTx->SR & (0x1 << USART_SR_IDLE);
621
622 /* Check the state of IDLEIE bit in CR1 */
623 temp2 = pUSARTHandle->pUSARTx->CR1 & (0x1 << USART_CR1_IDLEIE);
624
625 if (temp1 && temp2)
626 {
627 /* Clear IDLE flag. (Check the reference manual for clear sequence) */
628 temp1 = pUSARTHandle->pUSARTx->SR &= ~(0x1 << USART_SR_IDLE);
629
630 /* Notify the application of the event USART_EV_IDLE */
631 USART_ApplicationEventCallback(pUSARTHandle, USART_EV_IDLE);
632 }
633
634 /* Check for Overrun detection flag --------------------------------------*/
635
636 /* Check the state of ORE flag in SR */
637 temp1 = pUSARTHandle->pUSARTx->SR & USART_SR_ORE;
638
639 /* Check the state of RXNEIE bit in CR1 */
640 temp2 = pUSARTHandle->pUSARTx->CR1 & USART_CR1_RXNEIE;
641
642 if (temp1 && temp2)
643 {
644 /* Need to clear the ORE flag here. Instead, give an API for the
645 * application to clear the ORE flag.
646 */
647
648 /* Notify the application of the event USART_EV_IDLE */
649 USART_ApplicationEventCallback(pUSARTHandle, USART_ER_ORE);
650 }
651
652 /* Check for Error flag --------------------------------------------------*/
653 /* Note: Noise flag, overrun error and framing error in multibuffer
654 * communication. Multibuffer communication is not dealt in this
655 * driver. Please refer to the MCU reference manual.
656 *
657 * The following code will be executed in multibuffer mode only!
658 */
659
660 temp2 = pUSARTHandle->pUSARTx->CR3 & (0x1 << USART_CR3_EIE);
661
662 if (temp2)
663 {
664 temp1 = pUSARTHandle->pUSARTx->SR;
665
666 if (temp1 & (0x1 << USART_SR_FE))
667 {
668 /* This bit is set by hardware when a de-synchronization, excessive
669 * noise or break character is detected. It is cleared by a software
670 * sequence (i.e., reading USART_SR followed by reading USART_DR).
671 */
672 USART_ApplicationEventCallback(pUSARTHandle, USART_ER_FE);
673 }
674
675 if (temp1 & (0x1 << USART_SR_NF))
676 {
677 /* This bit si set by hardware when noise is detected on a received
678 * frame. It is cleared software sequence (i.e., reading USART_SR
679 * followed by reading USART_DR).
680 */
681 USART_ApplicationEventCallback(pUSARTHandle, USART_ER_NE);
682 }
683
684 if (temp1 & (0x1 << USART_SR_ORE))
685 {
686 USART_ApplicationEventCallback(pUSARTHandle, USART_ER_ORE);
687 }
688 }
689} /* End of USART_IRQHandling */
690
691/**
692 * USART_PeriClockControl()
693 * Brief : Enables or disables USART peripheral
694 * Param : @pUSARTx - base address of USARTx peripheral
695 * @state - ENABLE or DISABLE macro
696 * Retval : None
697 * Note : N/A
698 */
699void USART_PeriControl(USART_TypeDef *pUSARTx, uint8_t state)
700{
701 if (state == ENABLE)
702 {
703 pUSARTx->CR1 |= (0x1 << USART_CR1_UE);
704 }
705 else
706 {
707 pUSARTx->CR1 &= ~(0x1 << USART_CR1_UE);
708 }
709} /* End of USART_PeriControl */
710
711/**
712 * USART_SetBaudRate()
713 * Brief : Sets the baurate for USART communication
714 * Param : @pUSARTx - base address of USARTx peripheral
715 * @baudrate - baudrate in bps
716 * Retval : None
717 * Note : N/A
718 */
719void USART_SetBaudRate(USART_TypeDef *pUSARTx, uint32_t baudrate)
720{
721 uint32_t PCLKx; /* APB bus clock frequency */
722 uint32_t usartdiv;
723 uint32_t mantissa, fraction;
724 uint32_t temp = 0;
725
726 /* Get the APB bus clock frequency into 'PCLKx' */
727 if (pUSARTx == USART1 || pUSARTx == USART6)
728 {
729 /* USART1 and USART6 are connected to APB2 bus */
730 PCLKx = RCC_GetPCLK2Value();
731 }
732 else
733 {
734 /* USART2, USART3, UART4, UART5 are connected to APB1 bus */
735 PCLKx = RCC_GetPCLK1Value();
736 }
737
738 /* Check the oversampling value (OVER8) */
739 if (pUSARTx->CR1 & (0x1 << USART_CR1_OVER8))
740 {
741 /* OVER8=1, oversampling by 8 */
742 usartdiv = ((25 * PCLKx) / (2 * baudrate));
743 }
744 else
745 {
746 /* OVER8=0, oversampling by 16 */
747 usartdiv = ((25 * PCLKx) / (4 * baudrate));
748 }
749
750 /* Calculate the mantissa part */
751 mantissa = usartdiv/100;
752
753 /* Write the mantissa part in the appropriate bit position in 'temp' */
754 temp |= (mantissa << USART_BRR_DIV_MANTISSA);
755
756 /* Extract the fraction part */
757 fraction = (usartdiv - (mantissa * 100));
758
759 /* Calculate the final fraction */
760 if (pUSARTx->CR1 & (0x1 << USART_CR1_OVER8))
761 {
762 /* OVER8=1, oversampling by 8 */
763 fraction = (((fraction * 8) + 50) / 100) & ((uint8_t)0x07);
764 }
765 else
766 {
767 /* OVER8=0, oversampling by 16 */
768 fraction = (((fraction * 16) + 50) / 100) & ((uint8_t)0x0F);
769 }
770
771 /* Write the fraction part in the appropriate bit position in 'temp' */
772 temp |= fraction;
773
774 /* Copy the contents of 'temp' into USART_BRR register */
775 pUSARTx->BRR = temp;
776} /* End of USART_SetBaudRate */
777
778/**
779 * USART_ApplicationEventCallback()
780 * Brief : Notifies the application of the event occurred
781 * Param : @pUSARTHandle - pointer to USART handle structure
782 * @appEvent - USART event occurred
783 * Retval : None
784 * Note : This function must be implemented by the application. Since the driver
785 * does not know in which application this function will be implemented,
786 * the driver defines it as a weak function. The application may override
787 * this function.
788 * If the application does not implement this function, the following
789 * definition will be executed.
790 */
791__WEAK void USART_ApplicationEventCallback(USART_Handle_TypeDef *pUSARTHandle, uint8_t appEvent)
792{
793 /* Implemented in the application */
794} /* End of USART_ApplicationEventCallback */