|
一. 简介 将前面几篇文章介绍的几个小游戏整合在一起,加入了简陋的数字时钟和图片显示功能,合在一起作为一个小项目分享给大家,希望大家喜欢。只需要两个外设即可实现----显示屏和红外控制模块1 u8 a# n- P `$ x
+ N# U2 {& h% r6 q二. 功能介绍
8 @1 \/ Z' j7 _ 作为一个小项目来说,功能还是比较齐全的。1. 上电开机后,会进行一段开机动画的加载。
# s: t) |1 {% q2 f$ X2. 然后是主界面的显示,一共包括三个部分,时钟、游戏和相册。
7 v5 G$ y2 o5 o! c3 b7 z3. 通过红外按键进行选择。3 y7 t* g) Z7 c2 C$ F
4. 时钟 : 一个简单的时分秒的显示(#^.^#)。
9 l) E; f8 l; d. _$ ]5. 游戏 : 游戏下面又有一个界面显示,用来选择对应的游戏,贪吃蛇,俄罗斯方块和2048,都是一些常规的游戏。, h p$ K, r) u3 T
6. 相册:一个简单的二值相册(经过边缘检测后的图像)显示,包括了我预先存储的三张图片。# \) z' g$ J5 Q/ }) B+ a/ X) P' ?
7. 贪吃蛇: 贪吃蛇部分有必要单独拿出来说说,其中加入了算法部分,利用A*算法,可以自动寻找到食物的位置,并指导贪吃蛇的移动。算法的学习与贪吃蛇结合也是一个值得学习的点,同时也是一个难点。
9 Q! H6 ]6 U8 z8 Y0 ^以上就是本次小项目全部功能了。
: c. m+ s( g8 z3 d; B# H/ E三. 实现框架介绍( M$ n7 z! D, y
这次的设计为裸机程序,所以只能采用前后台系统的方式来实现。2 {3 n8 z7 x" [& g' o: I
前台为我们的应用程序,后外为我们的中断回调函数,里面主要用来红外模块数据的接收,以及时间的产生(贪吃蛇的移动以及俄罗斯方块的下落)。 - ~% @$ K0 Z0 K; y+ H1 X
前台程序简要介绍
1 K. T1 m! L$ j. D 以贪吃蛇部分为例,进入到贪吃蛇部分后,就是清屏将上一个部分的显示清除掉,然后是贪吃蛇的初始化以及使能定时器4,用来记录数据,然后就是一个while循环了。根据不同的按键状态调用不同的函数。退出这个部分也很简单,修改当前的状态,然后break就可以了。其他部分都是如此。% ~" m: {7 h# j
- else if(CurrMode == Snake) //贪吃蛇游戏8 f: A9 }' M# J5 k9 E: Q
- {5 y% r/ L& u1 [7 n. d
- LCDDMAFullOn(BackGround);
3 ]: D' ?) Z3 q$ G$ X - SnakeInit();
8 e) j5 z" C/ x - TIM_Cmd(TIM4,ENABLE);' `0 r9 v- F* b
- while(1)
0 m8 r# z# T1 w3 e9 w- Q - {
3 K/ ^& a) {" ]; k& h# t - if(KEYState == KEYLEFT)
. m) q, d( V, Z2 w7 Q; h - DirectionChange(MoveLeft);1 F2 y" p9 o) |/ z7 d. k% |5 M3 c
- else if(KEYState == KEYRIGHT)# y/ |: Z* ^3 T. s( R2 l) c: L4 z. R
- DirectionChange(MoveRight);$ }& d# t' G9 n! N* H+ \6 Z
- else if(KEYState == KEYUP)1 q$ U+ _0 a4 s& ~+ o# v
- DirectionChange(MoveUp);
3 S1 V# w0 U5 q! h I$ _ - else if(KEYState == KEYDOWN)$ Y5 G. r) j" ~& O
- DirectionChange(MoveDown);
. ^5 y$ \$ j9 ]% l- D - else if(KEYState == KEYRETURN)
, I# e$ |" H( D" n - { f3 b. E7 v" p: p: W* L
- CurrIndex = 0;8 y& ?6 Z* Q7 e( k" {
- SnakeDestory();
4 F: [$ }5 v9 m! [) b# t6 s - TIM_Cmd(TIM4,DISABLE);
' m; |) w1 I9 x/ Q8 I. v2 v3 t - CurrMode = Main;5 t' ~* p z6 `5 m' Y6 H0 l
- break;
. ]6 {. C2 }( u; \ - }1 a( ^' \1 S: s; L: `! E7 Q5 [4 W
- }
% A" \% R9 s; E5 R+ o6 c - }
复制代码
0 C; z4 P! f7 H- N) ]$ o
; o' u2 n% g; u0 s* r7 U2. 后台程序简要介绍+ N2 _$ Q) g1 b& h
本次主要用到了两个后台程序,一个是红外数据的接收
7 @0 a! q" I: @5 l- i; P: _- void EXTI0_IRQHandler(void)
0 [& t8 B8 q6 I9 A% h - {
3 h" t+ r9 t. h3 W& d% z' R! A - if(EXTI_GetITStatus(EXTI_Line0) != RESET)
/ Y+ r3 G C9 ? - {. X: j0 [) P) u) h' R6 }. N: _
- uint8_t data;% [' p( u! }* d
- data = InfraredDataRecv();
4 W7 z* ]/ {! ^ - if(data == InfraredLeft)
& i: f9 f6 w. U- X( @0 M - KEYState = KEYLEFT;- ~+ {- x/ x7 L. U
- else if(data == InfraredRight)$ [7 E, i; G k
- KEYState = KEYRIGHT;
+ t; s: p6 e6 |6 l4 @2 z3 Y k - else if(data == InfraredUp)
1 t& V5 {/ Z4 P - KEYState = KEYUP;* y: ]( y$ p/ L5 i+ _/ o
- else if(data == InfraredDown)
5 ^) o! i2 d& _$ D% K; W& | - KEYState = KEYDOWN;
( v& f/ z, x% @& W( S' d" K6 p - else if(data == InfraredReturn)
, f5 X, j, F2 [ - KEYState = KEYRETURN;
& e8 ]+ @4 N5 a5 Q" q) e' J - delay_ms(10);' R+ H2 Q Q) r
- /*清除标志位 */
y* L; e2 P. L2 s7 e& ` - EXTI_ClearITPendingBit(EXTI_Line0);
4 k9 R4 t+ i2 c; V8 v' m - }
9 R, h- X" L8 U b; X- v9 X - }
复制代码 % \" d- G& E) b) R& ~% C# S
4 ~ B1 p: F$ ^ i- Z' m
% z0 n) C, I5 H ?" Q5 E
另外一个是定时器中断,其作用可以看注释
6 D) h g, ^/ A( f% Q k0 H- void TIM4_IRQHandler(void)6 L; s4 |' n9 `4 p
- {1 m, E0 M1 f% ^
- if(TIM_GetITStatus(TIM4,TIM_IT_Update) == SET) //判断是否发生中断/ {, i4 z3 k5 n; ^
- {4 k) ?) b/ D" k2 o+ O1 C! F
; K% X% f+ M3 m" D/ K) m- if(CurrMode == Snake)
1 r5 U" b" t! u9 j. Q5 n& p5 ?* L - SnakeGame(); //蛇的移动9 ]5 X7 H. L) a2 p2 y
- else if(CurrMode == Tetris)6 T' r& ^1 o/ B
- {: v* c+ v$ T3 r6 p# c% p
- TetrisFlag = 1; //俄罗斯方块下落标志
8 A/ {+ N$ T6 O A - }: r; k# B7 \ J& s: d) O( Q i
- else if(CurrMode == Clock)
1 }) \6 Y5 p6 Q0 u3 w; j- a6 i$ V - {
0 z7 {. C. r7 |2 _. E - DClockFlag = 1; //数字时钟加一标志
& N* c+ b. k9 y. E - }
6 O1 F' d2 a# _7 P - TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除中断标识4 e& \1 y3 F+ A4 d
- }- S( R4 q& M% x
- }
复制代码 : O& y. {5 E/ [' e+ D
7 N0 Z7 Z# Q0 U$ U
|