单片机实现挡位调节

简易挡位调节模块

1、初始化硬件

  • 这里就不过多赘述了,去看我之前的帖子,我这篇帖子选择TIM2的1通道

PWM的简单应用

2、触发方式

(1)中断

I 初始化硬件

  • 启用按钮的中断
    img

II 写入代码

  • 在主函数外写入中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
	uint16_t value;
	__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, value);
}
/* USER CODE END 0 */

(2)轮询

即在循环体内频繁判断按钮是否被按下

  • 在主循环外侧定义全局变量Value
uint16_t Value;
/* USER CODE END 0 */
  • 在循环体内读取按钮处接口状态
	  HAL_Delay(99);
	  if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == GPIO_PIN_RESET){
		  /*-----------写入增加比较值的代码-----------------*/

	  }

2、调节方式

I环状链表

代码部分

这里选择中断处理的方式来写

  • 在主函数外侧声明结构体数组并重构中断回调函数
/* USER CODE BEGIN 0 */
struct Node{
	uint16_t CompareValue;
}Level[6];
uint16_t value;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
	value = Level[value].CompareValue;
	__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, (value * 2000));
}
/* USER CODE END 0 */
  • 在主函数内初始化数组
  /* USER CODE BEGIN Init */
  Level[0].CompareValue = 1;
  Level[1].CompareValue = 2;
  Level[2].CompareValue = 3;
  Level[3].CompareValue = 4;
  Level[4].CompareValue = 5;
  Level[5].CompareValue = 0;
  /* USER CODE END Init */

原理

  • 当按钮触发后,会产生中断回调,将PWM比较值变成环状链表的下一个键值
    img

实验效果

  • 可呈现6个挡位得亮度变化
    img

流程图

  • 主程序
graph TD; A((开始)) ---> B[初始化GPIO] ---> C[初始化TIM] ---> D[声明并定义环状链表]
  • 中断
graph TD; A((触发中断)) ---> B{判断中断是否来自按钮} B{判断中断是否来自按钮} --> |是|C[将比较值改为链表下一个成员] B --> |否|D[结束中断] C ---> D

II循环体

这里以"轮询的代码为例"

  • 在主循环内写入以下内容
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    //判断比较值是否装满
	  if(Value > 19999)
		  	 Value = 0;
	  HAL_Delay(99);//延迟0.1秒
    //判断按钮是否按下
	  if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == GPIO_PIN_RESET){
      //如果按下,则增加比较值
		  Value += 500;
		  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, Value);
	  }

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

实验原理

  • 每隔0.1秒,询问一次按钮处GPIO的状态,如果为按下状态,则增加500比较值
  • 当比较值满了,则清空

实验效果

img

流程图

graph TD; begin((开始)) ---> GPIO_Init[初始化GPIO] ---> TIM_Init[初始化TIM] ---> scan{询问按钮是否被按下} scan --> |是|pend{判断比较值是否满了} pend --> |否|Add[将比较值加500] pend --> |是|Reload[将比较值清零] scan --> |否|Delay[延迟0.1秒] Add ---> Delay Reload ---> Delay Delay ---> scan

3、代码清单

  • stm32f4xx_hal.h
/**
  * @brief  读取指定的输入脚
  * @param  GPIOx 指定的GPIO口
  *                    
  * @param  GPIO_Pin 指定的GPIO引脚
  *         这里的数字可以为0到15 (0..15).
  * @retval 输入引脚的状态
  */
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
  • stm32f4xx_hal_gpio.h
/** 
  * @brief  GPIO 状态
  */
typedef enum
{
  GPIO_PIN_RESET = 0,//置0
  GPIO_PIN_SET//置1
}GPIO_PinState;

4、总结

(1)触发方式

触发方式 特点
轮询 占用资源,效率高
中断 效率高,但是占用资源

(2)调节方式

调节方式 特点
环状链表 读写方便,但数据离散,占资源
循环体 可连续显示效果,但可读性不高
posted @ 2025-09-15 14:55  奶龙大王  阅读(35)  评论(0)    收藏  举报