|
自家用多麗牌落地風扇,型號是FS11-40,最近出現故障,無規律自動開機、關機,無規律自變檔位。特別是晚上睡覺后自動開機,很是煩惱。上網查詢打算網購一塊電腦板,但均找不到匹配的。家里正好有一些單片機配件,決定自己改裝及維修。 第一步:拆機。
觀察電路板上單片機芯片,型號為“KEJIE-38/S8EC_94H4”,DIP20封裝,測單片機供電只有4.5V,懷疑供電不足,在斷開220V交流電的情況下,用直流5V直接供電,故障依然無規律出現,所以基本判斷芯片內部損壞,決定自己改裝。
第二步:改裝準備。
1.遙控器的匹配,在單片機開發板上測試原機遙控器,無響應,讀不出鍵值。試了家里海信電視的遙控器,能讀出鍵值,最下面四個按鍵鍵值分別為“62、64、63、65”,這四個按鍵電視機用不上,所以決定用作風扇的控制,功能分別定為“關機、開機/風速、搖頭、定時”。
01.jpg (105.82 KB, 下載次數: 31)
下載附件
2024-7-15 15:29 上傳
2.功能增減:
風扇原遙控器有“風類”調節功能,由單片機“定時器+PWM”控制電機模擬各種風類,由于這個功能平時不常用,所以刪減了這個功能。
家人經常有出門不關風扇的情況發生,決定增加無條件定時關機功能,定時時間為4小時,一但開機,4小時后必定自動關機。
原電路采用15個LED顯示工作狀態,包括顯示“1、2、3”檔位和“0.5h、1.0h、2.0h、4.0h”定時狀態和風類等信息。這15個LED和4個按鍵采用查理復用電路或是矩陣電路,沒有深究,因待改裝的單片機型號為STC89C52,IO口夠用,所以決定用兩位共陽數碼管代替原機的15個LED,4個按鍵保留。
第三步:改裝。
1.將原機單片機芯片拆下,焊下15個LED,保留原機阻容降壓電路、整流濾波電路、5.1V穩壓電路、4個按鍵、紅外接收管、4路雙向可控硅電路等。將數碼管用硅膠固定在原LED相應位置,8個段線分別加100歐限流電阻,2個位線分別加8550三極管驅動。用洞洞板焊了一個最小系統板,用硅膠固定在原電路板的背面,不妨礙安裝即可。
2.連線,數碼管10線、按鍵4線、風扇電機3線、搖頭電機1線、蜂鳴器1線、電源2線、紅外接收管1線、共22根線。
03.jpg (134.63 KB, 下載次數: 27)
下載附件
2024-7-15 17:25 上傳
04.jpg (124.75 KB, 下載次數: 27)
下載附件
2024-7-15 17:25 上傳
第四步:編程與仿真。
除紅外遙控功能外,其他功能都可以仿真。程序附后。
02.jpg (144.62 KB, 下載次數: 26)
下載附件
2024-7-15 17:10 上傳
第五步:程序下載與測試。
測試成功,最終效果不錯。附件中有視頻。
05.jpg (108.15 KB, 下載次數: 26)
下載附件
2024-7-15 18:16 上傳
附單片機程序(部分):
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
uchar code SEG[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //數碼管代碼
sbit IR_GET = P3^2; //紅外接收頭數據輸入端
uchar RXDDATA[]={0x00,0x00,0x00,0x00}; //存放接收到的四組紅外編碼
uchar IRDATA; //遙控鍵鍵值
sbit COM1 = P1^6; //數碼管十位
sbit COM2 = P1^7; //數碼管個位
sbit KEY1 = P3^4; //關
sbit KEY2 = P3^5; //開/風速
sbit KEY3 = P3^6; //搖頭
sbit KEY4 = P3^7; //定時
sbit LED1 = P1^0; //一檔,仿真用LED,實際接電機低速檔(藍色線)
sbit LED2 = P1^1; //二檔,電機中速檔(白色線)
sbit LED3 = P1^2; //三檔 電機高速檔(紅色線)
sbit LED4 = P1^3; //搖頭,電機高速檔(紫色線)
sbit BEEP = P1^4; //蜂鳴器
uchar keypress; //KEY2的按鍵值,即檔位值
uint keytime; //倒計時時間,單位為小時,數碼管顯示值
int time=14759; //倒計時時間,單位為秒
uint cnt1; //定時器1計數變量
uchar flag=0; //檔位標志
bit L_R=0; //搖頭狀態變量
bit L_R_flag; //搖頭標志
bit key4_flag; //定時按鍵標志
/*--------------1ms延時---------------*/
void delay_ms(uint xms)
{
uchar i;
while(xms--)
{
i=123;
while(i--);
}
}
/*--------紅外專用延時,約0.1ms延時函數----------*/
void delay(uchar x)
{
unsigned char i;
while(x--)
{
for (i = 0; i<10; i++);
}
}
/*--------數碼管顯示一:顯示檔位---------------*/
void show_seg1(uchar dat)
{
if(flag!=0)
{
if(L_R==1) //如果是搖頭狀態,則十位顯示“-”,否則不顯示
{
P2=0xbf; //“-”
COM1=0;
delay_ms(4);
COM1=1;
}
P2=SEG[dat%10]; //個位顯示檔位“123”
COM2=0;
delay_ms(4);
COM2=1;
}
}
/*--------數碼管顯示二:顯示倒計時時間---------------*/
void show_seg2(uchar time)
{
if(cnt1<500) P2=SEG[time/10] & 0x7f; //顯示時間十位,帶秒點并閃爍
else P2=SEG[time/10];
COM1=0;
delay_ms(4);
COM1=1;
P2=SEG[time%10]; //顯示時間個位
COM2=0;
delay_ms(4);
COM2=1;
}
/*--------蜂鳴器函數---------------*/
void beep() //蜂鳴器,這里選用有源蜂鳴器
{
BEEP=0; //若選用無源蜂鳴器,則可模擬輸出方波驅動發聲
delay_ms(70);
BEEP=1; //關閉蜂鳴器
}
/*--------------按鍵掃描---------------*/
void scan_key()
{
if(KEY1==0) //關機控制
{
beep(); //使用蜂鳴器發聲時的延時作消抖
if(KEY1==0)
{
flag=0; //檔位標志復位,關閉風扇電機
keypress=0; //KEY2的按鍵值復位
L_R_flag=0; //搖頭狀態標志復位,關閉搖頭電機
}
}
if(KEY2==0) //開機、檔位變換控制
{
beep();
if(KEY2==0)
{
keypress++; //檔位加
if(keypress > 3) keypress = 1; //值的約束,在開機狀態下,輪流顯示“123”,表示123檔
flag = keypress; //檔位值賦給狀態標志
while(!KEY2)show_seg1(keypress); //按鍵松手檢測
}
}
if(flag!=0) //搖頭控制
{
if(KEY3==0)
{
beep();
if(KEY3==0)
{
L_R = ! L_R; //搖頭狀態翻轉,開或關兩個狀態
LED4 = ! L_R; //搖頭電機開啟或狀態, P1^3輸出0為開啟搖頭電機
while(!KEY3)show_seg1(keypress);
}
}
}
if(flag!=0) //定時設置
{
if(KEY4==0)
{
beep();
if(KEY4==0)
{
key4_flag = 1; //定時狀態標志
keytime = keytime+5; //按鍵每按一次加5,即“0-5-10-15-20-25-30”,這里加大了10位,后面需縮小10倍處理
//實際顯示“0.0-0.5-1.0-1.5-2.0-2.5-3.0”,單位為小時
if(keytime > 30) keytime = 0; //定時時間最大定為3小時,用戶可以更改
if(keytime!=0) time = keytime*360+359; //時間換算成秒,這里本應為“*3600”,因需縮小10倍處理,故為“*360”
while(!KEY4) show_seg2(keytime) ;
}
}
}
}
/*--------------定時器1初始化---------------*/
void Timer_Init(void) //1000微秒@12.000MHz
{
TMOD |= 0x10; //設置定時器模式
TL1 = 0x18; //設置定時初始值
TH1 = 0xFC; //設置定時初始值
ET1 = 1; //使能定時器0中斷
}
/*------------外部中斷EX0初始化-------------*/
void init()
{
EX0= 1; //使能 INT0 外部中斷
IT0 =1; //外中斷0下降沿觸發
IR_GET=1; //I/O口初始化
}
/*--------------主程序---------------*/
void main()
{
Timer_Init();
init();
EA = 1;
beep(); beep(); beep();
while(1)
{
scan_key();
if((key4_flag==0)|(keytime==0)) show_seg1(keypress); //非定時狀態或定時設定時間為0時,顯示檔位值
else show_seg2(time/360); //否則顯示倒計時時間
switch(flag)
{
case 0: LED1 = 1; LED2 = 1; LED3 = 1; LED4 = 1; L_R=0; keypress=0; keytime=0; TR1=0; time=14759; break;
case 1: LED1 = 1; LED2 = 1; LED3 = 1; LED1 = 0; TR1=1; break; //考慮到檔位電壓的沖撞,先關閉所有檔位再打開,下同
case 2: LED1 = 1; LED2 = 1; LED3 = 1; LED2 = 0; TR1=1; break;
case 3: LED1 = 1; LED2 = 1; LED3 = 1; LED3 = 0; TR1=1; break;
}
}
}
/*--------------定時器中斷處理---------------*/
void Timer1_Isr(void) interrupt 3
{
TL1 = 0x18; //重裝初始值
TH1 = 0xFC; //重裝初始值
cnt1++;
if(cnt1>1000) //1秒溢出
{
cnt1=0;
time--; //定時時間秒自減1
if(time<358) {flag=0;time=14759;} //時間到,關機
}
}
/*--------------外部中斷處理:處理紅外碼--------------*/
void intt_0() interrupt 0 //下降沿觸發:接收不到紅外時OUT高電平,接收到紅外時OUT低電平。
{
uchar four,one,num=0;
EX0 = 0; //關中斷0使能,防止處理過程中再接收紅外信號
delay_ms(2); //稍延時2ms,防干擾
if (IR_GET) //再檢測紅外接收腳(9ms的前導低電平),為高電平說明是干擾
{
EX0 =1; //使能中斷0
return; //退出中斷程序
}
while(!IR_GET); //等IR變為高電平,跳過9ms的前導低電平信號。
while (IR_GET); //等 IR 變為低電平,跳過4.5ms的前導高電平信號。
for (four=0;four<4;four++) //四組數據
{
for (one=0;one<8;one++) //每組數據8位
{
while (!IR_GET); //等 IR 變為高電平
while (IR_GET) //計算IR高電平時長(低電平時長是一樣的,不用計)
{
delay(1); //計時
num++; //計時N次
if (num>=20) //20*0.1ms=2ms
{ //數據“1”的時長最長也就1.685ms,計數超過則數據錯誤,退出中斷
EX0=1; //使能中斷0
return; //退出中斷
}
} //高電平計數完畢
RXDDATA[four]>>=1; //從低位讀出,隨著one的循環8次剛好讀出一字節
if(num>6&&num<20) // 20*0.1ms=2ms>1.685ms
RXDDATA[four]|=0x80; //數據“1”
num=0; //計時值清0,為下一位數據的計時做準備
}//一組數據接收結束
}//全部四組數據接收結束
if (RXDDATA[2]!=~RXDDATA[3]) //檢測接收到的數據是否正確
{ //不正確則
EX0=1; //使能中斷0
return; //退出中斷
}
IRDATA=RXDDATA[2];
switch(IRDATA)
{
……
}
EX0 = 1; //處理完紅外接收,使能中斷0,退出中斷0
}
|
-
-
仿真+程序.7z
2024-7-16 03:50 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
54.18 KB, 下載次數: 31, 下載積分: 黑幣 -5
-
-
控制效果視頻.7z
2024-7-16 03:50 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
15.71 MB, 下載次數: 14, 下載積分: 黑幣 -5
評分
-
查看全部評分
|