2017년 128강좌 > [BK-AVR128] LCD 시간표시

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

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


BASIC4MCU | 2017년 128강좌 | [BK-AVR128] LCD 시간표시

페이지 정보

작성자 키트 작성일2017-09-12 15:09 조회2,248회 댓글0건

본문

 

3660040649_UhOJ7fLV_IMG_20170729_223245_HDR.jpg3Ftype3Dw740

3660040649_JgjxKs4H_IMG_20170729_223239_HDR.jpg3Ftype3Dw740

LCD 커넥터 1번이 우측이라서 LCD를 돌려서 끼웠습니다.


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
212
213
214
215
216
217
218
219
220
#include 
#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;
U08 ms10=0,str[30];
bit sec_flg;
//
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){  
    if(r<2)LCD_CMD(0x80+(c+r*0x40));
    else   LCD_CMD(0x94+(c+(r-2)*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(0x0C); 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);
    for(i=0;i<8;i++){ //write
        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);
    }
    RTC_D_DDR=0; RTC_D_WR=1;
    for(i=0;i<8;i++){ // read
        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
//}
//
void disp_hms(){
  fnd_buf[0]=time[3]>>4; fnd_buf[1]=time[3]&0x0F; //h
  fnd_buf[2]=time[4]>>4; fnd_buf[3]=time[4]&0x0F; //m
  fnd_buf[4]=time[5]>>4; fnd_buf[5]=time[5]&0x0F; //s
  digit=5; //on
}
//
interrupt [TIM2_COMP] void timer2_comp_isr(void){ //100us
  static U08 cnt2=0,fnd_cnt=0,key_cnt1=0,key_cnt2=0,ms=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:
      if(++ms>9){ ms=0; //10ms
        if(++ms10>99){ ms10=0; sec_flg=1; }
        fnd_buf[6]=ms10/10; fnd_buf[7]=ms10%10; //10ms
      }
      break
    case 4: case 5: case 6: case 7: case 8: case 9: break;
  }
  if(++cnt2>9)cnt2=0; 
}
//
void main(void){
  U08 tp;
  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){
    if(sec_flg){ sec_flg=0; 
      get_time(); disp_hms();
      sprintf(str,"20%02X/%02X/%02X %02X:%02X:%02X",time[0],time[1],time[2],time[3],time[4],time[5]); 
      LCD_POS(0,0); LCD_STR(str);
    }
    //
    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;
    }
  }
}

먼저 소스에서 수정한 내용을 간단하게 적어드리겠습니다.

    case 3:
      if(++ms>9){ ms=0; //10ms
        if(++ms10>99){ ms10=0; sec_flg=1; }
        fnd_buf[6]=ms10/10; fnd_buf[7]=ms10%10; //10ms
      }
      break

타이머 인터럽트에서 10ms를 카운트 하기 위해서 코드를 추가 했습니다.
//
sec_flg는 메인 1초마다 set 시키서 
무한루프에서 시간을 읽어오는 동기 신호로 사용하고 있습니다.

//

void LCD_INIT(void){
    delay_ms(50);
    LCD_CMD(0x38); LCD_CMD(0x38); LCD_CMD(0x38);
    LCD_CMD(0x0C); LCD_CMD(0x06); LCD_CLR();
}
LCD 커서가 보기 싫어서 지웠고
//

void LCD_POS(U08 c,U08 r){  
    if(r<2)LCD_CMD(0x80+(c+r*0x40));
    else   LCD_CMD(0x94+(c+(r-2)*0x40));
}

4라인 출력 가능하도록 수정 했습니다.

//

 sprintf(str,"20%02X/%02X/%02X %02X:%02X:%02X",time[0],time[1],time[2],time[3],time[4],time[5]); 
%02d를 사용하지 않고 %02x를 사용한 것은
1302 시간 값이  BCD 타입이라서 HEX값으로 그대로 출력해야합니다.

%02X 와 %02x 에서 X가 대문자 소문자로 다른 경우
16진수 ABCDEF 대문자로 출력하려면 X를 대문자, abcdef 소문자로 출력하려면 x 소문자를 사용하면 됩니다.
물론 BCD는 ABCDEF가 없으므로 상관없지만 모르는 분이 계실 것 같아서 적어둡니다.

//
LED 백라이트에 5V를 직접 가해도 되는 LCD는 상관없지만
4.2V를 가해야하는 LCD는 저항이나 다이오드를 걸어줘야합니다. ---  경고 3

백라이트 전류제한 회로를 구성하고, 점퍼로 선택할 수 있도록 했으면 더 좋겠습니다. 

댓글 0

조회수 2,248

등록된 댓글이 없습니다.

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
현재글 [BK-AVR128] LCD 시간표시 키트 17-09-12 2249
29 [BK-AVR128] KEY 매트릭스 추가 키트 17-09-12 1779
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
모바일버전으로보기