找回密码
 注册
关于网站域名变更的通知
查看: 757|回复: 5
打印 上一主题 下一主题

可调矩阵按键+LCD1602简单万年历程序 已制作出实物

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-1-8 13:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
可调矩阵按键+LCD1602简单万年历程序 已制作出实物
0 v6 }6 X2 r, u用开发板上的矩阵按键 DS1302 LCD1602 写了一个简单的万年历程序$ B0 b+ O) y5 w) @2 }2 i, m
显示 年月日 时间 星期 温度 可用矩阵按键调整(其中的几个按键  具体的看程序)) |& V3 \/ P+ i, l1 X2 e8 p
程序包括了矩阵按键扫描 、 DS1302、LCD1602、DS18B20 底层文件 可以用来移植到别的程序中1 X+ I$ m2 g! F4 x
希望对新人的学习有所帮助!
, _( j* p8 R! x实物图:
: R9 F6 ^8 G# o7 } $ }' V# t! `) w& y6 C- K1 o" t
3 f; c- P+ t7 X
4 E7 G0 |9 u& H9 v+ c/ I1 R
. f9 C3 q! r; t+ I
单片机主程序:7 Z5 x7 G( p1 C  G
+ ~2 R; Z! F: |$ |
//******************************Write By F H X***********************************//# u" d2 F/ L$ ]* L# y0 F( o

9 ~, y6 T$ E. `//****************LCD1602万年历 :显示 年月日、 温度、 时间、 星期****************//# \8 z( l7 x, n# Z4 Z2 K" i
//******************************矩阵按键可调整***********************************//
8 A. Z( }- T7 p5 ~//*****************************LCD1602界面如下***********************************//5 b5 ]) W4 p9 w; }1 V
//************************ ■〓〓〓〓〓〓〓〓〓〓〓■ *****************************//
' J6 H4 C5 Y/ ]2 O. W' z//************************ ■ 2017年03月20日 15°C  ■ *****************************//! p  z0 h8 D* G2 L
//************************ ■ 12:30:00    week:1   ■ *****************************//
/ D: h; m+ L- l+ ^8 `//************************ ■〓〓〓〓〓〓〓〓〓〓〓■ *****************************//
& \6 U4 |  j" L  m+ t+ W! X( ]) O; B9 p$ ^1 O. x2 }5 p
6 u; q  d; o, U" W, d
#include"function.h"- s! r+ e9 {( w% Y6 k
9 K% C* |( @$ r4 u) S7 r2 u4 W
uchar T0RH=0;
$ l' p, M1 U; Wuchar T0RL=0;5 q7 A5 h) g. Z+ o# p
bit flag200ms=1;                          //到达200ms标志2 i/ f9 K6 q3 p- _! L' O
uchar mode=0;                             //设置变量
2 ?( |  k  R0 c, Dstruct STime bufTime;                     //日期时间缓冲区  Y6 a7 `0 I4 K7 ~/ f: ]
uchar tflag;
: y; ]. H; a3 _( M9 m7 k, w( x! Uvoid Timer0Init(uint ms);5 v! T5 R/ P; H% ^: T4 q3 ~" v( k% S
. J0 c8 N9 j2 R/ U2 v

0 {5 m. Z& I# K8 t6 b6 A  i/**************************************************主函数***********************************************************/) ]( l$ s; |9 V( s1 q
/*                                                                                                                 */         
7 a3 \# U$ E. g  X, k9 `3 u7 j: Q( h/*******************************************************************************************************************/
& G, D" @: w( [6 S, [4 ]. W& r: H2 \. ]! nvoid main()4 c8 b  \/ o0 B. c+ }4 V/ ]2 K
{8 v# N0 n- [/ Z. Q
        uchar psec = 0xAA;                      //确保第一次读取时间能刷新显示. k1 ^6 @7 `( e+ L, ]( {( ]5 L
        EA=1;                                   //打开总中断6 l. X1 h( Q2 Z- Z; Y9 l" P
        Timer0Init(1);                          //初始化定时器0 定时1ms
/ x. S  B) B  \! E/ x2 L2 c8 C        RESET_DS18B20();                        //复位18B20
) ^3 u' t5 T# \. ?. A        InitDS1302();                           //初始化DS13029 V: K; x( E5 `5 q4 S, w
        InitLcd1602();                          //初始化LCD1602
& s) f% n+ e- b1 R
5 E- N6 d# e0 O4 W        LcdShowStr(0,0,"20");                   //固定显示内容
: Z7 _9 ?; X/ ^- k        Display_user();                         //显示自定义字符 年 月 日
& t" I/ l7 R6 [; N7 d# I/ k) j        LcdShowDat(14,0,0xDF);                  //显示°5 |* G9 A& [! l5 {; x) u
        LcdShowStr(15,0,"C");               
5 @* z: \  X  r# n# H4 T1 n$ H        LcdShowStr(0,1,"  :  :  ");
% P. J  r0 y9 H1 l        LcdShowStr(9,1,"week:");
3 w  G" C* f% d; g! R- A: r* O        while(1)
% ?3 G, O8 L. c! f8 B/ \) K6 J        {1 `& j! Y/ u6 B5 x
                KeyDrive();& X( d4 c0 N# k3 t0 y+ m
                if(flag200ms&&(mode==0))         //到达200ms且没有进入设置模式时) d3 E! q: D. `
                {
5 i* \5 a8 _# }& ?. A$ }                        flag200ms=0;  z6 u' d1 l- h
                        GetRealTime(&bufTime);              //获取当前时间/ C; w: Y2 F5 J' S8 g! Q
                        Display_Tem();                      //显示温度) t1 p; G/ f) y5 f5 [
                        if(psec!=bufTime.sec)               //检测时间有变化时刷新时间显示
$ C+ v, w+ C( I: n                        {
, N/ z* |2 K% J& f                                Refresh_TimeShow();                 //更新显示8 s7 x' y# l* X6 N# w
                                psec=bufTime.sec;3 I7 {! C+ U- k
                        }
4 {; e' K7 r8 H! e8 ]                }1 N8 g4 I$ p  y( t, l% F2 a  N" W
        }
1 ]& N" B6 ?! L1 J9 k}+ u% {  _0 O# j: A, }/ B; Q3 z

9 e1 y2 h) P( P6 Z) k  H3 t
1 I2 R: X1 q& S, u, M* W3 ?
& }# j' `6 F- o5 d4 Z1 ?/*********************************************定时器0初始化函数***************************************************/
6 E  g# |9 A: k  r6 G. }/*                                           形参ms 当ms=1 定时1毫秒                                             */
, C  v# F+ Q6 D/*****************************************************************************************************************/
. \- `" G6 o* i# D; z$ c6 J4 `void Timer0Init(uint ms)
# C7 Z) s; X# W/ @6 L" E$ o{' ~5 v& e+ E7 O: _
        ulong tmp;                              //16位长整型变量tmp
+ X7 v& K( l0 R$ p+ `3 k! D/ |" D        tmp=12000000/12;                        //用晶振频率除以12得到定时器计数频率+ ]5 Q+ w+ y0 ?  r) {* o& {
        tmp=(tmp*ms)/1000;                      //计算出需要多少个机器周期
3 z$ j6 q, @! u        tmp=65536-tmp;                          //定时器的初始值' Z$ t" k4 B: h( d
        tmp=tmp+27;                             //补偿中断延时响应造成的误差
8 v1 b" e" e3 P3 D. c+ y; w        T0RH=(uchar)(tmp>>8);                   //将tmp高8位右移8位 赋值给T0RH
: U7 B! E- S0 x1 y: P7 k2 d# k        T0RL=(uchar)tmp;                        //将tmp低8位赋值给T0RL
. S2 n# ^( }: I  T9 a. c        TMOD&=0xF0;                             //TMOD高4位不变 低四位清零
% l+ {9 X, _; N( |$ P; |$ ]) t        TMOD|=0x01;                             //TMOD低四位变成00010 a. p/ K, z7 _* ]' A
        TH0=T0RH;                               //装载初值
# x# }; ?! b6 T$ S        TL0=T0RL;: f) `2 C. o! @% N9 y
        ET0=1;                                  //开启定时器0中断         
* x3 N+ O* u3 [2 B& V        TR0=1;                                  //开启定时器0
0 |- w% W6 _/ D}
/ M) C7 \; m- T; E: ~1 h! {# I
) }1 w" i. G: `6 e/ W. {- O/*************************************************T0中断服务函数**************************************************/
" ~* d5 H- D/ i$ ?6 z. E/*                                                                                                               */: B4 g9 Z0 Z+ z* F% m, F
/*****************************************************************************************************************/7 b5 }2 s& W% T) n
void InterruptTimer0() interrupt 1
1 {% e9 o3 s/ S* F) l{7 p" \3 T- [; V7 z3 w) n
        static uchar tmr_ms=0;4 [! {6 l6 s% j1 D8 I( r2 T, B% C7 e
        TH0=T0RH;
  o; }" Y6 a( _, o  o# I! r" Z. ?        TL0=T0RL;
8 J+ T, J7 j2 x$ n' m. \. j) z$ L        KeyScan();
6 ?: n( X/ P1 K1 B) S6 h        tmr_ms++;
! A+ ?/ p* k: _  [* w        if(tmr_ms>=200)                       //定时200ms
: L0 F7 ^& t9 w+ R        {+ O. C9 N9 t/ N0 n0 f$ J* s& J1 [
                tmr_ms=0;! Z+ @# F& G# `& g& Z
                flag200ms=1;
2 A4 P3 j5 q. y        }
5 J; a9 L/ |# ]}) }! U/ D9 K: Y$ r# X9 l  w8 |
( t4 c) p5 o/ A. i$ ]( Z
按键程序:$ i& h, ^/ Z( x
#include"key.h": B9 [% C2 o1 L5 I. r; A% Z
//**********************Disigned By F H X***************************//
5 A" C6 E, X4 v//*********************4*4矩阵键盘扫描程序**************************//( _1 a. H9 K% H: U: W( S* T
//*****1 按键驱动函数 :检测按键动作 执行 mian.c 中按键动作函数*****//
: {, {4 v: q3 A* g' F; E' Y* D& l4 x//*****2 按键扫描函数 :扫描按键状态 在main.c 中的中断函数被调用****//
) I$ I, v8 X! c! Z6 w5 ?1 C5 L6 t9 D5 m7 l8 H
3 G3 K8 j& V3 o8 b1 e
/*uchar code KeyCodeMap[4][4]={             //ASCⅡ键码
5 f. I* w, e8 D- v& c     {'1','2','3',0x26},               //数字键1,数字键2,数字键3,向上键
+ y' V1 [' s" `5 K% ^9 r$ q     {'4','5','6',0x25},               //数字键4,数字键5,数字键6,向左键
  z3 ?9 i3 A0 Q0 d! e# \1 Q/ @     {'7','8','9',0x28},               //数字键7,数字键8,数字键9,向下键
0 |! u9 @& C9 Y     {'0',0x1B,0x0D,0x27}                //数字键0,  ESC键 ,回车键 ,向右键
. Q' r# j' Z7 i# N* k8 J};*/1 x+ @! p; `8 F$ ^8 n8 u

1 R5 z# P( e+ A/ Y

% T( Y. B3 a( I" q8 quchar code KeyCodeMap[4][4]={            $ h# g" O; f/ c6 `. ?/ A! `' R
     {0x31,0x32,0x33,0x26},               
1 `& `) I3 m, }' H     {0x34,0x35,0x36,0x25},              
. C' @8 E) k1 X; L' H' T# J     {0x37,0x38,0x39,0x28},            
' ~  {- h& h' O; R1 K* y     {0x30,0x1B,0x0D,0x27}               
; R/ f6 ~: @# r' n};$ x' ]) t; w9 q) ]; U- h
. M% O9 R' b% }$ }, k

( }. j) I; |" S" v# Q- I, guchar KeySta[4][4]={                      //16个按键当前状态' r3 ^% M# F2 P% J
           {1,1,1,1},
) l! A5 z5 G& U. T     {1,1,1,1}," e0 |# C: _6 n* f5 s5 ~/ Y; O& H
     {1,1,1,1},
* j+ j0 j6 {. \: R* v     {1,1,1,1} 8 d5 a" E/ m; ^) r
};                                        : I* V) o/ ?( k5 r$ j4 v
ulong pdata KeyDownTime[4][4]={           //16个按键按下时间
. O* j) e& C9 c  r6 D) N7 y     {0,0,0,0},2 s( ?: ]2 h- N2 c+ p" x$ S
     {0,0,0,0},5 _2 W# g  M8 i+ M! z
     {0,0,0,0},
; r4 F9 W9 M. x! |+ a& P     {0,0,0,0} 2 M: [) ]( Q. a3 M8 @
};  
2 t5 c) }" j! j4 s# L7 ]+ X
% m. j4 |$ y: z$ P: k

; S4 }9 u: P) V. j1 X8 r+ }
' T5 g% @# C& }- Z/ t. a, S7 r3 n

0 c* H- o3 V+ r1 S6 B( O8 f/**********按键驱动函数**********/$ o4 R( g6 e; S
void KeyDrive()
1 {- y: @* |& l* N0 a# f! L; g{: E. B. L+ s  z3 _# S3 e
        uchar i,j;
" w: X" |: M. r9 B; S# x        static uchar backup[4][4]={             //保存上次按键状态 默认都为弹起5 U' w# s* n# T
     {1,1,1,1},% o) U  @8 l7 l$ v
     {1,1,1,1},& W5 j! T0 w& n. p) Z: n+ |
     {1,1,1,1},) t# @- m5 J, U
     {1,1,1,1}
1 ]( I. A! N5 a- q$ ^; d        };0 H; M" O7 x* M) P, N6 }3 q6 P$ r+ L# q* h
        static ulong pdata TimeTh[4][4]={       //按键按下时间阈值 超过阈值则为长按模式2 G. d- S1 Y6 C0 h7 ^
     {1000,1000,1000,1000},% o. l2 v& r( q) y/ a
     {1000,1000,1000,1000},
3 f' q/ s) F8 q3 C) J     {1000,1000,1000,1000},& C+ `8 y7 b' F3 W/ Y
     {1000,1000,1000,1000}4 \+ ]7 @5 d' w( L  \' k9 y
        };
5 H2 M) K  {7 d2 A% _        for(i=0;i<4;i++)                        //循环扫描4×4矩阵键盘6 K4 |0 n6 [  G1 ~/ P; d- s
        {* a/ D/ J( @$ C4 b9 t( i
                for(j=0;j<4;j++)* L8 T' }# D9 N7 g- c* c0 V" e$ D7 m
                {8 _) R8 |) ]; v# [) r& W% \2 Z
                        if(backup[j]!=KeySta[j])      //检测按键动作
  {0 [+ u+ X; |& Z+ i                        {' @! @4 d3 v1 W' h
                                if(KeySta[j]==0)               //按键被按下
! Z. e/ `4 |1 h& J                                {
! t) j/ c& W4 ~* N. {( @4 X                                        KeyDown(KeyCodeMap[j]);      //执行按键动作函数1 M  d+ @8 s  o5 \" ?3 s2 m
                                }
. P& B# l+ z6 ?* y/ o1 g* G7 f                                backup[j]=KeySta[j];        //保存当前按键值' V5 w! J2 v# F0 p
                        }# D4 B4 G3 v2 J! G, t; j% ~
                        if(KeyDownTime[j]>0)             //检测按键按下时间, ]7 @% n3 r, u) r7 X
                        {
" \6 P" s8 W8 I5 \: _; [                                if(KeyDownTime[j]>=TimeTh[j])
% U, E- M" D+ x& [- j( l                                {/ a, `9 L3 ^, Q1 b; ]+ o
                                        KeyDown(KeyCodeMap[j]);      //按键按下时间大于阈值 执行按键动作函数
" _( `9 \' I/ O9 M( W6 w( Z' I4 u                                        TimeTh[j]+=200;              //阈值自增
' l4 H: T0 |" Z$ _! O' w                                }9 v$ d6 m2 H) ^7 c5 b
                        }
. }0 j. c2 A- n9 B; ]8 |5 N# ~1 J+ N                        else ( L3 F! j* P0 W: x! I
                        {
  b4 g& U" I+ G% B                                TimeTh[j]=1000;                //按键弹起时恢复阈值时间- p, x/ f7 u; ]( v; i4 z+ k6 j
                        }1 S/ u# L' l) V& x
                }
+ v; b. |5 H2 ]9 d        }
! K+ `8 _& ?/ s! T}- T0 H3 A+ L) \7 T$ n

2 u' j- F) t2 H, F+ g

/ x, b2 F# Q  I/ f# A# W- Q0 Q) }! i/**********按键扫描函数**********/1 v2 V+ [0 \# q0 A. D. ~$ A
void KeyScan()
  D: k' H; t! [7 s{
7 f: _- g& h- O8 P5 ?/ Q1 y* l        uchar i;7 D, K7 ?6 {$ e; g1 d& ?4 ^3 ]5 M
        static uchar keyout=0;                  //矩阵按键扫描输出索引4 }$ ]& @2 r, B5 E) B2 C0 Q- s
        static uchar Keybuff[4][4]={            //按键扫描缓冲区
8 w# x7 h6 V8 J) u& P- Z1 Y                {0xFF,0xFF,0xFF,0xFF},4 p7 B! Z+ U+ m; a2 s
    {0xFF,0xFF,0xFF,0xFF}," W- C! o/ J: B& `
    {0xFF,0xFF,0xFF,0xFF},
