S32 Design Studio PE工具配置UART

配置操作

先得配置下GPIO用的是哪个引脚

跟之前的外设一样,它这里有两个UART可以用。

这里只能用UART0和2的原因是UART1被LIN使用了。

配置的内容为

生成代码对应

首先会根据components名称创建个驱动状态结构体

/*! Driver state structure */
lpuart_state_t lpuart2_State;

配置状态结构体

/*! lpuart2 configuration structure */
const lpuart_user_config_t lpuart2_InitConfig0 = {
  .transferType = LPUART_USING_INTERRUPTS,
  .baudRate = 115200U,
  .parityMode = LPUART_PARITY_DISABLED,
  .stopBitCount = LPUART_ONE_STOP_BIT,
  .bitCountPerChar = LPUART_8_BITS_PER_CHAR,
  .rxDMAChannel = 0U,
  .txDMAChannel = 0U,
};

只读的话就是配置状态结构体类型前面加个const

传输方式可以选择中断或者DMA

选择中断方式的话,后面的接收和发送DMA通道都会变成0,不起作用。

DMA模式可以不等到CPU来处理中断的时候才进行数据传输,可以直接通过DMA通道搬运数据,降低对应功能对CPU使用率。

这两种方式只是硬件处理上的不同,软件只需要配置一下就OK,使用方法和步骤都是一样的。

/*! @brief Type of LPUART transfer (based on interrupts or DMA).
 *
 * Implements : lpuart_transfer_type_t_Class
 */
typedef enum
{
    LPUART_USING_DMA         = 0,    /*!< The driver will use DMA to perform UART transfer */
    LPUART_USING_INTERRUPTS          /*!< The driver will use interrupts to perform UART transfer */
} lpuart_transfer_type_t;

中断是最常用的,如果选择DMA模式的话,需要在DMA里面设置对应的通道,我在这里就新建了通道2和3,并且映射到UART2里面的RX和TX。

dmaController1.c文件和dmaController1.h文件新定义了两个DMA通道结构体和两个DMA通道配置结构体

edma_chn_state_t dmaController1Chn0_State;

edma_chn_state_t dmaController1Chn1_State;

edma_chn_state_t dmaController1Chn2_State;//新增

edma_chn_state_t dmaController1Chn3_State;//新增

edma_chn_state_t * const edmaChnStateArray[] = {
    &dmaController1Chn0_State,
    &dmaController1Chn1_State,
    &dmaController1Chn2_State,//新增
    &dmaController1Chn3_State//新增
};

edma_channel_config_t dmaController1Chn0_Config = {
    .channelPriority = EDMA_CHN_DEFAULT_PRIORITY,
    .virtChnConfig = EDMA_CHN0_NUMBER,
    .source = EDMA_REQ_LPSPI0_RX,
    .callback = NULL,
    .callbackParam = NULL,
    .enableTrigger = false
};
edma_channel_config_t dmaController1Chn1_Config = {
    .channelPriority = EDMA_CHN_DEFAULT_PRIORITY,
    .virtChnConfig = EDMA_CHN1_NUMBER,
    .source = EDMA_REQ_LPSPI0_TX,
    .callback = NULL,
    .callbackParam = NULL,
    .enableTrigger = false
};
edma_channel_config_t dmaController1Chn2_Config = {//新增
    .channelPriority = EDMA_CHN_DEFAULT_PRIORITY,
    .virtChnConfig = EDMA_CHN2_NUMBER,
    .source = EDMA_REQ_LPUART2_RX,
    .callback = NULL,
    .callbackParam = NULL,
    .enableTrigger = false
};
edma_channel_config_t dmaController1Chn3_Config = {//新增
    .channelPriority = EDMA_CHN_DEFAULT_PRIORITY,
    .virtChnConfig = EDMA_CHN3_NUMBER,
    .source = EDMA_REQ_LPUART2_TX,
    .callback = NULL,
    .callbackParam = NULL,
    .enableTrigger = false
};
const edma_channel_config_t * const edmaChnConfigArray[] = {
    &dmaController1Chn0_Config,
    &dmaController1Chn1_Config,
    &dmaController1Chn2_Config,//新增
    &dmaController1Chn3_Config//新增
};

UART2配置里面DMA通道也要响应地进行配置

生成的代码就会有对应的改变

/*! lpuart2 configuration structure */
const lpuart_user_config_t lpuart2_InitConfig0 = {
  .transferType = LPUART_USING_DMA,
  .baudRate = 115200U,
  .parityMode = LPUART_PARITY_DISABLED,
  .stopBitCount = LPUART_ONE_STOP_BIT,
  .bitCountPerChar = LPUART_8_BITS_PER_CHAR,
  .rxDMAChannel = 2U,//DMA接收通道
  .txDMAChannel = 3U,//DMA发送通道
};

波特率大家都懂,Clock configuration是用来根据设置的波特率来计算出实际波特率的,一般写0就好。它有自己的一套算法,考虑到波特率漂移的情况。设置波特率比较低的时候,实际波特率跟设置波特率一致。设置波特率较高的时候,实际波特率会逐渐跟设置波特率拉开。

