其实这是最简单最好用的外设啦,库函数给了很多方法,但是我不太喜欢,主要是功能上有些迷人,也不太耐优化,啃吃了一会手册,自己写了个.
首先官方提供那么几个例子:
- polling 轮询
- polling_seven_bits 轮询(7位)
- interrupt 自己实现中断传输
- interrupt_transfer 中断传输(非阻塞,回调方式)
- interrupt_rb_transfer 中断传输(非阻塞,环形缓冲)
- interrupt_transfer_seven_bits 中断传输(非阻塞,回调方式)
- edma_transfer DMA传输(数据量少并不划算)
我实测下,官方的历程均没使用FIFO,简直暴殄天物,而且DMA在数据量较少(比如几百字节)时候还不如FIFO + Interrupt方法呢.所以我自己也了个中断 + FIFO方法.实测TX FIFO为0,依然可以做到连续发送,说明硬件上取出数据后立马就减FIFO threshold,还是不错的.
代码参考:https://gist.github.com/nickfox-taterli/50d2b38319662967fee7eed16933b0e4
#include "board.h"
#include "fsl_lpuart.h"
#include "pin_mux.h"
#include "clock_config.h"
uint8_t txData[] = "Hello,World!";
uint8_t rxData[512];
typedef struct
{
uint8_t *txData;
uint16_t txIndex;
uint16_t txLength;
uint8_t *rxData;
uint16_t rxIndex;
uint16_t rxLength;
} LPUART_DataHandler;
LPUART_DataHandler LPUART1_DataHandler;
void LPUART1_IRQHandler(void)
{
uint8_t count;
if ((kLPUART_TxDataRegEmptyFlag)&LPUART_GetStatusFlags(LPUART1))
{
if (LPUART1_DataHandler.txLength == LPUART1_DataHandler.txIndex)
{
LPUART_DisableInterrupts(LPUART1, kLPUART_TxDataRegEmptyInterruptEnable);
// 全部发送完毕,可以通知用户处理.
__BKPT(0);
}
for (count = 0;
count < MIN(4 - ((LPUART1->WATER >> 8U) & 0x07), LPUART1_DataHandler.txLength - LPUART1_DataHandler.txIndex);
count++)
{
LPUART1->DATA = LPUART1_DataHandler.txData[LPUART1_DataHandler.txIndex++];
}
}
if ((kLPUART_RxDataRegFullFlag)&LPUART_GetStatusFlags(LPUART1))
{
for (count = 0;
count < ((LPUART1->WATER >> 24U) & 0x07) + 1;
count++)
{
LPUART1_DataHandler.rxData[LPUART1_DataHandler.rxIndex] = LPUART1->DATA;
LPUART1_DataHandler.rxIndex++;
LPUART1_DataHandler.rxLength++;
}
}
if ((kLPUART_IdleLineFlag)&LPUART_GetStatusFlags(LPUART1))
{
for (count = 0;
count < ((LPUART1->WATER >> 24U) & 0x07) + 1;
count++)
{
LPUART1_DataHandler.rxData[LPUART1_DataHandler.rxIndex] = LPUART1->DATA;
LPUART1_DataHandler.rxIndex++;
LPUART1_DataHandler.rxLength++;
}
LPUART1_DataHandler.rxIndex = 0;
LPUART_ClearStatusFlags(LPUART1, kLPUART_IdleLineFlag);
// 全部接收完成,可以通知用戶处理.
__BKPT(0);
}
}
void LPUART1_Send(uint8_t *xfer, uint8_t len)
{
LPUART1_DataHandler.txData = xfer;
LPUART1_DataHandler.txIndex = 0;
LPUART1_DataHandler.txLength = len;
LPUART_EnableInterrupts(LPUART1, kLPUART_TxDataRegEmptyInterruptEnable);
}
int main(void)
{
lpuart_config_t config;
BOARD_ConfigMPU();
BOARD_InitPins();
BOARD_BootClockRUN();
LPUART_GetDefaultConfig(&config);
config.baudRate_Bps = 115200U;
config.parityMode = kLPUART_ParityDisabled;
config.stopBitCount = kLPUART_OneStopBit;
config.rxFifoWatermark = 0;
config.rxFifoWatermark = 3;
config.enableTx = true;
config.enableRx = true;
LPUART_Init(LPUART1, &config, BOARD_DebugConsoleSrcFreq());
LPUART1_DataHandler.rxData = rxData;
LPUART_EnableInterrupts(LPUART1, kLPUART_RxDataRegFullInterruptEnable);
LPUART_EnableInterrupts(LPUART1, kLPUART_IdleLineInterruptEnable);
EnableIRQ(LPUART1_IRQn);
LPUART1_Send(txData, strlen((const char *)txData));
while (1)
{
}
}
在IMX1010 EVK上实测,官方库函数DMA在370字节左右开始,才能拼得上我这个简易程序的速度,当然,官方是考虑更周详,所以也有轻微的牺牲,只是奇怪的是,竟然没用上FIFO,真是奇怪.