stm32wb55rg (4) 启用usart串口

code repo: 访问gitee

上节课成功点亮了LED,这次来把usart 用起来,毕竟有交互才是系统。

技术准备

首先查看手册,发现mcu有1个usart和1个 lpuart。

usart 的使用需要两个pin,一个接收一个发送。继续查看pin and ball definitions, 寻找使用usart可用的pin,发现可选择PA9+PA10 或者 PB6+PB7。

通过原理图发现,如果使用PA9+PA10组合,需要单独接线。而根据圈出的数字顺序号,发现PB7,PB6通过转换连接到了st-link usb接口的DM和DP,因此使用stlink的虚拟串口功能。

查看memory mapping, 得到USART的寻址为:AHB1 --> APB2 --> USART1.

查看时钟树,usart 的clock source有4个选择,分别是PCLKn, SYSCLK, HSI16, LSE.

除此之外,还应当了解有哪些寄存器,以及各个寄存器的作用和意义。但开发优先,可以调用api来开发,多数api都是自注释的。所以可以等到需要的时候再查询寄存器。

代码实现

在main函数中,首先定义一个usart 变量,方便配置usart相关参数,然后新增一个usart初始化函数,并在main中进行调用。初始化函数中定义了串口的配置,波特率,长度等等。

c 复制代码
UART_HandleTypeDef huart1;

void USART1_UART_Init(void)
{
  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
}

还要实现一个HAL_UART_MspInit 接口,该接口是usart初始化的回调接口,用于设置用于usart功能的pin,使能gpio和usart的时钟

c 复制代码
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
    PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PB6     ------> USART1_TX
    PB7     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  }
}

最后实现一个fputc

c 复制代码
int fputc(int ch, FILE *f)
{
  uint8_t data = (uint8_t)ch;
  if (HAL_UART_Transmit(&huart1, &data, 1, 10) != HAL_OK) // Reduced timeout to 10ms
  {
    // Handle transmission error
    Error_Handler();
  }
  return ch;
}

这样我们就可以使用printf来输出了。但是别忘记了在工程设置里面使用lib库,如图所示。

bugfix:如果在main中调用printf仍旧没有输出,可以使用setvbuf设置标准输出流(stdout)的缓冲模式

c 复制代码
setvbuf(stdout, NULL, _IONBF, 0);

效果如下:

code repo: 访问gitee

commit: 89cba38e2296

搞定收工

相关推荐
d111111111d26 分钟前
直流电机位置式 PID 控制 和 舵机的区别
笔记·stm32·单片机·嵌入式硬件·学习
d111111111d3 小时前
了解Modbus
网络·笔记·stm32·单片机·嵌入式硬件·学习
gihigo19986 小时前
MAX30102 + STM32 人体血氧饱和度(SpO₂)测量方案
stm32·单片机·嵌入式硬件
LCG元6 小时前
STM32实战:基于uC/OS-III的STM32移植与多任务应用
stm32·单片机·嵌入式硬件
今日待办7 小时前
【CEM5881-M11雷达模块】使用开发指南
stm32·雷达模块·cem5881-m11
Deitymoon7 小时前
STM32——433M无线遥控灯
stm32·单片机·嵌入式硬件
Wallace Zhang8 小时前
SimpleFOC源码学习09(v2.3.2) - 磁编码器MagneticSensorSPI.cpp与MagneticSensorSPI.h
驱动开发·stm32·simplefoc·foc电机控制
12.=0.8 小时前
【stm32_7】定时器的原理与应用、基本定时器、通用定时器、PWM、模拟脉冲信号的宽度、利用PWM控制外设、逻辑分析仪的使用
c语言·stm32·单片机·嵌入式硬件
Deitymoon8 小时前
STM32——振动传感器控制继电器
stm32·单片机·嵌入式硬件
国产芯片设计9 小时前
DIY实战|0.8寸WiFi自动授时电子钟,国产数码管驱动芯片方案分享
stm32·单片机·mcu·51单片机·硬件工程