Clock configuration和实际波特率都不会体现在代码上,只是给你个参考,譬如你的串口工具如果波特率设置为115200的话,就容易出现乱码,设置为115942的时候性能就会稳定很多。

校验模式可以选择奇校验、偶校验和不校验。disabled不校验校验位是0个,EVEN偶校验1位,ODD奇校验一位。

/*! @brief LPUART number of bits in a character
 *
 * Implements : lpuart_bit_count_per_char_t_Class
 */
typedef enum
{
    LPUART_8_BITS_PER_CHAR  = 0x0U, /*!< 8-bit data characters */
    LPUART_9_BITS_PER_CHAR  = 0x1U, /*!< 9-bit data characters */
    LPUART_10_BITS_PER_CHAR = 0x2U  /*!< 10-bit data characters */
} lpuart_bit_count_per_char_t;

停止位长度、数据位长度两个也是很常见的了,在这里不再赘述。

接口使用

生成的接口在lpuart_driver.c文件和lpuart_driver.h文件里面,这个文件不在Generated_Code路径下面,而是在SDK\platform\drivers\src\lpuart和SDK\platform\drivers\inc里面。

LPUART_DRV_GetDefaultConfig

获取默认配置

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_GetDefaultConfig
 * Description   : Initializes the LPUART configuration structure with
 *                 default values.
 *
 * Implements    : LPUART_DRV_GetDefaultConfig_Activity
 *END**************************************************************************/
void LPUART_DRV_GetDefaultConfig(lpuart_user_config_t * lpuartUserConfig)
{
    DEV_ASSERT(lpuartUserConfig != NULL);

    lpuartUserConfig->transferType = LPUART_USING_INTERRUPTS;
    lpuartUserConfig->baudRate = 9600U;
    lpuartUserConfig->parityMode = LPUART_PARITY_DISABLED;
    lpuartUserConfig->stopBitCount = LPUART_ONE_STOP_BIT;
    lpuartUserConfig->bitCountPerChar = LPUART_8_BITS_PER_CHAR;
    lpuartUserConfig->rxDMAChannel = 0U;
    lpuartUserConfig->txDMAChannel = 0U;
}

LPUART_DRV_Init

初始化函数,第一个入参是驱动序号,在lpuart.h里面定义的,第二个入参是驱动状态结构体,第三个入参是配置结构体。

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_Init
 * Description   : This function initializes a LPUART instance for operation.
 * This function will initialize the run-time state structure to keep track of
 * the on-going transfers, ungate the clock to the LPUART module, initialize the
 * module to user defined settings and default settings, configure the IRQ state
 * structure and enable the module-level interrupt to the core, and enable the
 * LPUART module transmitter and receiver.
 * The following is an example of how to set up the lpuart_state_t and the
 * lpuart_user_config_t parameters and how to call the LPUART_DRV_Init function
 * by passing in these parameters:
 *    lpuart_user_config_t lpuartConfig;
 *    lpuartConfig.baudRate = 9600;
 *    lpuartConfig.bitCountPerChar = LPUART_8_BITS_PER_CHAR;
 *    lpuartConfig.parityMode = LPUART_PARITY_DISABLED;
 *    lpuartConfig.stopBitCount = LPUART_ONE_STOP_BIT;
 *    lpuartConfig.transferType = LPUART_USING_INTERRUPTS;
 *    lpuart_state_t lpuartState;
 *    LPUART_DRV_Init(instance, &lpuartState, &lpuartConfig);
 *
 * Implements    : LPUART_DRV_Init_Activity
 *END**************************************************************************/
status_t LPUART_DRV_Init(uint32_t instance, lpuart_state_t * lpuartStatePtr,
                         const lpuart_user_config_t * lpuartUserConfig)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(lpuartStatePtr != NULL);
    DEV_ASSERT(lpuartUserConfig != NULL);

    status_t osStatusRxSem;
    status_t osStatusTxSem;
    LPUART_Type * base = s_lpuartBase[instance];
    uint32_t idx;
    uint32_t lpuartSourceClock;
    clock_names_t instanceClkName = s_lpuartClkNames[instance];

    /* Get the LPUART clock as configured in the clock manager */
    (void)CLOCK_SYS_GetFreq(instanceClkName, &lpuartSourceClock);

    /* Check if current instance is clock gated off. */
    DEV_ASSERT(lpuartSourceClock > 0U);

    /* Check if current instance is already initialized. */
    DEV_ASSERT(s_lpuartStatePtr[instance] == NULL);

#if FEATURE_LPUART_HAS_DMA_ENABLE
    /* In DMA mode, only 8-bits chars are supported */
    DEV_ASSERT((lpuartUserConfig->transferType != LPUART_USING_DMA) ||
               (lpuartUserConfig->bitCountPerChar == LPUART_8_BITS_PER_CHAR));
