2017년 128강좌 > [BK-AVR128] KEY 매트릭스 추가

TODAY1,976 TOTAL2,153,362
사이트 이용안내
Login▼/회원가입
최신글보기 질문게시판 기술자료 동영상강좌

아두이노 센서 ATMEGA128 PWM LED 초음파 AVR 블루투스 LCD UART 모터 적외선


BASIC4MCU | 2017년 128강좌 | [BK-AVR128] KEY 매트릭스 추가

페이지 정보

작성자 키트 작성일2017-09-12 15:08 조회1,779회 댓글0건

본문

 

3660040649_ZXYQhPi5_25EC25A0259C25EB25AA25A9_25EC2597258625EC259D258C.png3Ftype3Dw740

아래에 있는 4개의 키 때문에 코드를 작성하는데 시간이 좀 걸렸습니다.
이런 (그지같은) 설계는 하지 않는 것이 좋습니다. ---  경고 2
4x5로 4개 추가하고 싶으면 포트를 한개 더 할당하는 것이 좋습니다.^^

PD4~PD7 출력은 PORTx를 0으로 두고서 
키 스캔 시에 해당 비트만 DDRx=1로 출력으로 설정해서 오픈드레인으로 작용하므로
어느 키를 누르든, 몇개를 동시에 누르든 전기적인 데미지가 생기지 않습니다.
소스전류는 PD0~PD3 입력핀의 내부 풀업저항 수십K옴 밖에 없습니다.

아래 소스 분석하려면 머리좀 아프겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include 
#include 
//
#define U08 unsigned char
#define U16 unsigned int
 
