嵌入式系统项目设计——基于LED、按键、蜂鸣器的打地鼠游戏(完整代码)

这篇具有很好参考价值的文章主要介绍了嵌入式系统项目设计——基于LED、按键、蜂鸣器的打地鼠游戏(完整代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

内容摘自上学期嵌入式系统课程设计最终的实验报告,因为CSDN不支持上传word资料,所以我就摘录下来写进文章里了,希望可以帮助到你

第一章 绪论

1.1选题背景
打地鼠游戏是一种非常受小孩子欢迎的游戏,拥有数量极其广大的受众,所以它的市场前景非常广阔。当今社会虽然存在各种各样的打地鼠游戏,但大多功能不完善,因此,本次课程设计的目的就是设计一款功能较为完善的打地鼠游戏。

1.2 项目需求分析
1.2.1 基本功能
通过驱动实现8个LED的随机点亮,按下对应按键计一分,且下一个灯立即随机亮起,若超过响应时间且对应按键未按下,则下一个灯随机亮起,按错或超时都不符合要求。

1.2.2 扩展功能
打地鼠时,累计三次按错,游戏结束并播放一闪一闪亮晶晶的音乐,并记录且显示分数,与之前最高分进行比较是否为最高分,并将比较后的最高分显示出来。

1.3 论文主要工作
论文主要包括四个部分,第一部分为绪论,对课题的设计背景及所要实现的功能进行简单的介绍;第二部分为系统的总体方案设计,这部分主要阐述了打地鼠游戏的设计思路与系统的设计框图,对打地鼠游戏进行一个整体的概括;第三部分为系统的实现过程及关键技术分析,此部分主要对打地鼠游戏所涉及的软硬件进行分析;第四部分为问题与解决,这部分交代了设计过程中遇到的问题与解决方法;最后一部分为总结与展望,主要分析此课题设计方案的优缺点,并给出未来的改进方向。

第二章 系统的总体方案设计

2.1 设计思路
系统的主要设计思路是:
1.打开设备文件,定义变量。
2.调用随机函数产生随机数使LED灯随机亮起。
3.将按键编号与灯的编号进行比较,若相等,计一分;若不等或超时,不计分。
4.累计三次按键错误,游戏结束并播放一闪一闪亮晶晶的音乐。
5.最后,将积分与最高分进行比较,然后显示最高分。具体系统设计思路如下所示:
嵌入式系统项目设计——基于LED、按键、蜂鸣器的打地鼠游戏(完整代码)

2.2 系统框图
按照功能可以将系统划分为LED模块,按键模块,蜂鸣器模块。具体系统框图如下:
嵌入式系统项目设计——基于LED、按键、蜂鸣器的打地鼠游戏(完整代码)

第三章 关键技术分析及实现过程

课题实现的关键技术主要分为软硬件部分,硬件主要包括三部分:LED模块、按键模块及蜂鸣器模块,接下来我分别对这三个模块进行介绍。

3.1系统硬件驱动部分
3.1.1 LED模块
硬件电路如下:
嵌入式系统项目设计——基于LED、按键、蜂鸣器的打地鼠游戏(完整代码)

图中U3是CH452,U8和U9是两个3位数码管。CH452是数码管显示驱动和键盘扫描控制芯片,内置时钟振荡电路,可以动态驱动8位数码管或者64只LED,具有BCD 译码、闪烁、移位、段位寻址、光柱译码等功能,同时还可以进行64键的键盘扫描。CH452 通过可以级联的4线串行接口或者2线IIC串行接口与主芯片交换数据。本实训平台CH452芯片与S5PV210主芯片采用2线接口方式相连。

程序:

/*********************CH452******************/
void CH452_I2c_WrByte(unsigned char dat)	//写一个字节数据
{
	unsigned char i;
	CH452_SDA_D_OUT;   /* 设置SDA为输出方向 */
	for(i=0;i!=8;i++)  // 输出8位数据
	{
		if(dat&0x80) {CH452_SDA_SET;}
		else {CH452_SDA_CLR;}
		DELAY_1US;//延迟1US
		CH452_SCL_SET;
		dat<<=1;
		DELAY_1US;
		DELAY_1US;
		CH452_SCL_CLR;
		DELAY_1US;
	}
	CH452_SDA_D_IN;   /* 设置SDA为输入方向 */
	CH452_SDA_SET;
	DELAY_1US;
	CH452_SCL_SET;  // 接收应答
	DELAY_1US;
	DELAY_1US;
	CH452_SCL_CLR;
	DELAY_1US;
}
void CH452_Write(unsigned short cmd)
{
	CH452_I2c_Start();             
#ifdef	ENABLE_2_CH452				// 若有两个CH452并联
	CH452_I2c_WrByte(((unsigned char)(cmd>>7)&CH452_I2C_MASK)|CH452_I2C_ADDR0);  // CH452的ADDR=0时
#else 
	CH452_I2c_WrByte(((unsigned char)(cmd>>7)&CH452_I2C_MASK)|CH452_I2C_ADDR1);  // CH452的ADDR=1时(默认)
#endif
	CH452_I2c_WrByte((unsigned char)cmd);    
	CH452_I2c_Stop();   
}
static ssize_t ch452_dev_write(struct file *file, const char *buffer,
		size_t count, loff_t *ppos)
{
	unsigned short cmd;
	int ret;
	if (count == 0) {
		return count;
	}
	ret = copy_from_user(&cmd, buffer, sizeof cmd) ? -EFAULT : 0;
//实现了从用户写入到led设备文件
	if (ret) {
		return ret;
	}
	CH452_Write(cmd);
	return count;
}
static int ch452_open(struct inode *inode,struct file *filp)
{
   CH452_Write(CH452_RESET);
delay(100);
   CH452_Write(CH452_SYSON1);//开显示
delay(100);
   CH452_Write(CH452_NO_BCD);
printk("open CH452 device");
return 0;
}
static struct file_operations CH452_fops={
        .owner=        THIS_MODULE,
        .open=         ch452_open, 
        .write=		ch452_dev_write,
}; //一个函数指针的集合,定义能在设备上进行的操作,这里主要有打开和写设备。
static int __init CH452_init(void)
{
	int ret=0;
	ret = gpio_request(S5PV210_GPD1(2), "I2C1_SDA");//gpio口的请求
	if (ret) {
		printk("%s: request GPIO %d for 452 failed, ret = %d\n", "452",
				S5PV210_GPD1(2), ret);
		return ret;
	}
		ret = gpio_request(S5PV210_GPD1(3), "I2C1_SCL");
	if (ret) {
		printk("%s: request GPIO %d for 452 failed, ret = %d\n", "452",
				S5PV210_GPD1(3), ret);
		return ret;
	}
 ret = register_chrdev(Major, "CH452", &CH452_fops);//字符设备的注册
if(ret < 0)
        {printk("fail to registern");
return -1;
        }
        s3c_gpio_cfgpin(S5PV210_GPD1(2), S3C_GPIO_OUTPUT);//sda output
        s3c_gpio_cfgpin(S5PV210_GPD1(3), S3C_GPIO_OUTPUT);//scl output
printk("success to registern");
	return 0;
}
static void __exit CH452_exit(void)
{gpio_free(S5PV210_GPD1(2));
gpio_free(S5PV210_GPD1(3));
unregister_chrdev(Major,"CH452");
}
module_init(CH452_init);
module_exit(CH452_exit);
MODULE_LICENSE("GPL");

3.1.2 按键模块
硬件电路如下:
嵌入式系统项目设计——基于LED、按键、蜂鸣器的打地鼠游戏(完整代码)

电路中八只按键通过GPIO端口与S5PV210主芯片相连,用到了GPH2(4)、GPH0(4)、GPH0(3)、GPH0(0)、GPH0(2)、GPH3(5)、GPH3(6)、GPH3(7)八个端口作为输入端,GPB7、GPB8、GPB9、GPB10作为输出端。所以相应的端口需要设置成相应输入/输出模式。
程序:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <mach/map.h>
#include <mach/gpio.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
#define DEVICE_NAME "Buttons"
struct button_desc {
int gpio;
int number;
char *name;
struct timer_list timer;
};
static struct button_desc buttons[] = {
{ S5PV210_GPH2(4), 0, "KEY0" },
{ S5PV210_GPH0(4), 1, "KEY1" },
{ S5PV210_GPH0(3), 2, "KEY2" },
{ S5PV210_GPH0(0), 3, "KEY3" },
{ S5PV210_GPH0(2), 4, "KEY4" },{ S5PV210_GPH3(5), 5, "KEY5" },
{ S5PV210_GPH3(6), 6, "KEY6" },
{ S5PV210_GPH3(7), 7, "KEY7" },
};
static volatile char key_values[] = {
'0', '0', '0', '0', '0', '0', '0', '0'
};
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static volatile int ev_press = 0;
static void lx_buttons_timer(unsigned long _data)
{
struct button_desc *bdata = (struct button_desc *)_data;
int down;
int number;
unsigned tmp;
tmp = gpio_get_value(bdata->gpio);
/* active low */
down = !tmp;
printk("KEY %d: %08x\n", bdata->number, down);
number = bdata->number;
if (down != (key_values[number] & 1)) {
key_values[number] = '0' + down;
ev_press = 1;
wake_up_interruptible(&button_waitq);
}
}
//*************中断处理程序********
static irqreturn_t button_interrupt(int irq, void *dev_id)
{
struct button_desc *bdata = (struct button_desc *)dev_id;
mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(40));//定时器
return IRQ_HANDLED;
}
//************打开设备**************static int lx_buttons_open(struct inode *inode, struct file *file)
{
int irq;
int i;
int err = 0;
for (i = 0; i < ARRAY_SIZE(buttons); i++) {
if (!buttons[i].gpio)
continue;
setup_timer(&buttons[i].timer, lx_buttons_timer,
(unsigned long)&buttons[i]);
irq = gpio_to_irq(buttons[i].gpio);
err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, 
buttons[i].name, (void *)&buttons[i]);//把中断注册进内核
if (err)
break;
}
if (err) {
i--;
for (; i >= 0; i--) {
if (!buttons[i].gpio)
continue;
irq = gpio_to_irq(buttons[i].gpio);
disable_irq(irq);
free_irq(irq, (void *)&buttons[i]);
del_timer_sync(&buttons[i].timer);
}
return -EBUSY;
}
ev_press = 1;
return 0;
}
//************关闭设备********************
static int lx_buttons_close(struct inode *inode, struct file *file)
{
int irq, i;
for (i = 0; i < ARRAY_SIZE(buttons); i++) {if (!buttons[i].gpio)
continue;
irq = gpio_to_irq(buttons[i].gpio);
free_irq(irq, (void *)&buttons[i]);//中断注销
del_timer_sync(&buttons[i].timer);
}
return 0;
}
//*************读设备************************
static int lx_buttons_read(struct file *filp, char __user *buff,
size_t count, loff_t *offp)
{
unsigned long err;
//阻塞方式
if (!ev_press) {
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
else
wait_event_interruptible(button_waitq, ev_press);
}
ev_press = 0;
err = copy_to_user((void *)buff, (const void *)(&key_values),
min(sizeof(key_values), count));//从设备中读取键值
return err ? -EFAULT : min(sizeof(key_values), count);
}
//***********用来实现按键多路监听*************
static unsigned int lx_buttons_poll( struct file *file,
struct poll_table_struct *wait)
{
unsigned int mask = 0;
poll_wait(file, &button_waitq, wait);//使用 poll_wait 将等待队列添加到
poll_table 中。
if (ev_press)
mask |= POLLIN | POLLRDNORM;//返回描述设备是否可读的掩码return mask;
}
//一个函数指针的集合,定义能在设备上进行的操作,这里主要有打开,关闭,读和监
听设备。
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = lx_buttons_open,
.release = lx_buttons_close, 
.read = lx_buttons_read,
.poll = lx_buttons_poll,//用来实现按键多路监听
};
//使用 struct miscdevice 来描述一个混杂设备。
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,//动态获取次设备号,混杂设备的主设备号10
.name = DEVICE_NAME,//设备名
.fops = &dev_fops,//设备的操作集合
};
//***************模块加载函数************
static int __init button_dev_init(void)
{
int ret;
ret = misc_register(&misc);//使用 misc_register 函数来注册一个混杂设备驱
动。
printk(DEVICE_NAME"\tinitialized\n");
return ret;
}
//***************模块卸载函数*************
static void __exit button_dev_exit(void)
{
misc_deregister(&misc);//使用 misc_deregister 函数来注销一个混杂设备驱动。
}
module_init(button_dev_init);
module_exit(button_dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lixin Inc.");

3.1.3 蜂鸣器模块
硬件电路如下:、
嵌入式系统项目设计——基于LED、按键、蜂鸣器的打地鼠游戏(完整代码)

S5PV210 主芯片通过通 过 GPD0.0 管脚连接蜂鸣器,高电平时驱动三极管 Q1 导通,蜂鸣器鸣响。当使用交流信号驱动蜂鸣器时, 信号频率改变蜂鸣器鸣叫频率。

程序:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#define DEVICE_NAME "pwm"
#define PWM_IOCTL_SET_FREQ 1
#define PWM_IOCTL_STOP 0
#define NS_IN_1HZ (1000000000UL)
#define BUZZER_PWM_ID 0
#define BUZZER_PMW_GPIO S5PV210_GPD0(0)
static struct pwm_device *pwm4buzzer;
static struct semaphore lock;
//**********设置蜂鸣变频的频率**********
static void pwm_set_freq(unsigned long freq) {
int period_ns = NS_IN_1HZ / freq;
pwm_config(pwm4buzzer, period_ns / 2, period_ns);
pwm_enable(pwm4buzzer);
s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_SFN(2));
}
static void pwm_stop(void) {s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_OUTPUT);
pwm_config(pwm4buzzer, 0, NS_IN_1HZ / 100);
pwm_disable(pwm4buzzer);
}
//************打开设备**************
static int mini210_pwm_open(struct inode *inode, struct file *file) {
if (!down_trylock(&lock))
return 0;
else
return -EBUSY;
}
//************关闭设备**************
static int mini210_pwm_close(struct inode *inode, struct file *file) {
up(&lock);
return 0;
}
//***********设备的 ioctl 控制***************
static long mini210_pwm_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg)
{
//cmd 参数由应用程序传递进来
switch (cmd) {
case PWM_IOCTL_SET_FREQ:
if (arg == 0)
return -EINVAL;
pwm_set_freq(arg);
break;
case PWM_IOCTL_STOP:
default:
pwm_stop();
break;
}
return 0;
}
//一个函数指针的集合,定义能在设备上进行的操作,这里主要有打开,关闭和 ioctl
控制设备。
static struct file_operations mini210_pwm_ops = {
.owner = THIS_MODULE,
.open = mini210_pwm_open,
.release = mini210_pwm_close, .unlocked_ioctl = mini210_pwm_ioctl,//设备的 ioctl 控制
};
//使用 struct miscdevice 来描述一个混杂设备。
static struct miscdevice mini210_misc_dev = {
.minor = MISC_DYNAMIC_MINOR,//动态获取次设备号,混杂设备的主设备号为 10
.name = DEVICE_NAME,//设备名
.fops = &mini210_pwm_ops,//设备的操作集合
};
//***************模块加载函数************
static int __init mini210_pwm_dev_init(void) {
int ret;
ret = gpio_request(BUZZER_PMW_GPIO, DEVICE_NAME);
if (ret) {
printk("request GPIO %d for pwm failed\n", BUZZER_PMW_GPIO);
return ret;
}
gpio_set_value(BUZZER_PMW_GPIO, 0);
s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_OUTPUT);
pwm4buzzer = pwm_request(BUZZER_PWM_ID, DEVICE_NAME);
if (IS_ERR(pwm4buzzer)) {
printk("request pwm %d for %s failed\n", BUZZER_PWM_ID, DEVICE_NAME);
return -ENODEV;
}
pwm_stop();
 sema_init(&lock, 1);