#endif

    /* For 10 bits per char, parity bit cannot be enabled */
    DEV_ASSERT((lpuartUserConfig->bitCountPerChar != LPUART_10_BITS_PER_CHAR) ||
               (lpuartUserConfig->parityMode == LPUART_PARITY_DISABLED));

    /* Clear the state struct for this instance. */
    uint8_t *clearStructPtr = (uint8_t *)lpuartStatePtr;
    for (idx = 0; idx < sizeof(lpuart_state_t); idx++)
    {
        clearStructPtr[idx] = 0;
    }

    /* Save runtime structure pointer.*/
    s_lpuartStatePtr[instance] = lpuartStatePtr;

    /* Save the transfer information for runtime retrieval */
    lpuartStatePtr->transferType = lpuartUserConfig->transferType;
    lpuartStatePtr->bitCountPerChar = lpuartUserConfig->bitCountPerChar;
#if FEATURE_LPUART_HAS_DMA_ENABLE
    lpuartStatePtr->rxDMAChannel = lpuartUserConfig->rxDMAChannel;
    lpuartStatePtr->txDMAChannel = lpuartUserConfig->txDMAChannel;
#endif

    /* initialize the LPUART instance */
    LPUART_Init(base);

    /* initialize the parameters of the LPUART config structure with desired data */
    (void)LPUART_DRV_SetBaudRate(instance, lpuartUserConfig->baudRate);

    if (lpuartUserConfig->parityMode != LPUART_PARITY_DISABLED)
    {
        LPUART_SetBitCountPerChar(base, lpuartUserConfig->bitCountPerChar, true);
    }
    else
    {
        LPUART_SetBitCountPerChar(base, lpuartUserConfig->bitCountPerChar, false);
    }
    LPUART_SetParityMode(base, lpuartUserConfig->parityMode);
    LPUART_SetStopBitCount(base, lpuartUserConfig->stopBitCount);

    /* initialize last driver operation status */
    lpuartStatePtr->transmitStatus = STATUS_SUCCESS;
    lpuartStatePtr->receiveStatus = STATUS_SUCCESS;

    /* Create the synchronization objects */
    osStatusRxSem = OSIF_SemaCreate(&lpuartStatePtr->rxComplete, 0);
    osStatusTxSem = OSIF_SemaCreate(&lpuartStatePtr->txComplete, 0);
    if ((osStatusRxSem == STATUS_ERROR) || (osStatusTxSem == STATUS_ERROR))
    {
        return STATUS_ERROR;
    }

    /* Install LPUART irq handler */
    INT_SYS_InstallHandler(s_lpuartRxTxIrqId[instance], g_lpuartIsr[instance], (isr_t*) 0);

    /* Enable LPUART interrupt. */
    INT_SYS_EnableIRQ(s_lpuartRxTxIrqId[instance]);

    return STATUS_SUCCESS;
}

初始化的时候会把g_lpuartIsr[]安装进去UART,里面有对应的接收中断

/* Array storing references to LPUART irq handlers */
isr_t g_lpuartIsr[LPUART_INSTANCE_COUNT] =
{
#if (LPUART_INSTANCE_COUNT > 0U)
    LPUART0_IrqHandler,
#endif
#if (LPUART_INSTANCE_COUNT > 1U)
    LPUART1_IrqHandler,
#endif
#if (LPUART_INSTANCE_COUNT > 2U)
    LPUART2_IrqHandler,
#endif
#if (LPUART_INSTANCE_COUNT > 3U)
    LPUART3_IrqHandler,
#endif
};

譬如这个UART2中断,默认是调用LPUART_DRV_IRQHandler

/* Implementation of LPUART2 handler named in startup code. */
void LPUART2_IrqHandler(void)
{
    //LPUART_DRV_IRQHandler(2);
    DebugUart_IRQHandler();
}

LPUART_DRV_Deinit

逆初始化

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_Deinit
 * Description   : This function shuts down the UART by disabling interrupts and
 *                 transmitter/receiver.
 *
 * Implements    : LPUART_DRV_Deinit_Activity
 *END**************************************************************************/
status_t LPUART_DRV_Deinit(uint32_t instance)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);

    clock_names_t instanceClkName = s_lpuartClkNames[instance];
    uint32_t lpuartSourceClock;
    const LPUART_Type * base = s_lpuartBase[instance];
    const lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    (void)CLOCK_SYS_GetFreq(instanceClkName, &lpuartSourceClock);

    /* Check if current instance is already de-initialized or is gated.*/
    DEV_ASSERT(s_lpuartStatePtr[instance] != NULL);
    DEV_ASSERT(lpuartSourceClock > 0U);

    /* Wait until the data is completely shifted out of shift register */
    while (!LPUART_GetStatusFlag(base, LPUART_TX_COMPLETE)) {}

    /* Destroy the synchronization objects */
    (void)OSIF_SemaDestroy(&lpuartState->rxComplete);
    (void)OSIF_SemaDestroy(&lpuartState->txComplete);

    /* Disable LPUART interrupt. */
    INT_SYS_DisableIRQ(s_lpuartRxTxIrqId[instance]);

    /* Restore default handler. */
    INT_SYS_InstallHandler(s_lpuartRxTxIrqId[instance], DefaultISR, (isr_t*) 0);

    /* Clear our saved pointer to the state structure */
    s_lpuartStatePtr[instance] = NULL;

    return STATUS_SUCCESS;
}

