?? mkq_m8.c.bak
字號:
//2007-7-19 9:46
//2007-7-18 20:03門控器設計開始
//端口:DUC(PB1) 報警指示燈 低有效 輸出
// KEY(PB7) 鑰匙輸入 低有效 輸入
// TXD(PD1) 串口發送 測試用 輸出
// INT0(PD2)INT1(PD3)密碼正確脈沖輸入 負脈沖? 輸入
// close(PC0)正轉電機控制 低有效 輸出
// open(PC1) 反轉電機控制 低有效 輸出
// zh(PC2) 電機線圈繼電器控制 低有效 輸出
// XD(PC3) 門鎖緊行程信號 低有效 輸入
// XC(PC4) 門關上行程信號 低有效 輸入
// XU(PC5) 門開啟行程信號 低有效 輸入
//DDRX =1 輸出 =0輸入
//輸入時(PORTB=1 使能上拉 PORTB=0 高阻態)
/* B7654_3210
DDRB=0x02; //B0000_0010 PB7(輸入 高阻 外有上拉 ) PB1(輸出 常態出高熄滅)
PORTB=0x7f;//B0111_1111
DDRC=0x00; //B0000_0111 PC(5 4 3)(輸入 高阻 外有上拉 ) 2 1 0(輸出 常態出高)
PORTC=0xff;//B1100_0111
DDRD=0x00; //B0000_0010 PD3(輸入 高阻 外有上拉 ) PD2(輸入 上拉) PD1(輸出 常態出高)
PORTD=0xff;//B1111_0111
*/
/*電機控制
正轉 PC0=0 PC2=1 到位 PC0=1
反轉 PC1=0 PC2=0 到位 PC1=1
PC2控制切換繼電器 PC2=1 正轉位置 PC2=0 反轉位置
*/
//要有等待電機停止后才能改變轉向的處理?!
/*行程開關檢測
XD(PC3) 門鎖緊行程信號 低有效 輸入
XC(PC4) 門關上行程信號 低有效 輸入
XU(PC5) 門開啟行程信號 低有效 輸入
*/
//用3-8譯碼器接LED作為輸出狀態指示 PD765輸出常態出低
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//注: 內部函數_delay_ms() 最高延時 262.144mS@1MHz 即 32.768ms@8MHz
//時鐘內部8M,不分頻
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define NOP asm("nop")
#define T0_10MS 0x064//定時器--1ms中斷定時器重裝值(256-x)*8/1000=2
#define CONST_10S 50////////////tst50
#define CONST_12S 60////////////tst60
//-----------位操作定義----
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
//報警
#define ERR_OFF sbi(PORTB,1)
#define ERR_ON cbi(PORTB,1)
//正轉 PC0
#define LOCK_OFF sbi(PORTC,0)
#define LOCK_ON cbi(PORTC,0)
//反轉 PC1
#define UNLOCK_OFF sbi(PORTC,1)
#define UNLOCK_ON cbi(PORTC,1)
//切換繼電器 PC2
#define JDQ_OFF sbi(PORTC,2)
#define JDQ_ON cbi(PORTC,2)
#define KEY (PINB&0x80) //KEY=0x00 鑰匙啟動開門 電機反轉
#define XCKG (PINC&0x38) //0011_1000 0X38 位345有0表示行程開關接通
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
// 時間變量
uchar f_10ms;
uchar cnt_20ms;
uchar f_20ms;
uchar cnt_100ms;
uchar f_100ms;
uchar cnt_200ms;
uchar f_200ms;
uchar cnt_12s;//反轉時限
uchar f_12s;
uchar cnt_10s;//正轉時限
uchar f_10s;
uchar f_key;
//控制變量
uchar err_f; //=1報警
uchar state; //0鎖緊 1打開 2鎖門 3開門 4異常
uchar key_state;
uchar blink_b;//=1亮 =0滅
/////////////////////////////////////////////
void timer0_init(void);
void main_init(void);
void tim0_mainloop(void);
void led_alarm(uchar err_f);
void moto_fan(void);
void moto_zhen(void);
void door_state_init(void);
void keypd_mainloop(void);
void door_mainloop(void);
void delay_ms(uint temp);
//****************************
void timer0_init(void)
{
//T0定時10ms
TCCR0 = 0x00; //stop
TCNT0 = T0_10MS; //setup
TCCR0 = 0x03; //start timer --64分頻--1M內部系統時鐘--10ms中斷一次
TIMSK = 0x01; //溢出中斷TOIE0
}
//************************************
SIGNAL(SIG_OVERFLOW0)//T0溢出中斷10ms
{
TCNT0 = T0_10MS;
f_10ms=1;
}
//************************************
void main_init(void)
{
DDRB=0x02; //B0000_0010 PB7(輸入 高阻 外有上拉 ) PB1(輸出 常態出高熄滅)
PORTB=0x7f;//B1111_1111
DDRC=0x07; //B0000_0111 PC(5 4 3)(輸入 高阻 外有上拉 ) 2 1 0(輸出 常態出高)
PORTC=0xff;//B1111_1111
//DDRD=0x02; //B0000_0010 PD3(輸入 高阻 外有上拉 ) PD2(輸入 上拉) PD1(輸出 常態出高)
//PORTD=0xf7;//B1111_0111
DDRD=0xf0; //B1111_0000 PD3(輸入 高阻 外有上拉 ) PD2(輸入 上拉) PD1(輸出 常態出高)
PORTD=0x0f;//B0000_1111
timer0_init();
cnt_20ms=2;
cnt_100ms=5;
cnt_200ms=2;
cnt_10s=CONST_10S;
cnt_12s=CONST_12S;
}
//************************************
//10ms一次中斷產生檢測時間20ms,報警時間100ms 時限保護10s 12s
void tim0_mainloop(void)
{
if(f_10ms==1)
{
f_10ms=0;
if(--cnt_20ms==0)//判斷按鈕
{
cnt_20ms=2;f_20ms=1;
if(--cnt_100ms==0)//閃爍時間
{
cnt_100ms = 2;f_100ms = 1;
if(--cnt_200ms==0)//行程開關檢測時間
{
cnt_200ms=2;f_200ms=1;
if(--cnt_10s==0)//正轉時間
{
cnt_10s=CONST_10S;f_10s=1;
}
if(--cnt_12s==0)//反轉時間
{
cnt_12s=CONST_12S;f_12s=1;
}
}
}
}
}
}
//************************************
//錯誤報警 輸入參數=1 報警 =0 不報警
void led_alarm(uchar alarm)
{
if((alarm==1)&&(f_100ms==1)) //同時滿足 100ms時間到,報警標志為1
{
f_100ms=0;
if(blink_b==0)
{
ERR_ON;blink_b=1;
}
else
{
ERR_OFF;blink_b=0;
}
}
}
//************************************
void moto_zhen(void)
{
JDQ_OFF;
_delay_ms(10);
LOCK_ON;//正轉鎖緊
}
//************************************
void moto_fan(void)
{
JDQ_ON;
_delay_ms(10);
UNLOCK_ON;//反轉松開
}
//************************************
void door_state_init(void)//門狀態起始判斷
{
uchar temp;
temp=XCKG;
temp>>=3;
err_f=0;ERR_OFF;
//上電后若門合上,但未鎖定100,執行鎖定
//若門鎖緊 進入0
//若門全開 進入4
//若門安裝初態111 進入11
//若行程開關位置有沖突,報警,直到正確為止 包括 000 010 110
//對于執行報警或鎖緊的步驟,要加入上電初始化標志powon_f=1;
temp=7;
switch(temp)//PC5(解鎖) 4(關上) 3(鎖緊)
{
case 0://000 行程開關位置有沖突 報警
state=8;err_f=1;
break;
case 1://001解鎖+關閉---啟動鎖緊并一直報警直到門鎖緊為止
moto_zhen();f_10s=0;cnt_10s=CONST_10S;
state=3;
err_f=1;
break;
case 2://010 行程開關位置有沖突 報警
state=8;err_f=1;
break;
case 3://011 門全開
state=2;
break;
case 4://100已經鎖緊
state=0; break; case 5://101 門安裝初態 門合上但行程開關不到位 啟動鎖緊并一直報警直到門鎖緊為止
moto_zhen();f_10s=0;cnt_10s=CONST_10S;
state=3;
err_f=1;
break;
case 6://110 行程開關位置有沖突 報警
state=8;err_f=1;
break;
case 7://111 門安裝初態111 門未合上
state=4;err_f=1;
break;
}
//101 111為安裝初態處理 (鎖緊機構在中間,既未鎖緊也未解鎖)
//001為可能的斷電恢復處理(門合上且解鎖)
//000 010 110為行程開關不正常組合,應解除故障再操作!
PORTD|=0XF0;PORTD&=(state<<4);//狀態指示
}
//************************************
void door_mainloop(void)
{
uchar temp;
if(!f_200ms)return;
f_200ms=0;
temp=XCKG;
temp>>=3;
err_f=0;ERR_OFF;//暫時關閉報警
switch(state)
{
case 0://鎖緊
switch(temp)//鎖緊態,只有按鈕和密碼板脈沖才能開啟。
{
case 4:if(f_key){state=1;moto_fan();f_12s=0;cnt_12s=CONST_12S;}//進入開門初始態
break;
default:state=8;f_key=0;err_f=1;
break;
//3 5 7 行程開關位置錯誤 此錯誤只有手動使門鎖緊行程開關合上=0,才能恢復
}
break;
case 1://正開門態
switch(temp)
{
case 3: state=2;UNLOCK_OFF;f_key=0;
break;//完成開門
default:
if(f_12s==1)
{
state=8;f_key=0;UNLOCK_OFF;err_f=1;//門規定時間解不了鎖
if(temp==4){state=6;}//門一直鎖緊
}
break;
}
break;
case 2://打開
switch(temp)
{
case 3:
break;//門已打開
case 1: //門被合上
state=3;moto_zhen();f_10s=0;cnt_10s=CONST_10S;//進入關門態
break;
default:state=8;err_f=1;
break;
}
break;
case 3://正鎖門態
switch(temp)
{
case 4: state=0;LOCK_OFF;
break;//門鎖
default:if(f_10s==1){state=8;LOCK_OFF;err_f=1;}//門規定時間鎖不上
break;
}
break;
case 4://安裝等關門
err_f=1;
switch(temp)
{
case 5:state=5;moto_zhen();f_10s=0;cnt_10s=CONST_10S;//進入關門態
break;
default:break;
}
break;
case 5://安裝的鎖門
err_f=1;
switch(temp)
{
case 4: state=0;LOCK_OFF;err_f=0;
break;//門鎖
default:if(f_10s==1){state=8;LOCK_OFF;}//門規定時間鎖不上
break;
}
break;
case 6://門一直鎖緊,只有按鍵能使它退出
switch(temp)//鎖緊態,只有按鈕和密碼板脈沖才能開啟。
{
case 4:
if(f_key){state=1;moto_fan();f_12s=0;cnt_12s=CONST_12S;}//進入開門初始態
else{err_f=1;}
break;
default:state=8;f_key=0;err_f=1;
break;
}
break;
case 8://異常 只有門全開和門鎖緊正常 才能退出異常
switch(temp)
{
case 3: state=2;break;//門開
case 4: state=0;break;//門鎖
default:err_f=1;break;
}
break;
default: break;
}
//開門解鎖后的關門(開門解鎖后,沒有手動拉開門導致報警,此時又手動合上門,如何處理?)
//不會出現,因為close開關緊貼門邊的
//關門過程中的開門(在門合上正在鎖緊的過程中,里面手動按下開門按鈕或外面密碼板有信號,如何處理?)
//關門過程中不響應開門!
PORTD|=0XF0;PORTD&=state<<4;//狀態指示
if((blink_b==1)&&(err_f==1)){ERR_ON;}
}
//************************************
void keypd_mainloop(void)
{
uchar temp;
static uchar keystate;
if((f_20ms==1)&&(f_key==0))
{
f_20ms=0;
temp = PINB;
switch(keystate)
{
case 0:/*有鍵按下*/
if((temp&BIT7)==0) keystate=1;
break;
case 1://確認有鍵
if((temp&BIT7)==0) {keystate=2;}
else {keystate=0;}
break;
case 2://等待釋放
if((temp&BIT7)!=0)
{
keystate=0;
f_key=1;
}
break;
}
}
}
//************************************
int main(void)
{
main_init();
door_state_init();
sei();
while(1)
{
tim0_mainloop();//10ms時間處理
led_alarm(err_f);//100ms報警閃爍
keypd_mainloop();//20ms檢測按鍵和密碼脈沖---》fkey=1;
door_mainloop();//200ms根據行程開關和KEY進行響應處理
}
}
/*
0 鎖緊
1 門開中
2 門開
3 門鎖中
4 門裝待關
5 門裝正鎖
6 門無法解鎖
8 異常*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -