【简介】
S32K146 的SDK的串口配置使用起来相对还是很容易的,SDK的软件相对会依赖性会更强。某些场景我们不能直接使用SDK来配置串口只需要一段hard code 来配置串口打印,我们基于此场景直接操作寄存器来实现uart 的printf 打印。对应芯片的UART 的框图如下
【PINMUX 配置】
在S32K146 芯片中PIN MUX 配置port 的功能配置的寄存器为PORT->PORT_PCRn 每个pin 都有一个寄存器来配置,寄存器描述如下。
MUX 信号用来控制功能选择
DSE 用来配置端口的驱动能力
【UART 参数配置】
我们本次实验UART 的参数使用115200 8N1 的配置,本地的UART的IP 输入时钟为16MHZ,S32K146 的波特率配置通过LPUART Baud Rate Register (BAUD) 寄存器来配置,对应配置说明如下
从上面的描述 通过配置OSR/SBR 信号来配置通信的波特率,根据公式我们配置115200 的波特率 16000000/((22+1)*6) = 115942 我们按照上述计算配置更新OSR/SDR寄存器配置波特率参数。
LPUART Control Register (CTRL) 寄存器的TE 发送使能,PE/PT 用来配置检验位配置,M 位配置发送数据的长度。
PE/PT 信号控制校验位的输出
我们编写如下的代码配置uart,并验证uart 的printf 输出功能。
#include "clock_config.h" #include <stddef.h> #include <stdio.h> int main(void) { /* Initialize and configure clocks * - Setup system clocks, dividers * - see clock manager component for more details */ CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT, g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT); CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT); /* config PTC9-LPUART1_TX */ uint32_t regValue = PORTC->PCR[9]; regValue &= ~(PORT_PCR_MUX_MASK); regValue |= PORT_PCR_MUX(2); regValue &= ~(PORT_PCR_DSE_MASK); regValue &= ~(PORT_PCR_PE_MASK); regValue &= ~(PORT_PCR_PFE_MASK); PORTC->PCR[9] = regValue; /* reset lpuart1 register */ /* Set the default oversampling ratio (16) and baud-rate divider (4) */ LPUART1->BAUD = ((uint32_t)((FEATURE_LPUART_DEFAULT_OSR << LPUART_BAUD_OSR_SHIFT) | \ (FEATURE_LPUART_DEFAULT_SBR << LPUART_BAUD_SBR_SHIFT))); /* Clear the error/interrupt flags */ LPUART1->STAT = FEATURE_LPUART_STAT_REG_FLAGS_MASK; /* Reset all features/interrupts by default */ LPUART1->CTRL = 0x00000000; /* Reset match addresses */ LPUART1->MATCH = 0x00000000; /* Reset IrDA modem features */ LPUART1->MODIR = 0x00000000; /* Reset FIFO feature */ LPUART1->FIFO = FEATURE_LPUART_FIFO_RESET_MASK; /* Reset FIFO Watermark values */ LPUART1->WATER = 0x00000000; /* config lpuart1 15200 8n1 */ /* config 115200 */ regValue = LPUART1->BAUD; regValue &= ~(LPUART_BAUD_OSR_MASK); regValue |= LPUART_BAUD_OSR(22); LPUART1->BAUD = regValue; regValue = LPUART1->BAUD; regValue &= ~(LPUART_BAUD_SBR_MASK); /* Removed the shift operation as the SBR field position is zero; shifting with 0 violates MISRA */ regValue |= (6) & LPUART_BAUD_SBR_MASK; LPUART1->BAUD = regValue; /* config 8-bit (M=0) */ /* config 8-bit (M=0) or 9-bits (M=1) */ LPUART1->CTRL = (LPUART1->CTRL & ~LPUART_CTRL_M_MASK) | (0 << LPUART_CTRL_M_SHIFT); /* clear M10 to make sure not 10-bit mode */ LPUART1->BAUD &= ~LPUART_BAUD_M10_MASK; LPUART1->BAUD = (LPUART1->BAUD & ~LPUART_BAUD_SBNS_MASK) | ((uint32_t)0 << LPUART_BAUD_SBNS_SHIFT); /* Enable lpuart tx */ LPUART1->CTRL = (LPUART1->CTRL & ~LPUART_CTRL_TE_MASK) | ((1UL) << LPUART_CTRL_TE_SHIFT); /* Wait for the register write operation to complete */ while((bool)((LPUART1->CTRL & LPUART_CTRL_TE_MASK) != 0U) != 1) {} while(1) { printf("hello world\r\n"); } } size_t __write(int handle, const unsigned char *buffer, size_t size) { for(int i = 0;i < size;i++) { while(!(LPUART1->STAT & LPUART_STAT_TDRE_MASK)); volatile uint8_t * dataRegBytes = (volatile uint8_t *)(&(LPUART1->DATA)); dataRegBytes[0] = buffer[i]; } return size; }
上述运行验证发送hello world 可以从串口持续输出