这篇我们要先讲下程序主题框架
定义:
定义端口
KEY0(起点/终点1)
KEY1轮廓、
KEY2(起点/终点2)
BEER(蜂鸣器)
数码管控制
变量
设置一个变量 time_sys来表示当前状态:
状态名称 | 触发方式 | |
0 | 复位 | 开机器 KEY0(起点/终点1)、KEY2(起点/终点2)同时接地。当移动框(GND)触及起点或终点时候按下按就可以触发。 |
1 | 左向右等待 | 在复位状态下松按键,如果左侧还接触移动框(GND),则进入左向右等待状态。 |
2 | 左向右开始 | 在左向右等待状态下,移动框(GND)离开左侧起点,系统开始计时。 |
3 | 右向左等待 | 在复位状态下松按键,如果右侧还接触移动框(GND),则进入右向左状态。 |
4 | 右向左开始 | 在左向右等待状态下,移动框(GND)离开右侧起点,系统开始计时。 |
5 | 超时 | 计时超过99.00秒,进入超时模式。需要复位才能重新开始游戏。 备注:在开始描轮廓时移动框(GND)碰触到轮廓时是按100倍计时进行。 |
6 | 成功 | 在“左向右开始”或者“右向左开始”模式用时没超过99秒,成功到达另一端。 |
其他变量这里就不做介绍了。
初始化:
- Io口初始化
- 我们采取的是动框接地,然后通过判断与起点、轮廓、终点是否接触,从而判断状态,所以需要将KEY0(起点/终点1)、KEY1轮廓、KEY2(起点/终点2)设置为默认高电平。
- 蜂鸣器驱动的电压比较大,所以我们需要将其设置为推挽输出,设置方式需要查手册,偷懒就通过软件生成,比如:
依次设置1,2,3,然后在4地方复制粘贴到我们程序里就好了
- 定时器初始化
主循环:
- 显示根据不同状态显示不同内容
这里只要把要显示的内容存入LEDw[0-3],然后通过定时器进行扫描,具体怎么显示在上一篇已经介绍过了。
2.判断是否进入复位状态,就是检查KEY0、KEY2是非同时为1
3.状态判断,主要是切换1,2,3,4,6状态。
4.超时判断,主要是为了进入超时状态。碰触的100计是在定时器里设置的。
5.蜂鸣器控制。
---------------------------------
完整程序
#include <STC15F2K60S2.H>
#include <stdlib.h>
typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
typedef unsigned long uint32_t;
uint8_t display_t;//控制显示切换用
uint32_t time_1MS;//1ms计数
//数码管显示
uint8_t LEDDI1[10]={0x3F,0x6,0x5B,0x4F,0x66,0x6D,0x7D,0x7,0x7F,0x6F};
uint8_t LEDDI2[10]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF};
uint8_t LEDw[4];
uint8_t time_sys;
/*
0 复位
1 左向右
2 左向右开始
3 右向左
4 右向左开始
5 超时
6 成功
*/
//触点检查
sbit KEY0 =P2^0; //行程端A测量点
sbit KEY1 =P2^1; //轮廓钢丝测量点
sbit KEY2 =P2^2; //行程端B测量点
//喇叭输出
sbit BEER =P2^3; //蜂蜜喇叭
//数码管显示 共阴级
//从左到右位依次1,2,3,4
sbit LED_C1 =P2^4; //位控制1
sbit LED_C2 =P2^5; //位控制2
sbit LED_C3 =P2^6; //位控制3
sbit LED_C4 =P2^7; //位控制4
void Timer0_Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
}
void Timer0_interrupt_handle(void) interrupt 1//定时器中断处理
{
if((time_sys==2)||(time_sys==4))
{time_1MS ;
if(KEY1==0)
{time_1MS=time_1MS 100;
}
}
if(display_t >=4)display_t=0;
LED_C1=1; LED_C2=1;LED_C3=1;LED_C4=1;
P1=LEDw[display_t];
switch (display_t)
{
case 0:
LED_C1=0;
break;
case 1:
LED_C2=0;
break;
case 2:
LED_C3=0;
break;
case 3:
LED_C4=0;
break;
}
}
void main(void)
{
uint8_t K;
/*初始化*/
//检测点初始化
KEY0=1;
KEY1=1;
KEY2=1;
P2M1 = 0x00; P2M0 = 0x08; //P2(00000000B,00001000B)
BEER=0;
time_sys=0;
//定时器初始化
Timer0_Init();
K= rand();
while (1)
{
//显示
switch (time_sys)
{
//复位
case 0:
LEDw[0]=LEDDI1[0];
LEDw[1]=LEDDI1[0];
LEDw[2]=LEDDI1[0];
LEDw[3]=LEDDI2[0];
break;
//准备开始
case 1:
LEDw[0]=0x63;
LEDw[1]=0x40;
LEDw[2]=0x40;
LEDw[3]=0x40;
break;
case 3:
LEDw[0]=0x40;
LEDw[1]=0x40;
LEDw[2]=0x40;
LEDw[3]=0x63;
break;
//移动和成功都显示时间
case 2:
case 4:
case 6:
/*更新时间*/
if(time_1MS<10000)LEDw[0]=0;
else LEDw[0]=LEDDI1[time_1MS/10000];
LEDw[1]=LEDDI1[time_1MS/1000];
LEDw[2]=LEDDI1[time_1MS/100];
LEDw[3]=LEDDI2[time_1MS/10];
break;
//超时
case 5:
LEDw[0]=0x5c;
LEDw[1]=0x5c;
LEDw[2]=0x5c;
LEDw[3]=0x5c;
break;
}
//直接复位
if(KEY0==0&KEY2==0) time_1MS=0,time_sys=0;
//复位后判断向那边运动
switch (time_sys)
{
case 0:
if(KEY0==0 & KEY2==1) time_sys=1;
if(KEY0==1 & KEY2==0) time_sys=3;
break;
case 1:
if(KEY0==1&KEY2==1) time_sys=2;
break;
case 3:
if(KEY0==1&KEY2==1) time_sys=4;
break;
case 2:
if(KEY2==0) time_sys=6;
break;
case 4:
if(KEY0==0) time_sys=6;
break;
}
//超过99.99秒结束
if(time_1MS>=99000)time_sys=5;
//声音报警器
if(KEY1)BEER=0;
else if((time_sys==2)||(time_sys==4)) BEER=1;
}
}
----------------------------------------------
电路部分
https://www.toutiao.com/item/6999898228321780232/
定时器部分
https://www.toutiao.com/item/7002029670900285964/
显示器部分
https://www.toutiao.com/item/7003526469167153702/