无线充电电动牙刷软件源码

基于STM32+Qi无线充电+无刷电机控制


一、系统架构

Qi无线充电 → 电池管理 → STM32主控 → 无刷电机驱动 → 振动电机
      ↓           ↓          ↓           ↓
   充电状态    电量检测    触摸感应      PWM控制
      ↓           ↓          ↓           ↓
   LED指示    低电保护    模式切换    强度调节

主要特性

  • 支持Qi 5W无线充电
  • 智能电池管理(过充/过放保护)
  • 触摸感应开关
  • 四种清洁模式
  • 压力感应保护
  • 2分钟智能定时
  • 30秒换区提醒
  • 低功耗设计(待机<10μA)

二、硬件配置

1、主控芯片

  • STM32L051C8T6:超低功耗,32MHz, 64KB Flash, 8KB RAM
  • 工作电流:运行89μA/MHz,待机0.4μA

2、无线充电接收

  • BQ51013B:Qi无线充电接收IC
  • 输出:5V/1A
  • 效率:>85%

3、电池管理

  • BQ29700:锂电池保护
  • 电池:3.7V 600mAh 锂电池
  • 充电电流:500mA

4、电机驱动

  • DRV8837:H桥驱动
  • 电机:无刷振动电机(10000-40000rpm)

5、触摸感应

  • TTP223 或 STM32自带触摸按键

三、软件架构

Toothbrush_Firmware/
├── Core/
│   ├── main.c
│   └── system_stm32l0xx.c
├── Drivers/
│   ├── battery.c
│   ├── wireless_charge.c
│   ├── motor.c
│   ├── touch.c
│   ├── timer.c
│   └── led.c
├── Application/
│   ├── cleaning_mode.c
│   ├── user_interface.c
│   ├── power_manager.c
│   └── error_handler.c
└── Config/
    ├── hardware_config.h
    └── system_config.h

四、核心源码实现

1、主控制头文件

// toothbrush.h
#ifndef __TOOTHBRUSH_H
#define __TOOTHBRUSH_H

#include "stm32l0xx_hal.h"

// 系统状态
typedef enum {
    STATE_POWER_OFF = 0,
    STATE_STANDBY,
    STATE_CHARGING,
    STATE_OPERATING,
    STATE_ERROR
} System_State_t;

// 清洁模式
typedef enum {
    MODE_CLEAN = 0,      // 清洁模式
    MODE_WHITE,          // 美白模式
    MODE_SENSITIVE,      // 敏感模式
    MODE_MASSAGE,        // 按摩模式
    MODE_MAX
} Cleaning_Mode_t;

// 电池状态
typedef enum {
    BATTERY_EMPTY = 0,   // 电量<10%
    BATTERY_LOW,         // 10%-20%
    BATTERY_MEDIUM,      // 20%-80%
    BATTERY_HIGH,        // 80%-100%
    BATTERY_FULL         // 100%
} Battery_Level_t;

// 牙刷结构体
typedef struct {
    System_State_t state;
    Cleaning_Mode_t mode;
    Battery_Level_t battery_level;
    
    uint8_t intensity;           // 强度 1-5
    uint16_t timer_seconds;      // 计时器
    uint8_t pressure;            // 压力 0-100%
    uint8_t quadrant;            // 当前区域 1-4
    
    uint8_t led_brightness;      // LED亮度
    uint8_t motor_speed;         // 电机速度
    uint8_t auto_shutdown;       // 自动关机标志
} Toothbrush_System_t;

// 全局系统实例
extern Toothbrush_System_t toothbrush;

// 函数声明
void System_Init(void);
void System_State_Machine(void);
void Enter_Low_Power_Mode(void);
void System_Shutdown(void);
void System_Reset(void);

#endif

2、主程序框架

// main.c
#include "toothbrush.h"
#include "battery.h"
#include "wireless_charge.h"
#include "motor.h"
#include "touch.h"
#include "timer.h"
#include "led.h"

Toothbrush_System_t toothbrush = {0};