#define FU08 flash unsigned char
//
#define  LCD_PORT    PORTA
#define  LCD_C_WR    PORTB=(PORTB&0x1F)|0x80
#define  LCD_D_WR    PORTB=(PORTB&0x1F)|0xA0
//
#define  LCD_EN_1    PORTB|=0x80
#define  LCD_EN_0    PORTB&=~0x80
//
//#define  LCD_RW_1    PORTB|=0x40
//#define  LCD_RW_0    PORTB&=~0x40
//
//#define  LCD_RS_1    PORTB|=0x20
//#define  LCD_RS_0    PORTB&=~0x20
//
#define    SEC         0x80
#define    MIN         0x82
#define    HOUR        0x84
#define    DATE        0x86
#define    MONTH       0x88
#define    YEAR        0x8c
//
#define    RTC_SCL     PORTE.2      // PE2
#define    RTC_D_WR    PORTE.3      // PE3
#define    RTC_D_RD    PINE.3       // PE3
#define    RTC_D_DDR   DDRE.3       // PE3
#define    RTC_RST     PORTE.4      // PE4
//
U08 rtc_Init[8]={0x17,1,2,3,4,5,6,7}; // 시간초기값 년월일시분초
U08 time[8];                          // 년월일시분초
U08 fnd[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF}; //애노드
U08 led_buf=0,fnd_buf[8]={0,},digit=5;
U08 old_key=0,new_key,key_buf=0;
//
void LCD_DATA(U08 d){ LCD_PORT=d; LCD_D_WR; delay_us(1); LCD_EN_0; delay_us(50); }
void LCD_CMD (U08 c){ LCD_PORT=c; LCD_C_WR; delay_us(1); LCD_EN_0; delay_ms( 3); }
void LCD_POS(U08 c,U08 r){ LCD_CMD(0x80|(c+r*0x40)); }
void LCD_CLR(void){ LCD_CMD(1); }
void LCD_STR (U08  *s){ while(*s)LCD_DATA(*s++); }
void LCD_STRf(FU08 *s){ while(*s)LCD_DATA(*s++); }
//
void LCD_INIT(void){
    delay_ms(50);
    LCD_CMD(0x38); LCD_CMD(0x38); LCD_CMD(0x38);
    LCD_CMD(0x0E); LCD_CMD(0x06); LCD_CLR();
}
//
void write_ds1302(U08 addr, U08 data){
    U08 i;
    RTC_SCL=0; RTC_RST=1; delay_us(2);
    for(i=0;i<8;i++){
        if((addr>>i)&1)RTC_D_WR=1; else RTC_D_WR=0;
        delay_us(2); RTC_SCL=1; delay_us(1); RTC_SCL=0; delay_us(1);
    }
    for(i=0;i<8;i++){
        if((data>>i)&0x01)RTC_D_WR=1; else RTC_D_WR=0;
        delay_us(2); RTC_SCL=1; delay_us(1); RTC_SCL=0; delay_us(1);
    }
    RTC_RST=0;
}
//
U08 read_ds1302(U08 addr){
    U08 i, data=0;
    RTC_RST=1; delay_us(2);
    //write
    for(i=0;i<8;i++){
        if((addr>>i)&1)RTC_D_WR=1; else RTC_D_WR=0;
        delay_us(2); RTC_SCL=1; delay_us(1); RTC_SCL=0; delay_us(1);
    }
    // read
    RTC_D_DDR=0; RTC_D_WR=1;
    for(i=0;i<8;i++){
        data>>= 1;
        if(RTC_D_RD)data|=0x80;
        delay_us(1); RTC_SCL=1; delay_us(2); RTC_SCL=0; delay_us(1);
    }
    RTC_D_DDR=1; RTC_SCL=0; delay_us(1); RTC_RST=0;
    return data;
}
//
void save_time(void){
    write_ds1302(YEAR,time[0]); write_ds1302(MONTH,time[1]);
    write_ds1302(DATE,time[2]); write_ds1302(HOUR, time[3]);
    write_ds1302(MIN, time[4]); write_ds1302(SEC,  time[5]);
}
//
void init_time(void){
    U08 i;
    for(i=0;i<8;i++)time[i]=rtc_Init[i];
    save_time();
}
//
void get_time(void){
    time[0]=read_ds1302(YEAR +1); if(time[0]>0x99)init_time();
    time[1]=read_ds1302(MONTH+1); if(time[1]>0x12)init_time();
    time[2]=read_ds1302(DATE +1); if(time[2]>0x31)init_time();
    time[3]=read_ds1302(HOUR +1); if(time[3]>0x23)init_time();
    time[4]=read_ds1302(MIN  +1); if(time[4]>0x59)init_time();
    time[5]=read_ds1302(SEC  +1); if(time[5]>0x59)init_time();
}
//
void disp_ymd(){
  fnd_buf[0]=2;          fnd_buf[1]=0;            //20
  fnd_buf[2]=time[0]>>4; fnd_buf[3]=time[0]&0x0F; //yy
  fnd_buf[4]=time[1]>>4; fnd_buf[5]=time[1]&0x0F; //mm
  fnd_buf[6]=time[2]>>4; fnd_buf[7]=time[2]&0x0F; //dd
  digit=8; //off
  led_buf=1; LCD_POS(0,0); LCD_STRf("1"); 
}
void disp_hms(){
  fnd_buf[0]=16;         fnd_buf[1]=16;           //off
  fnd_buf[2]=time[3]>>4; fnd_buf[3]=time[3]&0x0F; //h
  fnd_buf[4]=time[4]>>4; fnd_buf[5]=time[4]&0x0F; //m
  fnd_buf[6]=time[5]>>4; fnd_buf[7]=time[5]&0x0F; //s
  digit=5; //on
  led_buf=0; LCD_POS(0,0); LCD_STRf("0");
}
//
interrupt [TIM2_COMP] void timer2_comp_isr(void){ //100us
  static U08 cnt2=0,fnd_cnt=0,key_cnt1=0,key_cnt2=0;
  switch(cnt2){
    case 0: PORTA=~led_buf; PORTF|=8; PORTF&=~8; break// led out
    case 1:                           // fnd out
      PORTA=0; PORTF|=4; PORTF&=~4;   // common off
      PORTC=fnd[fnd_buf[fnd_cnt]];    // segment data
      if(fnd_cnt==digit)PORTC&=~0x80; // digit out 
      PORTF|=2;PORTF&=~2;                    // 573 segment out
      PORTA=1<// common out
      if(++fnd_cnt>7)fnd_cnt=0; 
      break;
    case 2:
      if(++key_cnt1>49){ key_cnt1=0; //50ms
        switch(key_cnt2){
          case 0:
            if((PIND&0x0F)!=0x0F)new_key=0;
            if(!PIND.0)new_key=17; if(!PIND.1)new_key=18; if(!PIND.2)new_key=19; if(!PIND.3)new_key=20;
            break;
          case 1:
            if((PIND&0x0F)==0x0F){
              new_key=0; DDRD.4=1; delay_us(1); 
              if(!PIND.0)new_key=1; if(!PIND.1)new_key=5; if(!PIND.2)new_key=9; if(!PIND.3)new_key=13;
              DDRD.4=0; DDRD.5=1; delay_us(1); 
              if(!PIND.0)new_key=2; if(!PIND.1)new_key=6; if(!PIND.2)new_key=10; if(!PIND.3)new_key=14;
              DDRD.5=0; DDRD.6=1; delay_us(1); 
              if(!PIND.0)new_key=3; if(!PIND.1)new_key=7; if(!PIND.2)new_key=11; if(!PIND.3)new_key=15;
              DDRD.6=0; DDRD.7=1; delay_us(1); 
              if(!PIND.0)new_key=4; if(!PIND.1)new_key=8; if(!PIND.2)new_key=12; if(!PIND.3)new_key=16;
              DDRD.7=0; 
            }
            break;
        }
        if(++key_cnt2>1)key_cnt2=0;
        if(old_key!=new_key){ old_key=new_key; if(new_key)key_buf=new_key; }
      } 
      break;
    case 3: case 4: case 5: case 6: case 7: case 8: case 9: break;
  }
  if(++cnt2>9)cnt2=0; 
}
//
void main(void){
  U08 tp;
  U16 i=0;
  DDRA=0xFF; // FND_COMMON & LED & lcd data
  DDRC=0xFF; // FND_SEGMENT
  DDRF=0x0E; // LED & FND 573_sel
  DDRB=0xE0; // LCD control
  PORTD=0x0F; // KEY in:PD0~PD3, out:pd4~pd7 
  led_buf=0; // led off
  RTC_RST=0; RTC_D_WR=0; RTC_SCL=0;
  DDRE=0x1C; // rtc PE2~PE4 out
  write_ds1302(0x8E,0); write_ds1302(0x90,0xA4);
  TCCR2=0x0B; OCR2= 24; TIMSK=0x80; //16000000/64/(1+ 24),100us
  LCD_INIT();
  SREG=0x80;
  while(1){
    delay_ms(1);
    if(++i>999){ get_time(); i=0; disp_ymd(); }
    if(i==500){ disp_hms(); }
    //
    if(key_buf){
      switch(key_buf){
        case 1:                              // yy증가 
          tp=(time[0]>>4)*10+(time[0]&0x0F); // BCD to Binary
          if(tp<99)tp++;                     // 증가
          tp=((tp/10)<<4)+(tp%10);           // Binary to BCD
          write_ds1302(YEAR,tp);
          break;
        case  2: tp=(time[1]>>4)*10+(time[1]&0x0F); if(tp<12)tp++; tp=((tp/10)<<4)+(tp%10); write_ds1302(MONTH,tp); break//mm증가 
        case  3: tp=(time[2]>>4)*10+(time[2]&0x0F); if(tp<31)tp++; tp=((tp/10)<<4)+(tp%10); write_ds1302(DATE ,tp); break//dd증가
        case  5: tp=(time[0]>>4)*10+(time[0]&0x0F); if(tp)tp--;    tp=((tp/10)<<4)+(tp%10); write_ds1302(YEAR ,tp); break//yy감소
        case  6: tp=(time[1]>>4)*10+(time[1]&0x0F); if(tp)tp--;    tp=((tp/10)<<4)+(tp%10); write_ds1302(MONTH,tp); break//mm감소
        case  7: tp=(time[2]>>4)*10+(time[2]&0x0F); if(tp)tp--;    tp=((tp/10)<<4)+(tp%10); write_ds1302(DATE ,tp); break//dd감소
        case  9: tp=(time[3]>>4)*10+(time[3]&0x0F); if(tp<23)tp++; tp=((tp/10)<<4)+(tp%10); write_ds1302(HOUR ,tp); break//h증가
        case 10: tp=(time[4]>>4)*10+(time[4]&0x0F); if(tp<59)tp++; tp=((tp/10)<<4)+(tp%10); write_ds1302(MIN  ,tp); break//m증가
        case 11: tp=(time[5]>>4)*10+(time[5]&0x0F); if(tp<59)tp++; tp=((tp/10)<<4)+(tp%10); write_ds1302(SEC  ,tp); break//s증가
        case 13: tp=(time[3]>>4)*10+(time[3]&0x0F); if(tp)tp--;    tp=((tp/10)<<4)+(tp%10); write_ds1302(HOUR ,tp); break//h감소 
        case 14: tp=(time[4]>>4)*10+(time[4]&0x0F); if(tp)tp--;    tp=((tp/10)<<4)+(tp%10); write_ds1302(MIN  ,tp); break//m감소 
        case 15: tp=(time[5]>>4)*10+(time[5]&0x0F); if(tp)tp--;    tp=((tp/10)<<4)+(tp%10); write_ds1302(SEC  ,tp); break//s감소 
        case 20: init_time();                                                                                       break//시간 초기화
      }
      key_buf=0;
    }
  }
}


