用开发板上的矩阵按键 DS1302 LCD1602 写了一个简单的万年历程序
显示 年月日 时间 星期 温度 可用矩阵按键调整(其中的几个按键 具体的看程序)
程序包括了矩阵按键扫描 、 DS1302、LCD1602、DS18B20 底层文件 可以用来移植到别的程序中
希望对新人的学习有所帮助!
实物图:
原理图:
pcb图:
单片机主程序:
- //******************************Write By F H X***********************************//
- //****************LCD1602万年历 :显示 年月日、 温度、 时间、 星期****************//
- //******************************矩阵按键可调整***********************************//
- //*****************************LCD1602界面如下***********************************//
- //************************ ■〓〓〓〓〓〓〓〓〓〓〓■ *****************************//
- //************************ ■ 2017年03月20日 15°C ■ *****************************//
- //************************ ■ 12:30:00 week:1 ■ *****************************//
- //************************ ■〓〓〓〓〓〓〓〓〓〓〓■ *****************************//
- #include"function.h"
- uchar T0RH=0;
- uchar T0RL=0;
- bit flag200ms=1; //到达200ms标志
- uchar mode=0; //设置变量
- struct STime bufTime; //日期时间缓冲区
- uchar tflag;
- void Timer0Init(uint ms);
- /**************************************************主函数***********************************************************/
- /* */
- /*******************************************************************************************************************/
- void main()
- {
- uchar psec = 0xAA; //确保第一次读取时间能刷新显示
- EA=1; //打开总中断
- Timer0Init(1); //初始化定时器0 定时1ms
- RESET_DS18B20(); //复位18B20
- InitDS1302(); //初始化DS1302
- InitLcd1602(); //初始化LCD1602
-
- LcdShowStr(0,0,"20"); //固定显示内容
- Display_user(); //显示自定义字符 年 月 日
- LcdShowDat(14,0,0xDF); //显示°
- LcdShowStr(15,0,"C");
- LcdShowStr(0,1," : : ");
- LcdShowStr(9,1,"week:");
- while(1)
- {
- KeyDrive();
- if(flag200ms&&(mode==0)) //到达200ms且没有进入设置模式时
- {
- flag200ms=0;
- GetRealTime(&bufTime); //获取当前时间
- Display_Tem(); //显示温度
- if(psec!=bufTime.sec) //检测时间有变化时刷新时间显示
- {
- Refresh_TimeShow(); //更新显示
- psec=bufTime.sec;
- }
- }
- }
- }
- /*********************************************定时器0初始化函数***************************************************/
- /* 形参ms 当ms=1 定时1毫秒 */
- /*****************************************************************************************************************/
- void Timer0Init(uint ms)
- {
- ulong tmp; //16位长整型变量tmp
- tmp=12000000/12; //用晶振频率除以12得到定时器计数频率
- tmp=(tmp*ms)/1000; //计算出需要多少个机器周期
- tmp=65536-tmp; //定时器的初始值
- tmp=tmp+27; //补偿中断延时响应造成的误差
- T0RH=(uchar)(tmp>>8); //将tmp高8位右移8位 赋值给T0RH
- T0RL=(uchar)tmp; //将tmp低8位赋值给T0RL
- TMOD&=0xF0; //TMOD高4位不变 低四位清零
- TMOD|=0x01; //TMOD低四位变成0001
- TH0=T0RH; //装载初值
- TL0=T0RL;
- ET0=1; //开启定时器0中断
- TR0=1; //开启定时器0
- }
- /*************************************************T0中断服务函数**************************************************/
- /* */
- /*****************************************************************************************************************/
- void InterruptTimer0() interrupt 1
- {
- static uchar tmr_ms=0;
- TH0=T0RH;
- TL0=T0RL;
- KeyScan();
- tmr_ms++;
- if(tmr_ms>=200) //定时200ms
- {
- tmr_ms=0;
- flag200ms=1;
- }
- }
复制代码
按键程序:
- #include"key.h"
- //**********************Disigned By F H X***************************//
- //*********************4*4矩阵键盘扫描程序**************************//
- //*****1 按键驱动函数 :检测按键动作 执行 mian.c 中按键动作函数*****//
- //*****2 按键扫描函数 :扫描按键状态 在main.c 中的中断函数被调用****//
- /*uchar code KeyCodeMap[4][4]={ //ASCⅡ键码
- {'1','2','3',0x26}, //数字键1,数字键2,数字键3,向上键
- {'4','5','6',0x25}, //数字键4,数字键5,数字键6,向左键
- {'7','8','9',0x28}, //数字键7,数字键8,数字键9,向下键
- {'0',0x1B,0x0D,0x27} //数字键0, ESC键 ,回车键 ,向右键
- };*/
- uchar code KeyCodeMap[4][4]={
- {0x31,0x32,0x33,0x26},
- {0x34,0x35,0x36,0x25},
- {0x37,0x38,0x39,0x28},
- {0x30,0x1B,0x0D,0x27}
- };
- uchar KeySta[4][4]={ //16个按键当前状态
- {1,1,1,1},
- {1,1,1,1},
- {1,1,1,1},
- {1,1,1,1}
- };
- ulong pdata KeyDownTime[4][4]={ //16个按键按下时间
- {0,0,0,0},
- {0,0,0,0},
- {0,0,0,0},
- {0,0,0,0}
- };
- /**********按键驱动函数**********/
- void KeyDrive()
- {
- uchar i,j;
- static uchar backup[4][4]={ //保存上次按键状态 默认都为弹起
- {1,1,1,1},
- {1,1,1,1},
- {1,1,1,1},
- {1,1,1,1}
- };
- static ulong pdata TimeTh[4][4]={ //按键按下时间阈值 超过阈值则为长按模式
- {1000,1000,1000,1000},
- {1000,1000,1000,1000},
- {1000,1000,1000,1000},
- {1000,1000,1000,1000}
- };
- for(i=0;i<4;i++) //循环扫描4×4矩阵键盘
- {
- for(j=0;j<4;j++)
- {
- if(backup[i][j]!=KeySta[i][j]) //检测按键动作
- {
- if(KeySta[i][j]==0) //按键被按下
- {
- KeyDown(KeyCodeMap[i][j]); //执行按键动作函数
- }
- backup[i][j]=KeySta[i][j]; //保存当前按键值
- }
- if(KeyDownTime[i][j]>0) //检测按键按下时间
- {
- if(KeyDownTime[i][j]>=TimeTh[i][j])
- {
- KeyDown(KeyCodeMap[i][j]); //按键按下时间大于阈值 执行按键动作函数
- TimeTh[i][j]+=200; //阈值自增
- }
- }
- else
- {
- TimeTh[i][j]=1000; //按键弹起时恢复阈值时间
- }
- }
- }
- }
- /**********按键扫描函数**********/
- void KeyScan()
- {
- uchar i;
- static uchar keyout=0; //矩阵按键扫描输出索引
- static uchar Keybuff[4][4]={ //按键扫描缓冲区
- {0xFF,0xFF,0xFF,0xFF},
- {0xFF,0xFF,0xFF,0xFF},
- {0xFF,0xFF,0xFF,0xFF},
- {0xFF,0xFF,0xFF,0xFF}
- };
- //逐行检测按键是否被按下 起到按键消抖作用
- Keybuff[keyout][0]=(Keybuff[keyout][0]<<1)|KEY_IN_1;
- Keybuff[keyout][1]=(Keybuff[keyout][1]<<1)|KEY_IN_2;
- Keybuff[keyout][2]=(Keybuff[keyout][2]<<1)|KEY_IN_3;
- Keybuff[keyout][3]=(Keybuff[keyout][3]<<1)|KEY_IN_4;
- for(i=0;i<4;i++)
- {
- if((Keybuff[keyout][i]&0x0F)==0x00) //检测某个按键被按下
- {
- KeySta[keyout][i]=0; //改变该按键状态
- KeyDownTime[keyout][i]+=4; //该按键按下时间累加
- }
- else if((Keybuff[keyout][i]&0x0F)==0x0F)//检测某个按键弹起
- {
- KeySta[keyout][i] = 1; //改变该按键状态
- KeyDownTime[keyout][i] = 0; //该按键按下时间清零
- }
-
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
资料下载:
按键可调万年历.rar
(318.62 KB, 下载次数: 145)
|