#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_tim.h"
#include "lcd1602.h"
// 硬件引脚定义
#define FLOW_SENSOR_PIN GPIO_Pin_0 // PA0(外部中断)
#define STEPPER_A GPIO_Pin_1 // PB1
#define STEPPER_B GPIO_Pin_2 // PB2
#define BUZZER_PIN GPIO_Pin_3 // PB3
#define KEY_SET GPIO_Pin_4 // PB4(设置键)
// 系统参数
#define FLOW_CALIB_FACTOR 7.5f // 流量校准系数(L/min/Hz)
#define SAMPLE_INTERVAL 1000 // 流量采样间隔(ms)
#define FLOW_TOLERANCE 0.5f // 流量偏差阈值(L)
// 全局变量
volatile uint32_t pulse_count = 0; // 流量脉冲计数
float current_flow = 0.0f; // 当前流量(L/min)
float target_flow = 1.0f; // 目标流量(L/min)
uint8_t system_mode = 0; // 系统模式(0:停机 1:运行)
uint8_t alarm_flag = 0; // 报警标志
// 步进电机相位表(四相四拍)
const uint8_t phase_table[4] = {0x01, 0x02, 0x04, 0x08};
// PID参数
typedef struct {
float Kp, Ki, Kd;
float integral;
float prev_error;
} PID_Controller;
PID_Controller pid = {0.8, 0.05, 0.1, 0, 0};
/***************************** 硬件初始化 *****************************/
void HW_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
// 启用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
// 流量传感器输入(浮空输入)
GPIO_InitStruct.GPIO_Pin = FLOW_SENSOR_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 步进电机输出(推挽输出)
GPIO_InitStruct.GPIO_Pin = STEPPER_A | STEPPER_B;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// 蜂鸣器控制
GPIO_InitStruct.GPIO_Pin = BUZZER_PIN;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// 外部中断配置(PA0)
EXTI_InitTypeDef EXTI_InitStruct = {
.EXTI_Line = EXTI_Line0,
.EXTI_Mode = EXTI_Mode_Interrupt,
.EXTI_Trigger = EXTI_Trigger_Rising,
.EXTI_LineCmd = ENABLE
};
EXTI_Init(&EXTI_InitStruct);
NVIC_InitTypeDef NVIC_InitStruct = {
.NVIC_IRQChannel = EXTI0_IRQn,
.NVIC_IRQChannelPreemptionPriority = 0,
.NVIC_IRQChannelSubPriority = 0,
.NVIC_IRQChannelCmd = ENABLE
};
NVIC_Init(&NVIC_InitStruct);
// 定时器3配置(1ms中断)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM_InitStruct = {
.TIM_Prescaler = 7200 - 1, // 72MHz/7200=10kHz
.TIM_CounterMode = TIM_CounterMode_Up,
.TIM_Period = 10000 - 1, // 1秒周期
.TIM_ClockDivision = TIM_CKD_DIV1
};
TIM_TimeBaseInit(TIM3, &TIM_InitStruct);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM3, ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
NVIC_Init(&NVIC_InitStruct);
}
/***************************** PID计算 *****************************/
float PID_Compute(float setpoint, float input) {
float error = setpoint - input;
pid.integral += error;
float derivative = error - pid.prev_error;
pid.prev_error = error;
return pid.Kp*error + pid.Ki*pid.integral + pid.Kd*derivative;
}
/***************************** 步进电机控制 *****************************/
void Stepper_Drive(int steps) {
static uint8_t phase = 0;
static uint32_t last_step = 0;
if(steps != 0 && (HAL_GetTick() - last_step) > 10) { // 10ms步间隔
phase = (phase + (steps > 0 ? 1 : 3)) % 4; // 正反转控制
GPIOB->ODR = (GPIOB->ODR & 0xFFF0) | (phase_table[phase] >> 1);
last_step = HAL_GetTick();
}
}
/***************************** 中断服务程序 *****************************/
void EXTI0_IRQHandler(void) {
if(EXTI_GetITStatus(EXTI_Line0) != RESET) {
pulse_count++; // 脉冲计数
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void TIM3_IRQHandler(void) {
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
// 计算实时流量
current_flow = (pulse_count / FLOW_CALIB_FACTOR) * (60000.0 / SAMPLE_INTERVAL);
pulse_count = 0;
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
/***************************** 主程序 *****************************/
int main(void) {
// 初始化阶段
SystemInit();
HW_Init();
LCD_Init();
__enable_irq();
// 主循环
while(1) {
// 按键处理
if(GPIO_ReadInputDataBit(GPIOB, KEY_SET) == Bit_RESET) {
DelayMs(20);
if(GPIO_ReadInputDataBit(GPIOB, KEY_SET) == Bit_RESET) {
system_mode ^= 0x01;
while(GPIO_ReadInputDataBit(GPIOB, KEY_SET) == Bit_RESET);
}
}
// 运行模式控制
if(system_mode) {
float control = PID_Compute(target_flow, current_flow);
Stepper_Drive((int)control);
// 异常检测
alarm_flag = (fabs(current_flow - target_flow) > FLOW_TOLERANCE);
} else {
Stepper_Drive(0);
alarm_flag = 0;
}
// 显示更新
char buf[17];
snprintf(buf, sizeof(buf), "Flow:%5.2f L/m", current_flow);
LCD_Write_String(0, 0, buf);
snprintf(buf, sizeof(buf), "Target:%5.1f L/m", target_flow);
LCD_Write_String(0, 1, buf);
// 报警控制
GPIO_WriteBit(GPIOB, BUZZER_PIN, alarm_flag ? Bit_SET : Bit_RESET);
}
}