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