int main(void)
{
    // 1. HAL库初始化
    HAL_Init();
    
    // 2. 系统时钟配置(低功耗)
    SystemClock_Config_LowPower();
    
    // 3. 外设初始化
    MX_GPIO_Init();
    MX_ADC_Init();
    MX_TIM2_Init();     // 电机PWM
    MX_TIM6_Init();     // 系统定时器
    MX_IWDG_Init();     // 看门狗
    
    // 4. 驱动初始化
    Battery_Init();
    Wireless_Charge_Init();
    Motor_Init();
    Touch_Init();
    LED_Init();
    Timer_Init();
    
    // 5. 系统初始化
    System_Init();
    
    // 6. 启动看门狗
    HAL_IWDG_Start(&hiwdg);
    
    // 7. 主循环
    while (1)
    {
        // 系统状态机
        System_State_Machine();
        
        // 喂狗
        HAL_IWDG_Refresh(&hiwdg);
        
        // 低功耗处理
        if (toothbrush.state == STATE_STANDBY) {
            Enter_Low_Power_Mode();
        }
    }
}

// 系统初始化
void System_Init(void)
{
    // 默认状态
    toothbrush.state = STATE_STANDBY;
    toothbrush.mode = MODE_CLEAN;
    toothbrush.intensity = 3;  // 默认中等强度
    toothbrush.timer_seconds = 0;
    toothbrush.quadrant = 1;
    toothbrush.auto_shutdown = 0;
    
    // 读取EEPROM保存的设置
    Load_User_Settings();
    
    // 检查电池状态
    Battery_Check_Status();
    
    // 检查是否在充电座上
    if (Wireless_Charge_Detected()) {
        toothbrush.state = STATE_CHARGING;
    }
}

// 系统状态机
void System_State_Machine(void)
{
    static uint32_t state_timer = 0;
    
    switch (toothbrush.state)
    {
        case STATE_POWER_OFF:
            // 完全关机,只有充电可唤醒
            if (Wireless_Charge_Detected()) {
                toothbrush.state = STATE_CHARGING;
            }
            break;
            
        case STATE_STANDBY:
            // 待机状态,等待用户操作
            if (Touch_Detected()) {
                toothbrush.state = STATE_OPERATING;
                state_timer = HAL_GetTick();
                
                // 启动电机
                Motor_Start(toothbrush.mode, toothbrush.intensity);
                
                // LED显示模式
                LED_Show_Mode(toothbrush.mode);
            }
            break;
            
        case STATE_CHARGING:
            // 充电状态
            Wireless_Charge_Process();
            
            // 更新LED充电状态
            LED_Show_Charging_Status();
            
            // 充满电后进入待机
            if (Battery_Is_Full()) {
                toothbrush.state = STATE_STANDBY;
            }
            break;
            
        case STATE_OPERATING:
            // 工作状态
            if (Touch_Long_Press()) {
                // 长按关机
                Motor_Stop();
                toothbrush.state = STATE_STANDBY;
                break;
            }
            
            if (Touch_Double_Click()) {
                // 双击切换模式
                toothbrush.mode = (toothbrush.mode + 1) % MODE_MAX;
                Motor_Set_Mode(toothbrush.mode);
                LED_Show_Mode(toothbrush.mode);
            }
            
            // 2分钟定时
            if (HAL_GetTick() - state_timer >= 120000) {  // 2分钟
                Motor_Stop();
                toothbrush.state = STATE_STANDBY;
                toothbrush.auto_shutdown = 1;
                
                // 关机提示
                LED_Shutdown_Alert();
                break;
            }
            
            // 30秒换区提醒
            static uint8_t last_quadrant = 0;
            if (toothbrush.timer_seconds >= 30 && 
                toothbrush.timer_seconds % 30 == 0 &&
                last_quadrant != toothbrush.quadrant) {
                
                toothbrush.quadrant++;
                if (toothbrush.quadrant > 4) toothbrush.quadrant = 1;
                
                // 振动提示换区
                Motor_Quadrant_Alert();
                LED_Show_Quadrant(toothbrush.quadrant);
                
                last_quadrant = toothbrush.quadrant;
            }
            
            // 压力保护
            if (toothbrush.pressure > 80) {  // 压力过大
                Motor_Reduce_Power();
                LED_Show_Pressure_Warning();
            }
            
            break;
            
        case STATE_ERROR:
            // 错误状态
            Error_Handler();
            break;
    }
}

// 进入低功耗模式
void Enter_Low_Power_Mode(void)
{
    // 关闭不需要的外设
    HAL_ADC_Stop(&hadc);
    HAL_TIM_Base_Stop(&htim6);
    
    // 进入停止模式
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    
    // 唤醒后重新初始化时钟
    SystemClock_Config_LowPower();
}

3、无线充电管理

// wireless_charge.c
#include "wireless_charge.h"

// 无线充电状态
typedef enum {
    CHARGE_IDLE = 0,
    CHARGE_CHARGING,
    CHARGE_DONE,
    CHARGE_FAULT
} Charge_State_t;