ret = misc_register(&mini210_misc_dev);//使用 misc_deregister 函数来注销
一个混杂设备驱动。
printk(DEVICE_NAME "\tinitialized\n");
return ret;
}
//***************模块卸载函数*************
static void __exit mini210_pwm_dev_exit(void) {
pwm_stop();
misc_deregister(&mini210_misc_dev);
gpio_free(BUZZER_PMW_GPIO);
}
module_init(mini210_pwm_dev_init);
module_exit(mini210_pwm_dev_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARM Inc.");
MODULE_DESCRIPTION("S5PV210 PWM Driver");

3.2 程序设计分析
打地鼠代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>

#define CH452_CLR_BIT	0x0180					
#define CH452_SET_BIT	0x01C0	

#define PWM_IOCTL_SET_FREQ		1
#define PWM_IOCTL_STOP			0

int key_value = 0;
int i;
int m = 0;
char a[];
int cnt1=0;
int cnt2=0;
int t=0;
int count = 0;
int game_flag = 1;
char current_buttons[8];

void *thread(void *fd)    //LED多线程
{
	int j,n;
	int speed =0;
	unsigned short cmd;
	int led_fd = *(int *)fd;
	printf("\nPlease choose speed!! high(1) or slow(2)\n");
	scanf("%d", &speed);    //选择速度
	printf("**********Start!!!**********\n");
	while(1){
		srand((unsigned)time(NULL));		
		a[m] = rand() % 8;    //产生随机数,保存在数组当中
		for (j=0;j<8;j++){                //循环使8个灯熄灭
			cmd=CH452_CLR_BIT|0x08+j;    
			write(led_fd,&cmd,sizeof(cmd));  
		}
		cmd=CH452_SET_BIT|0x08+a[m];
		m++;
		write(led_fd,&cmd,sizeof(cmd));	  //利用产生的随机数点亮随机灯	
		for(n=0;n<(speed*100-t);n++){       //根据选择的速度选择变换灯的延迟
			usleep(10000);
			if((key_value-1)==a[m-1]) break; //如果按对相应按键,则马上变换灯
		}
		t+=5;  //根据游戏进程的推进,加快变换灯的速度
		if (t>80) t=80;
	}	
	return NULL;
}

void *but(void *fd)     //buttons多线程
{	
	int buttons_fd = *(int *)fd;
	char buttons[8] = {'0', '0', '0', '0', '0', '0', '0', '0'};  //初始化8个按键
	while(1){    //在此线程中一直读按键是否按下的情况
		if (read(buttons_fd, current_buttons, sizeof current_buttons) != sizeof current_buttons) {     //等待按下按键的值
			perror("read buttons:");
			exit(1);
		}
		for (i = 0; i < sizeof buttons / sizeof buttons[0]; i++) {
			if (current_buttons[i] == '1') {
				key_value = i + 1;    //记录按键按下的值
				break;
			}
		}
		cnt1 = 1;
		cnt2 = cnt1;
	}
}

int main(void)
{
	pthread_t pth,pth2;   //定义两个新线程
	int buttons_fd, led_fd, buzz_fd;
	int freq = 1000;
	int fr;
        int freq1=140,freq2=280,freq3=420,freq4=560,freq5=700,freq6=840;
	int sum = 0;	

	buzz_fd = open("/dev/pwm", 0);    //打开蜂鸣器驱动
	if (buzz_fd < 0) {
		perror("open pwm_buzzer device");
		exit(1);
	}

	buttons_fd = open("/dev/Buttons", 0);  //打开按键驱动
	if (buttons_fd < 0) {
		perror("open device buttons");
		exit(1);
	}

	led_fd = open("/dev/CH452", O_RDWR);   //打开LED驱动
	if(led_fd < 0){
		fprintf(stderr, "Error open: %s\n", strerror(errno));
		return -1;
	}

	int start = 0;
    printf("\nPlease input 1 to start or input other key to exit!\n");
	scanf("%d", &start);
	if(start != 1) return;  //判断是否游玩

	int ret = pthread_create(&pth, NULL, thread, &led_fd);  //加载LED新线程
	int err = pthread_create(&pth2, NULL, but, &buttons_fd); //加载buttons新线程
	
	while(start == 1){
	if(cnt1 != cnt2) continue;

	if(key_value > 0 && current_buttons[i] == '1')
		printf("Key is %d\n", key_value); //按键按下时输出按下的是哪个按键

	if(key_value == a[m-1] + 1 && current_buttons[i] == '1'){
		printf("YES!\n");     
		sum++;        //按键按对时得分+1,并显示此时的总分
                printf("**********Current score is %d **********\n", sum);
	}
	if(key_value != a[m-1] + 1 && key_value != 0 && current_buttons[i] == '1'){
		printf("Miss!!!!\n");   
		fr = ioctl(buzz_fd, PWM_IOCTL_SET_FREQ, freq2);
		usleep(10000);
		fr = ioctl(buzz_fd, PWM_IOCTL_STOP);
		count ++;	    //按错次数累加至count中,并每次按错时蜂鸣器响一声
	}

	if(count == 3){   //按键按错三次,播放结束音乐
		count = 0;
		game_flag = 0;   //游戏标志位置0,使进入显示分数界面
		fr = ioctl(buzz_fd, PWM_IOCTL_SET_FREQ, freq1);
                usleep(228500);
		fr = ioctl(buzz_fd, PWM_IOCTL_STOP);
		fr = ioctl(buzz_fd, PWM_IOCTL_SET_FREQ, freq1);
                usleep(228500);
		fr = ioctl(buzz_fd, PWM_IOCTL_STOP);
		fr = ioctl(buzz_fd, PWM_IOCTL_SET_FREQ, freq5);
                usleep(228500);
		fr = ioctl(buzz_fd, PWM_IOCTL_STOP);
		fr = ioctl(buzz_fd, PWM_IOCTL_SET_FREQ, freq5);
                usleep(228500);
		fr = ioctl(buzz_fd, PWM_IOCTL_STOP);
		fr = ioctl(buzz_fd, PWM_IOCTL_SET_FREQ, freq6);
                usleep(228500);
		fr = ioctl(buzz_fd, PWM_IOCTL_STOP);
		fr = ioctl(buzz_fd, PWM_IOCTL_SET_FREQ, freq6);
                usleep(228500);
		fr = ioctl(buzz_fd, PWM_IOCTL_STOP);
		fr = ioctl(buzz_fd, PWM_IOCTL_SET_FREQ, freq5);
                usleep(228500);
		fr = ioctl(buzz_fd, PWM_IOCTL_STOP);

	}
	
	if(game_flag == 0){
		int s;
		FILE *fpread=fopen("source.txt","r");  //打开存储最高分的txt文件
		fscanf(fpread,"%d",&s);
		fclose(fpread);
		if(sum>s){   //如果本次得分大于保存的最高分,则覆盖且保存在txt文件中
			s = sum;
			FILE *fpwrite=fopen("source.txt","w");
			fprintf(fpwrite,"%d",s);
			fclose(fpwrite);
		}
		printf("**********Game over!!!!**********\n");
		printf("**********Final score is %d **********\n", sum);
		printf("*********The Best soure is %d ********\n",s);	
		sum = 0;
		game_flag = 1;
		t=0;
		printf("Please input 1 to start or input other key to exit!\n");	
		scanf("%d", &start);   
		if(start != 1) return;   //判断是否继续游玩
		printf("**********Start!!!**********\n");
		sleep(1);
	}
	cnt2++;	
	}
	
	close(buttons_fd);
	close(led_fd);
	pthread_join(pth, NULL);
	pthread_join(pth2, NULL);
	
	return 0;
}

总体分析:在现实生活中,我们打地鼠时,地鼠是随机出现的。添加了两个多线程分别是LED与buttons,为了实现这一功能,我们调用了随机函数rand()将代表地鼠的LED灯随机点亮,因为有8个LED灯,所以需要对随机数对8取余,然后读取按键的对应的值并与LED灯的对应的值进行比较,判断是否相同,若相同,计数加一,且马上变换灯。若不同,也进行错误计数。当按键对应的值与LED灯亮的值不同时,计数达到3,本次游戏结束并播放一闪一闪亮晶晶的音乐,之后可以选择是否继续游戏。

第四章 问题与解决

问题一:LED不能随机显示,而是一直显示某一个灯。
解决:查找资料知道可以利用rand()函数并且利用时间产生随机数种子能够生成随机数,这样就能实现随机灯亮了。

问题二:在刚开始运行程序,发现LED不会按照指定的延迟进行变换,而是等待按键的按下再开始变换。
解决:将LED变成一个新的线程,与按键互不干扰,在LED线程当中LED能够按照设定好的延迟进行变换。

问题三:将LED规划成一个新线程之后,如果按键按对了,灯不会立即变换,不符合打地鼠的实际应用,应该打中后会立即消失(相应灯熄灭),从另外一个洞里出现(另外一个灯亮起)。
解决:将LED灯变换的延迟函数变成一个循环,每个循环延时一小会,在循环中添加判断,如果按键按下的值与灯亮的值相对应,则立马退出循环,即实现了灯立即熄灭。

问题四:按键时,按下与弹起会使按键响应两次,但灯在第一次响应时就会变换,这样第二次相应就会显示按键错误
解决:在判断按键时,只接收按键按下的情况,不接收按键弹起的情况,这样按键只会响应一次。

第五章 总结与展望

5.1总结
本次课程设计基本完成了我们所想要实现的功能,但由于时间问题,我们没有解决如何直接终止游戏,只能通过累计三次失误来终止游戏。但总的来说,功能已经相当完善了。通过这次课程设计,我们对主要模块的驱动及多线程有了一定的了解,熟悉了如何通过驱动完成代码要实现的功能。

5.2 展望
本次课程设计我们设定了两种模式:快速模式、正常模式,快速模式用来满足手速反应快并且勇于挑战自我的玩家,正常模式适用于反应较慢的人群。同时,我们还设定了最高分记录,激起玩家的胜负欲。如今是互联网时代,我们要紧跟时代潮流,我们设计游戏的代码也要与时俱进,在未来我们可以实现多人同时在线PK打地鼠并举办赛事,也可以划分段位,手速大致相当的人会匹配在一起进行PK,刺激玩家的胜负欲及成就感等等。还有许多我们可以考虑的地方,但是需要我们进行更进一步的实践与完善。
基于LED、按键、蜂鸣器的打地鼠游戏的制作是我们进行软硬件开发的一次小小的经历,希望在未来我们可以做出更多有意义,能为祖国富强出一份力的东西。文章来源地址https://www.toymoban.com/news/detail-490100.html

到了这里,关于嵌入式系统项目设计——基于LED、按键、蜂鸣器的打地鼠游戏(完整代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【速成】蓝桥杯嵌入式省一教程:(五)用按键和屏幕实现嵌入式交互系统

    一个完整的嵌入式系统,包括任务执行部分和人机交互部分。在前四节中,我们已经讲解了LED、LCD和按键,用这三者就能够实现一个人机交互系统,也即搭建整个嵌入式系统的框架。在后续,只要将各个功能加入到这个交互系统中,即可完成整个嵌入式系统的设计。因此,尽

    2024年02月09日
    浏览(60)
  • 基于IAP的嵌入式系统在线编程设计(学习)

    摘要:为了实现嵌入式系统程序的在线升级,提出一种基于IAP在线编程的程序更新方法。 以STM32L431控制器为例,该方法对控制器的片内FLASH进行区域划分,分别存放引导程序、执行程序及待更新程序。 系统通过运行引导程序将待更新程序更新到执行程序的FLASH区域,程序更新

    2024年02月15日
    浏览(50)
  • 速通蓝桥杯嵌入式省一教程:(五)用按键和屏幕实现嵌入式交互系统

    一个完整的嵌入式系统,包括任务执行部分和人机交互部分。在前四节中,我们已经讲解了LED、LCD和按键,用这三者就能够实现一个人机交互系统,也即搭建整个嵌入式系统的框架。在后续,只要将各个功能加入到这个交互系统中,即可完成整个嵌入式系统的设计。因此,尽

    2024年02月12日
    浏览(42)
  • 【小黑嵌入式系统第八课】初识PSoC Creator™开发——关于PSoC Creator&下载、创建项目、单片机中的hello world(点亮一个led)

    上一课: 【小黑嵌入式系统第七课】PSoC® 5LP 开发套件(CY8CKIT-050B )——PSoC® 5LP主芯片、I/O系统、GPIO控制LED流水灯的实现 下一课: 【小黑嵌入式系统第九课】PSoC 5LP第一个实验——LED、字符型LCD显示实验 本课程主要介绍了 PSoC® 5LP, 一个基于 ARM® Cortex®-M3 的可编程片上系

    2024年02月03日
    浏览(57)
  • 【嵌入式项目】基于ARM+Linux的车载系统(完整工程资料源码)

            基于ARM+Linux的车载系统演示效果 基于ARM+Linux的车载系统         本项目计划主要应用于家用,办公等领域轿车中实施的基于物联网云平台的车载系统项目,既能够为车主在行驶过程中提供舒适的体验,又能提供一定的安全保障。            基于ARM+Linux的车

    2024年03月26日
    浏览(109)
  • 读书·基于RISC-V和FPGA的嵌入式系统设计

    引言:第八届集成电路创新创业大赛龙芯杯是有关嵌入式SoC设计的         由于我本身是做纯硬件设计,此前没怎么接触软硬协同         玩过Zynq,但是到SDK部分就去吃灰了         现在后悔了,所以,做人一定要有始有终啊~TAT ------------------------------------------------------

    2024年03月17日
    浏览(51)
  • 基于FPGA的多通道数据采集系统Verilog设计嵌入式

    基于FPGA的多通道数据采集系统Verilog设计嵌入式 在本文中,我们将介绍基于FPGA的多通道数据采集系统的Verilog设计,该系统可用于同时采集和处理多个通道的数据。我们将详细讨论系统的设计原理和实现步骤,并提供相应的Verilog源代码。 系统概述 多通道数据采集系统是一种

    2024年02月07日
    浏览(61)
  • 嵌入式系统实验报告实验一 GPIO 口控制LED 实验

    1 实验目的 1.) 了解并掌握如何控制 STM32 的 GPIO; 2.) 掌握控制 LED 的电路原理和程序代码; 2 实验环境 1.) 硬件:1 个空气温湿度传感器模块、1 个 ST-Link 调试器、1 根USB2.0 方口线、1根USB3.0 数据线、1 台PC 机; 2.) 软件:Windows 10、MDK 集成开发环境。 3 实验功能 实现LED灯依

    2024年02月01日
    浏览(58)
  • 基于嵌入式AI的ROI区域视频传输系统设计与实现

    在当今快速发展的智能监控领域,实现高效的视频流处理和传输成为了一项重要挑战。本文介绍了一个基于嵌入式AI平台的视频传输系统设计,该系统能够识别视频中的关键区域(ROI),并对这些区域进行高效的编码处理。特别地,我们利用Python语言来实现AI处理部分,使得整

    2024年01月19日
    浏览(36)
  • 合肥中科深谷嵌入式项目实战——基于ARM语音识别的智能家居系统(三)

    我们上一篇,我们实现在Linux系统下编译程序,我们首先通过两个小练习来熟悉一下如何去编译。今天,我们来介绍一下LCD屏幕基本使用。 如何使用LCD屏幕?     1、打开开发板LCD设备驱动文件。  (/dev/fb0)     2、准备颜色数据。     3、写入颜色像素点数据。     4、关闭

    2024年02月04日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包