【简介】
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 可以从串口持续输出

我要赚赏金