static Charge_State_t charge_state = CHARGE_IDLE;
static uint32_t charge_timer = 0;

// 初始化无线充电
void Wireless_Charge_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 使能时钟
    __HAL_RCC_GPIOC_CLK_ENABLE();
    
    // 配置充电检测引脚
    GPIO_InitStruct.Pin = GPIO_PIN_13;  // 充电检测
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    // 配置充电状态引脚
    GPIO_InitStruct.Pin = GPIO_PIN_14;  // 充电状态
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

// 检测是否在充电座上
uint8_t Wireless_Charge_Detected(void)
{
    // 检测CHG_DET引脚(低电平表示在充电座上)
    return (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET);
}

// 获取充电状态
Charge_State_t Wireless_Charge_Get_Status(void)
{
    // CHG_STAT引脚:高电平=充电中,低电平=充满/未充电
    if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_14) == GPIO_PIN_SET) {
        return CHARGE_CHARGING;
    } else {
        if (Wireless_Charge_Detected()) {
            return CHARGE_DONE;
        } else {
            return CHARGE_IDLE;
        }
    }
}

// 充电处理
void Wireless_Charge_Process(void)
{
    static uint8_t last_state = CHARGE_IDLE;
    Charge_State_t current_state = Wireless_Charge_Get_Status();
    
    if (current_state != last_state) {
        last_state = current_state;
        
        switch (current_state) {
            case CHARGE_CHARGING:
                printf("开始充电...\n");
                charge_timer = HAL_GetTick();
                break;
                
            case CHARGE_DONE:
                printf("充电完成\n");
                // 记录充电时间
                uint32_t charge_time = HAL_GetTick() - charge_timer;
                Save_Charge_History(charge_time);
                break;
                
            case CHARGE_FAULT:
                printf("充电故障\n");
                Error_Handler();
                break;
                
            default:
                break;
        }
    }
    
    // 充电过程保护
    if (current_state == CHARGE_CHARGING) {
        // 检查电池温度
        float temp = Battery_Get_Temperature();
        if (temp > 45.0f) {  // 温度过高
            // 降低充电电流或暂停充电
            Wireless_Charge_Reduce_Current();
        }
        
        // 检查充电时间
        if (HAL_GetTick() - charge_timer > 4*60*60*1000) {  // 4小时超时
            printf("充电超时\n");
            Wireless_Charge_Stop();
        }
    }
}

// 获取充电电流(估算)
float Wireless_Charge_Get_Current(void)
{
    // 通过ADC读取电流检测电阻电压
    uint16_t adc_value = 0;
    float voltage, current;
    
    HAL_ADC_Start(&hadc);
    HAL_ADC_PollForConversion(&hadc, 10);
    adc_value = HAL_ADC_GetValue(&hadc);
    HAL_ADC_Stop(&hadc);
    
    // 计算电流(检测电阻0.1Ω)
    voltage = adc_value * 3.3f / 4095.0f;
    current = voltage / 0.1f;  // I = V/R
    
    return current;
}

4、电池管理系统

// battery.c
#include "battery.h"
#include <math.h>

// 电池参数
#define BATTERY_CAPACITY_MAH     600    // 600mAh
#define BATTERY_VOLTAGE_FULL     4.2f   // 满电电压
#define BATTERY_VOLTAGE_EMPTY    3.0f   // 放空电压
#define BATTERY_VOLTAGE_LOW      3.3f   // 低电报警

static float battery_voltage = 0;
static float battery_current = 0;
static float battery_temperature = 25.0f;
static uint32_t battery_capacity_remain = BATTERY_CAPACITY_MAH;

// 初始化电池管理
void Battery_Init(void)
{
    // 初始化ADC用于电压检测
    MX_ADC_Init();
    
    // 初始化温度传感器
    __HAL_RCC_ADC1_CLK_ENABLE();
    
    // 校准ADC
    HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED);
}

// 读取电池电压
float Battery_Read_Voltage(void)
{
    uint16_t adc_value = 0;
    float voltage;
    
    // 分压比 2:1 (8.4V->4.2V)
    HAL_ADC_Start(&hadc);
    HAL_ADC_PollForConversion(&hadc, 10);
    adc_value = HAL_ADC_GetValue(&hadc);
    HAL_ADC_Stop(&hadc);
    
    // 计算实际电压
    voltage = adc_value * 3.3f * 2.0f / 4095.0f;
    
    // 滤波处理
    static float filtered_voltage = 0;
    filtered_voltage = filtered_voltage * 0.9f + voltage * 0.1f;
    
    return filtered_voltage;
}

