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
11
14
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 */42
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 */82
87/**88 * @GPIO_PIN_PUPD89 * GPIO pin pull-up / pull-down configurations90 */91
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
11
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 */