/**************************************************
**************抽油煙機主控板程序*******************
**************MCU=PIC16F716-04/pq*****************
**************deisigned By 小強**********************
**************date=2008年7月25日*******************
說明:
1,四個獨立按鍵。
2,ht1621驅動液晶
3,用到的外圍模塊不是很多,但控制邏輯比較複雜點,對按鍵的處理要求也比較高的,另外還有時間顯示和定時,倒計時功能,還有,液晶是段式顯示的,還有圖形轉動,對處理技巧要求比較高,標誌位也非常多,有些程序段稍微改億下就可以用到你自己的程序中!
4,用picc寫的
/5,本著學自網路,奉獻網路的精神發了本程序,希望對初學者有用
***************************************************/
#include
#define uint unsigned int
#define TMR0Init 0x3e
#define keyOnDelay 0x08
#define keyBuzzerDelay 0x09
#define off 0
#define on 1
#define outLight RB0 //外部燈
#define we RB1 //弱風
#define st RB2 //強風
#define bz RB3 //蜂鳴器
#define backLight RB4 //背光燈
#define da RB5 //數據線
#define wr RB6 //控制線
#define cs RB7 //片選線
#define RBon 0 //低電平選通相應的功能 相當於負邏輯
#define RBoff 1 //高低電平關閉選通相應的功能
#define switchKey RA0
#define lightKey RA1
#define adjustKey RA2
#define setKey RA3
bit lightKeyFlag,switchKeyFlag,setKeyFlag,adjustKeyFlag,switchFlag,strongFlag,colFlag,f3Flag;
bit setFlag,endFlag,hourFlag,backLightFlag,twoMinutesFlag,halfSecondFlag ,LCDLightFlag,f2Flag;
bit f6Flag,f7Flag,f4Flag,f5Flag,longKeyFlag,shortKeyFlag,l1Flag,l2Flag,l3Flag,f1Flag;
signed char timeNumber[4]={0,3,0,0};
signed char timeNumberTemp[4]={0,3,0,0};
char sWeiTemp,bWeiTemp,qWeiTemp;
char gWeiTemp;
char fiveSecondTime;//5秒定時;
char weakCount,strongCount,switchCount,setCount,endTimeCount;
uint count,backLightTime;
char gWei,sWei,bWei,qWei;
char count2;//倒計時關機用
char secondCount;//每秒遞增;
char keyOnTime;//每過0.05s鍾,keyOnTime++;
uint twoMinutesCount;//每0.05s時twoMinutesCount自增1,當twoMinutesCoun=2400時到達兩分鐘,風機關閉;
char map[]={0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f};//映射到LCDRAM寄存器內容的MAP數組;
char num[]={0x5f,0x06,0x3d,0x2f,0x66,0x6b,0x7b,0x0e,0x7f,0x6f,0x00};//注意:0x00代表空顯示,數字顯示對應的筆段碼,分別顯示(0123456789空格)十個字元;
void delayms(unsigned char a);//延時函數
void sendHighBit(char data,char count);//發送data數據里的高count位
void sendLowBit(char data,char low);//發送data數據里的低low位
void init(void);//系統初始化
void writeData(char *pa, char *pm);//刷LCD新顯示
void writeCommand(char command);//LCD寫命令;
void refurbish(void); //刷新MAP數組;
void strongWindOff(void);//關強風
void weakWindOff(void);//關弱風
void timeCount(void);//時間計時函數
void keyScan(void); //鍵盤掃描函數
void keyOnResponse(void);//按鍵起作用時通常要做出響應的函數
void recover(void);//還原定時時間
void colFliker(void);//秒針閃動函數
void twoMinutes(void);//當switchCount=1,也就是相當於開關按第2次時的處理程序
void endFunction(void);//endFlag==on時的處理程序片段
void setFlagOn();//*********************設置標誌為ON時的相關操作
void main()
{
init();//初始化
writeCommand(0x01); //lcd系統使能
writeCommand(0x29); //占空比設置等
writeCommand(0x03); //開啟LCD
writeData(0,map);//調用顯示函數
while(1)
{
if(T0IF==1)
{
T0IF=0;
TMR0=0x3e;//T0再賦計數初值
count++;
if(count==10)//到0.5S關蜂鳴器
bz=RBoff;
if(count==40)//延時2s
{
count=0;
l3Flag=on;
break;//跳出循環
}
}
}
while(1)
{
while(T0IF==1)
{
T0IF=0;
TMR0=0x3e;//TMR0賦初值
count++;//每50ms count自增1;
if(backLightFlag==on)//backLightFlag==on,則背光源一直亮;
{
backLight=on;//背光開
}
else //backLightFlag==off時,若沒有按任何鍵,則背光源過15秒熄滅
{
backLightTime++;
if(backLightTime==300)
backLight=off;//背光關
}
colFliker();//col每一秒閃爍一次
timeCount();//時間
keyScan(); //鍵盤掃描函數
if(LCDLightFlag==on)
{
outLight=RBon;
}
else
{
LCDLightFlag=off;
outLight=RBoff;
}
//******************************************燈開光按鍵操作子程序*****************************************
if((lightKeyFlag==on)&&(lightKey ==1))
{
lightKeyFlag=off;
LCDLightFlag=!LCDLightFlag;
keyOnResponse();
}
//***************************************** 強弱風鍵操作 ********************************
if(setFlag==off)//當setFlag==off時的處理;
{
if((adjustKeyFlag==on)&&(adjustKey==1))
{
adjustKeyFlag=off;
if(switchFlag==on)
{
backLightTime=0;
backLight=on;
strongFlag=!strongFlag;
keyOnResponse();
}
}
}
else//setFlag標誌位起作用時的處理
{
if(setCount!=3)
{
if(adjustKeyFlag==on)
{ keyOnTime++;
if(keyOnTime>10)
longKeyFlag=on;
if(adjustKey==1)
{
adjustKeyFlag=off;
longKeyFlag=off;
shortKeyFlag=on;
keyOnTime=0;
keyOnResponse();
}
}
}
else
{
if((adjustKeyFlag==on)&&(adjustKey==1))
{
strongFlag=!strongFlag;
adjustKeyFlag=off;
keyOnResponse();
}
}
}
//***************************************** 排風開關按鍵處理程序片段 **********************************
if((switchKeyFlag==on)&&(switchKey==1))
{
switchKeyFlag=off;
twoMinutesFlag=off;
if(switchFlag==off)
{
switchFlag=on;
strongFlag=on;
}
else
{
switchCount++;
if(switchCount==1)
twoMinutesFlag=on;
if(switchCount==2)//按兩次按鈕,關掉
{
switchCount=0;
switchFlag=off;
setFlag=off;
recover();
gWeiTemp=timeNumber[0];
sWeiTemp=timeNumber[1];
bWeiTemp=timeNumber[2];
qWeiTemp=timeNumber[3];
}
}
keyOnResponse();
}
//**********************************設置按鈕鍵操作處理程序段**************************************************************
if((setKeyFlag==on)&&(setKey==1))
{
setKeyFlag=off;
setFlag=on;
setCount++;//按設置鍵的次數;
fiveSecondTime=0;//時間計數複位
keyOnTime=0;
count2=0;
hourFlag=off;
if(switchFlag==on)
{
if(setCount>=4)
{
recover(); //數據從timeNumberTemp數組重新寫回到timeNumber中;
setFlag=0;
gWeiTemp=timeNumber[0];
sWeiTemp=timeNumber[1];
bWeiTemp=timeNumber[2];
qWeiTemp=timeNumber[3];
}
}
else
{
if(setCount>=3)
{
recover(); //數據從timeNumberTemp數組重新寫回到timeNumber中;
setFlag=0;
gWeiTemp=timeNumber[0];
sWeiTemp=timeNumber[1];
bWeiTemp=timeNumber[2];
qWeiTemp=timeNumber[3];
}
}
keyOnResponse();
}
//*********************設置標誌為ON時的相關操作*************************************************************
setFlagOn();
//************************************ switchFlag標誌為on或者off時的相應程序片段*************************************************
if(switchFlag==on)
{
backLightFlag=on;
if(strongFlag==on)
{
weakWindOff();
st=RBon;
l1Flag=on;
strongCount++;
switch(strongCount)
{
case 0x01: f1Flag=on; f2Flag=off; f3Flag=on; f4Flag=off; break;
case 0x02: f1Flag=on; f2Flag=off; f3Flag=on; f4Flag=off; break;
case 0x03: f1Flag=off; f2Flag=on; f3Flag=off; f4Flag=on; break;
case 0x04: f1Flag=off; f2Flag=on; f3Flag=off; f4Flag=on; break;
default: strongCount=0x00; break;
}
}
else
{
strongWindOff();
we=RBon;
l2Flag=on;
weakCount++;
switch(weakCount)
{
case 0x01: f5Flag=on;f6Flag=on;f7Flag=off; break;
case 0x02: f5Flag=on;f6Flag=on;f7Flag=off; break;
case 0x03: f5Flag=off;f6Flag=on;f7Flag=on; break;
case 0x04: f5Flag=off;f6Flag=on;f7Flag=on; break;
case 0x05: f5Flag=on;f6Flag=off;f7Flag=on; break;
case 0x06: f5Flag=on;f6Flag=off;f7Flag=on; break;
default: weakCount=0;break;
}
}
}
else
{
strongWindOff();
weakWindOff();
backLightFlag=off;
switchCount=0;
}
endFunction();
twoMinutes();
refurbish();//刷新寄存器
writeData(0,map);//顯示
if(count==60000)
count=0;
}
}
}
//************************************** 時 間 計 時 函 數 **************************************************
void timeCount(void)
{
if(count%20==0)
{
secondCount++;
if(secondCount==60)
{
secondCount=0;
gWei++;
if(gWei==10)
{
gWei=0;
sWei++;
if(sWei==6)
{
sWei=0;
bWei++;
if(qWei==2&&bWei==4)
{
bWei=0;
qWei=0;
}
if(bWei==10)
{
bWei=0;
qWei++;
}
}
}
}
}
}
//*******************************************鍵 盤 掃 描 函 數 *****************************************
void keyScan(void)
{
if(lightKeyFlag==off)
{
if(lightKey ==0)//判斷lightKey 鍵是否按下,outLight燈和LCDLigh圖形燈開關鍵
{
delayms(keyOnDelay);
if(lightKey ==0)
{
lightKeyFlag=on;
}
}
}
if(switchKeyFlag==off)
{
if(switchKey==0)//判斷switchKey鍵是否按下 風機開關鍵
{
delayms(keyOnDelay);
if(switchKey==0)
{
switchKeyFlag=on;
}
}
}
if(setKeyFlag==off)
{
if(setKey==0)//判斷setKey鍵是否按下 設置鍵
{
delayms(keyOnDelay);
if(setKey==0)
{
setKeyFlag=on;
}
}
}
if(adjustKeyFlag==off)
{
if(adjustKey==0)//判斷adjustKey鍵是否按下 強弱控制鍵
{
delayms(keyOnDelay);
if(adjustKey==0)
{
adjustKeyFlag=on;
}
}
}
}
//************************************************刷 新 顯 示 內 容*****************************************
void refurbish(void) //刷新顯示內容;LCD要顯示的內容和本地的map數組一一對應;
{
if(setFlag==1)
{
map[0]=num[gWeiTemp];
map[1]=num[gWeiTemp]>>4;
if(l3Flag==on)
map[1]=map[1] | 0x08;
map[2]=num[sWeiTemp];
map[3]=num[sWeiTemp]>>4;
if(colFlag==on)
map[3]=map[3] | 0x08;
map[4]=num[bWeiTemp];
map[5]=num[bWeiTemp]>>4;
if(l2Flag==on)
map[5]=map[5] | 0x08;
map[6]=num[qWeiTemp];
map[7]=num[qWeiTemp]>>4;
}
else
{
map[0]=num[gWei];
map[1]=num[gWei]>>4;
if(l3Flag==on)
map[1]=map[1] | 0x08;
map[2]=num[sWei];
map[3]=num[sWei]>>4;
if(colFlag==on)
map[3]=map[3] | 0x08;
map[4]=num[bWei];
map[5]=num[bWei]>>4;
if(l2Flag==on)
map[5]=map[5] | 0x08;
map[6]=num[qWei];
map[7]=num[qWei]>>4;
}
if(f6Flag==on)
map[7]=map[7]| 0x08;
//*******************map[8]賦值*****************
if(LCDLightFlag==on)
map[8]=0x01;
else
map[8]=0;
if(f1Flag==on)
map[8]=map[8] | 0x02;
if(f2Flag==on)
map[8]=map[8] | 0x04;
if(l1Flag==on)
map[8]=map[8] |0x08;
//*******************map[9]賦值*****************
if(f4Flag==on)
map[9]=0x01;
else
map[9]=0;
if(f3Flag==on)
map[9]=map[9] | 0x02;
if(f5Flag==on)
map[9]=map[9] | 0x04;
if(f7Flag==on)
map[9]=map[9] | 0x08;
}
//***************************** 系 統 初 始 化 ******************************************************
void init(void)
{
GIE=0;//關總中斷
T0IE=0;//關T0中斷
OPTION=0x07;//設置預分頻器TMR0並設置分頻比為256;
ADCON1=0x07;
TMR0=TMR0Init;//賦初值
T0IF=0;
TRISB=0x00;//設置B口為輸出
TRISA0=1;//設置A口為輸出
TRISA1=1;
TRISA2=1;
TRISA3=1;
backLight=on;//LCD背光亮
bz=RBon;//蜂鳴器響
we=RBoff; //弱風
st=RBoff; //強風//背光燈
outLight=RBoff;
lightKeyFlag=off;
switchKeyFlag=off;
setKeyFlag=off;
adjustKeyFlag=off;
strongFlag=off;
switchFlag=off;
LCDLightFlag=off;
colFlag=on;//col標誌置位
setFlag=off;
halfSecondFlag=off;
twoMinutesFlag=0;
longKeyFlag=off;
shortKeyFlag=off;
setCount=0;
endFlag=off;
backLightFlag=off;
backLightTime=0;
endTimeCount=0;
fiveSecondTime=0;
twoMinutesCount=0;
keyOnTime=0;
secondCount=0;
count2=0;
hourFlag=off;
}
//***************************************發送data數據里的低low位*************************
void sendLowBit(char data,char low)
{
char i;
for(i=0;i<low;i++)
{
if((data&0x01)==0)
da=0;
else
da=1;
wr=0;
asm("nop");
wr=1;
asm("nop");
data>>=1;
}
}
//************************************發送data數據里的高count位************************
void sendHighBit(char data,char count)
{
char i;
for(i=0;i<count;i++)
{
if (data & 0x80)
da = 1;
else
da = 0;
wr = 0;
asm("nop");
wr = 1;
asm("nop");
data <<= 1;
}
}
//***********************************************延時毫秒函數******************************
void delayms(unsigned char a)
{
uint mmm;
while(a-->1)
{
for(mmm = 0; mmm < 1000;mmm ++) {}
}
}
//**********************************************刷新LCD顯示********************************
void writeData(char *pa, char *pm)
{
char i;
cs=1;
asm("nop");
cs=0;
asm("nop");
sendHighBit(0xa0,3);//發送寫數據命令
sendHighBit(*pa<<2,6);//寫器件地址; 高位先發; 在本程序里都是從第0位開始寫
for(i=0;i<10;i++)//數據4位4位的寫,一共寫10次;寫數據時低位先發;
{
sendLowBit(*pm++,4);
}
}
//*******************************************LCD寫命令函數***********************************
void writeCommand(char command)
{
cs=1;
asm("nop");
cs=0;
asm("nop");
sendHighBit(0x80,3);
sendHighBit(command,9);
}
//************************************關 強 風****************************************************************
void strongWindOff()//關強風
{
st=RBoff;
l1Flag=off;
f1Flag=off;
f2Flag=off;
f3Flag=off;
f4Flag=off;
}
//************************************關 弱 風****************************************************************
void weakWindOff(void)
{
we=RBoff;
l2Flag=off;
f5Flag=off;
f6Flag=off;
f7Flag=off;
}
//********************************按鍵起作用時通常要做出的響應***************************************************
void keyOnResponse(void)
{
bz=RBon;//蜂鳴器開
backLightTime=0;//LCD背光延時時間清零;
backLight=on;//LCD背光燈開
delayms(keyBuzzerDelay);//蜂鳴器延時開
bz=RBoff;//蜂鳴器關;
}
//*********************************從備份數組中去吃數據還原定時數據**********************************************
void recover(void) //還原定時數據
{
setCount=0;
setFlag=off;
timeNumber[0]=timeNumberTemp[0];
timeNumber[1]=timeNumberTemp[1];
timeNumber[2]=timeNumberTemp[2];
timeNumber[3]=timeNumberTemp[3];
}
//***************************當switchCount=1,也就是相當於開關按第2次時的處理程序*********************************
void twoMinutes(void)
{
if(twoMinutesFlag==on)
{
twoMinutesCount++;
if(twoMinutesCount>=2400)
{
bz=RBon;
LCDLightFlag=off;
switchFlag=off;
backLightFlag=off;
backLight=off;
switchCount=0;
setFlag=0;
if(twoMinutesCount==2404)
{
bz=RBoff;
twoMinutesFlag=off;
gWeiTemp=timeNumber[0];
sWeiTemp=timeNumber[1];
bWeiTemp=timeNumber[2];
qWeiTemp=timeNumber[3];
}
}
}
else
{
twoMinutesCount=0;
}
}
//***********************endFlag==on時的處理程序片段*************************************************************
void endFunction(void)//定時結束:當倒計時結束時,蜂鳴器以0.5S內發出三次提示音,一秒為一周期共5個周期.
{
if(endFlag==on)
{
backLight=off;
setFlag=off;
LCDLightFlag=off;
switchFlag=off;
endTimeCount++;
if(endTimeCount%3==0)
bz=!bz;
if(endTimeCount==100)
{
bz=RBoff;
endFlag=off;
endTimeCount=0;
}
}
}
//*********************設置標誌為ON時的相關操作**********************************************************
void setFlagOn()
{
if(setFlag==on)
{
if(setCount==1)
{
fiveSecondTime++;
if(longKeyFlag==on)
{
backLightTime=0;
fiveSecondTime=0;
if(count%4==0)
{
timeNumber[2]++;
if((timeNumber[3]==2)&&(timeNumber[2]==4))
{
timeNumber[3]=0;
timeNumber[2]=0;
}
else
{
if(timeNumber[2]==10)
{
timeNumber[2]=0;
timeNumber[3]++;
}
}
timeNumberTemp[2]=timeNumber[2];//更新高2位顯示數據
timeNumberTemp[3]=timeNumber[3]; //更新高2位顯示數據
}
}
else
{
if(shortKeyFlag==on)
{
shortKeyFlag=off;
fiveSecondTime=0;
timeNumber[2]++;
if((timeNumber[3]==2)&&(timeNumber[2]==4))
{
timeNumber[3]=0;
timeNumber[2]=0;
}
else
{
if(timeNumber[2]==10)
{
timeNumber[2]=0;
timeNumber[3]++;
}
}
timeNumberTemp[2]=timeNumber[2];
timeNumberTemp[3]=timeNumber[3];
}
}
if(fiveSecondTime%10==0)
halfSecondFlag=!halfSecondFlag;
if((longKeyFlag==off)&&(halfSecondFlag==off))//每一秒閃爍一次
{
bWeiTemp=10;
qWeiTemp=10;
colFlag=on;
}
else
{
gWeiTemp=timeNumber[0];
sWeiTemp=timeNumber[1];
bWeiTemp=timeNumber[2];
qWeiTemp=timeNumber[3];
colFlag=on;
}
if(fiveSecondTime==100)
{
fiveSecondTime=0;
setFlag=off;
setCount=0;
keyOnTime=0;
}
}
//××××××××××××××××××××××× if(setCount==2)時的處理程序 ××××××××××××××××××××××××××
if(setCount==2)
{
fiveSecondTime++;
if(longKeyFlag==on)
{
backLightTime=0;
fiveSecondTime=0;
if(count%4==0)
{
timeNumber[0]++;
if(timeNumber[0]==10)
{
timeNumber[0]=0;
timeNumber[1] ++;
if(timeNumber[1]==6)
{
timeNumber[0]=0;
timeNumber[1]=0;
}
}
timeNumberTemp[0]=timeNumber[0];
timeNumberTemp[1]=timeNumber[1];
}
}
else
{
if(shortKeyFlag==on)
{
shortKeyFlag=off;
fiveSecondTime=0;
timeNumber[0]++;
if(timeNumber[0]==10)
{
timeNumber[0]=0;
timeNumber[1] ++;
if(timeNumber[1]==6)
{
timeNumber[0]=0;
timeNumber[1]=0;
}
}
timeNumberTemp[0]=timeNumber[0];
timeNumberTemp[1]=timeNumber[1];
}
}
if(fiveSecondTime%10==0)
halfSecondFlag=!halfSecondFlag;
if((longKeyFlag==off)&&(halfSecondFlag==off))//每一秒閃爍一次
{
gWeiTemp=10;
sWeiTemp=10;
colFlag=on;
}
else
{
gWeiTemp=timeNumber[0];
sWeiTemp=timeNumber[1];
bWeiTemp=timeNumber[2];
qWeiTemp=timeNumber[3];
colFlag=on;
}
if(fiveSecondTime==100)
{
fiveSecondTime=0;
setFlag=off;//回到上一次狀態
setCount=0;//
keyOnTime=0;
}
}
//×××××××××××××××××××××××× setCount==3 時的處理程序段××××××××××××××××××
if(setCount==3)
{
if(hourFlag==off)
{
if((timeNumber[3]==0)&&(timeNumber[2]==0))
{
hourFlag=on;
count2=0;
timeNumber[3]=timeNumber[1];
timeNumber[2]=timeNumber[0];
timeNumber[1]=0;
timeNumber[0]=0;
}
else
{
if(count%20==0)
{
count2++;
if(count2==60)
{
count2=0;
timeNumber[0]--;
&nbs p; if(timeNumber[0]<0)
{
timeNumber[0]=9;
timeNumber[1]--;
if(timeNumber[1]<0)
{
timeNumber[1]=5;
timeNumber[2]--;
if(timeNumber[2]<0)
{
timeNumber[2]=9;
timeNumber[3]--;
}
}
}
}
}
}
}
else
{
if(count%20==0)
{
timeNumber[0]--;
if(timeNumber[0]<0)
{
timeNumber[0]=9;
timeNumber[1]--;
if(timeNumber[1]<0)
{
timeNumber[1]=5;
timeNumber[2]--;
if(timeNumber[2]<0)
{
timeNumber[2]=9;
timeNumber[3]--;
if(timeNumber[3]<0)
{
endFlag=on;
hourFlag=off;
bz=RBon;
recover();
gWeiTemp=timeNumber[0];
sWeiTemp=timeNumber[1];
bWeiTemp=timeNumber[2];
qWeiTemp=timeNumber[3];
}
}
}
}
}
}
gWeiTemp=timeNumber[0];
sWeiTemp=timeNumber[1];
bWeiTemp=timeNumber[2];
qWeiTemp=timeNumber[3];
colFlag=on;
}
}
else
{
setCount=0;
}
}
//*******************************col每 一 秒 閃 爍 一 次********************************************************
void colFliker(void)
{
if(count%10==0)
{
colFlag=!colFlag;
}
}
[admin via 研發互助社區 ] PIC16F716抽油煙機主控板程序已經有2301次圍觀
http://cocdig.com/docs/show-post-42106.html