单片机实现挡位调节
简易挡位调节模块
1、初始化硬件
- 这里就不过多赘述了,去看我之前的帖子,我这篇帖子选择
TIM2的1通道
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比较值
- 当比较值满了,则清空
实验效果

流程图
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)调节方式
| 调节方式 | 特点 |
|---|---|
| 环状链表 | 读写方便,但数据离散,占资源 |
| 循环体 | 可连续显示效果,但可读性不高 |




浙公网安备 33010602011771号