Home | Projects | Notes > MCU Peripheral Drivers > GPIO Driver (stm32f407xx_gpio_driver.h/.c
)
stm32f407xx_gpio_driver.h/.c
)
GPIO initialization
Enable/Disable GPIO port clock
Read from a GPIO pin
Write to GPIO pin
Configure alternate functionality
Interrupt handling
stm32f407xx_gpio_driver.h
Path: Project/Drivers/Inc/
xxxxxxxxxx
1291/*******************************************************************************
2 * File : stm32f407xx_gpio_driver.h
3 * Brief : STM32F407xx MCU specific GPIO driver header file
4 * Author ; Kyungjae Lee
5 * Date : May 21, 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 * GPIOx peripheral structures
18 ******************************************************************************/
19
20/* GPIO pin configuration structure */
21typedef struct
22{
23 uint8_t GPIO_PinNumber; /* Available values @GPIO_PIN_NUMBERS */
24 uint8_t GPIO_PinMode; /* Available values @GPIO_PIN_MODES */
25 uint8_t GPIO_PinSpeed; /* Available values @GPIO_PIN_SPEED */
26 uint8_t GPIO_PinPuPdControl; /* Available values @GPIO_PIN_PUPD */
27 uint8_t GPIO_PinOutType; /* Available values @GPIO_PIN_OUT_TYPES */
28 uint8_t GPIO_PinAltFcnMode; /* Only applicable when mode is set to alternate function mode */
29} GPIO_PinConfig_TypeDef;
30
31/* GPIO pin handle structure */
32typedef struct
33{
34 GPIO_TypeDef *pGPIOx; /* Holds the base address of the GPIO port to which the pin belongs */
35 GPIO_PinConfig_TypeDef GPIO_PinConfig; /* Holds the GPIO pin configuration settings */
36} GPIO_Handle_TypeDef;
37
38/**
39 * @GPIO_PIN_NUMBERS
40 * GPIO pin numbers
41 */
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59/**
60 * @GPIO_PIN_MODES
61 * GPIO pin modes
62 */
63/* Non-interrupt mode */
64/* Non-interrupt mode */
65/* Non-interrupt mode */
66/* Non-interrupt mode */
67/* Falling edge trigger (for interrupt) */
68/* Rising edge trigger (for interrupt) */
69/* Rising falling edge trigger (for interrupt) */
70
71/**
72 * @GPIO_PIN_OUT_TYPES
73 * GPIO pin output types
74 */
75/* Push-pull type */
76/* Open-drain type */
77
78/**
79 * @GPIO_PIN_SPEED
80 * GPIO pin output speeds
81 */
82
83
84
85
86
87/**
88 * @GPIO_PIN_PUPD
89 * GPIO pin pull-up / pull-down configurations
90 */
91
92
93
94
95
96/*******************************************************************************
97 * APIs supported by the GPIO driver
98 * (See function definitions for more information)
99 ******************************************************************************/
100
101/**
102 * Peripheral clock setup
103 */
104void GPIO_PeriClockControl(GPIO_TypeDef *pGPIOx, uint8_t state);
105
106/**
107 * Init and De-init
108 */
109void GPIO_Init(GPIO_Handle_TypeDef *pGPIOHandle);
110void GPIO_DeInit(GPIO_TypeDef *pGPIOx); /* Utilize RCC_AHB1RSTR (AHB1 peripheral reset register) */
111
112/**
113 * Data read and write
114 */
115uint8_t GPIO_ReadFromInputPin(GPIO_TypeDef *pGPIOx, uint8_t pinNumber);
116uint16_t GPIO_ReadFromInputPort(GPIO_TypeDef *pGPIOx); /* Returns the contents of IDR */
117void GPIO_WriteToOutputPin(GPIO_TypeDef *pGPIOx, uint8_t pinNumber, uint8_t value);
118void GPIO_WriteToOutputPort(GPIO_TypeDef *pGPIOx, uint16_t value);
119void GPIO_ToggleOutputPin(GPIO_TypeDef *pGPIOx, uint8_t pinNumber);
120
121/**
122 * IRQ configuration and ISR handling
123 */
124void GPIO_IRQInterruptConfig(uint8_t irqNumber, uint8_t state);
125void GPIO_IRQPriorityConfig(uint8_t irqNumber, uint32_t irqPriority);
126void GPIO_IRQHandling(uint8_t pinNumber);
127
128
129/* STM32F407XX_GPIO_DRIVER_H */
stm32f407xx_gpio_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 */