基于51单片机的全自动洗衣机Protues仿真设计

基于51单片机的全自动洗衣机Protues仿真设计
目录一、设计背景二、实现功能三、硬件方案与管脚分配四、软件设计4.1 状态机设计7状态FSM4.2 电机正反转四相循环4.3 双定时器分工4.4 按键消抖五、工作流程5.1 待机设置阶段5.2 自动运行流程5.3 暂停与恢复六、仿真结果七、代码实现八、总结九、相关资料获取一、设计背景洗衣机是现代家庭必备电器。传统机械式洗衣机依靠定时器和机械开关控制功能单一、精度低。基于单片机的全自动洗衣机通过程序控制进水、洗涤、排水、脱水等全流程支持多种洗涤模式、水位调节和时间设定大幅提升用户体验。本设计以STC89C52为控制核心采用LCD16024位数据模式显示工作状态ADC0832采集水位信号L298N驱动直流电机并支持 PWM 调速配合继电器控制进水/排水阀、按键模块、6路LED模式指示和蜂鸣器在 Proteus 中完成全自动洗衣机控制系统的仿真验证。二、实现功能6种洗涤模式参数表正转/停顿时间以50ms为基本单位如motor_ons[2]80表示 80×50ms4秒。其余功能还包括3档水位调节低(L)/中(M)/高(H)对应ADC阈值 42/85/120满量程128约33%/66%/94%时间可调按TIME键进入调整模式MODE键加、WATER键减范围1~99秒LCD1602实时显示待机显示模式/水位/时间/水位百分比运行显示状态和倒计时分:秒PWM电机调速洗涤50%占空比脱水100%占空比停止0%暂停/恢复运行中按START暂停再按START恢复完成提示蜂鸣3秒 LCD显示Wash Finished!注意模式选择MODE水位设定WATER洗涤/脱水时间设置TIME,开始/暂停START。三、硬件方案与管脚分配四、软件设计4.1 状态机设计7状态FSM系统采用7状态有限状态机状态转换在 Timer0 中断中自动完成。4.2 电机正反转四相循环洗涤阶段电机按正转→停→反转→停四相循环由 Timer0 的50ms中断驱动4.3 双定时器分工4.4 按键消抖采用软件计数消抖检测到按键后计数器递增连续20次约200ms确认有效设置key_done标志防止重复触发按键释放后复位计数器。五、工作流程5.1 待机设置阶段开机后系统进入 S_IDLE 状态LCD显示默认参数模式2-标准水位M-中。用户可MODE键切换洗涤模式0→1→2→3→4→5→0循环自动加载该模式默认时间WATER键切换水位档位L→M→H→L循环TIME键进入时间调整模式正常→调洗涤→调脱水→正常调整时MODE加/WATER减START键启动洗衣机5.2 自动运行流程单脱水模式(5)例外按START后直接进入 S_SPIN跳过进水和洗涤阶段。5.3 暂停与恢复运行中按 START 键进入 S_PAUSE电机停止、进水阀和排水阀关闭、保存当前状态到prev_state。再按 START 恢复根据prev_state恢复阀门和电机运行。六、仿真结果待机界面M:2 L:M W:40s / S:15s H:59%模式2 LED点亮水位百分比随变阻器变化。进水过程INLET WATER... / Cur:59% T:66%调节变阻器水位上升达目标后自动转洗涤。洗涤过程WASHING 00:37电机交替正反转。排水过程DRAINING...排水阀继电器闭合10秒后转脱水。脱水过程SPINNING 00:11电机全速正转。完成提示*** DONE *** / Wash Finished!蜂鸣3秒后返回待机。暂停测试*** PAUSE *** / Press START电机阀门全停再按START恢复。模式切换M:0~5 动态更新6个LED依次点亮时间同步更新。快速模式。强洗模式。七、代码实现#include reg52.h /* 51单片机头文件 包含SFR定义 */ #include intrins.h /* 内部函数 _nop_() 空操作 */ #define uint unsigned int /* 16位无符号整型 0~65535 */ #define uchar unsigned char /* 8位无符号字符型 0~255 */ /* 引脚定义 */ /* LCD1602 4位模式 数据在P0.4-P0.7 */ sbit LCD_RS P2^6; /* LCD寄存器选择 0命令 1数据 */ sbit LCD_EN P2^7; /* LCD使能信号 下降沿锁存 */ sbit LCD_DB4 P0^4; /* LCD数据位4 (高4位中的最低位) */ sbit LCD_DB5 P0^5; /* LCD数据位5 */ sbit LCD_DB6 P0^6; /* LCD数据位6 */ sbit LCD_DB7 P0^7; /* LCD数据位7 (高4位中的最高位) */ /* ADC0832 8位串行ADC */ sbit ADC_CS P3^2; /* ADC片选 低有效 */ sbit ADC_CLK P3^0; /* ADC时钟 下降沿锁存配置 上升沿读数据 */ sbit ADC_DIO P3^1; /* ADC数据线 双向 写配置/读结果 */ /* 按键 低电平有效 */ sbit KEY_MODE P1^0; /* 模式选择/时间增加键 */ sbit KEY_WATER P1^1; /* 水位设定/时间减少键 */ sbit KEY_TIME P1^2; /* 时间设置切换键 */ sbit KEY_START P1^3; /* 开始/暂停键 */ /* 模式LED 低电平有效 共阴极接法 */ sbit LED_0 P2^0; /* 大件模式指示灯 */ sbit LED_1 P2^1; /* 轻柔模式指示灯 */ sbit LED_2 P2^2; /* 标准模式指示灯 */ sbit LED_3 P2^3; /* 快速模式指示灯 */ sbit LED_4 P2^4; /* 强洗模式指示灯 */ sbit LED_5 P2^5; /* 脱水模式指示灯 */ /* 继电器 高电平有效 */ sbit RELAY_IN P3^3; /* 进水阀继电器 1开 0关 */ sbit RELAY_OUT P3^4; /* 排水阀继电器 1开 0关 */ /* 电机驱动 L298N */ sbit MOTOR_IN1 P3^5; /* 电机方向控制1 */ sbit MOTOR_IN2 P3^6; /* 电机方向控制2 */ sbit MOTOR_ENA P0^0; /* 电机PWM使能 高有效 */ /* 蜂鸣器 低电平有效 */ sbit BUZZER P3^7; /* 蜂鸣器控制 0响 1停 */ /* 状态定义 */ #define S_IDLE 0 /* 待机状态 等待用户操作 */ #define S_INLET 1 /* 进水状态 开进水阀等待水位到达 */ #define S_WASH 2 /* 洗涤状态 电机正反转 */ #define S_DRAIN 3 /* 排水状态 开排水阀 */ #define S_SPIN 4 /* 脱水状态 电机全速正转 */ #define S_PAUSE 5 /* 暂停状态 保存当前状态 */ #define S_COMPLETE 6 /* 完成状态 蜂鸣提示 */ /* 模式参数 (code存ROM) */ uchar code wash_times[6] {60,30,40,20,60, 0}; /* 各模式洗涤时间(秒) 大件60/轻柔30/标准40/快速20/强洗60/脱水0 */ uchar code spin_times[6] {20,10,15, 5,20,20}; /* 各模式脱水时间(秒) */ uchar code motor_ons[6] {100,60,80,60,120,0}; /* 电机正反转运行时长(50ms计数) 即5s/3s/4s/3s/6s/0 */ uchar code motor_offs[6] {40,60,20,20, 20, 0}; /* 电机正反转停顿时长(50ms计数) 即2s/3s/1s/1s/1s/0 */ uchar code water_thresh[3] {42,85,120}; /* 水位ADC阈值 低33%/中66%/高94% (满量程128) */ /* 全局变量 */ uchar state S_IDLE; /* 当前运行状态 */ uchar prev_state S_IDLE; /* 暂停前的状态 用于恢复 */ uchar mode 2; /* 当前模式 默认标准(2) */ uchar water_level 1; /* 水位等级 0低 1中 2高 默认中 */ uchar wash_time 40; /* 洗涤时间(秒) 可手动调整 */ uchar spin_time 15; /* 脱水时间(秒) 可手动调整 */ uint time_remain 0; /* 剩余时间(秒) 倒计时用 */ uchar time_adj 0; /* 时间调整模式 0正常 1调洗涤 2调脱水 */ uchar tick_50ms 0; /* 50ms中断计数 满20次1秒 */ uchar motor_tick 0; /* 电机节拍计数 用于正反转切换 */ uchar motor_phase 0; /* 电机阶段 0正转 1正转停 2反转 3反转停 */ uchar adc_cnt 0; /* ADC采样计数 每4次(200ms)触发一次采样 */ uchar adc_value 0; /* ADC最新读数 0~128 */ bit adc_flag 0; /* ADC采样标志 1需要采样 */ bit disp_flag 0; /* 显示刷新标志 1需要刷新 */ uint beep_cnt 0; /* 蜂鸣倒计时(50ms为单位) 60次3秒 */ uchar pwm_cnt 0; /* PWM计数器 0~19循环 */ uchar pwm_duty 0; /* PWM占空比 0停 1050% 20100% */ /* 函数声明 */ void delay_ms(uint ms); /* 毫秒延时 */ void lcd_write_nibble(uchar nib); /* LCD写4位 */ void lcd_write_cmd(uchar cmd); /* LCD写命令 */ void lcd_write_data(uchar dat); /* LCD写数据 */ void lcd_init(void); /* LCD初始化 */ void lcd_string(char *str); /* LCD写字符串 */ void lcd_set_cursor(uchar pos); /* LCD设置光标位置 */ void lcd_char(char c); /* LCD写单个字符 */ void lcd_num2(uchar num); /* LCD显示2位数字 */ void lcd_num3(uchar num); /* LCD显示3位数字 */ uchar adc_read(uchar ch); /* 读ADC0832 返回0~255 */ void motor_set(uchar dir); /* 设置电机方向和速度 */ void valve_in(uchar on); /* 控制进水阀 */ void valve_out(uchar on); /* 控制排水阀 */ void led_mode(uchar m); /* 设置模式LED指示 */ uchar key_scan(void); /* 按键扫描 返回0~4 */ void update_display(void); /* 更新LCD显示 */ void start_machine(void); /* 启动洗衣机 */ void pause_machine(void); /* 暂停 */ void resume_machine(void); /* 恢复运行 */ void timer0_init(void); /* Timer0初始化 50ms */ void timer1_init(void); /* Timer1初始化 1ms PWM */ /* 延时函数 */ void delay_ms(uint ms) /* 粗略毫秒延时 12MHz */ { uint a,b; /* 双重循环计数器 */ for(a0;ams;a) /* 外循环 控制毫秒数 */ for(b0;b120;b); /* 内循环 约1ms */ } /* LCD1602 4位驱动 */ /* 用位操作写高4位 避免和P0.0(ENA)冲突 */ void lcd_write_nibble(uchar nib) /* 写4位数据到LCD */ { LCD_DB4 (nib 0) 1; /* 提取bit0 写到DB4 */ LCD_DB5 (nib 1) 1; /* 提取bit1 写到DB5 */ LCD_DB6 (nib 2) 1; /* 提取bit2 写到DB6 */ LCD_DB7 (nib 3) 1; /* 提取bit3 写到DB7 */ LCD_EN 0; /* EN拉低 准备上升沿 */ _nop_(); _nop_(); _nop_(); _nop_(); /* 等待4个机器周期 */ LCD_EN 1; /* EN拉高 产生上升沿 */ _nop_(); _nop_(); _nop_(); _nop_(); /* 保持高电平 */ _nop_(); _nop_(); _nop_(); _nop_(); /* 继续保持 */ LCD_EN 0; /* EN拉低 下降沿锁存数据 */ _nop_(); _nop_(); _nop_(); _nop_(); /* 等待锁存完成 */ } void lcd_write_cmd(uchar cmd) /* 写命令到LCD */ { LCD_RS 0; /* RS0 选择命令寄存器 */ _nop_(); /* 等待RS稳定 */ lcd_write_nibble(cmd 4); /* 先写高4位 */ lcd_write_nibble(cmd 0x0F); /* 再写低4位 */ delay_ms(2); /* 等待命令执行 */ } void lcd_write_data(uchar dat) /* 写数据到LCD */ { LCD_RS 1; /* RS1 选择数据寄存器 */ _nop_(); /* 等待RS稳定 */ lcd_write_nibble(dat 4); /* 先写高4位 */ lcd_write_nibble(dat 0x0F); /* 再写低4位 */ delay_ms(2); /* 等待数据写入 */ } void lcd_init(void) /* LCD1602初始化 4位模式 */ { LCD_EN 0; /* EN初始为低 */ LCD_RS 0; /* RS初始为低 命令模式 */ delay_ms(50); /* 等待LCD上电稳定 */ /* 强制8位模式3次 确保LCD同步 */ lcd_write_nibble(0x03); delay_ms(10); /* 第1次8位复位 */ lcd_write_nibble(0x03); delay_ms(5); /* 第2次8位复位 */ lcd_write_nibble(0x03); delay_ms(5); /* 第3次8位复位 */ /* 切换到4位模式 */ lcd_write_nibble(0x02); delay_ms(5); /* 发送4位模式指令 */ lcd_write_cmd(0x28); /* 功能设置: 4位/2行/5x8点阵 */ lcd_write_cmd(0x08); /* 显示控制: 显示关 */ lcd_write_cmd(0x01); /* 清屏 */ delay_ms(5); /* 等待清屏完成 */ lcd_write_cmd(0x06); /* 入口模式: 光标自增 不移屏 */ lcd_write_cmd(0x0C); /* 显示控制: 显示开 光标关 闪烁关 */ } void lcd_string(char *str) /* 发送字符串到LCD */ { while(*str) lcd_write_data(*str); /* 逐字符发送直到\0 */ } void lcd_set_cursor(uchar pos) /* 设置光标位置 */ { lcd_write_cmd(0x80 | pos); /* 0x80第一行 第二行起始0x40 */ } void lcd_char(char c) /* 写单个字符 */ { lcd_write_data(c); /* 直接调用写数据 */ } void lcd_num2(uchar num) /* 显示2位十进制数 00~99 */ { lcd_write_data(num / 10 0); /* 十位 转ASCII */ lcd_write_data(num % 10 0); /* 个位 转ASCII */ } void lcd_num3(uchar num) /* 显示3位十进制数 000~255 */ { lcd_write_data(num / 100 0); /* 百位 */ lcd_write_data(num % 100 / 10 0); /* 十位 */ lcd_write_data(num % 10 0); /* 个位 */ } /* ADC0832 驱动 */ uchar adc_read(uchar ch) /* 读取ADC0832 返回0~255 */ { uchar i, dat 0; /* i循环计数 dat读取结果 */ ADC_CS 0; /* 拉低CS 选中ADC */ ADC_CLK 0; /* CLK初始为低 */ ADC_DIO 1; _nop_(); /* 发送起始位(1) */ ADC_CLK 1; _nop_(); ADC_CLK 0; /* 时钟脉冲 */ ADC_DIO 1; _nop_(); /* 发送SGL/DIFF1 单端输入 */ ADC_CLK 1; _nop_(); ADC_CLK 0; /* 时钟脉冲 */ ADC_DIO ch; _nop_(); /* 发送通道选择 0CH0 1CH1 */ ADC_CLK 1; _nop_(); ADC_CLK 0; /* 时钟脉冲 */ ADC_DIO 1; /* 释放数据线 切换为输入模式 */ for(i0; i8; i) /* 读取8位数据 MSB先出 */ { ADC_CLK 1; _nop_(); /* 上升沿 ADC输出数据 */ dat (dat 1) | ADC_DIO; /* 左移后加入新位 */ ADC_CLK 0; _nop_(); /* 下降沿 准备下一位 */ } ADC_CS 1; /* 拉高CS 取消选中 */ return dat; /* 返回ADC值 */ } /* 电机控制 */ /* dir: 0停 1正转 2反转 3脱水(全速正转) */ void motor_set(uchar dir) /* 设置电机运行状态 */ { switch(dir) /* 根据方向参数切换 */ { case 0: MOTOR_IN10; MOTOR_IN20; pwm_duty0; break; /* 停止 PWM0% */ case 1: MOTOR_IN11; MOTOR_IN20; pwm_duty10; break; /* 正转 PWM50% */ case 2: MOTOR_IN10; MOTOR_IN21; pwm_duty10; break; /* 反转 PWM50% */ case 3: MOTOR_IN11; MOTOR_IN20; pwm_duty20; break; /* 脱水 PWM100% */ } } /* 阀门控制 */ void valve_in(uchar on) { RELAY_IN on; } /* 进水阀 高电平开 */ void valve_out(uchar on) { RELAY_OUT on; } /* 排水阀 高电平开 */ /* LED控制 */ void led_mode(uchar m) /* 点亮对应模式LED */ { LED_01; LED_11; LED_21; LED_31; LED_41; LED_51; /* 先全灭(高电平) */ switch(m) /* 点亮选中的LED(低电平) */ { case 0: LED_00; break; /* 大件 */ case 1: LED_10; break; /* 轻柔 */ case 2: LED_20; break; /* 标准 */ case 3: LED_30; break; /* 快速 */ case 4: LED_40; break; /* 强洗 */ case 5: LED_50; break; /* 脱水 */ } } /* 按键扫描 */ /* 返回: 0无键 1MODE 2WATER 3TIME 4START */ uchar key_scan(void) /* 非阻塞按键扫描 */ { static uchar key_cnt 0; /* 消抖计数器 */ static bit key_done 0; /* 已触发标志 防止重复 */ uchar cur_key 0; /* 当前检测到的键值 */ if(KEY_MODE0) cur_key 1; /* MODE键按下 */ else if(KEY_WATER0) cur_key 2; /* WATER键按下 */ else if(KEY_TIME0) cur_key 3; /* TIME键按下 */ else if(KEY_START0) cur_key 4; /* START键按下 */ if(cur_key) /* 有按键按下 */ { if(key_cnt 255) key_cnt; /* 计数(防溢出) */ if(key_cnt 20 !key_done) /* 连续20次(约200ms)确认 */ { key_done 1; /* 标记已触发 */ return cur_key; /* 返回键值 */ } } else /* 无按键 按键已松开 */ { key_cnt 0; /* 清零计数器 */ key_done 0; /* 清除已触发标志 */ } return 0; /* 返回无键 */ } /* 显示更新 */ void update_display(void) /* 根据状态刷新LCD显示 */ { switch(state) /* 按当前状态分支 */ { case S_IDLE: /* 待机状态 */ lcd_set_cursor(0x00); /* 第一行起始 */ lcd_string(M:); /* 显示模式编号 */ lcd_char(mode 0); /* 模式号 0~5转ASCII */ lcd_string( L:); /* 水位标签 */ lcd_char(water_level0 ? L : (water_level1 ? M : H)); /* L/M/H */ lcd_string( W:); /* 洗涤时间标签 */ lcd_num2(wash_time); /* 洗涤时间 */ lcd_string(s ); /* 单位补空格 */ lcd_set_cursor(0x40); /* 第二行起始 */ if(time_adj0) /* 正常模式 显示水位百分比 */ { lcd_string(S:); /* 脱水时间标签 */ lcd_num2(spin_time); /* 脱水时间 */ lcd_string(s H:); /* 水位百分比标签 */ lcd_num2((uint)adc_value * 100 / 128); /* ADC转百分比 */ lcd_char(0x25); /* 百分号% */ lcd_string( ); /* 补空格清尾 */ } else if(time_adj1) /* 调洗涤时间模式 */ { lcd_string(Wash:); /* 箭头指示 */ lcd_num2(wash_time); lcd_string(s ); } else /* 调脱水时间模式 */ { lcd_string(Spin:); lcd_num2(spin_time); lcd_string(s ); } break; case S_INLET: /* 进水状态 */ lcd_set_cursor(0x00); lcd_string(INLET WATER... ); /* 显示进水中 */ lcd_set_cursor(0x40); lcd_string(Cur:); /* 当前水位 */ lcd_num2((uint)adc_value * 100 / 128); /* 当前百分比 */ lcd_char(0x25); lcd_string( T:); /* 目标水位 */ lcd_num2((uint)water_thresh[water_level] * 100 / 128); lcd_char(0x25); lcd_string( ); break; case S_WASH: /* 洗涤状态 */ lcd_set_cursor(0x00); lcd_string(WASHING ); /* 显示洗涤中 */ lcd_num2(time_remain / 60); /* 剩余分钟 */ lcd_char(:); lcd_num2(time_remain % 60); /* 剩余秒 */ lcd_string( ); lcd_set_cursor(0x40); lcd_string(Mode:); /* 显示模式号 */ lcd_char(mode 0); lcd_string( ); break; case S_DRAIN: /* 排水状态 */ lcd_set_cursor(0x00); lcd_string(DRAINING... ); /* 显示排水中 */ lcd_set_cursor(0x40); lcd_string(Mode:); lcd_char(mode 0); lcd_string( ); break; case S_SPIN: /* 脱水状态 */ lcd_set_cursor(0x00); lcd_string(SPINNING ); /* 显示脱水中 */ lcd_num2(time_remain / 60); /* 剩余分钟 */ lcd_char(:); lcd_num2(time_remain % 60); /* 剩余秒 */ lcd_string( ); lcd_set_cursor(0x40); lcd_string(Mode:); lcd_char(mode 0); lcd_string( ); break; case S_PAUSE: /* 暂停状态 */ lcd_set_cursor(0x00); lcd_string(*** PAUSE *** ); /* 显示已暂停 */ lcd_set_cursor(0x40); lcd_string(Press START ); /* 提示按START恢复 */ break; case S_COMPLETE: /* 完成状态 */ lcd_set_cursor(0x00); lcd_string(*** DONE *** ); /* 显示完成 */ lcd_set_cursor(0x40); lcd_string(Wash Finished! ); /* 显示洗涤完成 */ break; } } /* 启动/暂停/恢复 */ void start_machine(void) /* 启动洗衣机 */ { led_mode(mode); /* 点亮对应LED */ if(mode 5) /* 脱水模式(5) */ { state S_SPIN; /* 直接进脱水 */ time_remain spin_time; /* 设置脱水时间 */ motor_set(3); /* 全速正转 */ valve_out(1); /* 开排水阀 */ } else /* 其他模式 先进水 */ { state S_INLET; /* 切换到进水状态 */ valve_in(1); /* 打开进水阀 */ } } void pause_machine(void) /* 暂停运行 */ { prev_state state; /* 保存当前状态 */ state S_PAUSE; /* 切换到暂停状态 */ motor_set(0); /* 电机停止 */ valve_in(0); /* 关进水阀 */ valve_out(0); /* 关排水阀 */ } void resume_machine(void) /* 恢复运行 */ { state prev_state; /* 恢复暂停前的状态 */ switch(state) /* 根据状态恢复执行 */ { case S_INLET: /* 恢复进水 */ valve_in(1); /* 开进水阀 */ break; case S_WASH: /* 恢复洗涤 */ motor_phase 0; /* 从正转开始 */ motor_tick 0; /* 清零计数 */ motor_set(1); /* 正转 */ break; case S_DRAIN: /* 恢复排水 */ valve_out(1); /* 开排水阀 */ break; case S_SPIN: /* 恢复脱水 */ motor_set(3); /* 全速正转 */ valve_out(1); /* 开排水阀 */ break; } } /* 定时器初始化 */ void timer0_init(void) /* Timer0初始化 50ms中断12MHz */ { TMOD (TMOD 0xF0) | 0x01; /* T0模式1(16位定时) 不影响T1 */ TH0 0x3C; /* 初值高字节 50ms12MHz */ TL0 0xB0; /* 初值低字节 */ ET0 1; /* 允许T0中断 */ TR0 1; /* 启动T0 */ } void timer1_init(void) /* Timer1初始化 1ms PWM12MHz */ { TMOD (TMOD 0x0F) | 0x10; /* T1模式1(16位定时) 不影响T0 */ TH1 0xFC; /* 初值高字节 1ms12MHz */ TL1 0x18; /* 初值低字节 */ ET1 1; /* 允许T1中断 */ TR1 1; /* 启动T1 */ } /* Timer0中断 50ms */ void timer0_isr(void) interrupt 1 /* Timer0中断服务 50ms触发 */ { TH0 0x3C; /* 重装初值高字节 */ TL0 0xB0; /* 重装初值低字节 */ /* 1秒倒计时 */ tick_50ms; /* 50ms计数1 */ if(tick_50ms 20) /* 20次1秒 */ { tick_50ms 0; /* 清零 */ if(time_remain 0) time_remain--; /* 剩余时间-1 */ } /* 洗涤电机正反转控制 */ if(state S_WASH) /* 仅洗涤状态控制正反转 */ { motor_tick; /* 50ms计数1 */ switch(motor_phase) /* 根据当前阶段 */ { case 0: /* 正转中 */ if(motor_tick motor_ons[mode]) /* 到达正转时长 */ { motor_tick 0; /* 清零计数 */ motor_phase 1; /* 切换到停顿 */ motor_set(0); /* 电机停止 */ } break; case 1: /* 正转停顿中 */ if(motor_tick motor_offs[mode]) /* 停顿结束 */ { motor_tick 0; motor_phase 2; /* 切换到反转 */ motor_set(2); /* 反转 */ } break; case 2: /* 反转中 */ if(motor_tick motor_ons[mode]) /* 到达反转时长 */ { motor_tick 0; motor_phase 3; /* 切换到停顿 */ motor_set(0); /* 电机停止 */ } break; case 3: /* 反转停顿中 */ if(motor_tick motor_offs[mode]) /* 停顿结束 */ { motor_tick 0; motor_phase 0; /* 回到正转 循环 */ motor_set(1); /* 正转 */ } break; } } /* ADC采样调度 200ms一次 */ adc_cnt; /* 50ms计数1 */ if(adc_cnt 4) /* 4次200ms */ { adc_cnt 0; /* 清零 */ adc_flag 1; /* 设置采样标志 */ disp_flag 1; /* 设置显示刷新标志 */ } /* 完成状态蜂鸣倒计时 */ if(state S_COMPLETE beep_cnt 0) /* 完成且蜂鸣中 */ { beep_cnt--; /* 蜂鸣计数-1 */ if(beep_cnt 0) /* 蜂鸣结束 */ { BUZZER 1; /* 关蜂鸣器(高电平) */ state S_IDLE; /* 回到待机 */ motor_set(0); /* 确保电机停 */ valve_in(0); /* 关进水阀 */ valve_out(0); /* 关排水阀 */ led_mode(mode); /* 恢复LED显示 */ } } /* 状态自动跳转 */ if(state S_WASH time_remain 0) /* 洗涤时间到 */ { motor_set(0); /* 电机停止 */ state S_DRAIN; /* 切换到排水 */ time_remain 10; /* 排水10秒 */ valve_out(1); /* 开排水阀 */ } else if(state S_DRAIN time_remain 0) /* 排水时间到 */ { valve_out(0); /* 先关排水阀 */ state S_SPIN; /* 切换到脱水 */ time_remain spin_time; /* 设置脱水时间 */ motor_set(3); /* 全速正转 */ valve_out(1); /* 脱水时排水阀保持开 */ } else if(state S_SPIN time_remain 0) /* 脱水时间到 */ { motor_set(0); /* 电机停止 */ valve_out(0); /* 关排水阀 */ state S_COMPLETE; /* 切换到完成 */ beep_cnt 60; /* 蜂鸣3秒 60x50ms */ BUZZER 0; /* 开蜂鸣器(低有效) */ } } /* Timer1中断 1ms PWM */ void timer1_isr(void) interrupt 3 /* Timer1中断 1ms触发 */ { TH1 0xFC; /* 重装初值高字节 */ TL1 0x18; /* 重装初值低字节 */ pwm_cnt; /* PWM计数1 */ if(pwm_cnt 20) pwm_cnt 0; /* 20次为一个PWM周期(20ms) */ if(pwm_cnt pwm_duty) MOTOR_ENA 1; /* 在占空比内 输出高 */ else MOTOR_ENA 0; /* 超出占空比 输出低 */ } /* 主函数 */ void main(void) { uchar key; /* 按键值暂存 */ /* 硬件初始化 */ P0 0xFF; /* P0全高 数据线有上拉 */ BUZZER 1; /* 蜂鸣器关(高电平) */ valve_in(0); /* 进水阀关 */ valve_out(0); /* 排水阀关 */ motor_set(0); /* 电机停 */ led_mode(mode); /* 点亮默认模式LED */ lcd_init(); /* 初始化LCD1602 */ timer0_init(); /* 初始化Timer0(50ms) */ timer1_init(); /* 初始化Timer1(1ms PWM) */ EA 1; /* 开总中断 */ adc_value adc_read(0); /* 开机预读一次ADC */ update_display(); /* 显示初始界面 */ while(1) /* 主循环 */ { key key_scan(); /* 扫描按键 */ if(key) /* 有按键 */ { switch(state) /* 根据当前状态处理 */ { case S_IDLE: /* 待机状态处理按键 */ if(key 1) /* MODE键 */ { if(time_adj 0) /* 正常模式 切换洗涤模式 */ { mode (mode 1) % 6; /* 模式0~5循环 */ wash_time wash_times[mode]; /* 加载默认洗涤时间 */ spin_time spin_times[mode]; /* 加载默认脱水时间 */ led_mode(mode); /* 更新LED */ } else if(time_adj 1) /* 调洗涤模式 按MODE加 */ { wash_time; if(wash_time 99) wash_time 1; /* 超过99回1 */ } else if(time_adj 2) /* 调脱水模式 按MODE加 */ { spin_time; if(spin_time 99) spin_time 1; } } else if(key 2) /* WATER键 */ { if(time_adj 0) /* 正常模式 切换水位 */ water_level (water_level 1) % 3; /* 低/中/高循环 */ else if(time_adj 1) /* 调洗涤模式 按WATER减 */ { if(wash_time 1) wash_time--; /* 减1 */ else wash_time 99; /* 减到1回99 */ } else if(time_adj 2) /* 调脱水模式 按WATER减 */ { if(spin_time 1) spin_time--; else spin_time 99; } } else if(key 3) /* TIME键 切换时间调整模式 */ { time_adj; /* 0→1→2→0循环 */ if(time_adj 2) time_adj 0; } else if(key 4) /* START键 启动 */ { time_adj 0; /* 退出时间调整 */ start_machine(); /* 启动洗衣机 */ } break; case S_PAUSE: /* 暂停状态 */ if(key 4) /* 按START恢复 */ resume_machine(); /* 恢复运行 */ break; default: /* 运行中(WASH/DRAIN/SPIN等) */ if(key 4) /* 按START暂停 */ pause_machine(); /* 暂停 */ break; } update_display(); /* 按键后立即刷新显示 */ } /* ADC采样 仅IDLE和INLET状态 */ if(adc_flag (state S_IDLE || state S_INLET)) { adc_flag 0; /* 清除采样标志 */ adc_value adc_read(0); /* 读取ADC通道0 */ if(state S_IDLE) disp_flag 1; /* IDLE时刷新显示 */ if(state S_INLET adc_value water_thresh[water_level]) { /* 水位达到阈值 */ valve_in(0); /* 关进水阀 */ state S_WASH; /* 进入洗涤状态 */ time_remain wash_time; /* 设置洗涤倒计时 */ motor_phase 0; /* 从正转开始 */ motor_tick 0; /* 清零计数 */ motor_set(1); /* 开始正转 */ } } /* 定时刷新显示 */ if(disp_flag) /* 收到刷新标志 */ { disp_flag 0; /* 清除标志 */ update_display(); /* 刷新LCD */ } } }八、总结系统特点.系统硬件清单该设计可直接用于单片机课程设计或毕业设计。扩展方向增加DS18B20温度传感器实现水温检测和加热控制、增加浊度传感器自动判断漂洗次数、增加红外遥控模块等。九、相关资料获取通过网盘分享的文件全自动洗衣机资料获取路径.zip链接: https://pan.baidu.com/s/1XA_bwsyTWVi5v8RlgfxgvA?pwd5iup 提取码: 5iup