/**************************************************
**************抽油烟机主控板程序*******************
**************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;
}
}