// 估算剩余电量
uint8_t Battery_Get_Percentage(void)
{
    float voltage = Battery_Read_Voltage();
    float percentage;
    
    // 电压-电量曲线(简化)
    if (voltage >= BATTERY_VOLTAGE_FULL) {
        percentage = 100.0f;
    } else if (voltage <= BATTERY_VOLTAGE_EMPTY) {
        percentage = 0.0f;
    } else {
        // 线性估算
        percentage = (voltage - BATTERY_VOLTAGE_EMPTY) * 100.0f / 
                    (BATTERY_VOLTAGE_FULL - BATTERY_VOLTAGE_EMPTY);
    }
    
    // 库仑计修正
    percentage = percentage * 0.7f + (battery_capacity_remain * 100.0f / BATTERY_CAPACITY_MAH) * 0.3f;
    
    return (uint8_t)percentage;
}

// 检查电池状态
Battery_Level_t Battery_Check_Status(void)
{
    uint8_t percentage = Battery_Get_Percentage();
    Battery_Level_t level;
    
    if (percentage < 10) {
        level = BATTERY_EMPTY;
    } else if (percentage < 20) {
        level = BATTERY_LOW;
    } else if (percentage < 80) {
        level = BATTERY_MEDIUM;
    } else if (percentage < 100) {
        level = BATTERY_HIGH;
    } else {
        level = BATTERY_FULL;
    }
    
    // 更新系统状态
    toothbrush.battery_level = level;
    
    // 低电保护
    if (level == BATTERY_EMPTY) {
        Motor_Stop();
        toothbrush.state = STATE_STANDBY;
        LED_Show_Battery_Empty();
    }
    
    return level;
}

// 库仑计(估算消耗电量)
void Battery_Coulomb_Counter(int16_t current_ma, uint32_t time_ms)
{
    static uint32_t last_time = 0;
    uint32_t delta_time = time_ms - last_time;
    
    if (delta_time > 1000) {  // 每秒更新一次
        // 消耗电量 = 电流 * 时间
        float consumed_mah = fabs(current_ma) * delta_time / 3600000.0f;
        
        if (current_ma > 0) {
            // 充电
            battery_capacity_remain += (uint32_t)consumed_mah;
            if (battery_capacity_remain > BATTERY_CAPACITY_MAH) {
                battery_capacity_remain = BATTERY_CAPACITY_MAH;
            }
        } else {
            // 放电
            if (battery_capacity_remain > consumed_mah) {
                battery_capacity_remain -= (uint32_t)consumed_mah;
            } else {
                battery_capacity_remain = 0;
            }
        }
        
        last_time = time_ms;
    }
}

// 获取电池温度
float Battery_Get_Temperature(void)
{
    uint16_t adc_value = 0;
    float voltage, temperature;
    
    // 使用内部温度传感器
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
    sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);
    
    HAL_ADC_Start(&hadc);
    HAL_ADC_PollForConversion(&hadc, 10);
    adc_value = HAL_ADC_GetValue(&hadc);
    HAL_ADC_Stop(&hadc);
    
    // 计算温度
    voltage = adc_value * 3.3f / 4095.0f;
    temperature = ((voltage - 0.76f) / 0.0025f) + 25.0f;
    
    return temperature;
}

5、电机驱动控制

// motor.c
#include "motor.h"

// 电机参数
typedef struct {
    uint16_t speed_rpm;      // 转速
    uint8_t intensity;       // 强度
    uint8_t mode;           // 工作模式
    uint8_t is_running;     // 运行标志
} Motor_Control_t;

static Motor_Control_t motor = {0};
static TIM_HandleTypeDef htim2;

// 初始化电机
void Motor_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 使能时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_TIM2_CLK_ENABLE();
    
    // 配置电机PWM引脚
    GPIO_InitStruct.Pin = GPIO_PIN_1;  // TIM2_CH2
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF2_TIM2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 配置电机使能引脚
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 初始化定时器2用于PWM
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 72 - 1;  // 1MHz
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 1000 - 1;   // 1kHz PWM频率
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    HAL_TIM_PWM_Init(&htim2);
    
    // 配置PWM通道
    TIM_OC_InitTypeDef sConfigOC = {0};
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 0;  // 初始占空比0%
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2);
    
    // 启动PWM
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
    
    // 默认关闭电机
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
}

