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/n/334687.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
CQMAGCQMAG
上一篇 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

发表回复

登录后才能评论