⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mykey.c

📁 在AVR单片机的控制下
💻 C
字号:
/* 此函数每次执行都产生一个扫描信号(四位,任一时刻只有一位为 '0')加于列线上,同时读取行线上的电平值以判断扫描信号为 '0'的列上是否有键按下。如果此函数被执行4次后,即经过一轮扫描后,没有发现按键被按下,则输出16(键盘值从0到15,因此16用以指示无效值)。另外,用LastNum存上次读到的按键值,CurrentNum存本次读到的按键值,如果两次读到的按键值同,亦输出16 。换句话说,无论用户按一个键按多久,都只返回一个有效值,当成一次按键。*/

/*注:此函数一般用于定时器中断中或主循环中,即本函数需隔一定的时间(10ms为宜)被执行一次,才能起到键盘扫描的作用。*/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <inttypes.h>                  //程序头文件

uint8_t Keyboard(void) //键盘扫描函数,返回一个键值或16(无效值)
{
   static uint8_t ScanCode=0xF7,TempNum=16,LastNum=16,CurrentNum=16,Times=0;
   switch(ScanCode)    // 扫描信号
   	{
   	  case 0xF7:ScanCode=0xFB; break;  // 扫描信号:0111→1011
      case 0xFB:ScanCode=0xFD; break;  // 1011→1101
      case 0xFD:ScanCode=0xFE; break;  // 1101→1110
      case 0xFE:ScanCode=0xF7; break;  // 1110→0111
      default: ScanCode=0xF7;  break;
   	}

   /*在main()函数里需将DDRC设成0x0F,即PC7~PC4为输入,PC3~PC0为输出。
    下面PORTC=ScanCode意味着,将PC7~PC4设为带上拉功能的输入,
    而PC3~PC0输出扫描信号。*/
   PORTC=ScanCode; 
   switch(PINC)  // 解读行列电平值与按键值的关系
  	{ 
/*TempNum记录读到的键值,由于此键值需经进一步处理,
所以是暂时数值(TempNum)。Times用以记录没有读到有效键值的次数,
如果次数达到4次(即扫描一轮后没有发现有效键值),
就表示没有键按下。*/   	 
          case 0xE7:TempNum=0;Times=0;break;
          case 0xD7:TempNum=1;Times=0;break; 
		  case 0xB7:TempNum=2;Times=0;break;
		  case 0x77:TempNum=3;Times=0;break;
		  case 0xEB:TempNum=4;Times=0;break;
		  case 0xDB:TempNum=5;Times=0;break;
	      case 0xBB:TempNum=6;Times=0;break;
	      case 0x7B:TempNum=7;Times=0;break;
	      case 0xED:TempNum=8;Times=0;break;
	      case 0xDD:TempNum=9;Times=0;break;
	      case 0xBD:TempNum=10;Times=0;break;
	      case 0x7D:TempNum=11;Times=0;break;
	      case 0xEE:TempNum=12;Times=0;break;
	      case 0xDE:TempNum=13;Times=0;break;
	      case 0xBE:TempNum=14;Times=0;break;
	      case 0x7E:TempNum=15;Times=0;break;
          default:{
                     Times++;
					 if  (Times==4) 
					 { 		TempNum=16;
						Times=0;
					 }
         		  }break;
  	}
  /*对读到的键值进行处理,每个有效键值仅返回一次*/

   LastNum=CurrentNum;  
   CurrentNum=TempNum;
   if (CurrentNum==LastNum) return(16);//相同的输入,认为是一次输入,这次返回无效值
   else  return(CurrentNum);           //返回键值
}


SIGNAL(SIG_OVERFLOW0)                  //定时器0
{ uint8_t Keynum=16;
   TCNT0=0xB2;
   Keynum=Keyboard(); //读取键盘值
   if(Keynum!=16)     //如果不是无效值,将它写入B端口显示
	 switch(Keynum)
 {     case 0:PORTB=0x3f;break;
       case 1:PORTB=0x06;break;
	   case 2:PORTB=0x5b;break;
       case 3:PORTB=0x4f;break;
	   case 4:PORTB=0x66;break;
	   case 5:PORTB=0x6d;break;
	   case 6:PORTB=0x7d;break;
	   case 7:PORTB=0x07;break;
	   case 8:PORTB=0x7f;break;
	   case 9:PORTB=0x6f;break;
	   case 10:PORTB=0x77;break;
	   case 11:PORTB=0x7c;break;
	   case 12:PORTB=0x39;break;
	   case 13:PORTB=0x5e;break;
	   case 14:PORTB=0x79;break;
	   case 15:PORTB=0x71;break;
	   default:PORTB=0x00;break;
 }
 PORTD=0x3e;    //用最后一个数码管
}
   
int main(void)
{
   DDRC=0x0F;   //初始化,PC7~PC4输入,PC3~PC0输出
   PORTC=0xFF;  //上拉及其输出值
   DDRD=0xFF;   //输出
   PORTD=0x00;  //初值
   DDRB=0xFF;
   PORTB=0x00;
   TCCR0=5;
   TCNT0=0xB2;
   TIMSK=(1<<TOIE0);//开中断
   sei();
   for (;;)   //死循环,等待信号变化
   	{}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -