STM32入门教程:电子锁应用
在本教程中,我们将学习如何使用STM32微控制器来实现一个简单的电子锁应用。电子锁是一种通过输入正确的密码来解锁的锁,它使用数字键盘输入密码,并通过驱动电机或继电器来控制锁的开闭。我们将使用STM32的GPIO控制数字键盘和驱动电机,以及通过UART和计算机通信来设置和验证密码。本教程将分为以下几个部分:
- 硬件准备
- 密码设置与验证
- 数字键盘和GPIO配置
- 驱动电机控制
- 完整代码案例
硬件准备
首先,我们需要以下硬件部件:
- STM32开发板(如STM32F103C8T6)
- 4x4数字键盘模块
- 直流电机(或继电器模块)
- Jumper wires和面包板
将STM32开发板与数字键盘模块和电机(或继电器模块)连接起来,并确保电源接入开发板。
密码设置与验证
在这个应用中,我们将预先设置一个4位数字密码,并在输入密码时进行验证。首先,在代码中定义一个全局变量来存储密码,例如:
uint8_t password[4] = {1, 2, 3, 4}; // 设置密码为1 2 3 4
然后,我们需要一个函数来验证输入的密码是否正确。我们可以创建一个名为checkPassword
的函数来实现这个功能。函数的输入参数是一个指向密码数组的指针和一个输入的4位数字密码。函数将返回一个布尔值,表示密码是否正确。
bool checkPassword(uint8_t *correctPassword, uint8_t *inputPassword) {
for (int i = 0; i < 4; i++) {
if (correctPassword[i] != inputPassword[i]) {
return false;
}
}
return true;
}
数字键盘和GPIO配置
接下来,我们需要配置STM32的GPIO来与数字键盘进行交互。4x4数字键盘模块具有16个按键,分为4行和4列。我们可以通过轮询来检测按键的输入。首先,我们需要定义4个GPIO引脚来控制行,以及4个GPIO引脚来读取列的状态。例如,我们可以将行连接到开发板的PB0至PB3引脚,将列连接到开发板的PB4至PB7引脚。
#define ROW_GPIO_PORT GPIOB
#define COL_GPIO_PORT GPIOB
#define ROW_GPIO_PIN_0 GPIO_PIN_0
#define ROW_GPIO_PIN_1 GPIO_PIN_1
#define ROW_GPIO_PIN_2 GPIO_PIN_2
#define ROW_GPIO_PIN_3 GPIO_PIN_3
#define COL_GPIO_PIN_0 GPIO_PIN_4
#define COL_GPIO_PIN_1 GPIO_PIN_5
#define COL_GPIO_PIN_2 GPIO_PIN_6
#define COL_GPIO_PIN_3 GPIO_PIN_7
然后,我们需要在代码中初始化这些引脚。我们可以使用STM32 HAL库提供的函数来完成这个任务。
GPIO_InitTypeDef GPIO_InitStruct;
// 初始化行引脚
GPIO_InitStruct.Pin = ROW_GPIO_PIN_0 | ROW_GPIO_PIN_1 | ROW_GPIO_PIN_2 | ROW_GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(ROW_GPIO_PORT, &GPIO_InitStruct);
// 初始化列引脚
GPIO_InitStruct.Pin = COL_GPIO_PIN_0 | COL_GPIO_PIN_1 | COL_GPIO_PIN_2 | COL_GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(COL_GPIO_PORT, &GPIO_InitStruct);
驱动电机控制
最后,在验证密码之后,我们可以使用GPIO控制电机或继电器来控制锁的开闭。我们可以定义两个GPIO引脚来控制电机的正向和反向转动。例如,我们可以将电机的正向引脚连接到开发板的PA0引脚,将反向引脚连接到开发板的PA1引脚。
#define MOTOR_FORWARD_GPIO_PIN GPIO_PIN_0
#define MOTOR_BACKWARD_GPIO_PIN GPIO_PIN_1
#define MOTOR_GPIO_PORT GPIOA
然后,我们需要在代码中初始化这些引脚。
GPIO_InitStruct.Pin = MOTOR_FORWARD_GPIO_PIN | MOTOR_BACKWARD_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(MOTOR_GPIO_PORT, &GPIO_InitStruct);
在验证密码之后,我们根据需要控制这两个引脚来进行电机转动。
// 电机正转
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_FORWARD_GPIO_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_BACKWARD_GPIO_PIN, GPIO_PIN_RESET);
// 等待一段时间
HAL_Delay(1000);
// 电机停止
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_FORWARD_GPIO_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_BACKWARD_GPIO_PIN, GPIO_PIN_RESET);
完整代码案例
以下是完整的STM32电子锁应用的代码:
#include "main.h"
GPIO_TypeDef *ROW_GPIO_PORT = GPIOB;
GPIO_TypeDef *COL_GPIO_PORT = GPIOB;
uint16_t ROW_GPIO_PIN_0 = GPIO_PIN_0;
uint16_t ROW_GPIO_PIN_1 = GPIO_PIN_1;
uint16_t ROW_GPIO_PIN_2 = GPIO_PIN_2;
uint16_t ROW_GPIO_PIN_3 = GPIO_PIN_3;
uint16_t COL_GPIO_PIN_0 = GPIO_PIN_4;
uint16_t COL_GPIO_PIN_1 = GPIO_PIN_5;
uint16_t COL_GPIO_PIN_2 = GPIO_PIN_6;
uint16_t COL_GPIO_PIN_3 = GPIO_PIN_7;
uint16_t MOTOR_FORWARD_GPIO_PIN = GPIO_PIN_0;
uint16_t MOTOR_BACKWARD_GPIO_PIN = GPIO_PIN_1;
GPIO_TypeDef *MOTOR_GPIO_PORT = GPIOA;
uint8_t password[4] = {1, 2, 3, 4}; // 设置密码为1 2 3 4
bool checkPassword(uint8_t *correctPassword, uint8_t *inputPassword) {
for (int i = 0; i < 4; i++) {
if (correctPassword[i] != inputPassword[i]) {
return false;
}
}
return true;
}
void GPIO_Config(void) {
GPIO_InitTypeDef GPIO_InitStruct;
// 初始化行引脚
GPIO_InitStruct.Pin = ROW_GPIO_PIN_0 | ROW_GPIO_PIN_1 | ROW_GPIO_PIN_2 | ROW_GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(ROW_GPIO_PORT, &GPIO_InitStruct);
// 初始化列引脚
GPIO_InitStruct.Pin = COL_GPIO_PIN_0 | COL_GPIO_PIN_1 | COL_GPIO_PIN_2 | COL_GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(COL_GPIO_PORT, &GPIO_InitStruct);
// 初始化电机引脚
GPIO_InitStruct.Pin = MOTOR_FORWARD_GPIO_PIN | MOTOR_BACKWARD_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(MOTOR_GPIO_PORT, &GPIO_InitStruct);
}
int main(void) {
HAL_Init();
GPIO_Config();
uint8_t inputPassword[4] = {0, 0, 0, 0};
uint8_t inputIndex = 0;
while (1) {
// 读取按键输入
for (int i = 0; i < 4; i++) {
HAL_GPIO_WritePin(ROW_GPIO_PORT, ROW_GPIO_PIN_0 << i, GPIO_PIN_RESET);
for (int j = 0; j < 4; j++) {
if (HAL_GPIO_ReadPin(COL_GPIO_PORT, COL_GPIO_PIN_0 << j) == GPIO_PIN_RESET) {
inputPassword[inputIndex] = i * 4 + j + 1;
inputIndex++;
while (HAL_GPIO_ReadPin(COL_GPIO_PORT, COL_GPIO_PIN_0 << j) == GPIO_PIN_RESET);
}
}
HAL_GPIO_WritePin(ROW_GPIO_PORT, ROW_GPIO_PIN_0 << i, GPIO_PIN_SET);
}
// 验证密码
if (input