/*! * @file apm32f10x_usart.c * * @brief This file provides all the USART firmware functions * * @version V1.0.4 * * @date 2022-12-01 * * @attention * * Copyright (C) 2020-2022 Geehy Semiconductor * * You may not use this file except in compliance with the * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope * that it will be useful and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions * and limitations under the License. */ #include "apm32f10x_usart.h" #include "apm32f10x_rcm.h" /** @addtogroup APM32F10x_StdPeriphDriver @{ */ /** @addtogroup USART_Driver USART Driver * @brief USART driver modules @{ */ /** @defgroup USART_Functions Functions @{ */ /*! * @brief Reset usart peripheral registers to their default reset values * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_Reset(USART_T* usart) { if (USART1 == usart) { RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_USART1); RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_USART1); } else if (USART2 == usart) { RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_USART2); RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_USART2); } else if (USART3 == usart) { RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_USART3); RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_USART3); } else if (UART4 == usart) { RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_UART4); RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_UART4); } else if (UART5 == usart) { RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_UART5); RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_UART5); } } /*! * @brief Configures the USART peripheral according to the specified parameters in the usartConfig * * @param uart: Select the USART or the UART peripheral * * @param usartConfig: pointer to a USART_Config_T structure * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_Config(USART_T* uart, USART_Config_T* usartConfig) { uint32_t temp, fCLK, intDiv, fractionalDiv; temp = uart->CTRL1; temp &= 0xE9F3; temp |= (uint32_t)usartConfig->mode | \ (uint32_t)usartConfig->parity | \ (uint32_t)usartConfig->wordLength; uart->CTRL1 = temp; temp = uart->CTRL2; temp &= 0xCFFF; temp |= usartConfig->stopBits; uart->CTRL2 = temp; temp = uart->CTRL3; temp &= 0xFCFF; temp |= (uint32_t)usartConfig->hardwareFlow; uart->CTRL3 = temp; if (uart == USART1) { RCM_ReadPCLKFreq(NULL, &fCLK); } else { RCM_ReadPCLKFreq(&fCLK, NULL); } intDiv = ((25 * fCLK) / (4 * (usartConfig->baudRate))); temp = (intDiv / 100) << 4; fractionalDiv = intDiv - (100 * (temp >> 4)); temp |= ((((fractionalDiv * 16) + 50) / 100)) & ((uint8_t)0x0F); uart->BR = temp; } /*! * @brief Fills each USART_InitStruct member with its default value * * @param usartConfig: pointer to a USART_Config_T structure which will be initialized * * @retval None */ void USART_ConfigStructInit(USART_Config_T* usartConfig) { usartConfig->baudRate = 9600; usartConfig->wordLength = USART_WORD_LEN_8B; usartConfig->stopBits = USART_STOP_BIT_1; usartConfig->parity = USART_PARITY_NONE ; usartConfig->mode = USART_MODE_TX_RX; usartConfig->hardwareFlow = USART_HARDWARE_FLOW_NONE; } /*! * @brief Configures communication clock * * @param usart: Select the USART or the UART peripheral * * @param clockConfig: Pointer to a USART_clockConfig_T structure * * @retval None * * @note The usart can be USART1, USART2, USART3 */ void USART_ConfigClock(USART_T* usart, USART_ClockConfig_T* clockConfig) { usart->CTRL2_B.CLKEN = clockConfig->clock; usart->CTRL2_B.CPHA = clockConfig->phase; usart->CTRL2_B.CPOL = clockConfig->polarity; usart->CTRL2_B.LBCPOEN = clockConfig->lastBit; } /*! * @brief Fills each clockConfig member with its default value * * @param clockConfig: Pointer to a USART_clockConfig_T structure * * @retval None * */ void USART_ConfigClockStructInit(USART_ClockConfig_T* clockConfig) { clockConfig->clock = USART_CLKEN_DISABLE; clockConfig->phase = USART_CLKPHA_1EDGE; clockConfig->polarity = USART_CLKPOL_LOW; clockConfig->lastBit = USART_LBCP_DISABLE; } /*! * @brief Enable the specified USART peripheral * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_Enable(USART_T* usart) { usart->CTRL1_B.UEN = BIT_SET; } /*! * @brief Disable the specified USART peripheral * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_Disable(USART_T* usart) { usart->CTRL1_B.UEN = BIT_RESET; } /*! * @brief Enable the USART DMA interface * * @param usart: Select the USART or the UART peripheral * * @param dmaReq: Specifies the DMA request * This parameter can be one of the following values: * @arg USART_DMA_TX: USART DMA receive request * @arg USART_DMA_RX: USART DMA transmit request * @arg USART_DMA_TX_RX: USART DMA transmit/receive request * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_EnableDMA(USART_T* usart, USART_DMA_T dmaReq) { usart->CTRL3 |= dmaReq; } /*! * @brief Disable the USART DMA interface * * @param usart: Select the USART or the UART peripheral * * @param dmaReq: Specifies the DMA request * This parameter can be one of the following values: * @arg USART_DMA_TX: USART DMA receive request * @arg USART_DMA_RX: USART DMA transmit request * @arg USART_DMA_TX_RX: USART DMA transmit/receive request * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_DisableDMA(USART_T* usart, USART_DMA_T dmaReq) { usart->CTRL3 &= (uint32_t)~dmaReq; } /*! * @brief Configures the address of the USART node * * @param usart: Select the USART or the UART peripheral * * @param address: Indicates the address of the USART node * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_Address(USART_T* usart, uint8_t address) { usart->CTRL2_B.ADDR = address; } /*! * @brief Selects the USART WakeUp method. * * @param usart: Select the USART or the UART peripheral * * @param wakeup: Specifies the selected USART auto baud rate method * This parameter can be one of the following values: * @arg USART_WAKEUP_IDLE_LINE: WakeUp by an idle line detection * @arg USART_WAKEUP_ADDRESS_MARK: WakeUp by an address mark * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_ConfigWakeUp(USART_T* usart, USART_WAKEUP_T wakeup) { usart->CTRL1_B.WUPMCFG = wakeup; } /*! * @brief Enable USART Receiver in mute mode * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_EnableMuteMode(USART_T* usart) { usart->CTRL1_B.RXMUTEEN = BIT_SET; } /*! * @brief Disable USART Receiver in active mode * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_DisableMuteMode(USART_T* usart) { usart->CTRL1_B.RXMUTEEN = BIT_RESET; } /*! * @brief Set the USART LIN Break detection length * * @param usart: Select the USART or the UART peripheral * * @param length: Specifies the LIN break detection length * This parameter can be one of the following values: * @arg USART_LBDL_10B: 10-bit break detection * @arg USART_LBDL_10B: 11-bit break detection * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_ConfigLINBreakDetectLength(USART_T* usart, USART_LBDL_T length) { usart->CTRL2_B.LBDLCFG = length; } /*! * @brief Enable the USART LIN MODE * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_EnableLIN(USART_T* usart) { usart->CTRL2_B.LINMEN = BIT_SET; } /*! * @brief Disable the USART LIN MODE * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_DisableLIN(USART_T* usart) { usart->CTRL2_B.LINMEN = BIT_RESET; } /*! * @brief Transmitter enable * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_EnableTx(USART_T* usart) { usart->CTRL1_B.TXEN = BIT_SET; } /*! * @brief Transmitter disable * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_DisableTx(USART_T* usart) { usart->CTRL1_B.TXEN = BIT_RESET; } /*! * @brief Receiver enable * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_EnableRx(USART_T* usart) { usart->CTRL1_B.RXEN = BIT_SET; } /*! * @brief Receiver disable * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_DisableRx(USART_T* usart) { usart->CTRL1_B.RXEN = BIT_RESET; } /*! * @brief Transmits single data * * @param usart: Select the USART or the UART peripheral * * @param data: the data to transmit * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_TxData(USART_T* usart, uint16_t data) { usart->DATA_B.DATA = data; } /*! * @brief Return the most recent received data * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ uint16_t USART_RxData(USART_T* usart) { return (uint16_t)(usart->DATA_B.DATA); } /*! * @brief Transmits break characters * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_TxBreak(USART_T* usart) { usart->CTRL1_B.TXBF = BIT_SET; } /*! * @brief Set the specified USART guard time * * @param usart: Select the USART or the UART peripheral * * @param guardTime: Specifies the guard time * * @retval None * * @note The usart can be USART1, USART2, USART3 */ void USART_ConfigGuardTime(USART_T* usart, uint8_t guardTime) { usart->GTPSC_B.GRDT = guardTime; } /*! * @brief Set the system clock divider number * * @param usart: Select the USART or the UART peripheral * * @param div: specifies the divider number * * @retval None * * @note The usart can be USART1, USART2, USART3 */ void USART_ConfigPrescaler(USART_T* usart, uint8_t div) { usart->GTPSC_B.PSC = div; } /*! * @brief Enable the USART Smart Card mode * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The Smart Card mode is not available for UART4 and UART5 */ void USART_EnableSmartCard(USART_T* usart) { usart->CTRL3_B.SCEN = BIT_SET; } /*! * @brief Disable the USART Smart Card mode * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The Smart Card mode is not available for UART4 and UART5 */ void USART_DisableSmartCard(USART_T* usart) { usart->CTRL3_B.SCEN = BIT_RESET; } /*! * @brief Enable NACK transmission * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The Smart Card mode is not available for UART4 and UART5 */ void USART_EnableSmartCardNACK(USART_T* usart) { usart->CTRL3_B.SCNACKEN = BIT_SET; } /*! * @brief Disable NACK transmission * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The Smart Card mode is not available for UART4 and UART5 */ void USART_DisableSmartCardNACK(USART_T* usart) { usart->CTRL3_B.SCNACKEN = BIT_RESET; } /*! * @brief Enable USART Half Duplex communication * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_EnableHalfDuplex(USART_T* usart) { usart->CTRL3_B.HDEN = BIT_SET; } /*! * @brief Disable USART Half Duplex communication * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_DisableHalfDuplex(USART_T* usart) { usart->CTRL3_B.HDEN = BIT_RESET; } /*! * @brief Configures the USART's IrDA interface * * @param usart: Select the USART or the UART peripheral * * @param IrDAMode: Specifies the IrDA mode * This parameter can be one of the following values: * @arg USART_IRDALP_NORMAL: Normal * @arg USART_IRDALP_LOWPOWER: Low-Power * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_ConfigIrDA(USART_T* usart, USART_IRDALP_T IrDAMode) { usart->CTRL3_B.IRLPEN = IrDAMode; } /*! * @brief Enable the USART's IrDA interface * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_EnableIrDA(USART_T* usart) { usart->CTRL3_B.IREN = BIT_SET; } /*! * @brief Disable the USART's IrDA interface * * @param usart: Select the USART or the UART peripheral * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_DisableIrDA(USART_T* usart) { usart->CTRL3_B.IREN = BIT_RESET; } /*! * @brief Enable the specified USART interrupts * * @param usart: Select the USART or the UART peripheral * * @param interrupt: Specifies the USART interrupts sources * The parameter can be one of following values: * @arg USART_INT_PE: Parity error interrupt * @arg USART_INT_TXBE: Tansmit data buffer empty interrupt * @arg USART_INT_TXC: Transmission complete interrupt * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt * @arg USART_INT_IDLE: Idle line detection interrupt * @arg USART_INT_LBD: LIN break detection interrupt * @arg USART_INT_CTS: CTS change interrupt * @arg USART_INT_ERR: Error interrupt(Frame error, noise error, overrun error) * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_EnableInterrupt(USART_T* usart, USART_INT_T interrupt) { uint32_t temp; temp = (uint32_t)(interrupt & 0xffff); if (interrupt & 0x10000) { usart->CTRL1 |= temp; } if (interrupt & 0x20000) { usart->CTRL2 |= temp; } if (interrupt & 0x40000) { usart->CTRL3 |= temp; } } /*! * @brief Disable the specified USART interrupts * * @param usart: Select the USART or the UART peripheral * * @param interrupt: Specifies the USART interrupts sources * The parameter can be one of following values: * @arg USART_INT_PE: Parity error interrupt * @arg USART_INT_TXBE: Tansmit data buffer empty interrupt * @arg USART_INT_TXC: Transmission complete interrupt * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt * @arg USART_INT_IDLE: Idle line detection interrupt * @arg USART_INT_LBD: LIN break detection interrupt * @arg USART_INT_CTS: CTS change interrupt * @arg USART_INT_ERR: Error interrupt(Frame error, noise error, overrun error) * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_DisableInterrupt(USART_T* usart, USART_INT_T interrupt) { uint32_t temp; temp = (uint32_t)~(interrupt & 0xffff); if (interrupt & 0x10000) { usart->CTRL1 &= temp; } if (interrupt & 0x20000) { usart->CTRL2 &= temp; } if (interrupt & 0x40000) { usart->CTRL3 &= temp; } } /*! * @brief Read the specified USART flag * * @param usart: Select the USART or the UART peripheral * * @param flag: Specifies the flag to check * The parameter can be one of following values: * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) * @arg USART_FLAG_LBD: LIN Break detection flag * @arg USART_FLAG_TXBE: Transmit data buffer empty flag * @arg USART_FLAG_TXC: Transmission Complete flag * @arg USART_FLAG_RXBNE: Receive data buffer not empty flag * @arg USART_FLAG_IDLE: Idle Line detection flag * @arg USART_FLAG_OVRE: OverRun Error flag * @arg USART_FLAG_NE: Noise Error flag * @arg USART_FLAG_FE: Framing Error flag * @arg USART_FLAG_PE: Parity Error flag * * @retval The new state of flag (SET or RESET) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ uint8_t USART_ReadStatusFlag(USART_T* usart, USART_FLAG_T flag) { return (usart->STS & flag) ? SET : RESET; } /*! * @brief Clear the USARTx's pending flags * * @param usart: Select the USART or the UART peripheral * * @param flag: Specifies the flag to clear * The parameter can be one of following values: * @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5) * @arg USART_FLAG_LBD: LIN Break detection flag * @arg USART_FLAG_TXC: Transmission Complete flag * @arg USART_FLAG_RXBNE: Receive data buffer not empty flag * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_ClearStatusFlag(USART_T* usart, USART_FLAG_T flag) { usart->STS &= (uint32_t)~flag; } /*! * @brief Read the specified USART interrupt flag * * @param usart: Select the USART or the UART peripheral * * @param flag: Specifies the USART interrupt source to check * The parameter can be one of following values: * @arg USART_INT_TXBE: Tansmit data buffer empty interrupt * @arg USART_INT_TXC: Transmission complete interrupt * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt * @arg USART_INT_IDLE: Idle line detection interrupt * @arg USART_INT_LBD: LIN break detection interrupt * @arg USART_INT_CTS: CTS change interrupt * @arg USART_INT_OVRE: OverRun Error interruptpt * @arg USART_INT_NE: Noise Error interrupt * @arg USART_INT_FE: Framing Error interrupt * @arg USART_INT_PE: Parity error interrupt * * @retval The new state of flag (SET or RESET) * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ uint8_t USART_ReadIntFlag(USART_T* usart, USART_INT_T flag) { uint32_t itFlag, srFlag; if (flag & 0x10000) { itFlag = usart->CTRL1 & flag & 0xffff; } else if (flag & 0x20000) { itFlag = usart->CTRL2 & flag & 0xffff; } else { itFlag = usart->CTRL3 & flag & 0xffff; } srFlag = flag >> 24; srFlag = (uint32_t)(1 << srFlag); srFlag = usart->STS & srFlag; if (srFlag && itFlag) { return SET; } return RESET; } /*! * @brief Clear the USART interrupt pending bits * * @param usart: Select the USART or the UART peripheral * * @param flag: Specifies the interrupt pending bit to clear * The parameter can be one of following values: * @arg USART_INT_RXBNE: Receive data buffer not empty interrupt * @arg USART_INT_TXC: Transmission complete interrupt * @arg USART_INT_LBD: LIN break detection interrupt * @arg USART_INT_CTS: CTS change interrupt * * @retval None * * @note The usart can be USART1, USART2, USART3, UART4 and UART5 */ void USART_ClearIntFlag(USART_T* usart, USART_INT_T flag) { uint32_t srFlag; srFlag = flag >> 24; srFlag = (uint32_t)(1 << srFlag); usart->STS &= (uint32_t)~srFlag; } /**@} end of group USART_Functions */ /**@} end of group USART_Driver */ /**@} end of group APM32F10x_StdPeriphDriver */