STM32使用 :串口的接收与发送

一、串口

  1. 在 STM32 中,串口(UART,通用异步收发传输器)是用于串行通信的外设。它在嵌入式系统中的作用非常广泛,主要包括几个方面
  • 数据通信
    串口用于微控制器与其他设备之间的数据传输。这些设备可以是其他微控制器、传感器、计算机或通信模块(例如蓝牙、Wi-Fi 模块等)。串口以异步方式传输数据,不需要时钟信号,因此实现起来相对简单。
  • 调试功能
    UART 在嵌入式开发中常用于打印调试信息。在 STM32 开发过程中,程序员可以使用 printf 函数将调试信息通过串口输出到计算机终端。
  • 固件升级
    在嵌入式设备的维护过程中,UART 可以用于通过串口线对设备进行固件升级。
  • 外部模块通信
    GPS模块,蓝牙模块
  1. UART通信的主要参数
  • 波特率(Baud Rate):数据传输速率,以每秒传输的比特数表示。常见波特率有9600、115200等。发送和接收设备的波特率必须相同。
  • 数据位(Data Bits):每次传输的数据位长度,通常是8位。
  • 停止位(Stop Bits):用于标识数据传输结束。可以选择1位或2位停止位。
  • 校验位(Parity Bit):用于检测数据传输错误,可以是无校验、偶校验或奇校验。
  1. 串口配置的主要步骤
选择波特率:设定发送和接收双方的波特率。

选择数据位、停止位和校验位:根据应用需求配置传输帧格式。

配置GPIO引脚:使用STM32的GPIO复用功能,将UART的TX和RX引脚连接到相应外设。

启用UART中断或DMA:用于非阻塞传输,避免阻塞主程序。

初始化并启动UART:通过配置UART外设,使其进入工作状态。
UART 串口的主要特点
  • 异步通信,全双工通信,易于实现,传输效率较快。
调试软件

www.mcuisp.com下载即可

串口的发送(调试功能)
  1. 设置RCC的high SPeed CLock的模式为Crystal/Ceramic

  2. 找到电路板的串口,看清楚串口连接的是哪一个,我的电路板串口启用的是UART1

  3. UART1挂载到APB2总线上,设置APB2为64MHZ即可。

  4. 对USART1模式设置为Asynchronous,即为异步通信方式,当然你也可以在这里设置串口的具体参数
    在这里插入图片描述

  5. 通常将 printf 函数的输出重定向到 UART,这样你可以使用 printf 在终端上输出调试信息。需要实现 __io_putchar 函数来将字符发送到 UART

  6. 实际上是对__io_putchar的改写

int __io_putchar(int ch)
{
   
   
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
  return ch;
}
参数:
int ch:传入的字符,将要通过串口输出的单个字符。

功能:
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY):这个函数使用 STM32 的 HAL 库,通过 huart1(UART1 的句柄)发送数据。
&huart1:表示使用 UART1,也可以换成串口2(uint8_t *)&ch:将字符 ch 的地址转换为 uint8_t* 类型,因为 UART 通常处理的是 8 位数据(字符)。
1:发送 1 个字节的数据。
HAL_MAX_DELAY:设置为最大等待时间,表示发送数据时系统会等待直到传输完成。

返回值:
return ch;:函数返回发送的字符 ch,这是为了和标准的 putchar 函数兼容,通常不用于实际逻辑。
  1. 代码示例
#include "main.h"

UART_HandleTypeDef huart1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
// 主函数
int main(void)
{
   
   
  // 初始化HAL库
  HAL_Init();

  // 配置系统时钟
  SystemClock_Config();

  // 初始化GPIO
  MX_GPIO_Init();

  // 初始化USART1
  MX_USART1_UART_Init();

  // 无限循环,用于发送测试信息
  while (1)
  {
   
   
    // 打印当前天气信息
    printf("today is sunshine,temp=45,shidu=35.\r\n");

    // 打印欢迎信息
    printf("hello world---------------->");

    // 延迟500毫秒
    HAL_Delay(500);
  }
}

// 重定向printf函数,使其可以通过USART1发送字符
int __io_putchar(int ch)
{
   
   
  // 通过USART1发送字符
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
  return ch;
}

// 配置系统时钟
void SystemClock_Config(void)
{
   
   
  RCC_OscInitTypeDef RCC_OscInitStruct = {
   
   0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {
   
   0};

  // 配置时钟源
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;         // 启用外部高速时钟 (HSE)
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; // HSE预分频值为1
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;         // 启用内部高速时钟 (HSI)
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;     // 启用锁相环 (PLL)
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL时钟源为HSE
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8;     // PLL倍频因子为8
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
   
   
    // 如果时钟配置失败,则进入错误处理
    Error_Handler();
  }

  // 配置时钟树
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 系统时钟源为PLL
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;       // AHB时钟不分频
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;        // APB1时钟分频为2
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;        // APB2时钟不分频

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
   
   
    // 如果时钟配置失败,则进入错误处理
    Error_Handler();
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值