// 启动电机
void Motor_Start(Cleaning_Mode_t mode, uint8_t intensity)
{
    // 设置模式
    motor.mode = mode;
    motor.intensity = intensity;
    motor.is_running = 1;
    
    // 根据模式设置转速
    switch (mode) {
        case MODE_CLEAN:
            motor.speed_rpm = 30000;  // 30,000 RPM
            break;
        case MODE_WHITE:
            motor.speed_rpm = 40000;  // 40,000 RPM
            break;
        case MODE_SENSITIVE:
            motor.speed_rpm = 20000;  // 20,000 RPM
            break;
        case MODE_MASSAGE:
            motor.speed_rpm = 25000;  // 25,000 RPM
            break;
    }
    
    // 根据强度调整转速
    motor.speed_rpm = motor.speed_rpm * intensity / 5;
    
    // 使能电机
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
    
    // 软启动
    Motor_Soft_Start();
    
    printf("电机启动: 模式=%d, 强度=%d, 转速=%d RPM\n", 
           mode, intensity, motor.speed_rpm);
}

// 停止电机
void Motor_Stop(void)
{
    // 软停止
    Motor_Soft_Stop();
    
    // 关闭电机
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
    
    motor.is_running = 0;
    motor.speed_rpm = 0;
    
    // 设置PWM为0
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, 0);
}

// 设置电机模式
void Motor_Set_Mode(Cleaning_Mode_t mode)
{
    if (!motor.is_running) return;
    
    motor.mode = mode;
    
    // 根据新模式调整转速
    switch (mode) {
        case MODE_CLEAN:
            motor.speed_rpm = 30000;
            break;
        case MODE_WHITE:
            motor.speed_rpm = 40000;
            break;
        case MODE_SENSITIVE:
            motor.speed_rpm = 20000;
            break;
        case MODE_MASSAGE:
            motor.speed_rpm = 25000;
            break;
    }
    
    // 应用强度
    motor.speed_rpm = motor.speed_rpm * motor.intensity / 5;
    
    // 更新PWM
    Motor_Update_PWM();
}

// 软启动(防止电流冲击)
void Motor_Soft_Start(void)
{
    for (int i = 0; i <= 100; i += 5) {
        __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, i);
        HAL_Delay(10);  // 10ms步进
    }
    
    // 达到目标转速
    Motor_Update_PWM();
}

// 软停止
void Motor_Soft_Stop(void)
{
    uint16_t current_duty = __HAL_TIM_GET_COMPARE(&htim2, TIM_CHANNEL_2);
    
    for (int i = current_duty; i >= 0; i -= 5) {
        __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, i);
        HAL_Delay(10);
    }
}

// 更新PWM占空比
void Motor_Update_PWM(void)
{
    // 将RPM转换为占空比
    uint16_t duty_cycle = motor.speed_rpm * 1000 / 40000;  // 40000RPM对应100%占空比
    
    if (duty_cycle > 1000) duty_cycle = 1000;
    
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, duty_cycle);
}

// 区域换区提醒
void Motor_Quadrant_Alert(void)
{
    if (!motor.is_running) return;
    
    // 保存当前转速
    uint16_t original_speed = motor.speed_rpm;
    
    // 短暂加速提示
    motor.speed_rpm = original_speed * 1.2f;  // 加速20%
    Motor_Update_PWM();
    HAL_Delay(200);
    
    // 恢复原速
    motor.speed_rpm = original_speed;
    Motor_Update_PWM();
}

// 压力过大保护
void Motor_Reduce_Power(void)
{
    if (!motor.is_running) return;
    
    // 降低到50%功率
    motor.speed_rpm = motor.speed_rpm * 0.5f;
    Motor_Update_PWM();
    
    // 3秒后恢复
    HAL_Delay(3000);
    
    // 恢复原速
    motor.speed_rpm = motor.speed_rpm * 2.0f;
    Motor_Update_PWM();
}

6、触摸控制

// touch.c
#include "touch.h"

// 触摸状态
typedef struct {
    uint8_t touched;          // 触摸状态
    uint32_t touch_time;      // 触摸时间
    uint32_t release_time;    // 释放时间
    uint8_t click_count;      // 点击计数
} Touch_State_t;

static Touch_State_t touch_state = {0};
static GPIO_TypeDef* TOUCH_PORT = GPIOB;
static uint16_t TOUCH_PIN = GPIO_PIN_1;

// 初始化触摸
void Touch_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    __HAL_RCC_GPIOB_CLK_ENABLE();
    
    // 配置触摸引脚
    GPIO_InitStruct.Pin = TOUCH_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(TOUCH_PORT, &GPIO_InitStruct);
}

