You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F103C6在Proteus中启用TIM2后BUS_FAULT及LCD异常求助

问题描述

我使用STM32F103C6、HCSR-04超声波传感器及LCD显示屏,在Proteus Professional 8中开展仿真工作时遇到两个核心问题:

  • 启用STM32的Timer 2后,STM32运行在36MHz、LCD显示屏频率为250kHz的情况下,程序反复弹出超1000次Access to register of unclocked peripheral at 0x40000000 cause BUS_FAULT [U2_CM3CORE]错误提示,随后崩溃。
  • 若在Proteus中提高STM32的运行频率,LCD显示屏则无法显示任何内容。
问题分析
  1. 错误提示中0x40000000是TIM2的基地址,说明访问TIM2寄存器时该外设未被正确使能时钟,触发总线错误。
  2. 系统时钟与LCD的I2C通信时钟不匹配,或时钟配置错误导致LCD时序异常,无法正常显示。
  3. TIM2初始化参数不合理(预分频器和自动重装载值为0),导致计数器溢出过快,引发系统异常。
  4. SysTick回调函数未按HAL库规范命名,导致LCD更新和超声波触发逻辑未被正确执行。
解决方案

1. 补全TIM2时钟使能代码

在main.c的USER CODE区添加TIM2的时钟使能函数,确保外设时钟被正确开启:

/* USER CODE BEGIN 4 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
  if(tim_baseHandle->Instance==TIM2)
  {
    __HAL_RCC_TIM2_CLK_ENABLE(); // 启用TIM2外设时钟
    // 配置TIM2中断优先级(根据需求调整)
    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
  }
}

// 原usDelay函数保持不变
void usDelay(uint32_t uSec)
{
    if(uSec < 2) uSec = 2;
    usTIM->ARR = uSec - 1;  /*sets the value in the auto-reload register*/
    usTIM->EGR = 1;             /*Re-initialises the timer*/
    usTIM->SR &= ~1;        //Resets the flag
    usTIM->CR1 |= 1;        //Enables the counter
    while((usTIM->SR&0x0001) != 1);
    usTIM->SR &= ~(0x0001);
}
/* USER CODE END 4 */

2. 调整TIM2初始化参数

修改MX_TIM2_Init中的预分频器和自动重装载值,适配36MHz系统时钟:

static void MX_TIM2_Init(void)
{
  // ... 保留自动生成的其他代码
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 35; // 36MHz/(35+1)=1MHz,计数器每1us递增1
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 65535; // 最大自动重装载值,避免频繁溢出
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  // ... 保留自动生成的其他代码
}

3. 修正SysTick回调函数命名

将SysTick_CallBack改为HAL库规范的HAL_SYSTICK_Callback,确保逻辑被自动调用:

void HAL_SYSTICK_Callback(void)
{
    TRIG_Ticks++;
    LCD_Ticks++;
    if(TRIG_Ticks >= 15) // 每15ms触发一次超声波
    {
        HCSR04_Trigger(HCSR04_SENSOR1);
        TRIG_Ticks = 0;
    }
    if(LCD_Ticks >= 200) // 每200ms更新一次LCD
    {
        lcd_clear();
        lcd_puts(0,0, (int8_t*)TEXT);
        LCD_Ticks = 0;
    }
}

4. 匹配LCD的I2C时钟频率

修改MX_I2C1_Init中的时钟配置,适配LCD的250kHz需求:

static void MX_I2C1_Init(void)
{
  // ... 保留自动生成的其他代码
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 250000; // 改为LCD支持的250kHz
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  // ... 保留自动生成的其他代码
}

5. Proteus仿真配置检查

  • 确保Proteus中STM32的时钟源与代码配置一致(代码使用HSI+PLL生成36MHz),不要手动修改STM32模型的频率参数。
  • 检查LCD仿真模型的属性,确认其支持250kHz的I2C时钟频率,若不支持则调整代码中的I2C时钟为模型兼容值。
修改后的完整代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 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"
#include "lcd_txt.h"
#include "stdio.h"

#include "HCSR04.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#define HCSR04_SENSOR1 8
uint16_t TRIG_Ticks = 0;
uint16_t LCD_Ticks = 0;
float Distance = 0.0;
char TEXT[16] = {0};
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define usTIM   TIM1

/* 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 ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

TIM_HandleTypeDef htim2;

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_I2C1_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM2_Init(void);
/* USER CODE BEGIN PFP */
void usDelay(uint32_t uSec);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
    uint32_t numTicks = 0;
    
  /* 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 */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART2_UART_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
    lcd_init();
    lcd_puts(1,0, (int8_t*)"test");
  /* USER CODE END 2 */
    HCSR04_Init(HCSR04_SENSOR1, &htim2);
    lcd_puts(0,0, (int8_t*)"test");

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
        Distance = HCSR04_Read(HCSR04_SENSOR1);
    sprintf(TEXT, "Dist= %.2f cm", Distance);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    HCSR04_TMR_IC_ISR(htim);
}
 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
    HCSR04_TMR_OVF_ISR(htim);
}
 
void HAL_SYSTICK_Callback(void)
{
    TRIG_Ticks++;
    LCD_Ticks++;
    if(TRIG_Ticks >= 15) // Each 15msec
    {
        HCSR04_Trigger(HCSR04_SENSOR1);
        TRIG_Ticks = 0;
    }
    if(LCD_Ticks >= 200) // Each 200msec
    {
        lcd_clear();
        lcd_puts(0,0, (int8_t*)TEXT);
        LCD_Ticks = 0;
    }
}
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {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.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  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_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 250000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 35;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 65535;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

/**
  * @brief 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 = 115200;
  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;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:50:33