동작시켜본 분은 답글로 인증샷 또는 동영상 남겨주세요^^

댓글 0

조회수 1,779

등록된 댓글이 없습니다.

2017년 128강좌HOME > 2017년 128강좌 목록

2017년 128강좌 목록
제목 작성자 작성일 조회
공지 MCU, AVR, 아두이노 등 전자공학에 관련된 질문은 질문게시판에서만 작성 가능합니다. 스태프 19-01-15 9603
공지 사이트 이용 안내댓글[24] master 17-10-29 29482
31 [BK-AVR128] WS2812B 키트 17-09-12 1776
30 [BK-AVR128] LCD 시간표시 키트 17-09-12 2249
현재글 [BK-AVR128] KEY 매트릭스 추가 키트 17-09-12 1780
28 [BK-AVR128] DS1302(RTC) read & write 키트 17-09-12 2458
27 [BK-AVR128] LED & FND 타이머2 인터럽트로 구동 키트 17-09-12 2092
26 [OpenM128] NRF24L01 RF Board (B) 키트 17-09-12 1865
25 [OpenM128] FAT45DBXX DataFlash Board 키트 17-09-12 1465
24 [OpenM128] FT245 USB FIFO Board (mini) 키트 17-09-12 1618
23 [OpenM128] PCF8563 RTC Board 키트 17-09-12 1484
22 [OpenM128] PL2303 USB UART Board (mini) 키트 17-09-12 1709
21 [OpenM128] AD Keypad 키트 17-09-12 1685
20 [OpenM128] 2.2inch 320x240 Touch LCD (A) 키트 17-09-12 2110
19 [OpenM128] Hardware design 이미지 키트 17-09-12 1804
게시물 검색

2022년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2021년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2020년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2019년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
2018년 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월
Privacy Policy
MCU BASIC ⓒ 2020
모바일버전으로보기