% x1 V3 Z$ O1 _8 \    {0xFF,0xFF,0xFF,0xFF}5 j' i* j: {! x3 Z1 J7 s3 j
        };
7 |* B5 O/ v, d% e2 ]                                                //逐行检测按键是否被按下 起到按键消抖作用
4 _5 e0 x+ v* b. Z% S  Keybuff[keyout][0]=(Keybuff[keyout][0]<<1)|KEY_IN_1;0 d! N' `0 Q/ G8 G# z+ ~8 b
        Keybuff[keyout][1]=(Keybuff[keyout][1]<<1)|KEY_IN_2;
6 q$ W+ {, z' ^  I- h: V        Keybuff[keyout][2]=(Keybuff[keyout][2]<<1)|KEY_IN_3;
$ s6 j. `- o9 J5 T        Keybuff[keyout][3]=(Keybuff[keyout][3]<<1)|KEY_IN_4;2 F+ c  _1 m# \5 p8 t
        for(i=0;i<4;i++)
" a5 C; Y+ N! M) [0 C  x        {; {, ]; _; R/ J8 ]. [, @" P. M
                if((Keybuff[keyout]&0x0F)==0x00)     //检测某个按键被按下' `: ?  v1 p- q
                {% n0 t" T2 ~# }0 c4 w+ Y: M; q
                        KeySta[keyout]=0;                //改变该按键状态
9 `: Y* ?# E2 f/ C0 V# A: X% |                        KeyDownTime[keyout]+=4;          //该按键按下时间累加5 b% J6 t7 @1 b' [" m
                }. K4 o9 l: u+ H
                else if((Keybuff[keyout]&0x0F)==0x0F)//检测某个按键弹起
8 Q9 b+ J4 K- @( \: [                {
1 W' z! X! P0 `! W: k                        KeySta[keyout] = 1;              //改变该按键状态
/ b* ?3 X& `- p8 W. N- c; m0 b      KeyDownTime[keyout] = 0;         //该按键按下时间清零
4 S, z4 J& e6 m                }& [( T& M8 U# w' C2 {# U( C
        2 E$ U* y" c  ]; {

+ K' U; F" |- q7 L0 N  O
: T# h- e! J5 j0 R+ p# C
…………限于本文篇幅 余下代码请从论坛下载附件…………* Y# ?2 m* F% c% O. E
游客,如果您要查看本帖隐藏内容请回复

2 L" ], J9 J" t# H; ~6 T$ x( O6 w
- l0 V- f& G6 ^3 |7 f" V5 x  @% N# r6 v
/ l8 J  m" L6 B$ K- Q# T" O# y

8 r7 i* B2 ^/ r' y* a9 v
; z5 R( Q, N' ^

该用户从未签到

3#
发表于 2019-12-24 21:13 | 只看该作者

该用户从未签到

4#
发表于 2020-3-4 09:09 | 只看该作者
get到了新技能,谢谢楼主
+ f9 E* d& k  g3 _, K. \

该用户从未签到

6#
发表于 2021-2-20 23:51 | 只看该作者
谢谢分享 收藏
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-7-21 05:48 , Processed in 0.140625 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表