黄河科技学院毕业设计说明书 第 21 页
附 录
附录A
基于单片机的八路抢答器原理图
附录B
#include
黄河科技学院毕业设计说明书 第 22 页
#include
#define uchar unsigned char #define uint unsigned int
sfr ISP_DATA = 0xe2; // 从Flash读出和要向Flash写入的的数据都放在这个寄存器中 sfr ISP_ADDRH = 0xe3; // 地址寄存器高八位 sfr ISP_ADDRL = 0xe4; // 地址寄存器低八位 sfr ISP_CMD = 0xe5; // 命令寄存器 sfr ISP_TRIG = 0xe6; // 命令触发寄存器 sfr ISP_CONTR = 0xe7; // 命令寄存器 sbit w1 = P2^3; sbit w2 = P2^2; sbit w3 = P2^1; sbit w4 = P2^0; sbit k1 = P1^0; sbit k2 = P1^1; sbit k3 = P1^2; sbit k4 = P1^3; sbit k5 = P1^4; sbit k6 = P1^5; sbit k7 = P1^6; sbit k8 = P1^7; sbit k9 = P3^7; sbit bp = P2^6;
// 定义了数码管第1位的控制脚 // 定义了数码管第2位的控制脚 // 定义了数码管第3位的控制脚 // 定义了数码管第4位的控制脚
// 定义了选手1的抢答按键(可用于进入设置抢答时间) // 定义了选手2的抢答按键(可用于进入设置答题时间) // 定义了选手3的抢答按键 // 定义了选手4的抢答按键 // 定义了选手5的抢答按键 // 定义了选手6的抢答按键
// 定义了选手7的抢答按键(设置时间时,是“减”的功能) // 定义了选手8的抢答按键(设置时间时,是“加”的功能) // 定义了开始抢答的按键 // 定义蜂鸣器的控制引脚
uchar code ShowDig[]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0xff}; uchar dig[4];
// dig[0]、dig[1]、dig[2]、dig[3]分别代表了四位数码管显示的内容
char gWaitTime,gAnswerTime; char gCount,gSecond; void ISP_Disable() {
ISP_CONTR = 0; ISP_ADDRH = 0; ISP_ADDRL = 0; }
unsigned char Byte_Read(unsigned int add)
黄河科技学院毕业设计说明书 第 23 页
{
ISP_DATA = 0x00; ISP_CONTR = 0x83; ISP_CMD = 0x01;
ISP_ADDRH = (unsigned char)(add>>8); ISP_ADDRL = (unsigned char)(add&0xff);
ISP_TRIG = 0x46; // 对STC89C51系列来说,每次要写入0x46, ISP_TRIG = 0xB9; // 再写入0xB9,ISP/IAP才会生效 _nop_();
ISP_Disable();
return (ISP_DATA); // 将读出的数据作为函数的返回值
}
void Byte_Program(unsigned int add,unsigned char ch) {
ISP_CONTR = 0x83; ISP_CMD = 0x02;
ISP_ADDRH = (unsigned char)(add>>8); ISP_ADDRL = (unsigned char)(add&0xff); ISP_DATA = ch; ISP_TRIG = 0x46; ISP_TRIG = 0xB9; _nop_();
ISP_Disable(); }
void Sector_Erase(unsigned int add) {
ISP_CONTR = 0x83; ISP_CMD = 0x03;
ISP_ADDRH = (unsigned char)(add>>8); ISP_ADDRL = (unsigned char)(add&0xff); ISP_TRIG = 0x46; ISP_TRIG = 0xB9; _nop_();
ISP_Disable(); }
void DelayMs(uint n) {
黄河科技学院毕业设计说明书 第 24 页
uint x,y;
for(x=n;x>0;x--) for(y=110;y>0;y--); }
void TimerInit() {
TMOD = 0x11;// 定时器0用于数码管的动态扫描,定时器1用于秒数的计时 TH0 = (65536-1000)/256; TL0 = (65536-1000)%6; TH1 = (65536-50000)/256; TL1 = (65536-50000)%6; TR0 = 1; ET0 = 1; ET1 = 1; EA = 1;
// 给定时器0的TH0装初值 // 给定时器0的TL0装初值 // 给定时器1的TH1装初值 // 给定时器1的TL1装初值
// 启动定时器0(开始动态扫描数码管) // 定时器0中断使能 // 定时器1中断使能 // 打开总中断
}
void WaitTimeSet(void) {
if(k1==0)// 判断按键1是否有按下,等于0代表按键按下了,则进入抢答时间设置{
// 数码管显示“EEEE” dig[0]=ShowDig[14]; dig[1]=ShowDig[14]; dig[2]=ShowDig[14]; dig[3]=ShowDig[14]; while(!k1);
// 等待按键释放 // 利用延时去抖 // 数码管显示“E EE” // 数码管显示“E 30”
DelayMs(500);
模式
dig[1]=ShowDig[17];
dig[2]=ShowDig[gWaitTime/10];
dig[3]=ShowDig[gWaitTime];
while(k1)// 当再次按下按键1时,退出抢答时间设置模式,否则一直扫描“加”、{
if(k8==0)// 判断“加”按键是否被按下 {
“减”按键
黄河科技学院毕业设计说明书 第 25 页
DelayMs(250);// 利用延时去抖
gWaitTime++;// 当前要设置的秒数自加1 if(gWaitTime==100) // 当自加到100时,自动清零
gWaitTime=0;
// 擦除内部EEPROM(写入之前必须先擦除)
// 将新设置的等待时间写入到
Sector_Erase(0x2000); }
Byte_Program(0x2000,gWaitTime);
内部EEPROM的0x2000这个地址
Byte_Program(0x2001,gAnswerTime); // 将答题时间写入到内部dig[2]=ShowDig[gWaitTime/10]; dig[3]=ShowDig[gWaitTime];
// 更新数码管的秒数显式(十位) // 更新数码管的秒数显式(个位)
EEPROM的0x2001这个地址
if(k7==0)// 判断“减”按键是否被按下 {
DelayMs(250);// 利用延时去抖
gWaitTime--;// 当前要设置的秒数自减1 if(gWaitTime==-1) // 自减到-1时,自动变成99
gWaitTime=99;
Sector_Erase(0x2000);// 擦除内部EEPROM(写入之前必须先擦除)
Byte_Program(0x2000,gWaitTime);// 将新设置的等待时间写入到内部Byte_Program(0x2001,gAnswerTime); // 将答题时间写入到内部dig[2]=ShowDig[gWaitTime/10];// 更新数码管的秒数显式(十位) dig[3]=ShowDig[gWaitTime];// 更新数码管的秒数显式(个位)
EEPROM的0x2000这个地址 EEPROM的0x2001这个地址
}
} while(!k1); DelayMs(500); } }
void AnswerTimeSet(void) {
if(k2==0)// 判断按键2是否有按下,等于0代表按键按下了,则进入答题时间设置