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_IRQHandlertypedef 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