// 检测触摸
uint8_t Touch_Detected(void)
{
    static uint8_t last_state = 0;
    uint8_t current_state = (HAL_GPIO_ReadPin(TOUCH_PORT, TOUCH_PIN) == GPIO_PIN_RESET);
    
    // 消抖处理
    if (current_state != last_state) {
        HAL_Delay(20);  // 20ms消抖
        current_state = (HAL_GPIO_ReadPin(TOUCH_PORT, TOUCH_PIN) == GPIO_PIN_RESET);
        
        if (current_state && !last_state) {
            // 触摸按下
            touch_state.touched = 1;
            touch_state.touch_time = HAL_GetTick();
            touch_state.click_count++;
            
            printf("触摸按下\n");
            return 1;
        }
        else if (!current_state && last_state) {
            // 触摸释放
            touch_state.touched = 0;
            touch_state.release_time = HAL_GetTick();
            
            printf("触摸释放, 持续时间: %lu ms\n", 
                   touch_state.release_time - touch_state.touch_time);
        }
    }
    
    last_state = current_state;
    return 0;
}

// 检测长按(>2秒)
uint8_t Touch_Long_Press(void)
{
    if (touch_state.touched) {
        uint32_t press_duration = HAL_GetTick() - touch_state.touch_time;
        
        if (press_duration > 2000) {  // 2秒
            printf("长按检测: %lu ms\n", press_duration);
            touch_state.touched = 0;  // 重置状态
            return 1;
        }
    }
    
    return 0;
}

// 检测双击
uint8_t Touch_Double_Click(void)
{
    static uint32_t last_click_time = 0;
    static uint8_t click_count = 0;
    
    if (touch_state.click_count > 0) {
        uint32_t current_time = HAL_GetTick();
        
        if (current_time - last_click_time < 500) {  // 500ms内
            click_count++;
        } else {
            click_count = 1;
        }
        
        last_click_time = current_time;
        
        if (click_count == 2) {
            click_count = 0;
            touch_state.click_count = 0;
            printf("双击检测\n");
            return 1;
        }
    }
    
    return 0;
}

// 获取触摸持续时间
uint32_t Touch_Get_Duration(void)
{
    if (touch_state.touched) {
        return HAL_GetTick() - touch_state.touch_time;
    }
    return 0;
}

7、LED指示灯控制

// led.c
#include "led.h"

// LED引脚定义
#define LED_R_PORT    GPIOA
#define LED_R_PIN     GPIO_PIN_3
#define LED_G_PORT    GPIOA
#define LED_G_PIN     GPIO_PIN_4
#define LED_B_PORT    GPIOA
#define LED_B_PIN     GPIO_PIN_5

// 初始化LED
void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    // 配置RGB LED引脚
    GPIO_InitStruct.Pin = LED_R_PIN | LED_G_PIN | LED_B_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 默认关闭所有LED
    LED_Off();
}

// 显示充电状态
void LED_Show_Charging_Status(void)
{
    static uint32_t last_blink = 0;
    static uint8_t led_state = 0;
    
    Battery_Level_t bat_level = Battery_Check_Status();
    
    if (bat_level == BATTERY_FULL) {
        // 充满电,绿灯常亮
        LED_Set_Color(0, 255, 0);
    } else {
        // 充电中,红灯闪烁
        if (HAL_GetTick() - last_blink > 500) {  // 500ms闪烁
            last_blink = HAL_GetTick();
            led_state = !led_state;
            
            if (led_state) {
                LED_Set_Color(255, 0, 0);  // 红
            } else {
                LED_Off();
            }
        }
    }
}

// 显示工作模式
void LED_Show_Mode(Cleaning_Mode_t mode)
{
    switch (mode) {
        case MODE_CLEAN:
            LED_Set_Color(0, 0, 255);    // 蓝
            break;
        case MODE_WHITE:
            LED_Set_Color(255, 255, 255); // 白
            break;
        case MODE_SENSITIVE:
            LED_Set_Color(0, 255, 0);    // 绿
            break;
        case MODE_MASSAGE:
            LED_Set_Color(255, 165, 0);  // 橙
            break;
    }
    
    HAL_Delay(1000);  // 显示1秒
    LED_Off();
}

// 显示电量低
void LED_Show_Battery_Low(void)
{
    static uint32_t last_blink = 0;
    static uint8_t led_state = 0;
    
    if (HAL_GetTick() - last_blink > 250) {  // 250ms快速闪烁
        last_blink = HAL_GetTick();
        led_state = !led_state;
        
        if (led_state) {
            LED_Set_Color(255, 0, 0);  // 红
        } else {
            LED_Off();
        }
    }
}