LPUART_DRV_InstallRxCallback

安装接收到回调后进入的函数,譬如下面这个UART2收到数据之后就会进入回调函数rxCallback里面。

LPUART_DRV_InstallRxCallback(INST_LPUART2, rxCallback, NULL);

函数定义

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_InstallRxCallback
 * Description   : Install receive data callback function.
 *
 * Implements    : LPUART_DRV_InstallRxCallback_Activity
 *END**************************************************************************/
uart_callback_t LPUART_DRV_InstallRxCallback(uint32_t instance,
                                             uart_callback_t function,
                                             void * callbackParam)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);

    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    uart_callback_t currentCallback = lpuartState->rxCallback;
    lpuartState->rxCallback = function;
    lpuartState->rxCallbackParam = callbackParam;

    return currentCallback;
}

LPUART_DRV_InstallTxCallback

安装发送回调函数,也就是设定个函数,在发送数据的时候回调下,一般用不到。

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_InstallTxCallback
 * Description   : Install transmit data callback function, pass in NULL pointer
 * as callback will uninstall.
 *
 * Implements    : LPUART_DRV_InstallTxCallback_Activity
 *END**************************************************************************/
uart_callback_t LPUART_DRV_InstallTxCallback(uint32_t instance,
                                             uart_callback_t function,
                                             void * callbackParam)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);

    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    uart_callback_t currentCallback = lpuartState->txCallback;
    lpuartState->txCallback = function;
    lpuartState->txCallbackParam = callbackParam;

    return currentCallback;
}

LPUART_DRV_SendDataBlocking

使用阻塞的方式发送数据,阻塞的意思是,一直等待直到所有数据发送完毕/发送成功或超时。如果数据成功发送完毕,则返回成功状态码;若超时或其他错误发生,则返回相应的错误状态码。

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_SendDataBlocking
 * Description   : This function sends data out through the LPUART module using
 * blocking method. The function does not return until the transmit is complete.
 *
 * Implements    : LPUART_DRV_SendDataBlocking_Activity
 *END**************************************************************************/
status_t LPUART_DRV_SendDataBlocking(uint32_t instance,
                                     const uint8_t * txBuff,
                                     uint32_t txSize,
                                     uint32_t timeout)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(txBuff != NULL);

    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
    status_t retVal = STATUS_SUCCESS;
    status_t syncStatus;

    /* Indicates this is a blocking transaction. */
    lpuartState->isTxBlocking = true;

    DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
               (lpuartState->transferType == LPUART_USING_DMA));

    if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
    {
        /* Start the transmission process using interrupts */
        retVal = LPUART_DRV_StartSendDataUsingInt(instance, txBuff, txSize);
    }
#if FEATURE_LPUART_HAS_DMA_ENABLE
    else
    {
        /* Start the transmission process using DMA */
        retVal = LPUART_DRV_StartSendDataUsingDma(instance, txBuff, txSize);
    }
#endif

    if (retVal == STATUS_SUCCESS)
    {
        /* Wait until the transmit is complete. */
        syncStatus = OSIF_SemaWait(&lpuartState->txComplete, timeout);

        /* Finish the transmission if timeout expired */
        if (syncStatus == STATUS_TIMEOUT)
        {
            lpuartState->isTxBlocking = false;
            lpuartState->transmitStatus = STATUS_TIMEOUT;

            if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
            {
                LPUART_DRV_CompleteSendDataUsingInt(instance);
            }
#if FEATURE_LPUART_HAS_DMA_ENABLE
            else
            {
                LPUART_DRV_StopTxDma(instance);
            }
#endif
        }
    }

    return lpuartState->transmitStatus;
}

LPUART_DRV_SendDataPolling

轮询方式发送数据,轮询所有要发送的数据

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_SendDataPolling
 * Description   : Send out multiple bytes of data using polling method.
 *
 * Implements    : LPUART_DRV_SendDataPolling_Activity
 *END**************************************************************************/
status_t LPUART_DRV_SendDataPolling(uint32_t instance,
                                const uint8_t *txBuff,
                                uint32_t txSize)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(txBuff != NULL);

    LPUART_Type * base = s_lpuartBase[instance];
    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    /* Check the validity of the parameters */
    DEV_ASSERT(txSize > 0U);
    DEV_ASSERT((lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR) ||
               ((txSize & 1U) == 0U));

    /* Check driver is not busy transmitting data from a previous asynchronous call */
    if (lpuartState->isTxBusy)
    {
        return STATUS_BUSY;
    }

    /* Enable the LPUART transmitter */
    LPUART_SetTransmitterCmd(base, true);

    while (txSize > 0U)
    {
        while (!LPUART_GetStatusFlag(base, LPUART_TX_DATA_REG_EMPTY))
        {}

        lpuartState->txBuff = txBuff;
        LPUART_DRV_PutData(instance);

        if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
        {
            ++txBuff;
            --txSize;
        }
        else
        {
            ++txBuff;
            ++txBuff;
            txSize -= 2U;
        }
    }

    /* Disable the LPUART transmitter */
    LPUART_SetTransmitterCmd(base, false);

    return STATUS_SUCCESS;
}

