无线充电电动牙刷软件源码
基于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标准 |
浙公网安备 33010602011771号