// 设置LED颜色
void LED_Set_Color(uint8_t r, uint8_t g, uint8_t b)
{
    // 简化控制,实际可能需要PWM调光
    HAL_GPIO_WritePin(LED_R_PORT, LED_R_PIN, r ? GPIO_PIN_SET : GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LED_G_PORT, LED_G_PIN, g ? GPIO_PIN_SET : GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LED_B_PORT, LED_B_PIN, b ? GPIO_PIN_SET : GPIO_PIN_RESET);
}

// 关闭所有LED
void LED_Off(void)
{
    HAL_GPIO_WritePin(LED_R_PORT, LED_R_PIN, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LED_G_PORT, LED_G_PIN, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LED_B_PORT, LED_B_PIN, GPIO_PIN_RESET);
}

五、用户设置存储

// eeprom.c
#include "eeprom.h"

// 用户设置结构
typedef struct {
    uint8_t default_mode;      // 默认模式
    uint8_t default_intensity; // 默认强度
    uint8_t led_brightness;    // LED亮度
    uint8_t auto_shutdown;     // 自动关机
    uint8_t quadrant_reminder; // 换区提醒
    uint32_t total_usage_time; // 总使用时间
    uint8_t brush_head_life;   // 刷头寿命
} User_Settings_t;

// 从EEPROM加载设置
void Load_User_Settings(void)
{
    // 模拟EEPROM读取
    User_Settings_t settings;
    
    // 从Flash读取
    uint32_t address = 0x0800F800;  // Flash最后一页
    
    // 检查是否已初始化
    uint32_t magic = *(uint32_t*)address;
    if (magic != 0xABCD1234) {
        // 使用默认设置
        settings.default_mode = MODE_CLEAN;
        settings.default_intensity = 3;
        settings.led_brightness = 100;
        settings.auto_shutdown = 1;
        settings.quadrant_reminder = 1;
        settings.total_usage_time = 0;
        settings.brush_head_life = 100;
        
        // 保存默认设置
        Save_User_Settings(&settings);
    } else {
        // 读取设置
        memcpy(&settings, (void*)(address + 4), sizeof(User_Settings_t));
    }
    
    // 应用到系统
    toothbrush.mode = settings.default_mode;
    toothbrush.intensity = settings.default_intensity;
    toothbrush.auto_shutdown = settings.auto_shutdown;
}

// 保存用户设置
void Save_User_Settings(User_Settings_t *settings)
{
    // 解锁Flash
    HAL_FLASH_Unlock();
    
    // 擦除最后一页
    FLASH_EraseInitTypeDef erase;
    erase.TypeErase = FLASH_TYPEERASE_PAGES;
    erase.PageAddress = 0x0800F800;
    erase.NbPages = 1;
    
    uint32_t error = 0;
    HAL_FLASHEx_Erase(&erase, &error);
    
    // 写入魔数
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0800F800, 0xABCD1234);
    
    // 写入设置
    uint32_t *data = (uint32_t*)settings;
    uint32_t size = (sizeof(User_Settings_t) + 3) / 4;  // 向上取整到4字节
    
    for (uint32_t i = 0; i < size; i++) {
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 
                         0x0800F800 + 4 + i*4, 
                         data[i]);
    }
    
    // 锁定Flash
    HAL_FLASH_Lock();
}

参考代码 无线充电电动牙刷软件源码 www.youwenfan.com/contentcnu/70091.html

六、功耗优化

// power_manager.c
#include "power_manager.h"

// 功耗状态
typedef enum {
    POWER_MODE_ACTIVE = 0,    // 活跃模式
    POWER_MODE_SLEEP,         // 睡眠模式
    POWER_MODE_DEEPSLEEP,     // 深度睡眠
    POWER_MODE_SHUTDOWN       // 关机
} Power_Mode_t;

static Power_Mode_t current_power_mode = POWER_MODE_ACTIVE;
static uint32_t idle_timer = 0;

