国信长天单片机竞赛训练之配合定时器实现立即计数和随按下按键的时间计数(二)
本次训练实现当按下S18时且时间<1s 只计算一次,当按下s18且按下按键时间大于1s则在不松开的情况每过1s计数加一,而按下s19则是减一,与上同理。难点在于通过按键扫描记录按下未松手的key值,配合定时器中断实现每过1s计数加减,并把数值通过数码管显示。
//mian.c
#include "sys.h"
#include "math.h"
u8 key_value=0;
static u32 example=0;
static u32 count=0;
static u32 time=0;
static u32 flag=0;
u8 temp1=0;
u8 temp2=0;
void main(){
sys_init();
ET0=1;
EA=1;
Timer0Init();
while(1){
key_value=keyscan();
temp1=key_value;//读取按键状态 0/被按下的状态
if(key_value>0){//有按键按下,temp2保留按键按下的状态
temp2=key_value;
flag=getsec();
}
smgshow(3,flag/10);
smgshow(4,flag%10);//显示case2的值
if(temp2<10){
smgshow(7,temp2%10);
}
if(temp2>10&&temp2<100){
smgshow(6,temp2/10);
smgshow(7,temp2%10);
}
if(example>=0&&example<10){
smgshow(0,example%10);
}
if(example>=10&&example<100){
smgshow(0,example/10);
smgshow(1,example%10);
}
if(temp2==temp1&&temp2==19){//s11 减
example--;
}
if(temp2==temp1&&temp2==18){//s10 增
example++;
}
if(example<0){
smgshow(0,12);
smgshow(1,abs(example));
}
if(time==1000&&flag==18){
example++;
time=0;
}
else if(time==1000&&flag==19){
example--;
time=0;
}
}
}
void timer0() interrupt 1{
if(flag>0&&flag==getsec()){
time++;
}
else if(flag!=getsec()){
time=0;
}
}
//sys.c
#include "sys.h"
static u8 key_state=0;
u8 key_press;
u8 code smg_index[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x7f,0xbf};
sbit buzzer=P0^6;
sbit relay=P0^4;
static u8 sec=0;
void sys_init(){
P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xa0;buzzer=0;relay=0;P2&=0x1f;
P2=(P2&0x1f)|0xc0;P0=0xff;P2&=0x1f;
P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
}
u8 keyscan(){
u8 row=0;
switch(key_state){
case 0:
P3=0X0F;
P42=0;
P44=0;
key_press=P3&0x0F;
if(key_press!=0x0F){
key_state=1;
}
break;
case 1:
P3=0X0F;
P42=0;
P44=0;
key_press=P3&0x0f;
if(key_press!=0x0f){
if(key_press==0x0e) row=7;
else if(key_press==0x0d) row=6;
else if(key_press==0x0b) row=5;
else if(key_press==0x07) row=4;
P3=0xf0;
P42=1;P44=1;
key_press=P3&0xf0;
if(key_press!=0xf0){
if(P44==0) row+=0;
else if(key_press==0xd0) row+=8;
else if(key_press==0xe0) row+=12;
else if(P42==0) row+=4;
}
sec=row;
key_state=2;
}
else key_state=0;
break;
case 2:
P3=0x0f;
key_press=P3&0x0f;
if(key_press==0x0f){
key_state=0;
}
break;
default :
break;
}
return row;
}
u8 getsec(){
if(key_state==2) return sec;
else return 0;
}
void smgshow(u8 weis,u8 dus){
P2=P2&0x1f;
P0=0xff;
P2=(P2&0x1f) | 0xe0; //消除干扰
P2=P2&0x1f;
P0=1<<weis; //位选
P2=(P2&0x1f)|0xc0;
P2=P2&0x1f;
P0=smg_index[dus]; //某位数码管显示的数字
P2=(P2&0x1f)|0xe0;
P2=P2&0x1f;
}
void Timer0Init(void) //1000??@11.0592MHz
{
AUXR |= 0x80;
TMOD &= 0xF0;
TL0 = 0xCD;
TH0 = 0xD4;
TF0 = 0;
TR0 = 1;
}
//sys.h
#ifndef __SYS_H__
#define __SYS_H__
#include "stc15f2k60s2.h"
typedef unsigned char u8;
typedef int u32;
void sys_init();
u8 keyscan();
u8 getsec();
void smgshow(u8 weis,u8 dus);
void Timer0Init();
#endif
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?