LPUART_DRV_SendData

也就是纯发数据,也叫非阻塞发送,发送的时候不会等待发送完成,闭上眼就发了。

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_SendData
 * Description   : This function sends data out through the LPUART module using
 * non-blocking method. The function will return immediately after calling this
 * function.
 *
 * Implements    : LPUART_DRV_SendData_Activity
 *END**************************************************************************/
status_t LPUART_DRV_SendData(uint32_t instance,
                             const uint8_t * txBuff,
                             uint32_t txSize)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(txBuff != NULL);

    status_t retVal = STATUS_SUCCESS;
    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    /* Indicates this is a non-blocking transaction. */
    lpuartState->isTxBlocking = false;

    DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
               (lpuartState->transferType == LPUART_USING_DMA));

    if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
    {
        /* Start the transmission process using interrupts */
        retVal = LPUART_DRV_StartSendDataUsingInt(instance, txBuff, txSize);
    }
#if FEATURE_LPUART_HAS_DMA_ENABLE
    else
    {
        /* Start the transmission process using DMA */
        retVal = LPUART_DRV_StartSendDataUsingDma(instance, txBuff, txSize);
    }
#endif

    return retVal;
}

LPUART_DRV_GetTransmitStatus

在非阻塞的时候获取发送状态,在忙或者发送完成。

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_GetTransmitStatus
 * Description   : This function returns whether the previous LPUART transmit has
 * finished. When performing non-blocking transmit, the user can call this
 * function to ascertain the state of the current transmission:
 * in progress (or busy) or complete (success). In addition, if the transmission
 * is still in progress, the user can obtain the number of words that have been
 * currently transferred.
 *
 * Implements    : LPUART_DRV_GetTransmitStatus_Activity
 *END**************************************************************************/
status_t LPUART_DRV_GetTransmitStatus(uint32_t instance, uint32_t * bytesRemaining)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);

    const lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    if (bytesRemaining != NULL)
    {
        if (lpuartState->isTxBusy)
        {
            /* Fill in the bytes not transferred yet. */
            if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
            {
                /* In interrupt-based communication, the remaining bytes are retrieved
                 * from the state structure
                 */
                *bytesRemaining = lpuartState->txSize;;
            }
#if FEATURE_LPUART_HAS_DMA_ENABLE
            else
            {
                /* In DMA-based communication, the remaining bytes are retrieved
                 * from the current DMA major loop count
                 */
                *bytesRemaining = EDMA_DRV_GetRemainingMajorIterationsCount(lpuartState->txDMAChannel);
            }
#endif
        }
        else
        {
            *bytesRemaining = 0;
        }
    }

    return lpuartState->transmitStatus;
}

LPUART_DRV_AbortSendingData

中断发送数据

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_AbortSendingData
 * Description   : This function terminates an non-blocking LPUART transmission
 * early. During a non-blocking LPUART transmission, the user has the option to
 * terminate the transmission early if the transmission is still in progress.
 *
 * Implements    : LPUART_DRV_AbortSendingData_Activity
 *END**************************************************************************/
status_t LPUART_DRV_AbortSendingData(uint32_t instance)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);

    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    /* Check if a transfer is running. */
    if (!lpuartState->isTxBusy)
    {
        return STATUS_SUCCESS;
    }

    /* Update the tx status */
    lpuartState->transmitStatus = STATUS_UART_ABORTED;

    /* Stop the running transfer. */
    if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
    {
        LPUART_DRV_CompleteSendDataUsingInt(instance);
    }
#if FEATURE_LPUART_HAS_DMA_ENABLE
    else
    {
        LPUART_DRV_StopTxDma(instance);
    }
#endif

    return STATUS_SUCCESS;
}

LPUART_DRV_ReceiveDataBlocking

阻塞模式接收数据,一直等待接收完毕。

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_ReceiveDataBlocking
 * Description   : This function receives data from LPUART module using blocking
 * method, the function does not return until the receive is complete.
 *
 * Implements    : LPUART_DRV_ReceiveDataBlocking_Activity
 *END**************************************************************************/
status_t LPUART_DRV_ReceiveDataBlocking(uint32_t instance,
                                        uint8_t * rxBuff,
                                        uint32_t rxSize,
                                        uint32_t timeout)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(rxBuff != NULL);

    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
    status_t retVal = STATUS_SUCCESS;
    status_t syncStatus;

    /* Indicates this is a blocking transaction. */
    lpuartState->isRxBlocking = true;

    DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
               (lpuartState->transferType == LPUART_USING_DMA));

    if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
    {
         /* Start the reception process using interrupts */
         retVal = LPUART_DRV_StartReceiveDataUsingInt(instance, rxBuff, rxSize);
    }
#if FEATURE_LPUART_HAS_DMA_ENABLE
    else
    {
        /* Start the reception process using DMA */
        retVal = LPUART_DRV_StartReceiveDataUsingDma(instance, rxBuff, rxSize);
    }
