蓝桥杯单片机(二) 数码管与按键

蓝桥杯单片机(二) 数码管与按键

1.数码管

蓝桥杯单片机(二) 数码管与按键_第1张图片

数码管的动态扫描使用1ms的定时器扫描,放在中断服务函数中,数码管显示很稳定

例子:数码管后五位显示12345

#include

typedef unsigned char uchar;
typedef unsigned int uint;

uchar dsp_code[]={
     0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar dsp_show[8]={
     0xff,0xff,0xff};  //数码管前三位熄灭,后五位显示12345
uint number=12345;

void Timer0Init(void)		//中断初始化,1毫秒@11.0592MHz
{
     
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0=1;  //记得加上这两句
	EA=1;
}

void Timer0_Service() interrupt 1  //中断入口
{
     
	static uchar bit_com=0;
	
	P0=0;      //消影,使所有数码管熄灭
	P2=0xc0;
	P2=0;
	
	P0=dsp_show[bit_com];  //段选内容,即要显示的数字
	P2=0xe0;    //打开锁存器控制数码管段选
	P2=0;       //关闭锁存器
	
	P0=1<<bit_com;   //位选左移一位
	P2=0xc0;         //打开锁存器控制数码管位选
	P2=0;
	
	if(++bit_com==8)
		bit_com=0;
}

void main()
{
     
	Timer0Init();  //中断初始化
	dsp_show[3]=dsp_code[number/10000];
	dsp_show[4]=dsp_code[number/1000%10];
	dsp_show[5]=dsp_code[number/100%10];
	dsp_show[6]=dsp_code[number/10%10];
	dsp_show[7]=dsp_code[number%10];
	
	while(1)
	{
     
		;
	}
}

2.按键

蓝桥杯单片机(二) 数码管与按键_第2张图片
按键部分分为独立按键与矩阵按键,跳帽J5接在BTN(button)时即原理图中23,独立按键生效。接在KBD(keyboard)时即原理图中12,矩阵按键生效。

2.1 独立按键:

跳线帽需要短接J5口的3和2引脚,按键能使用的仅有第一列(即上图中S4、S5、S6、S7)。当按键按下时,相应的P30-33口输入为低电平,由此编写独立按键扫描函数。

void KEY_1(void)
{
     
	static u8 key_flag = 1;
	if(key_flag && (P30 == 0||P31 == 0|| P32 == 0||P33 == 0))
	{
     
		key_flag = 0;
		if(P30 == 0)        //S7
		{
     	
		}
		else if(P31 == 0)   //S6
		{
     
		}
		else if(P32 == 0)   //S5
		{
     
		}
		else if(P33 == 0)   //S4
		{
     
		}
	}
	else if(P33 && P32 && P31 && P30) key_flag = 1;
}

例子:将跳帽J5接在BTN,按下S4点亮L4,按下S5点亮L5,按下S6点亮L6,按下S7点亮L7,每次只点亮一个LED

#include

typedef unsigned char uchar;
typedef unsigned int uint;

uchar cnt,trg;
uchar count_key;  //控制按键刷新率的变量

void scan_button()
{
     
	uchar readdat=P3^0xff;
	trg=readdat&(readdat^cnt);    //???
	cnt=readdat;
	
	if(trg&0x01)  //检测到按下S7,即0001,用trg==0x01会使按键不灵敏
		P0=~0x40;   //点亮L7
	else if(trg&0x02)   //检测到按下S6,即0010
		P0=~0x20;
	else if(trg&0x04)   //检测到按下S5,即0100
		P0=~0x10;
	else if(trg&0x08)   //检测到按下S4,即1000
		P0=~0x08;
	
	P2=0x80;
	P2=0;
}

		
void Timer0Init(void)		//1毫秒@11.0592MHz
{
     
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0=1;  //记得加上这两句
	EA=1;
}

void Timer0_Service() interrupt 1  //中断入口
{
     
	++count_key;
}

void main()
{
     
	P0=0x00;
	P2=0xa0;  //打开锁存器控制蜂鸣器和继电器
	P2=0;
	
	P0=0xff;
	P2=0x80;  //打开锁存器控制LED
	P2=0;
	Timer0Init();
	
	while(1)
	{
     
		if(count_key>9)  //10ms刷新一次,相当于消抖
		{
     
			count_key=0;   //控制刷新率的变量清零
		  scan_button(); //调用独立按键处理函数
		}
	}
}
		

2.2矩阵按键

跳线帽需要短接J5口的1和2引脚,按键能使用16个(即上图中S4-S19)。矩阵按键的扫描方法可采用行列扫描法,分为两步:

  • 将行的输出设为低电平(0),检测列的电平输入值。
  • 将列的输出设为低电平(0),检测行的电平输入值。

将两个检测值进行叠加,计算判断哪个按键被按下

例子:按下S7使数码管显示+1.按下S11使显示的数-1,数的范围0~200,当其为奇数时打开蜂鸣器关闭继电器,为偶数时打开继电器关闭蜂鸣器。

#include

typedef unsigned char uchar;
typedef unsigned int uint;

sbit buzzer=P0^6;
sbit relay=P0^4;

uchar dsp_code[]={
     0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};  //显示内容(0~9
uchar dsp_value[8]={
     0xff,0xff,0xff,0xff,0xff};//初始化,使前5位数码管熄灭
uchar number=10;
uchar count_key;//控制数码管刷新率


void Timer0_sevice() interrupt 1
{
     
	static uchar dsp_com=0;
	uchar P0_keeper=0,P2_keeper=0;
	
	P0_keeper=P0;P2_keeper=P2; //现场保护
	
	P0=0;
	P2=0xc0;   //消影,使所有数码管熄灭
	P2=0;  
	
	P0=dsp_value[dsp_com];
	P2=0xe0;      //打开锁存器控制数码管段选
	P2=0; 
	
	P0=1<<dsp_com;
	P2=0xc0;     //打开锁存器控制数码管位选
	P2=0;    
	
	if(++dsp_com==8) dsp_com=0;

	P0=P0_keeper;P2=P2_keeper;//返回现场
	
	++count_key;
}

void scan_key()
{
     
	static uchar key_stat=0;
	uchar key_val=0,key_x=0,key_y=0;
	
	P3=0x0f;P4=0x00;//行扫描
	if(!P30) key_x=3;
	else if(!P31) key_x=2;
	else if(!P32) key_x=1;
	else if(!P33) key_x=0;
	
	P3=0xf0;P4=0xff;//列扫描
	if(!P34) key_y=4;
	else if(!P35) key_y=3;
	else if(!P42) key_y=2;
	else if(!P44) key_y=1;
	
	key_val=key_x+key_y*4;//综合行、列扫描的结果,判断具体位置
	
	switch(key_stat)
	{
     
		case 0:
			if(key_val!=0) key_stat=1;//第一次检测到有按键按下,状态为1
			break;
		case 1:
			if(key_val==0) key_stat=0;//第二次(10ms后)若检测到无按键按下,返回状态0,按键防抖
			else
			{
     
				key_stat=2;//第二次(10ms后)再次检测到有按键按下,状态为2
				switch(key_val)
				{
     
					case 7:          //按下S7数字加一
						if(number<200)//注意判断后再执行,防止数超出范围
						{
     
							++number;
						}
						break;
					case 11:          //按下S11数字减一
						if(number>0)
							{
     --number;}
							break;
			    }
			}
			break;
		 case 2:                  //按键防抖设计
				if(key_val==0)key_stat=0;//第三次若检测到无按键按下,返回状态0
			break;
		}
}


void Timer0Init(void)		//1毫秒@11.0592MHz
{
     
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0=1;  //记得加上这两句
	EA=1;
}



void main()
{
     
	P0=0xff;P2=0x80;P2=0;
	P0=0x00;P2=0xa0;P2=0;
	Timer0Init();
	
	while(1)
	{
     
		if(number%2==1)
		{
     
			buzzer=1;
			relay=0;
		}
		else
		{
     
			relay=1;
			buzzer=0;
		}
		P2=0xa0;P2=0;
		
		if(number>9)
			dsp_value[6]=dsp_code[number/10%10];
		else
			dsp_value[6]=0xff;
		
		dsp_value[7]=dsp_code[number%10];
		
		if(count_key>9) //10ms刷新一次,相当于消抖10ms
		{
     
			count_key=0;  //控制刷新率的变量清零
			scan_key();   //调用矩阵按键处理函数
		}
	}
	
}
		

你可能感兴趣的:(蓝桥杯单片机)