天天看點

基于atmega48的掃描按鍵例子

仿真圖:其中左邊的的溫度傳感器等AD轉換與本例子無關

基于atmega48的掃描按鍵例子

#include “iom48v.h”

#include “macros.h”

#define uchar unsigned char

#define uint unsigned int

#define KEY_Press keycode!=0x00

#pragma interrupt_handler T1_refresh: 12

void delay(uint a)

{

while(a–);

}

const uchar disp[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,

0x80,0x90,0x88,0x83,0xA7,0xA1,0x86,0x8E};

uchar segcode[4]={0XFF,0XFF,0XFF,0XFF}; //段碼 (存放譯碼值)

uchar data[4]; //顯示資料

uchar keycode; //判斷按鍵位置

uchar n=0; //顯示重新整理标志

uchar key=0; //鍵值 PINB!=0X0F

uchar digit=0;

/IO口初始化函數/

void IO_Init(void)

{

DDRB = 0xF0;

PORTB = 0x0F; //上拉

DDRC = 0xFF;

PORTC = 0xFF;

DDRD = 0xFF;

PORTD = 0xFF;

}

/定時器T1初始化/

void T1_Init(void)

{

TCCR1A = 0x00; //CTC

TCCR1B = 0x0B; // 64分頻

OCR1A = 78; // 5ms

TIFR1 = 0x02;

TIMSK1 = 0X02; //開中斷

}

/定時器T1中斷服務—資料重新整理/

void T1_refresh(void)

{

n=(++n)%4;

//PORTC |=0X0F; //關閉位選(必須)

PORTC =0X0F;

PORTD = segcode[n]; //傳送資料位

switch(n)

{

case 0: PORTC = ~0x01; //顯示千位

break;

case 1: PORTC = ~0x02;

break; //顯示百位

case 2: PORTC = ~0x04;

break; //顯示十位

case 3: PORTC = ~0x08;

break; //顯示個位

default:  break;    
           

}

TIFR1 = 0X02; //清标志

}

/譯碼函數/

void decode(uchar *num)

{

if(digit1)

{

segcode[3]=disp[num[3]];

}

else if(digit2)

{

segcode[3]=disp[num[3]];

segcode[2]=disp[num[2]];

}

else if(digit==3)

{

segcode[3]=disp[num[3]];

segcode[2]=disp[num[2]];

segcode[1]=disp[num[1]];

}

else if(digit>3)

{

segcode[3]=disp[num[3]]; //個位

segcode[2]=disp[num[2]]; //十位

segcode[1]=disp[num[1]]; //百位

segcode[0]=disp[num[0]]; //千位

}

else

;

// segcode[0] &= ~0x80; // 加小數點

}

/輸入移位函數/

void Digit_Move(uchar *b)

{

uchar i,j;

for(i=0;i<3;i++)

{

b[i]=b[i+1];

}

b[3]=key;

}

/按鍵掃描及資料處理/

void KEY_Scan(void)

{

//keycode = (~PINB)&0X0F; //記錄按鍵在第幾行

PORTB = ~0X10; //掃描第一列

delay(10);

keycode = (~PINB)&0X0F;

while(PINB!=~0X10); //等待按鍵釋放(消抖)

//delay(20000);
  switch(keycode)          //讀取鍵值
  {
  case 0X01: key=0; Digit_Move(data); digit++;decode(data);break;
  case 0X02: key=1; Digit_Move(data); digit++;decode(data);break;
  case 0X04: key=2; Digit_Move(data); digit++;decode(data);break;
  case 0X08: key=3; Digit_Move(data); digit++;decode(data);break;
  default:break;
  }
  
  PORTB = ~0X20;delay(10);
 keycode = (~PINB) & 0X0F;
  while(PINB!=~0X20);
   
//delay(20000);
  switch(keycode)
  { 
  case 0X01: key=4; Digit_Move(data); digit++;decode(data);break;
  case 0X02: key=5; Digit_Move(data); digit++;decode(data);break;
  case 0X04: key=6; Digit_Move(data); digit++;decode(data);break;
  case 0X08: key=7; Digit_Move(data); digit++;decode(data);break;
  default:break;
  }


  PORTB = ~0X40;delay(10);
  keycode = (~PINB) & 0X0F;
  while(PINB!=~0X40);
  
//delay(20000);
  switch(keycode)
  {
  case 0X01: key=8; Digit_Move(data); digit++;decode(data);break;
  case 0X02: key=9; Digit_Move(data); digit++;decode(data);break;
  case 0X04: key=10;Digit_Move(data); digit++;decode(data);break;
  case 0X08: key=11;Digit_Move(data); digit++;decode(data);break;
  default:break;
  }


  PORTB = ~0X80;delay(10);
  keycode = (~PINB) & 0X0F;
  while(PINB!=~0X80);
  
 //delay(20000);
  switch(keycode)
  {
  case 0X01: key=12;Digit_Move(data); digit++;decode(data);break;
  case 0X02: key=13;Digit_Move(data); digit++;decode(data);break;
  case 0X04: key=14;Digit_Move(data); digit++;decode(data);break;
  case 0X08: key=15;Digit_Move(data); digit++;decode(data);break;
  default:break;
  }
           

}

/主函數/

void main(void)

{

CLI();

IO_Init();

T1_Init() ;

SEI();

while(1)

{

PORTB = 0X0F;

keycode = (~PINB)&0X0F;

if(KEY_Press)       //檢測按鍵是否按下
{
  KEY_Scan();
}
delay(30000);
           

}

}

/void delay(uint ms)

{

uint i,j;

for(i=0;i<ms;i++)

{

for(j=0;j<1141;j++);

}

}/