LPUART串口詳解

LPUART是低功耗UART,它是Kinetis系列晶元(單片機)所支持的新型UART。與傳統的UART不同的是,它可以在不同的低功耗模式下操作,同時支持更高的波特率。本文將會從以下幾個方面對LPUART串口進行詳細闡述。

一、LPUART基礎介紹

LPUART是一種帶有衝突檢測特性的USART,主要用於處理非同步串列通信。LPUART與傳統的UART類似,但是它支持更高的波特率,並且可以在低功耗模式下工作,這使得它非常適合用於那些對功耗要求較高的應用場合。在Kinetis系列晶元中,LPUART是內置的,同時也支持多個串口通信。LPUART的特點包括:

  • 支持非同步通信,包括8位和9位數據位模式
  • 支持可編程波特率發生器,可以支持幾乎任何波特率
  • 支持單個起始位或兩個起始位模式
  • 支持奇偶校驗和無校驗模式
  • 支持支持多種中斷模式和DMA傳輸模式

下面是LPUART的初始化函數,其中包含了LPUART的基本配置。

void LPUART_Init(LPUART_Type* base, const lpuart_config_t* config, uint32_t srcClock_Hz)
{
    assert(config != NULL);

    uint32_t baudRate_Bps;
    uint32_t osr, sbr;

    if ((config->parityMode == kLPUART_ParityDisabled) && (config->stopBitCount == kLPUART_OneStopBit) && (config->bitCountPerChar == kLPUART_EightBitsPerChar))
    {
        /* Calculate baudrate */
        baudRate_Bps = config->baudRate_Bps;

        /* Get the OSR value */
        osr = (((base->BAUD & LPUART_BAUD_OSR_MASK) >> LPUART_BAUD_OSR_SHIFT) + 1U);

        /* Calculate the sbr value using OSR and baud rate */
        sbr = (srcClock_Hz / (baudRate_Bps * osr));
        base->BAUD = LPUART_BAUD_OSR(osr - 1U) | LPUART_BAUD_SBR(sbr);
    }
    else
    {
        /* Configure parity/sb/char */
        base->CTRL = (base->CTRL & ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK)) | LPUART_CTRL_PE((config->parityMode != kLPUART_ParityDisabled ? 1UL : 0UL)) | LPUART_CTRL_PT((config->parityMode == kLPUART_ParityOdd ? 1UL : 0UL)) | LPUART_CTRL_M((config->bitCountPerChar == kLPUART_EightBitsPerChar ? 0UL : 1UL));

        /* Calculate baud rate */
        baudRate_Bps = config->baudRate_Bps;

        /* Calculate sbr */
        sbr = srcClock_Hz / (baudRate_Bps * ((base->BAUD & LPUART_BAUD_OSR_MASK) + 1U));
        base->BAUD = LPUART_BAUD_SBR(sbr);
    }
}

二、LPUART中斷使用

LPUART可以使用中斷來實現數據接收和發送的非同步操作。為了實現中斷操作,需要開啟LPUART的中斷使能,並且配置中斷處理函數。對於接收中斷,需要配置相應的中斷觸發條件,例如接收緩衝區非空時觸發中斷。當中斷觸發時,中斷處理函數會自動被調用,從而執行相應的接收或發送操作。下面是一個LPUART的中斷髮送和接收函數的例子:

void LPUART_TransferCreateHandle(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_callback_t callback, void *userData)
{
    uint32_t instance;

    /* Zero the handle. */
    memset(handle, 0, sizeof(*handle));

    /* Get the instance number */
    instance = LPUART_GetInstance(base);

    /* Save LPUART base and context used in IRQ handler */
    s_lpuartBases[instance] = base;
    s_lpuartHandle[instance] = handle;

    /* Enable interrupt in NVIC. */
    EnableIRQ(s_lpuartIRQ[instance]);

    /* Save callback and user data. */
    handle->callback = callback;
    handle->userData = userData;
}

三、LPUART DMA使用

LPUART還可以使用DMA來實現數據的接收和發送。DMA可以大大減小CPU的負載,同時也可以提高數據傳輸的效率。為了使用DMA來實現LPUART的數據傳輸,需要重新配置DMA模塊的通道、配置DMA傳輸模式以及DMA中斷處理函數等。下面是一個LPUART的DMA發送和接收函數的例子:

static void LPUART_TransferCompleteSendDMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
{
    lpuart_dma_handle_t *lpuartHandle = (lpuart_dma_handle_t *)userData;

    /* Disable LPUART TX DMA. */
    LPUART_TransferAbortSendDMA(lpuartHandle->base, lpuartHandle);

    /* Invoke callback. */
    if (lpuartHandle->callback)
    {
        lpuartHandle->callback(lpuartHandle, kStatus_LPUART_TxIdle, lpuartHandle->userData);
    }
}

四、LPUART應用實例

LPUART可以在多種應用場合中使用,例如醫療、智能家居、工業控制等領域。下面是一個LPUART應用的例子,該例子演示如何使用LPUART來實現兩種不同的數據傳輸方式。其中一種是通過中斷實現,另一種是通過DMA實現。

#include "fsl_lpuart.h"
#include "fsl_debug_console.h"
#include "board.h"

#include "fsl_dma.h"
#include "fsl_dmamux.h"
#include "fsl_common.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define DEMO_USART USART0
#define DEMO_USART_CLK_SRC kCLOCK_MainClk
#define DEMO_USART_CLK_FREQ CLOCK_GetFreq(kCLOCK_MainClk)
#define EXAMPLE_UART UART0
#define USART_IRQHandler FLEXCOMM0_IRQHandler
#define USART_IRQ FLEXCOMM0_IRQn

#define LPUART_DMA_DMAMUX_BASEADDR DMAMUX
#define LPUART_DMA_BASEADDR DMA0
#define LPUART_TX_DMA_CHANNEL 0U
#define LPUART_RX_DMA_CHANNEL 1U
#define LPUART_TX_DMA_REQUEST kDmaRequestMuxLPUART0Tx
#define LPUART_RX_DMA_REQUEST kDmaRequestMuxLPUART0Rx
#define LPUART_DMA_TX_COMPLETE_IRQn DMA0_Channel0_IRQn
#define LPUART_DMA_RX_COMPLETE_IRQn DMA0_Channel1_IRQn
#define LPUART_DMA_TX_COMPLETE_HANDLER DMA0_Channel0_IRQHandler
#define LPUART_DMA_RX_COMPLETE_HANDLER DMA0_Channel1_IRQHandler

typedef enum _lpuart_dma_mode
{
kLPUART_UartPolling, /*!< LPUART polling operation mode */
kLPUART_UartInterrupt, /*!< LPUART interrupt operation mode */
kLPUART_UartDma /*!< LPUART DMA operation mode */
} lpuart_dma_mode_t;

/*******************************************************************************
* Prototypes
******************************************************************************/

/*******************************************************************************
* Variables
******************************************************************************/
AT_NONCACHEABLE_SECTION_INIT(static uint8_t g_tipString[]) = "LPUART DMA example\r\nSend back received data.\r\n";
static lpuart_dma_mode_t s_dmaMode; /*!< LPUART DMA mode. */
static lpuart_transfer_t s_sendXfer; /* LPUART send data structure */
static lpuart_transfer_t s_receiveXfer; /* LPUART receive data structure */
static lpuart_handle_t s_lpuartHandle; /*!< Handler for LPUART driver */
static volatile bool s_lpuartTxIdle = false; /*!< LPUART transfer completed flag. */
static volatile bool s_lpuartRxIdle = false; /*!DATA, s_bufferLpuart, 1, sizeof(uint8_t), kDMA_PeripheralToMemory);
DMA_SubmitTransfer(&s_rxHandle);
DMA_StartTransfer(&s_rxHandle);
s_lpuartRxCompleteCount++;
}

void LPUART_DMA_TX_COMPLETE_HANDLER(void)
{
s_lpuartTxIdle = true;
s_lpuartTxCompleteCount++;
}

void LPUART_DmaUserCallback(LPUART_Type *base, lpuart_dma_handle_t *handle, status_t status, void *userData)
{
if (kStatus_LPUART_TxIdle == status)
{
s_lpuartTxIdle = true;
}

if (kStatus_LPUART_RxIdle == status)
{
s_lpuartRxIdle = true;
}
}

void LPUART_SendDataBlocking(LPUART_Type *base, const uint8_t *data, size_t length)
{
size_t i = 0;

while (i STAT & LPUART_STAT_TDRE_MASK))
{
}
base->DATA = data[i++];
}
}

status_t LPUART_RecvDataBlocking(LPUART_Type *base, uint8_t *data, size_t length)
{
size_t i = 0;

while (i STAT & LPUART_STAT_RDRF_MASK))
{
}
data[i++] = base->DATA;
}

return kStatus_Success;
}

void LPUART_TransferInit(LPUART_Type *base, lpuart_dma_handle_t *handle, lpuart_dma_mode_t mode, uint8_t *ringBuffer,
uint32_t ringBufferSize)
{
lpuart_transfer_t xfer;

memset(handle, 0, sizeof(*handle));
handle->dmaHandle = &s_txHandle;
handle->ringBuffer = ringBuffer;
handle->rxRingBufferIndex = 0;
handle->rxRingBufferSize = ringBufferSize;

switch (mode)
{
case kLPUART_UartDma:
LPUART_TransferCreateHandleDMA(base, handle, LPUART_DmaUserCallback, NULL, &s_dmamuxRxHandle, &s_dmamuxTxHandle);
handle->mode = kLPUART_UartDma;
break;
case kLPUART_UartInterrupt:
LPUART_TransferCreateHandle(base, handle, LPUART_UserCallback, NULL);
NVIC_SetPriority(DEMO_USART_IRQ, 2U);
handle->mode = kLPUART_UartInterrupt;
break;
case kLPUART_UartPolling:
xfer.data = handle->ringBuffer;
xfer.dataSize = 1;
LPUART_TransferSendNonBlocking(base, &s_sendXfer);
handle->mode = kLPUART_UartPolling;
break;
default:
break;
}
}

void DEMO_LPUART_Transfer(void)
{
lpuart_config_t config;
uint32_t srcClock_Hz;
s_lpuartTxIdle = false;
s_lpuartRxIdle = false;

/*
* config.baudRate_Bps = 115200U;

原創文章,作者:CQMAG,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/334687.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
CQMAG的頭像CQMAG
上一篇 2025-02-05 13:05
下一篇 2025-02-05 13:05

相關推薦

  • Python調用串口用法介紹

    本文將從以下幾個方面詳細闡述如何使用Python調用串口進行數據傳輸。 一、Python調用串口的基本知識 在使用Python調用串口之前,需要了解串口的相關知識。 串口是計算機與…

    編程 2025-04-27
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25
  • 神經網路代碼詳解

    神經網路作為一種人工智慧技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網路的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網路模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web伺服器。nginx是一個高性能的反向代理web伺服器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性感測器,能夠同時測量加速度和角速度。它由三個感測器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變數讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25

發表回復

登錄後才能評論