赞
踩
以单片机为核心,设计一个8位竞赛抢答器:同时供8名选手或8个代表队比赛,分别用8个按钮S0~S7表示。
设置一个系统清除和抢答控制开关S,开关由主持人控制。
抢答器具有锁存与显示功能。即选手按按钮,锁存相应的编号,并在优先抢答选手的编号一直保持到主持人将系统清除为止。
抢答器具有定时抢答功能,且一次抢答的时间由主持人设定(如30秒)。
当主持人启动“开始”键后,定时器进行减计时,同时扬声器发出短暂的声响,声响持续的时间为0.5s左右。
参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示器上显示选手的编号和抢答的时间,并保持到主持人将系统清除为止。
如果定时时间已到,无人抢答,本次抢答无效,系统报警并禁止抢答,定时显示器上显示00。
通过键盘改变抢答的时间,原理与闹钟时间的设定相同,将定时时间的变量置为全局变量后,通过键盘扫描程序使每按下一次按键,时间加1(超过30时置0)。同时单片机不断进行按键扫描,当参赛选手的按键按下时,用于产生时钟信号的定时计数器停止计数,同时将选手编号(按键号)和抢答时间分别显示在LED上。
- #include <reg52.h> // 包含reg52头文件
-
- #define uchar unsigned char // 定义uchar为无符号字符型
- #define uint unsigned int // 定义uint为无符号整型
- #define GPIO_DIG P0 // 定义GPIO_DIG为P0
- #define GPIO_KEY P1 // 定义GPIO_KEY为P1
-
- sbit en = P2^7; // 使能引脚
- sbit rs = P2^6; // 寄存器选择引脚
- sbit rw = P2^5; // 读/写选择引脚
- sbit beep = P1^5; // 蜂鸣器引脚
- sbit K0 = P3^0; // K0引脚
- sbit K1 = P3^1; // K1引脚
- sbit K2 = P3^2; // K2引脚
- sbit K3 = P3^3; // K3引脚
- sbit P20 = P2^0; // P20引脚
-
- // 数码管显示字符的编码
- uchar code start[] = "Welcome to game"; // 开始游戏提示语
- uchar code time[] = "0123456789";
- uchar name_time[] = "00";
- uchar name_time1[] = "00";
- uchar timer[] = {0, 0}; // 计时器数组,用于显示时间
- uint count = 0; // 定时器中断计数器
- uchar KeyValue = 0; // 键值
- uchar name1 = 0; // 名称
- uchar str1[] = {"012345678"};
- uchar str0[] = {"name"};
- uchar str2[] = {"replied"};
-
- void delay(uint z); // 延时函数声明
- void write_com(uchar com); // 写命令函数声明
- void init(); // 初始化函数声明
- void write_data(uchar date); // 写数据函数声明
- void LCD_SetCursor(uchar Line, uchar Columu); // 设置LCD光标函数声明
- void LCD_ShowString(unsigned char Line, unsigned char Columu, unsigned char* String); // LCD显示字符串函数声明
- void T0_init(); // 定时器T0初始化函数声明
- void T1_init(); // 定时器T1初始化函数声明
- void KeyDown(); // 按键检测函数声明
- void sound(); // 蜂鸣器函数声明
- void start_game(); // 游戏开始函数声明
- void timer_init(); // 计时器初始化函数声明
- void shijian();
-
-
- void main()
- {
- init(); // LCD初始化
- T0_init(); // 初始化定时器0
- T1_init(); // 初始化外部中断
- timer_init();
- write_com(0x80); // 设置LCD显示位置
- while(1)
- {
- start_game(); // 游戏开始
- }
- }
-
- // 延时函数
- void delay(uint z)
- {
- uint x, y;
- for (x = z; x > 0; x--)
- for (y = 110; y > 0; y--);
- }
- void delay1(unsigned int i) //延时函数
- {
- while (i--)
- ;
- }
- // 写命令
- void write_com(uchar com) {
- rs = 0; // 设置为命令寄存器
- rw = 0; // 写操作
- P0 = com; // 将命令写入数据口
- delay(10);
- en = 1; // 使能LCD
- en = 0; // 禁用LCD
- }
-
- // LCD初始化
- void init() {
- rw = 0; // 写操作
- en = 0; // 禁用LCD
- write_com(0x38); // 设置为8位数据接口,显示模式为2行显示,字符大小为5x8
- write_com(0x0c); // 开启显示,关闭光标
- write_com(0x06); // 光标右移,字符不移动
- write_com(0x01); // 清屏
- }
-
- // 写数据
- void write_data(uchar date) {
- rs = 1; // 设置为数据寄存器
- rw = 0; // 写操作
- P0 = date; // 将数据写入数据口
- delay(10);
- en = 1; // 使能LCD
- en = 0; // 禁用LCD
- }
-
- // 1s定时器
- void timer0() interrupt 1 {
- TH0 = (65536 - 50000) / 256; // 设置定时器初值高位
- TL0 = (65536 - 50000) % 256; // 设置定时器初值低位
- count++;
-
- if (count >= 20) { // 每计数20次(约1秒)
- count = 0;
-
- if (timer[0] == 0 && timer[1] == 0)
- {
- TR0 = 0;
- init(); // 清屏
- LCD_ShowString(1 , 1 , "no replied");
- } else
- {
- if (timer[1] == 0)
- {
- if (timer[0] > 0)
- {
- timer[0]--; // 减少十位
- timer[1] = 9; // 设置个位为9
- }
- } else
- {
- timer[1]--; // 仅减少个位
- }
- }
- }
- }
-
- //停止与继续中断函数
- void INT_1() interrupt 2 {
- if (!K3) {
- delay(10);
- if (!K3) {
- TR0 = !TR0; // 切换定时器启停状态
- while (!K3);
- }
- }
- }
-
- // 定时器T0初始化
- void T0_init() {
- TMOD = 0x01; // 定时器0工作在方式1(16位定时器)下
- TH0 = (65536 - 50000) / 256;
- TL0 = (65536 - 50000) % 256;
- EA = 1; // 允许中断
- ET0 = 1; // 允许定时器0中断
- }
-
- // 定时器T1初始化
- void T1_init() {
- EA = 1; // 开启总中断
- EX1 = 1; // 开启1号外部中断
- IT1 = 1; // 设置外部中断0为下降沿触发
- }
-
- // lcd显示函数
- void LCD_ShowString(uchar Line, uchar Columu, uchar* String)
- {
- unsigned char i = 0;
-
- // 设置LCD光标位置
- LCD_SetCursor(Line, Columu);
-
- // 遍历字符串并逐个显示字符
- for (i = 0; String[i] != '\0'; i++)
- {
- write_data(String[i]);
- }
- }
-
- // 设置LCD光标位置
- void LCD_SetCursor(uchar Line, uchar Columu)
- {
- if (Line == 1)
- {
- write_com(0x80 | (Columu - 1));
- }
- else
- {
- write_com(0x80 | (Columu - 1) + 0x40);
- }
- }
-
- // 蜂鸣器
- void sound()
- {
- uchar i = 50;
-
- // 循环控制蜂鸣器的开关以产生声音
- while (i--)
- {
- beep = ~beep;
- delay(200);
- }
- }
-
- // 矩阵键盘扫描
- void KeyDown()
- {
- GPIO_KEY = 0x0f;
-
- if (GPIO_KEY != 0x0f) // 如果按键按下
- {
- delay(10); // 延时10ms消抖
-
- if (GPIO_KEY != 0x0f) // 按键确实按下
- {
- // 判断按键所在列,以所在列的第一行的按键键值赋给KeyValue
- GPIO_KEY = 0X0F;
-
- switch (GPIO_KEY)
- {
- case (0X07): KeyValue = 1; break; // 第一列按下
- case (0X0b): KeyValue = 2; break; // 第二列按下
- case (0X0d): KeyValue = 3; break; // 第三列按下
- case (0X0e): KeyValue = 4; break; // 第四列按下
- }
-
- // 判断按键所在行
- GPIO_KEY = 0XF0;
-
- switch (GPIO_KEY)
- {
- case (0X70): KeyValue = KeyValue; break; // 第一行按下
- case (0Xb0): KeyValue = KeyValue + 4; break; // 第二行按下
- case (0Xd0): KeyValue = KeyValue + 8; break; // 第三行按下
- case (0Xe0): KeyValue = KeyValue + 12; break; // 第四行按下
- }
-
- while (GPIO_KEY != 0xf0); // 按键松手后退出
- }
- }
- }
-
- //蜂鸣器函数
- void beep1()
- {
- unsigned char i;
-
- for (i = 0; i < 100; i++)
- {
- delay1(100);
- beep = ~beep;
- }
- }
-
- //抢答器函数
- void xianshiqiangda()
- {
- unsigned int i = 0;
- unsigned int j;
- j = KeyValue;
- write_com(0x80);
- delay(1000);
-
- // 遍历字符串str0并逐个显示字符
- while (str0[i] != '\0')
- {
- write_data(str0[i]);
- i++;
- }
-
- TR0 = 0;
-
- // 计算name_time[0]的值
- name1 = name_time[0] * 10 - timer[0] * 10 - timer[1];
- name_time[0] = name1 / 10;
- name_time[1] = (name1 % 10)-1;
-
- write_com(0x80 + 0x06);
- delay(10);
- write_data(str1[j]);
- delay(10);
-
- // 在LCD上显示"name_number:"
- LCD_ShowString(2, 1, "name_number:");
-
- // 在LCD上显示name_time[0]和name_time[1]对应的时间
- write_data(time[name_time[0]]);
- delay(5);
- write_data(time[name_time[1]]);
-
- while (1);
- }
-
- // 开始函数
- void start_game()
- {
- if (!K2)
- {
- delay(5);
- if (!K2)
- {
- // 在LCD上显示"start"
- LCD_ShowString(1, 1, start);
- delay(10);
-
- // 在LCD上显示"time:"
- LCD_ShowString(2, 1, "time:");
-
- TR0 = 1;
-
- while (1)
- {
- // 在LCD上显示当前计时器的值
- write_com(0x80 + 0x40 + 0x07);
- write_data(time[timer[0]]);
- delay(5);
- write_data(time[timer[1]]);
- delay(5);
-
- if (GPIO_KEY != 0xf0)
- {
- break;
- }
- }
- }
-
- while (!K2);
- }
-
- if (timer[0] != 0 && timer[1] != 0)
- {
- write_com(0x01);
- KeyDown();
- beep1();
-
- if (KeyValue < 8)
- {
- while (1)
- {
- xianshiqiangda();
- }
-
- }
- }
- }
-
- //设置初时函数
- void timer_init()
- {
- // 在LCD上显示"set the time:"
- LCD_ShowString(1, 1, "set the time:");
-
- // 初始化计时器数组
- timer[0] = 0; // 初始化第一个元素
- timer[1] = 0; // 初始化第二个元素
-
- while (1)
- {
- KeyDown();
-
- // 获取按键值并赋给timer[0]
- timer[0] = KeyValue;
- name_time[0] = KeyValue;
- name_time[1] = 0;
-
- if (timer[0] != 0)
- {
- init();
-
- // 在LCD上显示"Countdown time:"
- LCD_ShowString(1, 1, "Countdown time:");
-
- // 在LCD上显示设置的倒计时时间
- write_com(0x80 + 0x40 + 0x03);
- write_data(time[timer[0]]);
- delay(5);
- write_data(time[timer[1]]);
- delay(5);
-
- KeyValue = 0;
- break;
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。