题目2:基于STM32和按键的电机调速系统 描述:直流电机广泛应用于工业和家庭设备中,实现了许多自动化和控制功能。为了满足不同工作需求和提高系统的效率,设计一个直流电机调速系统,能够实时监测电机的转速,并通过调整电压或电流来控制电机的转速。 具体要求: 1.通过高低电平控制电机正反转; 2.通过PWM实现电机3级调速; 3.通过按键实现电机调速; 4.串口输出电机目前的转速档位; 5.LED指示灯表明电机运行状态,电机停止熄灭,电机启动 点亮。芯片采用STM32F429,请帮我们编写代码使用 HAL 库
时间: 2025-07-28 08:06:19 浏览: 15
<think>我们基于STM32F429芯片,使用HAL库实现一个直流电机调速系统。系统要求:1.通过两个按键控制:一个用于正反转切换,另一个用于调速(三级调速:低速、中速、高速)2.使用PWM控制电机速度,三级速度对应不同的PWM占空比(例如:30%,60%,90%)3.通过串口输出当前状态:正反转状态和速度档位(例如:正转-高速)4.使用LED指示状态:例如,正转时LED1亮,反转时LED2亮,停止时两个LED都灭(或者根据需求设计)硬件连接假设:-电机驱动:使用H桥驱动芯片(如L298N),控制两个GPIO(IN1,IN2)决定方向,一个PWM引脚(EN)控制速度。-按键:两个按键,分别连接在GPIO上(例如PA0:正反转切换按键,PA1:速度档位切换按键)-LED:两个LED(例如PG13:正转指示灯,PG14:反转指示灯)-串口:使用USART1(PA9:TX,PA10:RX)输出信息软件设计:1.初始化系统时钟、GPIO、定时器(用于PWM)、串口。2.配置两个按键为输入模式,并启用外部中断或使用轮询方式检测按键。3.配置两个LED为输出模式。4.配置一个定时器(如TIM3)的通道(如通道1)为PWM输出,连接到电机驱动芯片的使能端(EN)。5.定义全局变量:-motor_direction:0表示正转,1表示反转-speed_level:0,1,2分别表示低速、中速、高速6.在按键中断或轮询中改变状态,并更新PWM占空比、LED状态和串口输出。由于用户要求使用HAL库,我们将使用HAL库函数进行配置。步骤:1.使用STM32CubeMX生成初始化代码,或者手动编写初始化代码。2.编写主循环或中断服务函数来处理按键。注意:按键去抖动处理(这里为了简化,我们使用简单的延时去抖动,实际应用中可以使用定时器去抖动)。代码结构:一、初始化部分二、主循环(轮询按键状态)由于问题中要求三级调速和正反转控制,我们设计如下:状态:方向状态:0-正转,1-反转速度档位:0-低速(30%占空比),1-中速(60%),2-高速(90%)按键功能:按键1(正反转切换):按下后,方向状态切换(0变1,1变0),同时更新LED状态和串口输出。按键2(速度切换):按下后,速度档位循环增加(0->1->2->0),同时更新PWM占空比和串口输出。注意:停止状态可以由速度档位0(低速)来实现?但这里我们要求三级调速,所以最低速是30%占空比,而不是0。如果要求停止,可以再增加一个停止按键或者通过长按等方式。但题目要求三级调速,所以这里我们不考虑停止,而是三级速度。如果用户需要停止,可以将速度档位0设置为0%占空比,但题目要求三级调速,所以这里按照30%、60%、90%设计。但题目要求LED指示运行状态:正转时LED1亮,反转时LED2亮。那么停止时?题目没有明确,我们可以设定:当速度档位为0(即低速)时,电机仍在转动,只是速度低。所以LED状态只与方向有关,与速度无关。也就是说,只要方向是正转,无论速度多少,LED1都亮,反转则LED2亮。然而,题目要求“LED指示运行状态”,我们也可以这样设计:正转且运行:LED1亮反转且运行:LED2亮停止:两个LED都灭但题目没有停止状态,所以我们可以考虑在速度档位0时,如果占空比不为0,电机还是在转的。所以这里我们按照只指示方向,不指示速度(即只要电机在转,正转LED1就亮,反转LED2就亮,两者不会同时亮)。但是,题目要求三级调速,并没有停止。所以我们按照:电机始终在转动,只是速度分三级,方向分正反转。因此,我们设计:正转时:LED1亮,LED2灭反转时:LED1灭,LED2亮串口输出内容示例:正转-低速反转-中速正转-高速代码实现:1.定义全局变量:uint8_tmotor_direction=0;//0:forward,1:backwarduint8_tspeed_level=0;//0:low,1:medium,2:high2.PWM占空比设置:假设定时器的自动重装载值为arr,则三个档位的比较值分别为:low:0.3*arrmedium:0.6*arrhigh:0.9*arr3.方向控制:我们使用两个GPIO(例如PA1和PA2)来控制H桥的方向。正转:IN1=1,IN2=0反转:IN1=0,IN2=14.按键处理:按键1(方向切换):切换motor_direction,并设置方向控制引脚,同时切换LED状态,串口输出。按键2(速度切换):speed_level循环增加(0->1->2->0),并更新PWM占空比,串口输出。5.注意:按键去抖动,这里我们使用HAL_Delay(200)来简单去抖。具体代码:由于我们使用HAL库,首先需要初始化相关外设。这里我们假设:PWM使用TIM3的通道1,对应引脚PA6(具体根据实际电路连接)方向控制引脚:PA1(IN1),PA2(IN2)按键:PA0(方向切换),PA1(速度切换)注意:这里PA1已经被用作方向控制,所以按键不能使用同一个引脚。因此我们调整按键引脚:方向切换按键接PC0,速度切换按键接PC1。LED:PG13(正转指示),PG14(反转指示)初始化代码(使用CubeMX配置后生成,这里只写关键部分):</think>基于您的需求,我将提供完整的STM32F429直流电机调速系统实现方案,使用HAL库实现所有功能。以下是系统设计和代码实现:
### 系统设计
#### 硬件连接
| 组件 | STM32F429引脚 | 功能描述 |
|-------------|---------------|-------------------------|
| 电机驱动IN1 | PD12 | 正转控制 |
| 电机驱动IN2 | PD13 | 反转控制 |
| PWM输出 | PA8 (TIM1_CH1)| 电机速度控制 |
| 正反转按键 | PC0 | 切换电机方向 |
| 调速按键 | PC1 | 循环切换三级速度 |
| LED1 | PG13 | 正转状态指示 |
| LED2 | PG14 | 反转状态指示 |
| UART TX | PA9 | 串口输出状态信息 |
#### 状态逻辑
```mermaid
stateDiagram-v2
[*] --> 正转_低速
正转_低速 --> 正转_中速: 调速按键
正转_中速 --> 正转_高速: 调速按键
正转_高速 --> 正转_低速: 调速按键
正转_低速 --> 反转_低速: 方向按键
正转_中速 --> 反转_中速: 方向按键
正转_高速 --> 反转_高速: 方向按键
反转_低速 --> 反转_中速: 调速按键
反转_中速 --> 反转_高速: 调速按键
反转_高速 --> 反转_低速: 调速按键
反转_低速 --> 正转_低速: 方向按键
反转_中速 --> 正转_中速: 方向按键
反转_高速 --> 正转_高速: 方向按键
```
### 代码实现
#### 1. 宏定义和全局变量
```c
// 电机状态定义
typedef enum {
FORWARD_LOW,
FORWARD_MEDIUM,
FORWARD_HIGH,
REVERSE_LOW,
REVERSE_MEDIUM,
REVERSE_HIGH
} MotorState;
// 引脚定义
#define DIR_KEY_PIN GPIO_PIN_0
#define SPEED_KEY_PIN GPIO_PIN_1
#define DIR_KEY_PORT GPIOC
#define SPEED_KEY_PORT GPIOC
#define IN1_PIN GPIO_PIN_12
#define IN2_PIN GPIO_PIN_13
#define MOTOR_PORT GPIOD
#define LED_FW_PIN GPIO_PIN_13
#define LED_BW_PIN GPIO_PIN_14
#define LED_PORT GPIOG
// PWM参数
#define PWM_TIMER htim1
#define PWM_CHANNEL TIM_CHANNEL_1
#define PWM_PERIOD 999 // 自动重装载值
#define LOW_SPEED 300 // 30%占空比
#define MEDIUM_SPEED 600 // 60%占空比
#define HIGH_SPEED 900 // 90%占空比
MotorState currentState = FORWARD_LOW; // 初始状态
char uartMsg[50]; // 串口消息缓冲区
```
#### 2. 初始化函数
```c
void System_Init(void) {
// 1. 初始化HAL库
HAL_Init();
// 2. 配置系统时钟
SystemClock_Config();
// 3. 初始化GPIO
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 按键配置 (上拉输入)
GPIO_InitStruct.Pin = DIR_KEY_PIN | SPEED_KEY_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
// 电机控制引脚
GPIO_InitStruct.Pin = IN1_PIN | IN2_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(MOTOR_PORT, &GPIO_InitStruct);
// LED指示灯
GPIO_InitStruct.Pin = LED_FW_PIN | LED_BW_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
// 4. 初始化PWM定时器
MX_TIM1_Init();
HAL_TIM_PWM_Start(&PWM_TIMER, PWM_CHANNEL);
// 5. 初始化串口
MX_USART1_UART_Init();
// 初始状态设置
Update_Motor_State();
}
```
#### 3. PWM定时器配置 (CubeMX生成)
```c
void MX_TIM1_Init(void) {
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 71; // 72MHz/(71+1) = 1MHz
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = PWM_PERIOD;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim1);
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);
HAL_TIM_PWM_Init(&htim1);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = LOW_SPEED;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_MspPostInit(&htim1);
}
```
#### 4. 电机状态更新函数
```c
void Update_Motor_State(void) {
// 1. 设置方向控制引脚
if(currentState <= FORWARD_HIGH) { // 正转状态
HAL_GPIO_WritePin(MOTOR_PORT, IN1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_PORT, IN2_PIN, GPIO_PIN_RESET);
} else { // 反转状态
HAL_GPIO_WritePin(MOTOR_PORT, IN1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_PORT, IN2_PIN, GPIO_PIN_SET);
}
// 2. 设置PWM占空比
switch(currentState) {
case FORWARD_LOW:
case REVERSE_LOW:
__HAL_TIM_SET_COMPARE(&PWM_TIMER, PWM_CHANNEL, LOW_SPEED);
break;
case FORWARD_MEDIUM:
case REVERSE_MEDIUM:
__HAL_TIM_SET_COMPARE(&PWM_TIMER, PWM_CHANNEL, MEDIUM_SPEED);
break;
case FORWARD_HIGH:
case REVERSE_HIGH:
__HAL_TIM_SET_COMPARE(&PWM_TIMER, PWM_CHANNEL, HIGH_SPEED);
break;
}
// 3. 更新LED状态
HAL_GPIO_WritePin(LED_PORT, LED_FW_PIN,
(currentState <= FORWARD_HIGH) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_PORT, LED_BW_PIN,
(currentState >= REVERSE_LOW) ? GPIO_PIN_SET : GPIO_PIN_RESET);
// 4. 串口输出状态信息
const char* direction = (currentState <= FORWARD_HIGH) ? "正转" : "反转";
const char* speed = "";
switch(currentState % 3) {
case 0: speed = "低速"; break;
case 1: speed = "中速"; break;
case 2: speed = "高速"; break;
}
sprintf(uartMsg, "状态: %s-%s\r\n", direction, speed);
HAL_UART_Transmit(&huart1, (uint8_t*)uartMsg, strlen(uartMsg), HAL_MAX_DELAY);
}
```
#### 5. 按键处理函数(带消抖)
```c
void Process_Keys(void) {
static uint32_t lastDirKeyTime = 0;
static uint32_t lastSpeedKeyTime = 0;
const uint32_t debounceTime = 200; // 消抖时间(ms)
// 方向按键处理
if(HAL_GPIO_ReadPin(DIR_KEY_PORT, DIR_KEY_PIN) == GPIO_PIN_RESET) {
if(HAL_GetTick() - lastDirKeyTime > debounceTime) {
// 切换方向状态
switch(currentState) {
case FORWARD_LOW: currentState = REVERSE_LOW; break;
case FORWARD_MEDIUM: currentState = REVERSE_MEDIUM; break;
case FORWARD_HIGH: currentState = REVERSE_HIGH; break;
case REVERSE_LOW: currentState = FORWARD_LOW; break;
case REVERSE_MEDIUM: currentState = FORWARD_MEDIUM; break;
case REVERSE_HIGH: currentState = FORWARD_HIGH; break;
}
Update_Motor_State();
lastDirKeyTime = HAL_GetTick();
}
}
// 速度按键处理
if(HAL_GPIO_ReadPin(SPEED_KEY_PORT, SPEED_KEY_PIN) == GPIO_PIN_RESET) {
if(HAL_GetTick() - lastSpeedKeyTime > debounceTime) {
// 循环切换速度档位
switch(currentState) {
case FORWARD_LOW: currentState = FORWARD_MEDIUM; break;
case FORWARD_MEDIUM: currentState = FORWARD_HIGH; break;
case FORWARD_HIGH: currentState = FORWARD_LOW; break;
case REVERSE_LOW: currentState = REVERSE_MEDIUM; break;
case REVERSE_MEDIUM: currentState = REVERSE_HIGH; break;
case REVERSE_HIGH: currentState = REVERSE_LOW; break;
}
Update_Motor_State();
lastSpeedKeyTime = HAL_GetTick();
}
}
}
```
#### 6. 主循环
```c
int main(void) {
System_Init();
while(1) {
Process_Keys();
HAL_Delay(10); // 降低CPU占用率
}
}
```
### 功能说明
1. **PWM三级调速**:
- 低速:占空比30% ($D = 0.3$)
- 中速:占空比60% ($D = 0.6$)
- 高速:占空比90% ($D = 0.9$)
2. **正反转控制**:
- 通过IN1/IN2引脚电平组合实现
- 正转:IN1=1, IN2=0
- 反转:IN1=0, IN2=1
3. **状态指示**:
- PG13 LED:正转时点亮
- PG14 LED:反转时点亮
- 串口输出:格式"正转-低速"等
4. **按键消抖**:
- 采用时间戳方式实现200ms消抖
- 防止机械按键抖动导致多次触发
### 扩展建议
1. 增加编码器反馈实现闭环控制
2. 添加PID算法提高速度稳定性
3. 实现软启动/软停止功能
4. 增加过流保护机制
阅读全文