仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit RS = P2^0;
- sbit RW = P2^1;
- sbit EN = P2^2;
- sbit K0 = P3^0;
- sbit K1 = P1^0;
- sbit K2 = P1^1;
- sbit K3 = P1^2;
- sbit K4 = P1^3;
- sbit K5 = P3^1;
- sbit K6 = P2^3;
- sbit K7 = P2^4;
- sbit K8 = P3^4;
- sbit Buzz = P3^7;
- uint cnt = 0;//记录中断次数
- uint cnt1= 0;
- uint sec = 20;//记录倒计时
- uchar num = 0;//记录抢答选手
- uchar flag = 1;//抢答标志
- uchar s_flag = 0;//开始标志
- uchar e_flag = 0;//结束标志
- uchar score[4]={0};
- void init1602();
- void Lcdshow(uchar x,uchar y,uchar *str);
- void KeyScan();
- void Keycontrol() ;
- void Judge();
- uchar IntToString(uchar *str, int dat);
- void main()
- {
- uchar str1[12];
- uchar str2[12];
- uchar len,len1;
- EA = 1;
- ET0 = 1;
- TMOD = 0x11;//打开定时器T0,T1
- TR0 = 0;
- TH0 = 0xFC;
- TL0 = 0x67;
-
- TR1 = 0;
- TH1 = 0xFC;
- TL1 = 0x67;
- ET1 = 1;
- init1602();
-
-
-
- Lcdshow(0,0,str1);
- while(1)
- {
- Keycontrol();
- KeyScan();
- len = IntToString(str1,sec);
- len1= IntToString(str2,num);
- if(e_flag==0)
- {
- Lcdshow(0,0,"Time:");
- Lcdshow(6,0,str1);
- }
- if(num!=0&&e_flag==0&&flag==0)//没有结束且有人按下按键
- {
- Lcdshow(0, 1, "answerer:");
- Lcdshow(9, 1, str2);
- }
- if(e_flag==1)
- {
- Judge();
- }
- }
- }
- /*等待液晶准备*/
- void Lcdready()
- {
- uchar sta;
- P0 = 0xFF;
- RS = 0;
- RW = 1;
- do
- {
- EN = 1;
- sta = P0;//读取状态字
- EN = 0;
- }while(sta & 0x80);
- }
- /* 向 LCD1602 液晶写入命令,cmd-待写入命令值 */
- void WriteCmd(uchar cmd)
- {
- Lcdready();
- RS = 0;
- RW = 0;
- P0 = cmd;
- EN = 1;
- EN = 0;
- }
- /* 向 LCD1602 液晶写入数据,dat-待写入数据 */
- void WriteData(uchar dat)
- {
- Lcdready();
- RS = 1;
- RW = 0;
- P0 = dat;
- EN = 1;
- EN = 0;
- }
- /* 设置显示 RAM 起始地址(x,y)-对应屏幕上的字符坐标 */
- void Lcdaddr(uchar x,uchar y)
- {
- uchar m;
- if(y==0)
- m = 0x00+x; //第一行字符地址从 0x00 起始
- else
- m = 0x40+x; //第二行字符地址从 0x40 起始
- WriteCmd(m | 0x80);//设置 RAM 地址
- }
- /* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
- void Lcdshow(uchar x,uchar y,uchar *str)
- {
- Lcdaddr(x,y);
- while(*str != '\0')
- {
- WriteData(*str++);
- }
- }
- /* 初始化 1602 液晶 */
- void init1602()
- {
- WriteCmd(0x38);
- WriteCmd(0x0C);
- WriteCmd(0x06);
- WriteCmd(0x01);
- }
- /* 整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */
- unsigned char IntToString(unsigned char *str, int dat)
- {
- uchar i = 0;
- unsigned char len = 0;
- unsigned char buf[6];
-
- if (dat < 0) //如果为负数,首先取绝对值,并在指针上添加负号
- {
- dat = -dat;
- *str++ = '-';
- len++;
- }
- do //先转换为低位在前的十进制数组
- {
- buf[i++] = dat % 10;
- dat /= 10;
- } while (dat > 0);
- len += i; //i最后的值就是有效字符的个数
- while (i-- > 0) //将数组值转换为ASCII码反向拷贝到接收指针上
- {
- *str++ = buf[i] + '0';
- }
- *str = '\0'; //添加字符串结束符
-
- return len; //返回字符串长度
- }
- /*简易延时*/
- void delay(uint x)
- {
- uchar i,j;
- for(i=x;i>0;i--)
- for(j=110;j>0;j--);
- }
- /*控制键扫描函数,开始结束*/
- void Keycontrol()
- {
- if(K0==0) //开始键
- {
- delay(10);
- if(K0==0)
- {
- while(!K0);
- WriteCmd(0x01);
- sec=20;
- TR0=~TR0;
- e_flag=0;
- flag=1;
- s_flag = 1;//表示已经开始
- }
- }
- if(K5==0)
- {
- delay(10);
- if(K5==0 && flag==0)
- {
- while(!K5);
- e_flag =1;//表示结束
- Buzz = 0;
- Lcdshow(9,0,"Successed");
- }
- }
- if(K8==0) //查分键
- {
- uchar ch;
- delay(10);
- if(K8==0 && e_flag==1) //按键按下且此时已结束
- {
- while(!K8);
- WriteCmd(0x01);
- Lcdshow(0,0,"P1:");
- ch=(char) (score[1]+48);
- WriteData(ch);
- Lcdshow(10,0,"P2:");
- ch=(char) (score[2]+48);
- WriteData(ch);
- Lcdshow(0,1,"P3:");
- ch=(char) (score[3]+48);
- WriteData(ch);
- Lcdshow(10,1,"P4:");
- ch=(char) (score[4]+48);
- WriteData(ch);
- }
- }
- }
- /*四路热键扫描(哪个键先按下,哪个优先级最高) */
- void KeyScan()
- {
- if( K1==0 && flag != 0 && s_flag==1)
- {
- delay(10);
- if(K1==0)
- {
- while(!K1);
- num=1; //数码管显示1号"1"
- TR0=0; //关闭定时器0,时间停止
- TR1=1; //按下抢答器,蜂鸣器提醒
- flag=0; //关闭开始键标志位,使再按其他三个键不会响应
- }
- }
- if( K2==0 && flag != 0 && s_flag==1) //以下三个按键同一
- {
- delay(10);
- if(K2==0)
- {
- while(!K1);
- num=2;
- TR0=0;
- TR1=1;
- flag=0;
- }
- }
- if( K3==0 && flag != 0 && s_flag==1)
- {
- delay(10);
- if(K3==0)
- {
- while(!K1);
- num=3;
- TR0=0;
- TR1=1;
- flag=0;
- }
- }
- if( K4==0 && flag != 0 && s_flag==1)
- {
- delay(10);
- if(K4==0)
- {
- while(!K1);
- num=4;
- TR0=0;
- TR1=1;
- flag=0;
- }
- }
-
- }
- void Judge()
- {
- if( K6==0 ) //Yes按键
- {
- delay(10);
- if(K6==0)
- {
- while(!K6);
- WriteCmd(0x01);
- Lcdshow(0, 0, "Your answer is:");
- Lcdshow(0, 1, "Right");
- score[num]++;//为选手加分
- }
- }
- if( K7==0 )
- {
- delay(10);
- if(K7==0)
- {
- while(!K7);
- WriteCmd(0x01);
- Lcdshow(0, 0, "Your answer is:");
- Lcdshow(0, 1, "Worry");
- }
- }
- }
- void Time0 () interrupt 1
- {
- TH0 = 0xFC;
- TL0 = 0x67;//重赋值
- cnt++;
- if(cnt>=1000)
- {
- cnt = 0;
- sec--;
- if(sec==0)
- TR0 = 0;
- }
- }
- void Time1 () interrupt 3
- {
- TH1=(65536-2000)/256;
- TL1=(65536-2000)%256;
- Buzz = ~Buzz;
- cnt1++;
- if(cnt1==1000)
- {
- cnt1=0;
- TR1=0;
- }
- }
复制代码
所有资料51hei提供下载:
4路抢答器1602显示.zip
(53.54 KB, 下载次数: 47)
|