#endif

    if (retVal == STATUS_SUCCESS)
    {
        /* Wait until the receive is complete. */
        syncStatus = OSIF_SemaWait(&lpuartState->rxComplete, timeout);

        /* Finish the reception if timeout expired */
        if (syncStatus == STATUS_TIMEOUT)
        {
            lpuartState->isRxBlocking = false;
            lpuartState->receiveStatus = STATUS_TIMEOUT;

            if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
            {
                LPUART_DRV_CompleteReceiveDataUsingInt(instance);
            }
#if FEATURE_LPUART_HAS_DMA_ENABLE
            else
            {
                LPUART_DRV_StopRxDma(instance);
            }
#endif
        }
    }

    return lpuartState->receiveStatus;
}

LPUART_DRV_ReceiveDataPolling

轮询模式接收数据

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_ReceiveDataPolling
 * Description   : Receive multiple bytes of data using polling method.
 *
 * Implements    : LPUART_DRV_ReceiveDataPolling_Activity
 *END**************************************************************************/
status_t LPUART_DRV_ReceiveDataPolling(uint32_t instance,
                                       uint8_t *rxBuff,
                                       uint32_t rxSize)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(rxBuff != NULL);

    uint8_t tmpByte;
    status_t retVal = STATUS_SUCCESS;
    status_t tmpState = STATUS_SUCCESS;
    LPUART_Type * base = s_lpuartBase[instance];
    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    /* Check the validity of the parameters */
    DEV_ASSERT(rxSize > 0U);
    DEV_ASSERT((lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR) ||
               ((rxSize & 1U) == 0U));

    /* Check driver is not busy receiving data from a previous asynchronous call */
    if (lpuartState->isRxBusy)
    {
        return STATUS_BUSY;
    }

    /* Enable the LPUART receiver */
    LPUART_SetReceiverCmd((LPUART_Type *)base, true);

    while (rxSize > 0U)
    {
        while (!LPUART_GetStatusFlag(base, LPUART_RX_DATA_REG_FULL))
        {}

        lpuartState->rxBuff = rxBuff;
        LPUART_DRV_GetData(instance);

        if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
        {
            ++rxBuff;
            --rxSize;
        }
        else
        {
            ++rxBuff;
            ++rxBuff;
            rxSize -= 2U;
        }

        /* Check for errors on received data */
        if (LPUART_GetStatusFlag(base, LPUART_FRAME_ERR))
        {
            tmpState = STATUS_UART_FRAMING_ERROR;
            /* Disable the LPUART receiver */
            LPUART_SetReceiverCmd((LPUART_Type *)base, false);
            /* Clear the flag */
            (void)LPUART_ClearStatusFlag(base, LPUART_FRAME_ERR);
            break;
        }
        else if (LPUART_GetStatusFlag(base, LPUART_NOISE_DETECT))
        {
            tmpState = STATUS_UART_NOISE_ERROR;
            /* Disable the LPUART receiver */
            LPUART_SetReceiverCmd((LPUART_Type *)base, false);
            /* Clear the flag */
            (void)LPUART_ClearStatusFlag(base, LPUART_NOISE_DETECT);
            break;
        }
        else if (LPUART_GetStatusFlag(base, LPUART_PARITY_ERR))
        {
            tmpState = STATUS_UART_PARITY_ERROR;
            /* Disable the LPUART receiver */
            LPUART_SetReceiverCmd((LPUART_Type *)base, false);
            /* Clear the flag */
            (void)LPUART_ClearStatusFlag(base, LPUART_PARITY_ERR);
            break;
        }
        else if (LPUART_GetStatusFlag(base, LPUART_RX_OVERRUN))
        {
            tmpState = STATUS_UART_RX_OVERRUN;
            /* Disable the LPUART receiver */
            LPUART_SetReceiverCmd((LPUART_Type *)base, false);
            /* Clear the flag */
            (void)LPUART_ClearStatusFlag(base, LPUART_RX_OVERRUN);
            break;
        }
        else
        {
            /* No error condition - avoid MISRA violation */
        }
    }

    /* Update received status */
    if ((rxSize == 0U) && (tmpState == STATUS_UART_RX_OVERRUN))
    {
        retVal = STATUS_SUCCESS;
    }
    else
    {
        retVal = tmpState;
    }

    if (retVal == STATUS_SUCCESS)
    {
        /* Disable the LPUART receiver */
        LPUART_SetReceiverCmd((LPUART_Type *)base, false);
    }

    /* Read dummy to clear RDRF flag */
    LPUART_Getchar(base, &tmpByte);

    return retVal;
}

LPUART_DRV_ReceiveData

纯接收数据

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_ReceiveData
 * Description   : This function receives data from LPUART module using
 * non-blocking method.  This function returns immediately after initiating the
 * receive function. The application has to get the receive status to see when
 * the receive is complete. In other words, after calling non-blocking get
 * function, the application must get the receive status to check if receive
 * is completed or not.
 *
 * Implements    : LPUART_DRV_ReceiveData_Activity
 *END**************************************************************************/
