赞
踩
uart的时钟路径
管理串口时钟的寄存器CCM_CSCDR1.
在此寄存器中我们可以设置UART_CLK_ROOT的时钟
上图中,第六位UART_CLK_SEL一般设置为0,即选择pll3_80m
而UART_CLK_PODF则为一个6位的分频器,将80MHz的频率分频作为UART_CLK_ROOT
一般设置为1分频,所以UART_CLK_ROOT=80MHz
lpuart1_ipg_clk 时钟,这是串口 1 的外设时钟,用于驱动串口 1 的正常运行(除波特率发生器以外的时钟,都由该时钟驱动),该时钟来自 IPG_CLK_ROOT,由 CCGR5[CG12]控制。
lpuart1_ipg_clk_s 时钟,这是串口 1 的访问时钟,必须开启该时钟,才可以访问串口 1 相关寄存器,该时钟来自 IPG_CLK_ROOT,由 CCGR5[CG12]控制。
lpuart1_lpuart_baud_clk 时钟,这是串口 1 波特率发生器的时钟源,来自:UART_CLK_ROOT,可以把它看作是 lpuart1_lpuart_baud_gateed_clk 时钟的上一级,它无需开关控制。
lpuart1_lpuart_baud_gateed_clk 时钟,这是串口 1 波特率发生器的时钟,该时钟同样是来自:UART_CLK_ROOT,串口 1 的波特率生成和这个时钟直接相关,由 CCGR5[CG12]控制。
1.时钟使能
需要使能3个时钟,lpuart1_ipg_clk、lpuart1_ipg_clk_s 、lpuart1_lpuart_baud_gateed_clk 这三个时钟均由CCGR5[CG12]控制
设置这两位为1
2.串口波特率设置
串口波特率设置。每个串口都有一个自己独立的波特率寄存器 BAUD,通过设置该寄存器就可以达到配置不同波特率的目的。
3.串口设置
LPUART Control Register (CTRL)
RIE 位(位 21)为接收中断使能位,设置该位为 1,则当 STAT 寄存器的 RDRF 位(接收数据寄存器满标志)为 1 时,将产生串口中断;
TE 位(位 19)为串口发送使能位,设置该位为 1,则开启串口发送功能;
RE 位(位 18)为串口接收使能位,设置该位为 1,则开启串口接收功能;
M 位(位 4)为 9/8 位模式选择位,设置该位为 0,则使用 8 位数据模式;
PE 位(位 1)为校验使能位,设置该位为 0,则不使用硬件奇偶校验。
4.数据接收和发送
LPUART Data Register (DATA)
当我们需要发送数据的时候,往 LPUARTx→DATA(x=1~8)寄存器写入你想要发送的数据,然后加载到 Tx Buffer,通过串口发送出去。
而当有串口数据接收到,需要读取出来的时候,通过读取 LPUARTx→DATA 寄存器,即可读取 Rx Buffer,将数据读取出来。
这里 Rx/Tx Buffer实际上上就是 RX/TX FIFO,因为我们没设置 FIFO,默认 Rx/Tx Buffer 就是 1 个字符。
5.串口状态
LPUART Status Register (STAT)
21位:RDRF(接收数据寄存器满标志),当该位被置 1 的时候,就是提示已经有数据被接收到了(存放在 Rx Buffer),并且可以读出来了。这时候我们要做的就是尽快去读取 LPUARTx→DATA,通过读 LPUARTx→DATA 可以将该位清零。
23位:TDRE(发送数据寄存器空标志),当该位被置位的时候,表示 Tx Buffer 里面的数据已经被发送完成了。如果设置了这个位的中断,则会产生中断。通过往 LPUARTx→DATA 寄存器写入数据可以将该位清零。
在fsl_lpuart.c 和 fsl_lpuart.h 中
status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz)
base:LPUART1~LPUART8。
config 用来设置串口的初始化参数
lpuart_config_t 定义如下:
typedef struct _lpuart_config { uint32_t baudRate_Bps; /*!< LPUART baud rate 波特率*/ lpuart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd 奇偶校验*/ lpuart_data_bits_t dataBitsCount; /*!< Data bits count, eight (default), seven 数据长度*/ bool isMsb; /*!< Data bits order, LSB (default), MSB 是否为MSB*/ #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT lpuart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits 停止位 */ #endif #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO uint8_t txFifoWatermark; /*!< TX FIFO watermark */ uint8_t rxFifoWatermark; /*!< RX FIFO watermark */ #endif #if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT bool enableRxRTS; /*!< RX RTS enable 接收RTS*/ bool enableTxCTS; /*!< TX CTS enable 发送RTS*/ lpuart_transmit_cts_source_t txCtsSource; /*!< TX CTS source */ lpuart_transmit_cts_config_t txCtsConfig; /*!< TX CTS configure */ #endif lpuart_idle_type_select_t rxIdleType; /*!< RX IDLE type. */ lpuart_idle_config_t rxIdleConfig; /*!< RX IDLE configuration. */ bool enableTx; /*!< Enable TX 使能发送*/ bool enableRx; /*!< Enable RX 使能接收*/ } lpuart_config_t;
baudRate_Bps 用来设置串口波特率。
parityMode 用来设置校验模式
typedef enum _lpuart_parity_mode
{
kLPUART_ParityDisabled = 0x0U, //无奇偶校验
kLPUART_ParityEven = 0x2U, //偶校验
kLPUART_ParityOdd = 0x3U, //奇校验
} lpuart_parity_mode_t;
dataBitsCount 用来设置数据数据长度,可以设置为 8 位数据或者 7 位数据(不包含停止位),
typedef enum _lpuart_data_bits
{
kLPUART_EightDataBits = 0x0U, //8 位数据位
#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) &&
FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
kLPUART_SevenDataBits = 0x1U, //7 位数据位
#endif
} lpuart_data_bits_t;
isMsb 用来设置是否开启高位在前的传输模式。
stopBitCount 用来设置停止位,可以设置 1 位或 2 位停止位
typedef enum _lpuart_stop_bit_count
{
kLPUART_OneStopBit = 0U, //1 位停止位
kLPUART_TwoStopBit = 1U, //2 位停止位
} lpuart_stop_bit_count_t;
enableTx 和 enableRx 用来设置串口的收发开关的。我们一般都是收发全部打开的。
srcClock_Hz 用来设置串口的根时钟频率,比如我们一般设置串口的根时钟频率为 PLL3_SW_CLK/6=80M,因此 srcClock_Hz=80000000。
LPUART_Init 函数会调用 CLOCK_EnableClock 函数来使能 LPUART 时钟的
void LPUART_GetDefaultConfig(lpuart_config_t *config) { assert(NULL != config); /* Initializes the configure structure to zero. */ (void)memset(config, 0, sizeof(*config)); config->baudRate_Bps = 115200U; //波特率115200 config->parityMode = kLPUART_ParityDisabled; //关闭奇偶校验 config->dataBitsCount = kLPUART_EightDataBits; //8位数据位 config->isMsb = false; #if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT config->stopBitCount = kLPUART_OneStopBit; //1位停止位 #endif #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO config->txFifoWatermark = 0U; config->rxFifoWatermark = 0U; #endif #if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT config->enableRxRTS = false; //关闭RTS config->enableTxCTS = false; //关闭CTS config->txCtsConfig = kLPUART_CtsSampleAtStart; config->txCtsSource = kLPUART_CtsSourcePin; #endif config->rxIdleType = kLPUART_IdleTypeStartBit; config->rxIdleConfig = kLPUART_IdleCharacter1; config->enableTx = false; //关闭发送 config->enableRx = false; //关闭接收 }
中断使能函数 LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask)
中断具体类型
enum _lpuart_interrupt_enable { #if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT kLPUART_LinBreakInterruptEnable = (LPUART_BAUD_LBKDIE_MASK >> 8), /*!< LIN break detect. */ #endif kLPUART_RxActiveEdgeInterruptEnable = (LPUART_BAUD_RXEDGIE_MASK >> 8), /*!< Receive Active Edge. */ kLPUART_TxDataRegEmptyInterruptEnable = (LPUART_CTRL_TIE_MASK), /*!< Transmit data register empty. */ kLPUART_TransmissionCompleteInterruptEnable = (LPUART_CTRL_TCIE_MASK), /*!< Transmission complete. */ kLPUART_RxDataRegFullInterruptEnable = (LPUART_CTRL_RIE_MASK), /*!< Receiver data register full. */ kLPUART_IdleLineInterruptEnable = (LPUART_CTRL_ILIE_MASK), /*!< Idle line. */ kLPUART_RxOverrunInterruptEnable = (LPUART_CTRL_ORIE_MASK), /*!< Receiver Overrun. */ kLPUART_NoiseErrorInterruptEnable = (LPUART_CTRL_NEIE_MASK), /*!< Noise error flag. */ kLPUART_FramingErrorInterruptEnable = (LPUART_CTRL_FEIE_MASK), /*!< Framing error flag. */ kLPUART_ParityErrorInterruptEnable = (LPUART_CTRL_PEIE_MASK), /*!< Parity error flag. */ #if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO kLPUART_TxFifoOverflowInterruptEnable = (LPUART_FIFO_TXOFE_MASK >> 8), /*!< Transmit FIFO Overflow. */ kLPUART_RxFifoUnderflowInterruptEnable = (LPUART_FIFO_RXUFE_MASK >> 8), /*!< Receive FIFO Underflow. */ #endif };
关闭中断的函数void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask)
数据发送函数
static inline void LPUART_WriteByte(LPUART_Type *base, uint8_t data)
{
base->DATA = data;
}
base:串口
data:写入的数据
数据接收函数
static inline uint8_t LPUART_ReadByte(LPUART_Type *base) { #if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT uint32_t ctrl = base->CTRL; uint8_t result; bool isSevenDataBits = (((ctrl & LPUART_CTRL_M7_MASK) != 0U) || (((ctrl & LPUART_CTRL_M7_MASK) == 0U) && ((ctrl & LPUART_CTRL_M_MASK) == 0U) && ((ctrl & LPUART_CTRL_PE_MASK) != 0U))); if (isSevenDataBits) { result = (uint8_t)(base->DATA & 0x7FU); } else { result = (uint8_t)base->DATA; } return result; #else return (uint8_t)(base->DATA); #endif }
参数 base 指定要操作的串口
函数返回值就是读取到的串口接收值,此函数就是读取串口的 DATA 寄存器。
多次数据收发
void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length)
status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length)
LPUART_WriteBlocking 用于多字节发送,此函数会产生阻塞,也就是每发送一个字节的数据,然后阻塞等待发送完成,发送完成以后就发送下一个字节的数据。参数 base 表明操作的哪个串口,data 是要发送的数据,length 是要发送的数据长度。
LPUART_ReadBlocking 用于多字节的接收,此函数也会产生阻塞。参数 base 表明操作的哪
个串口,data 是接收数据缓冲区,length 是要接收的数据长度。
观察串口的工作状态
uint32_t LPUART_GetStatusFlags(LPUART_Type *base)
{
uint32_t temp;
temp = base->STAT;
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
temp |= (base->FIFO &
(LPUART_FIFO_TXEMPT_MASK | LPUART_FIFO_RXEMPT_MASK | LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK)) >>
16U;
#endif
return temp;
}
void LPUART1_Init(uint32 bound) { lpuart_config_t lpuart1_config; uint32 freq=0; CLOCK_EnableClock(kCLOCK_Lpuart1);//使能LPUART1时钟,CCM_CCGR5_CG12 CLOCK_SetMux(kCLOCK_UartMux,0);//2路复用选择 CLOCK_SetDiv(kCLOCK_UartDiv,0);//分频 //set iomuxc IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_12_LPUART1_TX,0U); IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_13_LPUART1_RX,0U); //set io B0_12&B0_13 //关闭 Hyst,下拉 100K Ohm,选择Keeper,使能pull/keeper,关闭开漏,100MHz_SPEED1,驱动能力R0/6,低转换速度 IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_12_LPUART1_TX,0x10B0u); IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_13_LPUART1_RX,0x10B0u); freq = BOARD_DebugConsoleSrcFreq(); LPUART_GetDefaultConfig(&lpuart1_config); lpuart1_config.baudRate_Bps=bound; lpuart1_config.dataBitsCount=kLPUART_EightDataBits; lpuart1_config.stopBitCount=kLPUART_OneStopBit; lpuart1_config.parityMode=kLPUART_ParityDisabled; lpuart1_config.enableRx=true; lpuart1_config.enableTx=true; LPUART_Init(LPUART1,&lpuart1_config,freq); // NVIC_SetPriority(LPUART8_IRQn,15); // uart_rx_irq(USART_8,1); }
本文参照正点原子RT1052 开发指南。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。