/************************************************** **************抽油烟机主控板程序******************* **************MCU=PIC16F716-04/pq***************** **************deisigned By 小强********************** **************date=2008年7月25日******************* 说明: 1,四个独立按键。 2,ht1621驱动液晶 3,用到的外围模块不是很多,但控制逻辑比较复杂点,对按键的处理要求也比较高的,另外还有时间显示和定时,倒计时功能,还有,液晶是段式显示的,还有图形转动,对处理技巧要求比较高,标志位也非常多,有些程序段稍微改亿下就可以用到你自己的程序中! 4,用picc写的 /5,本着学自网络,奉献网络的精神发了本程序,希望对初学者有用 ***************************************************/ #include<pic16f716.h> #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]--; 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; } }
|