status_t LPUART_DRV_ReceiveData(uint32_t instance,
                                uint8_t * rxBuff,
                                uint32_t rxSize)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(rxBuff != NULL);

    status_t retVal = STATUS_SUCCESS;
    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    /* Indicates this is a non-blocking transaction. */
    lpuartState->isRxBlocking = false;

    DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
               (lpuartState->transferType == LPUART_USING_DMA));

    if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
    {
        /* Start the reception process using interrupts */
        retVal = LPUART_DRV_StartReceiveDataUsingInt(instance, rxBuff, rxSize);
    }
#if FEATURE_LPUART_HAS_DMA_ENABLE
    else
    {
        /* Start the reception process using DMA */
        retVal = LPUART_DRV_StartReceiveDataUsingDma(instance, rxBuff, rxSize);
    }
#endif

    return retVal;
}

LPUART_DRV_GetReceiveStatus

获取接收状态,正在接收还是接收完成。

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_GetReceiveStatus
 * Description   : This function returns whether the previous LPUART receive is
 * complete. When performing a non-blocking receive, the user can call this
 * function to ascertain the state of the current receive progress: in progress
 * or complete. In addition, if the receive is still in progress, the user can
 * obtain the number of words that have been currently received.
 *
 * Implements    : LPUART_DRV_GetReceiveStatus_Activity
 *END**************************************************************************/
status_t LPUART_DRV_GetReceiveStatus(uint32_t instance,
                                     uint32_t * bytesRemaining)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);

    const lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    if (bytesRemaining != NULL)
    {
        if (lpuartState->isRxBusy)
        {
            /* Fill in the bytes transferred. */
            if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
            {
                /* In interrupt-based communication, the remaining bytes are retrieved
                 * from the state structure
                 */
                *bytesRemaining = lpuartState->rxSize;
            }
#if FEATURE_LPUART_HAS_DMA_ENABLE
            else
            {
                /* In DMA-based communication, the remaining bytes are retrieved
                 * from the current DMA major loop count
                 */
                *bytesRemaining = EDMA_DRV_GetRemainingMajorIterationsCount(lpuartState->rxDMAChannel);
            }
#endif
        }
        else
        {
            *bytesRemaining = 0;
        }
    }

    return lpuartState->receiveStatus;
}

LPUART_DRV_AbortReceivingData

终止接收数据

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_AbortReceivingData
 * Description   : Terminates a non-blocking receive early.
 *
 * Implements    : LPUART_DRV_AbortReceivingData_Activity
 *END**************************************************************************/
status_t LPUART_DRV_AbortReceivingData(uint32_t instance)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);

    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    /* Check if a transfer is running. */
    if (!lpuartState->isRxBusy)
    {
        return STATUS_SUCCESS;
    }

    /* Update the rx status */
    lpuartState->receiveStatus = STATUS_UART_ABORTED;

    /* Stop the running transfer. */
    if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
    {
        LPUART_DRV_CompleteReceiveDataUsingInt(instance);
    }
#if FEATURE_LPUART_HAS_DMA_ENABLE
    else
    {
        LPUART_DRV_StopRxDma(instance);
    }
#endif

    return STATUS_SUCCESS;
}

LPUART_DRV_SetBaudRate

设置波特率

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_SetBaudRate
 * Description   : Configures the LPUART baud rate.
 * In some LPUART instances the user must disable the transmitter/receiver
 * before calling this function.
 * Generally, this may be applied to all LPUARTs to ensure safe operation.
 *
 * Implements    : LPUART_DRV_SetBaudRate_Activity
 *END**************************************************************************/
status_t LPUART_DRV_SetBaudRate(uint32_t instance, uint32_t desiredBaudRate)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);

    uint16_t sbr, sbrTemp, i;
    uint32_t osr, tempDiff, calculatedBaud, baudDiff;
    uint32_t lpuartSourceClock;
    clock_names_t instanceClkName = s_lpuartClkNames[instance];
    LPUART_Type * base = s_lpuartBase[instance];
    const lpuart_state_t * lpuartState;
    lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];

    if (lpuartState != NULL)
    {
        /* Check if there is an ongoing transfer */
        if (lpuartState->isTxBusy == true)
        {
            return STATUS_BUSY;
        }
        if (lpuartState->isRxBusy == true)
        {
            return STATUS_BUSY;
        }
    }

    /* Get the LPUART clock as configured in the clock manager */
    (void)CLOCK_SYS_GetFreq(instanceClkName, &lpuartSourceClock);

    /* Check if current instance is clock gated off. */
    DEV_ASSERT(lpuartSourceClock > 0U);
    /* Check if the desired baud rate can be configured with the current protocol clock. */
    DEV_ASSERT(lpuartSourceClock >= (desiredBaudRate * 4U));

    /* This lpuart instantiation uses a slightly different baud rate calculation
     * The idea is to use the best OSR (over-sampling rate) possible
     * Note, osr is typically hard-set to 16 in other lpuart instantiations
     * First calculate the baud rate using the minimum OSR possible (4) */
    osr = 4;
    sbr = (uint16_t)(lpuartSourceClock / (desiredBaudRate * osr));
    calculatedBaud = (lpuartSourceClock / (osr * sbr));

    if (calculatedBaud > desiredBaudRate)
    {
        baudDiff = calculatedBaud - desiredBaudRate;
    }
    else
    {
        baudDiff = desiredBaudRate - calculatedBaud;
    }

    /* loop to find the best osr value possible, one that generates minimum baudDiff
     * iterate through the rest of the supported values of osr */
    for (i = 5U; i <= 32U; i++)
    {
        /* calculate the temporary sbr value   */
        sbrTemp = (uint16_t)(lpuartSourceClock / (desiredBaudRate * i));
        /* calculate the baud rate based on the temporary osr and sbr values */
        calculatedBaud = (lpuartSourceClock / (i * sbrTemp));

        if (calculatedBaud > desiredBaudRate)
        {
            tempDiff = calculatedBaud - desiredBaudRate;
        }
        else
        {
            tempDiff = desiredBaudRate - calculatedBaud;
        }

        if (tempDiff <= baudDiff)
        {
            baudDiff = tempDiff;
            osr = i;  /* update and store the best osr value calculated */
            sbr = sbrTemp;  /* update store the best sbr value calculated */
        }
    }

    /* Check if osr is between 4x and 7x oversampling.
     * If so, then "BOTHEDGE" sampling must be turned on */
    if (osr < 8U)
    {
    	LPUART_EnableBothEdgeSamplingCmd(base);
    }

    /* program the osr value (bit value is one less than actual value) */
    LPUART_SetOversamplingRatio(base, (osr - 1U));

    /* write the sbr value to the BAUD registers */
    LPUART_SetBaudRateDivisor(base, sbr);

    return STATUS_SUCCESS;
}

LPUART_DRV_GetBaudRate

获取波特率

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_GetBaudRate
 * Description   : Returns the LPUART configured baud rate.
 *
 * Implements    : LPUART_DRV_GetBaudRate_Activity
 *END**************************************************************************/
void LPUART_DRV_GetBaudRate(uint32_t instance, uint32_t * configuredBaudRate)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(configuredBaudRate != NULL);

    uint8_t osr;
    uint16_t sbr;
    uint32_t lpuartSourceClock;
    clock_names_t instanceClkName = s_lpuartClkNames[instance];
    const LPUART_Type * base = s_lpuartBase[instance];

    /* Get the LPUART clock as configured in the clock manager */
    (void)CLOCK_SYS_GetFreq(instanceClkName, &lpuartSourceClock);

    osr = LPUART_GetOversamplingRatio(base);
    sbr = LPUART_GetBaudRateDivisor(base);

    *configuredBaudRate = (lpuartSourceClock / ((osr + 1UL) * sbr));
}

LPUART_DRV_SetTxBuffer

设置发送缓冲区

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_SetTxBuffer
 * Description   : Sets the driver internal reference to the tx buffer.
 *                 Can be called from the tx callback to provide a different
 *                 buffer for continuous transmission.
 *
 * Implements    : LPUART_DRV_SetTxBuffer_Activity
 *END**************************************************************************/
status_t LPUART_DRV_SetTxBuffer(uint32_t instance,
                                const uint8_t * txBuff,
                                uint32_t txSize)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(txBuff != NULL);
    DEV_ASSERT(txSize > 0U);

    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
    lpuartState->txBuff = txBuff;
    lpuartState->txSize = txSize;

    return STATUS_SUCCESS;
}

LPUART_DRV_SetRxBuffer

将接收到的数据放入接收缓冲区,也就是接收buffer。一般在接收回调函数里面执行该函数。

/*FUNCTION**********************************************************************
 *
 * Function Name : LPUART_DRV_SetRxBuffer
 * Description   : Sets the driver internal reference to the rx buffer.
 *                 Can be called from the rx callback to provide a different
 *                 buffer for continuous reception.
 *
 * Implements    : LPUART_DRV_SetRxBuffer_Activity
 *END**************************************************************************/
status_t LPUART_DRV_SetRxBuffer(uint32_t instance,
                                uint8_t * rxBuff,
                                uint32_t rxSize)
{
    DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
    DEV_ASSERT(rxBuff != NULL);
    DEV_ASSERT(rxSize > 0U);

    lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
    lpuartState->rxBuff = rxBuff;
    lpuartState->rxSize = rxSize;

    return STATUS_SUCCESS;
}

一般用法

初始化使用下面几步,初始化,允许发送,安装接收回调函数,设置将接收到的数据放到buffer。

 void DebugUart_Init(void)
 {
	LPUART_DRV_Init(INST_LPUART2, &lpuart2_State, &lpuart2_InitConfig0);

	LPUART_SetTransmitterCmd(LPUART2, true);

	/* Install the callback for rx events */
 	LPUART_DRV_InstallRxCallback(INST_LPUART2, rxCallback, NULL);

 	LPUART_DRV_ReceiveData(INST_LPUART2, &rxdata, 1UL);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃鱼的羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值