以下是一个基于STM32的简单智能停车场收费系统的代码案例。本案例主要涉及到STM32的外设使用、中断处理以及串口通信等方面。
- 硬件准备:
- STM32开发板(本案例以STM32F103为例)
- 1602液晶显示屏模块
- 红外传感器模块
- 数码管显示模块
- 扩展按键模块
- 其他所需电子元件和线路连接
- 软件准备:
- Keil MDK开发环境
- STM32 HAL库
-
连接硬件: 将1602液晶显示屏模块、红外传感器模块、数码管显示模块和扩展按键模块与STM32开发板连接,具体连接方式可参考各个模块的datasheet。
-
编写代码: 下面是一个简单的智能停车场收费系统的代码案例:
#include "stm32f1xx_hal.h"
#include "stdio.h"
// 定义红外传感器GPIO口
#define IR_SENSOR_GPIO GPIOA
#define IR_SENSOR_PIN GPIO_PIN_0
// 定义数码管显示GPIO口
#define SEGMENT_DISPLAY_GPIO GPIOB
#define SEGMENT_DISPLAY_PIN1 GPIO_PIN_0
#define SEGMENT_DISPLAY_PIN2 GPIO_PIN_1
#define SEGMENT_DISPLAY_PIN3 GPIO_PIN_2
#define SEGMENT_DISPLAY_PIN4 GPIO_PIN_3
// 定义扩展按键GPIO口
#define EXT_KEY_GPIO GPIOC
#define EXT_KEY_PIN GPIO_PIN_13
// 定义液晶显示GPIO口
#define LCD_GPIO GPIOB
#define LCD_RS_PIN GPIO_PIN_4
#define LCD_EN_PIN GPIO_PIN_5
#define LCD_D4_PIN GPIO_PIN_6
#define LCD_D5_PIN GPIO_PIN_7
#define LCD_D6_PIN GPIO_PIN_8
#define LCD_D7_PIN GPIO_PIN_9
// 定义停车场收费参数
#define RATE 1.0 // 每分钟收费1元
// 定义全局变量
volatile uint8_t parking_status = 0; // 停车状态:0-未停车,1-已停车
volatile uint32_t start_time = 0; // 开始停车时间
volatile uint32_t end_time = 0; // 结束停车时间
// 定义函数原型
void GPIO_Init();
void Timer_Init();
void EXTI_Init();
void LCD_Init();
void LCD_WriteCommand(uint8_t command);
void LCD_WriteData(uint8_t data);
void LCD_WriteString(char* string);
void LCD_WriteNumber(uint32_t number);
void DisplayTime(uint32_t time);
void DisplayFee(uint32_t fee);
int main()
{
// 初始化硬件
GPIO_Init();
Timer_Init();
EXTI_Init();
LCD_Init();
while(1)
{
if(parking_status == 0)
{
LCD_WriteCommand(0x01); // 清屏
LCD_WriteString("Welcome");
if(HAL_GPIO_ReadPin(EXT_KEY_GPIO, EXT_KEY_PIN) == GPIO_PIN_SET)
{
HAL_Delay(20); // 延时去抖
if(HAL_GPIO_ReadPin(EXT_KEY_GPIO, EXT_KEY_PIN) == GPIO_PIN_SET)
{
// 开始停车
parking_status = 1;
start_time = HAL_GetTick(); // 记录开始停车时间
}
}
}
else
{
uint32_t current_time = HAL_GetTick(); // 当前时间
uint32_t parking_time = current_time - start_time; // 停车时长
uint32_t fee = parking_time * RATE; // 收费金额
LCD_WriteCommand(0x01); // 清屏
LCD_WriteString("Parking Time:");
DisplayTime(parking_time);
LCD_WriteString("Fee:");
DisplayFee(fee);
if(HAL_GPIO_ReadPin(EXT_KEY_GPIO, EXT_KEY_PIN) == GPIO_PIN_SET)
{
HAL_Delay(20); // 延时去抖
if(HAL_GPIO_ReadPin(EXT_KEY_GPIO, EXT_KEY_PIN) == GPIO_PIN_SET)
{
// 结束停车
parking_status = 0;
end_time = current_time; // 记录结束停车时间
}
}
}
}
}
void GPIO_Init()
{
// 启用GPIOA、GPIOB、GPIOC时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
// 初始化红外传感器GPIO口
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = IR_SENSOR_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(IR_SENSOR_GPIO, &GPIO_InitStruct);
// 初始化数码管显示GPIO口
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pin = SEGMENT_DISPLAY_PIN1 | SEGMENT_DISPLAY_PIN2 |
SEGMENT_DISPLAY_PIN3 | SEGMENT_DISPLAY_PIN4;
HAL_GPIO_Init(SEGMENT_DISPLAY_GPIO, &GPIO_InitStruct);
// 初始化扩展按键GPIO口
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Pin = EXT_KEY_PIN;
HAL_GPIO_Init(EXT_KEY_GPIO, &GPIO_InitStruct);
// 初始化液晶显示GPIO口
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pin = LCD_RS_PIN | LCD_EN_PIN |
LCD_D4_PIN | LCD_D5_PIN |
LCD_D6_PIN | LCD_D7_PIN;
HAL_GPIO_Init(LCD_GPIO, &GPIO_InitStruct);
}
void Timer_Init()
{
// 启用TIM2时钟
__HAL_RCC_TIM2_CLK_ENABLE();
// 配置TIM2为计数器
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = SystemCoreClock / 1000 - 1; // 设置预分频器,1ms为一个计时单位
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0xFFFFFFFF; // 定时器溢出时间
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim2);
// 启动TIM2
HAL_TIM_Base_Start(&htim2);
}
void EXTI_Init()
{
// 启用EXTI时钟
__HAL_RCC_AFIO_CLK_ENABLE();
// 配置EXTI中断线
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0); // 设置中断优先级
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); // 使能中断
// 配置EXTI中断触发方式(下降沿触发)
EXTI_HandleTypeDef EXTI_InitStruct;
EXTI_InitStruct.Line = EXTI_LINE_13;
EXTI_InitStruct.Mode = EXTI_MODE_INTERRUPT;
EXTI_InitStruct.Trigger = EXTI_TRIGGER_FALLING;
EXTI_InitStruct.GPIOSel = EXTI_GPIOC;
HAL_EXTI_SetConfigLine(&EXTI_InitStruct);
}
void LCD_Init()
{
HAL_Delay(50); // 上电初始化延时
// 4位数据线方式,DL=0
LCD_WriteCommand(0x28);
HAL_Delay(5);
// 显示开关,D=1,C=0,B=0
LCD_WriteCommand(0x0C);
HAL_Delay(5);
// 清屏
LCD_WriteCommand(0x01);
HAL_Delay(5);
// 光标移动方向,I/D=1,S=0
LCD_WriteCommand(0x06);
HAL_Delay(5);
}
void LCD_WriteCommand(uint8_t command)
{
HAL_GPIO_WritePin(LCD_GPIO, LCD_RS_PIN, GPIO_PIN_RESET); // 指令模式
HAL_GPIO_WritePin(LCD_GPIO, LCD_EN_PIN, GPIO_PIN_RESET); // 使能拉低
HAL_GPIO_WritePin(LCD_GPIO, LCD_D4_PIN, (command >> 4) & 0x01);
HAL_GPIO_WritePin(LCD_GPIO, LCD_D5_PIN, (command >> 5) & 0x01);
HAL_GPIO_WritePin(LCD_GPIO, LCD_D6_PIN, (command >> 6) & 0x01);
HAL_GPIO_WritePin(LCD_GPIO, LCD_D7_PIN, (command >> 7) & 0x01);
HAL_GPIO_WritePin(LCD_GPIO, LCD_EN_PIN, GPIO_PIN_SET); // 使能拉高
HAL_Delay(1); // 持续时间
HAL_GPIO_WritePin(LCD_GPIO, LCD_EN_PIN, GPIO_PIN_RESET); // 使能拉