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.hPath: Project/Drivers/Inc/
xxxxxxxxxx1711/*******************************************************************************2 * File     : stm32f407xx_usart_driver.h3 * Brief    : STM32F407xx MCU specific USART driver header 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
14
16/*******************************************************************************17 * APIs supported by the USART driver18 * (See function definitions for more information)19 ******************************************************************************/20
21/* USARTx peripheral configuration structure */22typedef struct23{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 struct34{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_Mode47 * 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_Baud55 * Note: Baudrates are in 'bits per second (bps)' and can be found in the56 *       MCU reference manual.57 *       Check USART_BRR register.58 */59
72/**73 * @USART_NumOfStopBits74 * Note: Check STOP bit field in USART_CR2 register.75 */76
81/**82 * @USART_WordLength83 * Note: Check M bit in USART_CR1 register.84 */85
88/**89 * @USART_ParityControl90 * Note: Check PCE and PS bits in USART_CR1 register.91 */92
96/**97 * @USART_HWFlowControl98 * Note: Check CTSE and RTSE bits in USART_CR3 register.99 */100
105/**106 * TxRxState (Application communication state)107 */108
112/**113 * I2C application event macros114 */115
124
125/*******************************************************************************126 * APIs supported by the USART driver127 * (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-init135 */136void USART_Init(USART_Handle_TypeDef *pUSARTHandle);137void USART_DeInit(USART_TypeDef *pUSARTx);138
139
140/**141 * Data send and receive142 */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 handling151 */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 APIs159 */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 will166 *       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.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 */