本帖最后由 yinxiangxv 于 2025-5-26 22:31 编辑
之前在运行例程中的printf重定向函数的时候,总是输出乱码?
经过一番折腾,今天终于能正常输出字符了?看图,其中最关键的应该还是时钟和波特率的配置了。


看时钟树的配置:


这里选择的是12M的时钟PCLK
根据这个对波特率进行重新计算:
- 波特率 (Baud Rate): 指串口每秒传输的位数 (bits per second, bps)。通信双方必须使用相同的波特率才能正确解码数据。
- USART 时钟 (f_CK): 输入到 USART 外设的时钟频率。根据我们之前的分析,你的 USART2 时钟 (PCLK) 是 12 MHz (12,000,000 Hz)。
- 波特率寄存器 (USART_BRR): STM32 内部有一个寄存器,你需要写入一个特定的值 (USARTDIV),这个值是根据 f_CK 和目标波特率计算出来的,用于分频 f_CK 以产生实际的位时钟。
- 过采样 (Oversampling): USART 可以配置为过采样 16 次 (OVER8=0) 或 8 次 (OVER8=1)。这会影响波特率计算公式和精度。通常推荐使用过采样 16 次,除非需要非常高的波特率或有特殊功耗要求。
- 计算方法 :
- 计算写入 BRR 寄存器的值 (USARTDIV) 的基本公式:
- 过采样 16 次 (OVER8 = 0):
- USARTDIV = f_CK / Desired_BaudRate
- 过采样 8 次 (OVER8 = 1):
- USARTDIV = (2 * f_CK) / Desired_BaudRate
在配上修改后的代码:
- /* USER CODE BEGIN Header */
- /**
- ******************************************************************************
- * [url=home.php?mod=space&uid=288409]@file[/url] UART/UART_Printf/Src/main.c
- * [url=home.php?mod=space&uid=187600]@author[/url] MCD Application Team
- * [url=home.php?mod=space&uid=247401]@brief[/url] This example shows how to retarget the C library printf function
- * to the UART.
- ******************************************************************************
- * @attention
- *
- * Copyright (c) 2024 STMicroelectronics.
- * All rights reserved.
- *
- * This software is licensed under terms that can be found in the LICENSE file
- * in the root directory of this software component.
- * If no LICENSE file comes with this software, it is provided AS-IS.
- *
- ******************************************************************************
- */
- /* USER CODE END Header */
- /* Includes ------------------------------------------------------------------*/
- #include "main.h"
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
- /* USER CODE END Includes */
- /* Private typedef -----------------------------------------------------------*/
- /* USER CODE BEGIN PTD */
- /* USER CODE END PTD */
- /* Private define ------------------------------------------------------------*/
- /* USER CODE BEGIN PD */
- /* USER CODE END PD */
- /* Private macro -------------------------------------------------------------*/
- /* USER CODE BEGIN PM */
- /* USER CODE END PM */
- /* Private variables ---------------------------------------------------------*/
- UART_HandleTypeDef huart2;
- /* USER CODE BEGIN PV */
- /* USER CODE END PV */
- /* Private function prototypes -----------------------------------------------*/
- void SystemClock_Config(void);
- static void MX_GPIO_Init(void);
- static void MX_USART2_UART_Init(void);
- /* USER CODE BEGIN PFP */
- #if defined(__ICCARM__)
- __ATTRIBUTES size_t __write(int, const unsigned char *, size_t);
- #endif /* __ICCARM__ */
- #if defined(__ICCARM__)
- /* New definition from EWARM V9, compatible with EWARM8 */
- int iar_fputc(int ch);
- #define PUTCHAR_PROTOTYPE int iar_fputc(int ch)
- #elif defined ( __CC_ARM ) || defined(__ARMCC_VERSION)
- /* ARM Compiler 5/6*/
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #elif defined(__GNUC__)
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #endif /* __ICCARM__ */
- /* USER CODE END PFP */
- /* Private user code ---------------------------------------------------------*/
- /* USER CODE BEGIN 0 */
- /* USER CODE END 0 */
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] The application entry point.
- * @retval int
- */
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- /* STM32C0xx HAL library initialization:
- - Configure the Flash prefetch
- - Systick timer is configured by default as source of time base, but user
- can eventually implement his proper time base source (a general purpose
- timer for example or other time source), keeping in mind that Time base
- duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
- handled in milliseconds basis.
- - Low Level Initialization
- */
- /* USER CODE END 1 */
- /* MCU Configuration--------------------------------------------------------*/
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
- /* USER CODE BEGIN Init */
- /* USER CODE END Init */
- /* Configure the system clock */
- SystemClock_Config();
- /* USER CODE BEGIN SysInit */
- /* Initialize BSP Led for LED2 */
- BSP_LED_Init(LED2);
- /* USER CODE END SysInit */
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_USART2_UART_Init();
- /* USER CODE BEGIN 2 */
- /* Output a message on Hyperterminal using printf function */
- printf("\n\r UART Printf Example: retarget the C library printf function to the UART\n\r");
- printf("** Test finished successfully. ** \n\r");
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- printf("** Test finished successfully. ** \n\r");
- uint8_t test[] = {0x55, 0xAA, 'A', 'B', 'C'}; // 十六进制+ASCII混合数据
- HAL_UART_Transmit(&huart2, test, sizeof(test), 100);
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
- }
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] System Clock Configuration
- * @retval None
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- __HAL_FLASH_SET_LATENCY(FLASH_LATENCY_0);
- /** Initializes the RCC Oscillators according to the specified parameters
- * in the RCC_OscInitTypeDef structure.
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV4;
- RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /** Initializes the CPU, AHB and APB buses clocks
- */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
- RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV4;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
- {
- Error_Handler();
- }
- }
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] USART2 Initialization Function
- * @param None
- * @retval None
- */
- static void MX_USART2_UART_Init(void)
- {
- /* USER CODE BEGIN USART2_Init 0 */
- /* USER CODE END USART2_Init 0 */
- /* USER CODE BEGIN USART2_Init 1 */
- /* USER CODE END USART2_Init 1 */
- huart2.Instance = USART2;
- huart2.Init.BaudRate = 9600;
- huart2.Init.WordLength = UART_WORDLENGTH_8B;
- huart2.Init.StopBits = UART_STOPBITS_1;
- huart2.Init.Parity = UART_PARITY_NONE;
- huart2.Init.Mode = UART_MODE_TX_RX;
- huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart2.Init.OverSampling = UART_OVERSAMPLING_16;
- huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
- huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
- if (HAL_UART_Init(&huart2) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN USART2_Init 2 */
- /* USER CODE END USART2_Init 2 */
- }
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] GPIO Initialization Function
- * @param None
- * @retval None
- */
- static void MX_GPIO_Init(void)
- {
- /* USER CODE BEGIN MX_GPIO_Init_1 */
- /* USER CODE END MX_GPIO_Init_1 */
- /* GPIO Ports Clock Enable */
- __HAL_RCC_GPIOF_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
- /* USER CODE BEGIN MX_GPIO_Init_2 */
- /* USER CODE END MX_GPIO_Init_2 */
- }
- /* USER CODE BEGIN 4 */
- /**
- * @brief Retargets the C library printf function to the USART.
- * @param None
- * @retval None
- */
- PUTCHAR_PROTOTYPE
- {
- /* Place your implementation of fputc here */
- /* e.g. write a character to the USART2 and Loop until the end of transmission */
- HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);
- return ch;
- }
- #if defined(__ICCARM__)
- size_t __write(int file, unsigned char const *ptr, size_t len)
- {
- size_t idx;
- unsigned char const *pdata = ptr;
- for (idx = 0; idx < len; idx++)
- {
- iar_fputc((int)*pdata);
- pdata++;
- }
- return len;
- }
- #endif /* __ICCARM__ */
- void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
- if(huart->Instance == USART4) {
- printf("UART Error: 0x%lX\n", huart->ErrorCode);
- }
- }
- /* USER CODE END 4 */
- /**
- * @brief This function is executed in case of error occurrence.
- * @retval None
- */
- void Error_Handler(void)
- {
- /* USER CODE BEGIN Error_Handler_Debug */
- /* User can add his own implementation to report the HAL error return state */
- /* Turn LED2 on */
- BSP_LED_On(LED2);
- while (1);
- /* USER CODE END Error_Handler_Debug */
- }
- #ifdef USE_FULL_ASSERT
- /**
- * @brief Reports the name of the source file and the source line number
- * where the assert_param error has occurred.
- * @param file: pointer to the source file name
- * @param line: assert_param error line source number
- * @retval None
- */
- void assert_failed(uint8_t *file, uint32_t line)
- {
- /* USER CODE BEGIN 6 */
- /* User can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- /* Infinite loop */
- while (1)
- {
- }
- /* USER CODE END 6 */
- }
- #endif /* USE_FULL_ASSERT */
最后终于看到正常的输出了:


最近先折腾到这里,以后有板子还是要积极参与。
|