其实这是最简单最好用的外设啦,库函数给了很多方法,但是我不太喜欢,主要是功能上有些迷人,也不太耐优化,啃吃了一会手册,自己写了个.
首先官方提供那么几个例子:
- 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,真是奇怪.