蓝桥杯单片机快速开发笔记——特训2 按键的长按与短按

一、题目要求

在CT107D单片机综合训练平台上,通过I/O模式编写代码,实现以下功能:

  1. 系统上电后,关闭蜂鸣器、继电器和全部指示灯,数码管显示初始值为28,仅显示数码管最右边两位。
  2. 利用定时器0实现10ms间隔定时,作为长定时的基本单位,用于记录按键按下持续时间。
  3. 将J5的23脚短接,将S4设置为独立按键。
  4. 循环扫描S7按键,按下时间小于1秒为短按,数码管数字加1,超过99后恢复为00;按下时间大于1秒为长按,数码管计数清零。
  5. 在按键扫描和处理过程中,确保不干扰数码管正常显示,避免按键误触发和多次处理的情况发生。

二、利用烧写工具中的定时器计数器定时

记得手打打开总中断EA

三、示例代码

#include "stc15.h"

void hc573(unsigned char channel, unsigned char value)
{
	P2 = (P2 & 0x1f) | 0x00;
	P0 = value;
	
	switch(channel)
	{
		case 4:
			P2 = (P2 & 0x1f) | 0x80;   //LED
		break;
		
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;   //蜂鸣器继电器
		break;
		
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;   //数码管位选
		break;
		
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;   //数码管段选
		break;
	}
	
	
	P2 = (P2 & 0x1f) | 0x00;
}


void delay_smg(unsigned int t)
{
	while(t--);
}

void delay_key(unsigned int t)
{
	while(t--);
}


#define TSMG 500
unsigned char n = 28;

code unsigned char Seg_Table[] = 
{
	0xc0, //0
	0xf9, //1
	0xa4, //2
	0xb0, //3
	0x99, //4
	0x92, //5
	0x82, //6
	0xf8, //7
	0x80, //8
	0x90, //9
	0x88, //A
	0x83, //b
	0xc6, //C
	0xa1, //d
	0x86, //E
	0x8e //F
};

//控制所有数码管
void smg_all(unsigned char dat)
{
	hc573(6, 0xff);
	hc573(7, dat);
}

//控制单个数码管
void smg_bit(unsigned char pos, unsigned char dat)
{
	hc573(6, 0x01 << pos);
	hc573(7, dat);
	delay_smg(TSMG);
	hc573(6, 0x01 << pos);
	hc573(7, 0xff);
}

//数码管显示函数
void smg_display()
{
	smg_bit(6, Seg_Table[(n / 10)]);
	smg_bit(7, Seg_Table[(n % 10)]);
}



unsigned int count = 0;

extern unsigned char f_key;

void Timer0_Init(void)		//10毫秒@12.000MHz
{
  AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0xF0;				//设置定时初始值
	TH0 = 0xD8;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时

	ET0 = 1;
	EA = 1;
}

void service_timer0 () interrupt 1
{
	if(f_key == 1)
	{
		count++;
	}
}


#define TKEY 200

sbit s7 = P3^0;
unsigned char f_key = 0;


void key_scan()
{
	if(s7 == 0)
	{
		count = 0;
		f_key = 1;
		delay_key(TKEY);
		if(s7 == 0)
		{
			while(s7 == 0)
			{
				smg_display();
			}
			f_key = 0;
			if(count >= 100)
			{
				n = 0;
				count = 0;
			}
			else
			{
				n++;
				if(n > 99)
				{
					n = 0;
				}
				count = 0;
			}
		}
	}
	f_key = 0;
	count = 0;
	
}

void init_sys()
{
	hc573(5, 0x00);   //关闭所有蜂鸣器和继电器
	hc573(4, 0xff);   //熄灭所以LED
	smg_all(0xff);    //熄灭所有数码管
	Timer0_Init();
}


void main()
{
	init_sys();
	while(1)
	{
		smg_display();
		key_scan();
	}
}
  1. void hc573(unsigned char channel, unsigned char value):定义了一个函数hc573,用于控制573锁存器的输出。根据传入的通道号和数据值,设置相应的输出信号。

  2. void delay_smg(unsigned int t):定义了一个延时函数delay_smg,用于实现数码管显示的延时。

  3. void delay_key(unsigned int t):定义了一个延时函数delay_key,用于实现按键扫描的延时。

  4. #define TSMG 500:定义了一个宏TSMG,值为500,用于设置数码管显示的延时时间。

  5. unsigned char n = 28;:定义了一个无符号字符型变量n,初始值为28,用于存储数码管显示的数值。

  6. code unsigned char Seg_Table[] = {...}:定义了一个只读数据表Seg_Table,存储了数码管显示的段选值。

  7. void smg_all(unsigned char dat):定义了一个函数smg_all,用于控制所有数码管的显示。

  8. void smg_bit(unsigned char pos, unsigned char dat):定义了一个函数smg_bit,用于控制单个数码管的显示。

  9. void smg_display():定义了一个数码管显示函数smg_display,在其中调用了smg_bit函数实现数码管的显示。

  10. unsigned int count = 0;:定义了一个无符号整型变量count,用于记录按键按下的持续时间。

  11. extern unsigned char f_key;:声明了一个外部的无符号字符型变量f_key,用于按键扫描的标志。

  12. void Timer0_Init(void):定义了一个定时器0初始化函数Timer0_Init,用于设置定时器0的工作模式和初值,并开启定时器0。

  13. void service_timer0 () interrupt 1:定义了一个定时器0中断服务函数service_timer0,用于处理定时器0的中断事件。

  14. #define TKEY 200:定义了一个宏TKEY,值为200,用于设置按键扫描的延时时间。

  15. sbit s7 = P3^0;:定义了一个位变量s7,表示P3口的第0位,用于表示S7按键的状态。

  16. unsigned char f_key = 0;:定义了一个无符号字符型变量f_key,初始化为0,用于按键扫描的标志。

  17. void key_scan():定义了一个按键扫描函数key_scan,用于检测S7按键的按下情况并进行相应处理。

  18. void init_sys():定义了一个系统初始化函数init_sys,在其中关闭蜂鸣器、继电器、LED灯和数码管,并初始化定时器0。

  19. void main():定义了主函数main,在其中首先调用init_sys进行系统初始化,然后进入一个无限循环,在循环中持续进行数码管显示和按键扫描的操作。

  • 29
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木木不迷茫(˵¯͒¯͒˵)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值