概述
Whack a Mole 打地鼠
/**********************
Whack a Mole ´òµØÊó
ÐͺÅ:STC15F2K60S2 Ö÷Ƶ:11.0592MHz
************************/
#include "STC15F2K60S2.H"
#include <stdlib.h>
#define uint unsigned int
#define uchar unsigned char
#define T 30000
#define NUM 20
#define H 15
/*---------Òý½Å±ðÃû¶¨Òå---------*/
sbit k1 = P3 ^ 2;
sbit k2 = P3 ^ 3;
sbit k3 = P1 ^ 7;
sbit sbtBeep = P3 ^ 4;
sbit sbtLedSel = P2 ^ 3;
/*---------±äÁ¿¶¨Òå---------*/
uchar sec[]={0x08,0x48,0x49,0x48,0x08,0x48,0x49,0x48};
uchar loc[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
uchar num[]={0x00,0x00,0x76,0x06,0x07,0x00,0x00,0x00};
uchar number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar i = 0;
uchar j = 0;
uchar k = 0;
uint tmp = 0;
uint sum = 0;
uint counter = 0;
uint cishu = 0;
bit btBeepFlag;
bit flag;
/*---------³õʼ»¯º¯Êý---------*/
void Init()
{
P0M1 = 0x00;
P0M0 = 0xff;
P2M1 = 0x00;
P2M0 = 0x08;
P3M1 = 0x00;
P3M0 = 0x10;
flag = 1;
sbtBeep = 0;
btBeepFlag = 0;
sbtLedSel = 0;
P0 = 0x00;
EA = 1;
ET0 = 1;
TR0 = 1;
TMOD = 0x00;
TH0 = 0xff;
TL0 = 0x03;
ET1 = 0;
TR1 = 1;
TH1 = 0xb1;
TL1 = 0xe0;
}
/*---------ÑÓʱº¯Êý---------*/
void delay_20ms( int n )
{
int time;
for( time = 0; time < n; time++)
{
ET1 = 1;
TH1 = 0xb1;
TL1 = 0xe0;
while( TH1!=0xff || TL1!=0xff );
ET1 = 0;
}
}
void Delay(int n)
{
while(n--);
}
/*---------°´¼ü²¶×½º¯Êý--------*/
void Hit()
{
if( tmp == 0 && k3 == 0 )
{
delay_20ms( 1 );
if( k3 == 0 )
{
sum++;
flag = 0;
}
}
else if( tmp == 1 && k2 == 0 )
{
delay_20ms( 1 );
if( k2 == 0 )
{
sum++;
flag = 0;
}
}
else if( tmp == 2 && k1 == 0 )
{
delay_20ms( 1 );
if( k1 == 0 )
{
sum++;
flag = 0;
}
}
}
/*---------ÊýÂë¹ÜÉÁ˸º¯Êý---------*/
void DigitalTube()
{
delay_20ms( 50 );
for( i = 0; i < NUM; i++ )
{
tmp = rand()%3;
counter = 0;
flag = 1;
while( counter != T )
{
for( j = 0; j < 2; j++ )
{
if( j == 0 )
{
if( tmp == 0 )
P2 = 0x00;
else if( tmp == 1 )
P2 = 0x03;
else
P2 = 0x06;
P0 = 0x5a;
}
else
{
if( tmp == 0 )
P2 = 0x01;
else if( tmp == 1 )
P2 = 0x04;
else
P2 = 0x07;
P0 = 0x6c;
}
}
counter++;
if( flag )
Hit();
}
P0 = 0x00;
delay_20ms( 50 );
}
P0 = 0x00;
}
/*---------»÷ÖдÎÊýÏÔʾº¯Êý---------*/
void Display()
{
delay_20ms( 50 );
cishu = 0;
num[6] = number[sum/10];
num[7] = number[sum%10];
while( cishu != 50000 )
{
for( i = 0; i < 8; i++ )
{
P2 = loc[i];
P0 = num[i];
Delay( 600 );
}
cishu++;
if( k3 == 0 )
{
delay_20ms( 1 );
if( k3 == 0 )
break;
}
}
P0 = 0x00;
}
/*---------ÌôÕ½³É¹¦º¯Êý---------*/
void congratulation()
{
i = 8;
while( i-- )
{
k = 10000;
while( k-- )
{
for( j = 0; j < 8; j++ )
{
P0 = 0x00;
P2 = loc[i];
P0 = sec[i];
Delay(600);
}
}
btBeepFlag = ~btBeepFlag;
delay_20ms( 40 );
}
P0 = 0x00;
}
/*---------Ö÷º¯Êý---------*/
void main()
{
Init();
while( 1 )
{
sum = 0;
sbtLedSel = 0;
if( k2 == 0 )
{
delay_20ms( 1 );
if( k2 == 0 )
{
while( !k2 );
DigitalTube();
Display();
delay_20ms( 50 );
if( sum >= H )
congratulation();
}
}
}
}
/*---------T0¶¨Ê±Æ÷ÖжϷþÎñ´¦Àíº¯Êý--------*/
void T0_Process() interrupt 1
{
if( btBeepFlag )
{
sbtBeep = ~sbtBeep;
}
else
{
sbtBeep = 0;
}
}
创新大作业报告
创新大作业报告
一、 选题概述
本次创新大作业选题我选择的选题为“打地鼠游戏”,选择这个选题的原因也是认为这个题目较为新颖而且比较具有娱乐性,可以更好地激发我的学习热情,同时实现难度不低,也可以很好地锻炼我的单片机编程能力。
“打地鼠游戏”的具体实现功能:把代码生成的hex文件通过stc-isp下载到STC-B学习板上后,按下按键k2使程序开始运行。按下按键延迟1s后数码管开始显现“地鼠”,“地鼠”图样大小为数码管的两位显示位,形如“凸”字,考虑到按键k1、k2、k3只有三个,所以八位数码管左中右位置三个“地鼠”随机出现,相互间隔数码管的一位显示位。“地鼠”显现的频率为1s,可以更改,闪现时间也在1s左右。当“地鼠”出现时按下对应位置的按键(k3左k2中k1右)则“击中”。当“地鼠”全部出现完毕后,数码管显示HIT ??,??是击中个数。随后当击中个数大于或等于设定个数时蜂鸣器发声,数码管显示图案提示挑战成功。若击中个数不足则直接结束等待下一次开始。
二、 实现原理
① main() 主函数
主函数首先调用Init()初始化函数初始化接口数据,之后进入一个死循环,不断检测按键k2的值,当k2 = 0即按键k2按下时进入if分支,再利用软件手段进行按键消除前沿抖动,调用delay_20ms( int n )精确延时20ms。
如果此时仍k2 = 0,表示不是干扰,如上图的按键稳定。那
么再次进入if分支,再用一个while( !k2 )暂停程序,当按键k2没有松开时程序暂停。否则执行数码管闪烁函数DigitalTube();击中次数显示函数Display();延时1s后判定击中次数sum是否大于或等于设定次数H,若是则执行挑战成功函数congratulation();。
② Init() 初始化函数
将输出模式如此设定P0M1 = 0x00; P0M0 = 0xff;P2M1 = 0x00;P2M0 = 0x08;P3M1 = 0x00;P3M0 = 0x10;确保P0接口所有引脚,P2.3引脚,P3.7引脚推挽输出。之后设置蜂鸣器翻转标志位,蜂鸣器引脚以及T0、T1定时器的模式和初值。
定时器总开关EA = 1打开,ET0 = 1打开T0开关,ET1 = 0暂时关闭T1开关,TR0 = 1、TR1 = 1分别确保T0、T1能开始工作,TMOD = 0x00设定T0、T1的模式为16位自动重载(每次计时完毕都自动回到设定初值进行计时)。T0、T1的计数位都为16位,最大可计数65536,TH0、TL0、TH1、TL1分别代表T0的高八位、低八位和T1的高八位、低八位,设置初值分别为0xff、0x03、0xb1、0xe0。
③ delay_20ms( int n ) 精确延时20ms函数
我将定时器T1的n次计时包装为一个函数,函数参数n代表定时器T1定时次数。每次定时时间为20ms,因为定时器定时时间=计数值*机器周期,STC-B学习板晶体震荡频率为12MHz,机器周期则为1微秒。想要定时20ms,计数值就为20ms/0.001ms = 20000,定时器的计数终点是0xffff,所以设定初值为65536-20000 = 45536,转换为二进制1011 0001 1110 0000,所以T1初值设为TH1 = 0xb1,TL0 = 0xe0,ET1 = 1打开,循环while( TH1!=0xff || TL1!=0xff );当TH1 = TL1 = 0xff时计时完毕跳出循环。一个计时周期结束,ET1 = 0又暂时关闭。这样就实现了精确延时20ms的功能。
④ DigitalTube() 数码管闪烁函数
此函数为我设计的主体功能函数,实现“地鼠”的显示和按键的“击打”。函数开始执行先延时1s,随后进入主循环,功能是显示完所有设定的“地鼠”,“地鼠”数为NUM。tmp = rand()%3在{0,1,2}中获得一个随机数表示“地鼠”出现位置,counter = 0“地鼠”显示扫描次数标记设定初值,flag = 1标记为1,进入while( counter != T )扫描“地鼠”图样循环,T是扫描的次数,以此控制“地鼠”出现的时间。随后再进入for ( j = 0; j < 2; j++ )不断扫描“地鼠”图样的两位数码管。当j == 0时显示“地鼠”左半部分,段选信号hgfedcba为01011010,于是P0 = 0x5a,再由tmp随机值选定位置,tmp = 0为数码管0位选P2 = 0x00,tmp = 1为数码管3位选P2 = 0x03,tmp =2为数码管6位选P2 = 0x06。j == 1时同理,显示“地鼠”右半部分,段选信号hgfedcba为01101100,于是P0 = 0x6c,再由tmp随机值选定位置,tmp = 0为数码管1位选P2 = 0x01,tmp = 1为数码管4位选P2 = 0x04,tmp =2为数码管7位选P2 = 0x07。
之后若flag = 1则执行按键捕捉函数Hit(),判断按键是否在“地鼠”显示时间内按下。然后delay_20ms( 50 );延时1s给玩家反应时间,“地鼠”显示完毕后P0 = 0x00,熄灭数码管。
⑤ Hit() 按键捕捉函数
函数整体为一个if分支结构,当位置随机值tmp与按键对应时(tmp = 0,1,2对应按键k3,k2,k1 = 0),然后延时20ms消抖,当按键状态稳定时击中计数sum++,flag置为0,确保在一个“地鼠”的显示时间里最多触发按键捕捉函数Hit()一次,防止“作弊”。
⑥ Display() 击中次数显示函数
函数开始执行delay_20ms( 50 );延时1s,随后数码管扫描次数counter = 0初始化,然后在for( i = 0; i < 8; i++ )循环内不断扫描数码管0-7位置,每扫描一位进行Delay( 600 );延时。最后P0 = 0x00熄灭数码管返回。其中位选信号数组uchar loc[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};表示数码管0-7位置,上面有解析这里不再强调。段选信号数组uchar num[]={0x00,0x00,0x76,0x06,0x07,0x00,0x00,0x00};其中前六个表示显示的分别是熄灭、熄灭、“H”、“I”、“T”、熄灭,上面已有数码管显示解析,具体不再阐述。后两位初值为0x00熄灭,但是会有赋值,因为这两位表示的是击中次数,是由sum值具体确定的。num[6] = number[sum/10]; num[7] = number[sum%10];功能是sum/10取sum的十位,sum%10取sum的个位。然后uchar number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};数组下标数字就为数码管显示数字。以此来进行数码管6-7两位击中数字的显示。最后捕捉按键k3的值,当按键k3按下时break;跳出循环,P0 = 0x00熄灭数码管,函数返回。
⑦ congratulation() 挑战成功函数
利用i = 8来设置扫描位数,然后k = 50000设置扫描次数,for( j = 0; j < 8; j++)循环扫描,P2 = loc[i]获取数码管位选信号,P0 = sec[i]获取我事先设置好的图案段选信号,并且伴随着蜂鸣器的发声btBeepFlag = ~btBeepFlag,持续8次。
⑧ T0_Process() interrupt 1 T0定时器中断服务函数
Interrupt 1 表示定时器T0的中断,函数功能为当T0定时完毕后中断进程,判断蜂鸣器引脚标记位btBeep的值,为1时sbtBeep = ~sbtBeep;翻转蜂鸣器引脚产生方波蜂鸣器发声,否则sbtBeep = 0,停止发声。
三、 作业总结
本次小学期的单片机课程让我受益匪浅,整个STC-B学习板从元件焊接到亚克力背板设计到创新选题的确定再到创新大作业的实现全部是由自己独立完成。可以说是给了我们学生很大的自主性,所以当创新大作业完成后把hex文件下载到STC-B上进行运行看到功能按照自己的设计不断实现的时候会有很大的成就感。
而且因为是自学,老师提供答疑引导的学习模式,我觉得提升了自己独立思考和解决问题的能力,每个人选题的不同,实现也就千差万别,别人能提供的参考少之又少,只能依靠自己。不过也正是因此,我学习到的知识更加扎实,完全理解并且实际实现。总而言之,本次小学期是一段忙碌又充实的时光。
最后
以上就是不安猫咪为你收集整理的STC-B学习板单片机编程的全部内容,希望文章能够帮你解决STC-B学习板单片机编程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复