// 电源管理任务
void Power_Management_Task(void)
{
    static uint32_t last_check = 0;
    
    if (HAL_GetTick() - last_check < 1000) {
        return;  // 每秒检查一次
    }
    
    last_check = HAL_GetTick();
    
    switch (current_power_mode) {
        case POWER_MODE_ACTIVE:
            // 检查是否需要进入睡眠
            if (toothbrush.state == STATE_STANDBY) {
                if (HAL_GetTick() - idle_timer > 30000) {  // 30秒无操作
                    Enter_Sleep_Mode();
                }
            } else {
                idle_timer = HAL_GetTick();  // 重置空闲计时器
            }
            break;
            
        case POWER_MODE_SLEEP:
            // 睡眠模式,等待唤醒
            if (Touch_Detected() || Wireless_Charge_Detected()) {
                Wake_From_Sleep();
            }
            break;
            
        case POWER_MODE_DEEPSLEEP:
            // 只能通过外部中断唤醒
            break;
    }
}

// 进入睡眠模式
void Enter_Sleep_Mode(void)
{
    printf("进入睡眠模式\n");
    
    // 关闭电机
    Motor_Stop();
    
    // 关闭LED
    LED_Off();
    
    // 关闭ADC
    HAL_ADC_Stop(&hadc);
    
    // 进入STOP模式
    current_power_mode = POWER_MODE_SLEEP;
    
    // 配置唤醒源
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
    
    // 进入STOP模式
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    
    // 唤醒后
    Wake_From_Sleep();
}

// 从睡眠唤醒
void Wake_From_Sleep(void)
{
    printf("从睡眠唤醒\n");
    
    // 重新配置系统时钟
    SystemClock_Config();
    
    // 重新初始化外设
    MX_GPIO_Init();
    MX_ADC_Init();
    
    current_power_mode = POWER_MODE_ACTIVE;
    idle_timer = HAL_GetTick();
}

// 计算功耗
float Calculate_Power_Consumption(void)
{
    float voltage = Battery_Read_Voltage();
    float current = 0;
    
    switch (current_power_mode) {
        case POWER_MODE_ACTIVE:
            if (toothbrush.state == STATE_OPERATING) {
                current = 150.0f;  // 150mA 工作电流
            } else {
                current = 1.5f;    // 1.5mA 待机电流
            }
            break;
            
        case POWER_MODE_SLEEP:
            current = 0.1f;        // 100μA
            break;
            
        case POWER_MODE_DEEPSLEEP:
            current = 0.01f;       // 10μA
            break;
    }
    
    return voltage * current / 1000.0f;  // 返回mW
}

七、生产测试程序

// production_test.c
#include "production_test.h"

// 生产测试模式
void Production_Test_Mode(void)
{
    printf("=== 生产测试模式 ===\n");
    
    // 1. 测试LED
    printf("测试LED...\n");
    LED_Set_Color(255, 0, 0);  // 红
    HAL_Delay(500);
    LED_Set_Color(0, 255, 0);  // 绿
    HAL_Delay(500);
    LED_Set_Color(0, 0, 255);  // 蓝
    HAL_Delay(500);
    LED_Off();
    
    // 2. 测试电机
    printf("测试电机...\n");
    for (int i = 1; i <= 5; i++) {
        Motor_Start(MODE_CLEAN, i);
        HAL_Delay(1000);
        Motor_Stop();
        HAL_Delay(500);
    }
    
    // 3. 测试触摸
    printf("测试触摸,请触摸按钮...\n");
    uint32_t start_time = HAL_GetTick();
    while (HAL_GetTick() - start_time < 5000) {  // 5秒内
        if (Touch_Detected()) {
            printf("触摸测试通过\n");
            break;
        }
    }
    
    // 4. 测试充电检测
    printf("测试充电检测...\n");
    if (Wireless_Charge_Detected()) {
        printf("充电检测通过\n");
    } else {
        printf("充电检测失败\n");
    }
    
    // 5. 测试电池电压
    printf("测试电池电压...\n");
    float voltage = Battery_Read_Voltage();
    printf("电池电压: %.2fV\n", voltage);
    
    if (voltage > 3.0f && voltage < 4.3f) {
        printf("电池测试通过\n");
    } else {
        printf("电池测试失败\n");
    }
    
    printf("=== 生产测试完成 ===\n");
}

八、编译和烧录

1. 编译命令

# 使用STM32CubeIDE或Makefile
make clean
make all

2. 烧录命令

# ST-Link工具
st-flash write build/toothbrush.bin 0x08000000

九、性能指标

指标 数值 备注
待机电流 <10μA 深度睡眠
工作电流 150mA 最大强度
充电时间 2小时 0-100%
续航时间 14天 每天2次2分钟
电机转速 20k-40k RPM 可调
充电效率 >85% Qi标准
posted @ 2026-05-18 09:28  小前端攻城狮  阅读(3)  评论(0)    收藏  举报