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.hPath: Project/Drivers/Inc/
xxxxxxxxxx1291/*******************************************************************************2 * File : stm32f407xx_gpio_driver.h3 * Brief : STM32F407xx MCU specific GPIO driver header file4 * Author ; Kyungjae Lee5 * Date : May 21, 20236 *7 * Note : This code includes only the features that are necessary for my8 * personal projects.9 * ****************************************************************************/10
111213
1415
16/*******************************************************************************17 * GPIOx peripheral structures18 ******************************************************************************/19
20/* GPIO pin configuration structure */21typedef struct22{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 struct33{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_NUMBERS40 * GPIO pin numbers41 */4243444546474849505152535455565758
59/**60 * @GPIO_PIN_MODES61 * GPIO pin modes62 */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_TYPES73 * GPIO pin output types74 */75/* Push-pull type */76/* Open-drain type */77
78/**79 * @GPIO_PIN_SPEED80 * GPIO pin output speeds81 */8283848586
87/**88 * @GPIO_PIN_PUPD89 * GPIO pin pull-up / pull-down configurations90 */91929394
95
96/*******************************************************************************97 * APIs supported by the GPIO driver98 * (See function definitions for more information)99 ******************************************************************************/100
101/**102 * Peripheral clock setup103 */104void GPIO_PeriClockControl(GPIO_TypeDef *pGPIOx, uint8_t state);105
106/**107 * Init and De-init108 */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 write114 */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 handling123 */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.cPath: Project/Drivers/Src/
xxxxxxxxxx7941/*******************************************************************************2 * File : stm32f407xx_usart_driver.c3 * Brief : STM32F407xx MCU specific USART driver source file4 * Author ; Kyungjae Lee5 * Date : Jun 20, 20236 *7 * Note : This code includes only the features that are necessary for my8 * personal projects.9 * ****************************************************************************/10
1112
13/*******************************************************************************14 * APIs supported by the I2C driver15 * (See function definitions for more information)16 ******************************************************************************/17
18/**19 * USART_PeriClockControl()20 * Brief : Enables or disables USART peripheral clock21 * Param : @pUSARTx - base address of USARTx peripheral22 * @state - ENABLE or DISABLE macro23 * Retval : None24 * Note : N/A25 */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 else44 {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 peripheral63 * Param : @pUSARTHandle - pointer to USART handle structure64 * Retval : None65 * Note : N/A66 */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 by104 * default when parity is enabled105 */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 by114 * default when parity is enabled115 */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 peripheral167 * Param : @pUSARTx - base address of USARTx peripheral168 * Retval : None169 * Note : N/A170 */171void USART_DeInit(USART_TypeDef *pUSARTx)172{173
174} /* End of USART_DeInit */175
176/**177 * USART_TxBlocking()178 * Brief : Handles blocking-based USART transmission179 * Param : @pUSARTHandle - pointer to USART handle structure180 * @pTxBuffer - pointer to Tx buffer181 * @len -182 * Retval : None183 * Note : N/A184 */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 the201 * 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 user210 * data will be sent. (Need 2 bytes to transfer 9 bits)211 */212 pTxBuffer++;213 pTxBuffer++;214 }215 else216 {217 /* Parity bit is used in this transfer. So, 8-bit of user data218 * will be sent.219 * The 9th bit will be replaced by parity bit by the hardware.220 */221 pTxBuffer++;222 }223 }224 else225 {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 reception242 * Param : @pUSARTHandle - pointer to USART handle structure243 * @pRxBuffer - pointer to Rx buffer244 * @len -245 * Retval : None246 * Note : N/A247 */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 the265 * 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 else274 {275 /* Parity bit is used in this transfer. So, 8-bit of user data276 * 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 else284 {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 transmission297 * Param : @pUSARTHandle - pointer to USART handle structure298 * @pTxBuffer - pointer to Tx buffer299 * @len -300 * Retval : None301 * Note : N/A302 */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 reception326 * Param : @pUSARTHandle - pointer to USART handle structure327 * @pTxBuffer - pointer to Tx buffer328 * @len -329 * Retval : None330 * Note : N/A331 */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 interrupts354 * Param : @irqNumber - IRQ number355 * @state - ENABLE or DISABLE macro356 * Retval : None357 * Note : N/A358 */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 else372 {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 priorities386 * Param : @irqNumber - IRQ number387 * @irqPriotity - IRQ priority (Make sure this parameter is of388 * type uint32_t. Due to the number of bits it389 * needs to be shifted during the calculation,390 * declaring it as uint8_t did not do its job.391 * Retval : None392 * Note : N/A393 */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 IRQ406 * Param : @pUSARTHandle - pointer to USART handle structure407 * Retval : None408 * Note : This function will first decode the event that occurred, and409 * handle the event accordingly.410 * The compiler will generate unused variable for 'temp3'. (In411 * general, it is a good practice to check if an interrupt is412 * enabled, along with its status bit. Currently, to generalize413 * 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 the479 * 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 else494 {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 else501 {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 else551 {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 else559 {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 else571 {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 the645 * 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 multibuffer654 * communication. Multibuffer communication is not dealt in this655 * 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, excessive669 * noise or break character is detected. It is cleared by a software670 * 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 received678 * frame. It is cleared software sequence (i.e., reading USART_SR679 * 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 peripheral694 * Param : @pUSARTx - base address of USARTx peripheral695 * @state - ENABLE or DISABLE macro696 * Retval : None697 * Note : N/A698 */699void USART_PeriControl(USART_TypeDef *pUSARTx, uint8_t state)700{701 if (state == ENABLE)702 {703 pUSARTx->CR1 |= (0x1 << USART_CR1_UE);704 }705 else706 {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 communication714 * Param : @pUSARTx - base address of USARTx peripheral715 * @baudrate - baudrate in bps716 * Retval : None717 * Note : N/A718 */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 else733 {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 else745 {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 else766 {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 occurred781 * Param : @pUSARTHandle - pointer to USART handle structure782 * @appEvent - USART event occurred783 * Retval : None784 * Note : This function must be implemented by the application. Since the driver785 * does not know in which application this function will be implemented,786 * the driver defines it as a weak function. The application may override787 * this function.788 * If the application does not implement this function, the following789 * 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 */