본문 바로가기

컴퓨터/Cortex-M3(STM32F103)

[STM3210B]RTC를 이용하여 TEXT LCD에 날짜가 표시되는 시계

ARM Cortex-M3보드에 TEXT LCD를 연결하여 RTC를 이용한 시계입니다.
전원을 제거하더라도 시계는 계속 가고 있습니다.
오전/오후는 사용자 정의 문자를 이용하였습니다.
한국장애인고용공단 부산직업능력개발원 정보기술분야 학생 작품입니다.



/************************************************
제목 :TEXT LCD 날짜및 시간표시(RTC이용)
보드 : STM3210B
LCD : Dr.Kim TEXT LCD Module MLCD-100
최초작성일 : 2011.06.28
작성자 : 부산직업능력개발원 정보기술 ***

핀연결
1(DB5) : PA5
2(DB4) : PA4
3(DB6) : PA6
4(DB3) : PA3
5(DB7) : PA7
6(DB2) : PA2
8(DB1) : PA1
9(E)   : PB0
10(DB0) : PA0
11(RS)  : PE7
19(VCC) : 5V
20(GND) : GND
*************************************************/
#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
#include <time.h>

#define READ_UP   ((GPIOD->IDR & GPIO_Pin_8)==0)
#define READ_DOWN  ((GPIOD->IDR & GPIO_Pin_14)==0)
#define READ_LEFT  ((GPIOE->IDR & GPIO_Pin_1)==0)
#define READ_RIGHT  ((GPIOE->IDR & GPIO_Pin_0)==0)
#define READ_SET  ((GPIOD->IDR & GPIO_Pin_12)==0)

#define LCD_E GPIO_Pin_0 //b
#define LCD_RS GPIO_Pin_7  //e

char yoil[7][4]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; //_요일

void lcdw(void);
void lcdc(unsigned char data);
void lcdd(unsigned char data);
void String(char *);
void lcdcc(void);
void lcds(void);
void dis(u16 num, u8 digit);
void delay(u32 d1, u32 d2);
void RTC_Config(void);
void timeset(s32 t)
{
 RTC_Config();
 RTC_WaitForLastTask();
 RTC_SetCounter(t);
 RTC_WaitForLastTask();
}

void makefont()
{
 //00:오 01:전 02:후
 u8 a[][8]={
  {0x04, 0x0A, 0x11, 0x0A, 0x04, 0x04, 0x1F, 0x00}, //오
  {0x1D, 0x0B, 0x09, 0x15, 0x00, 0x10, 0x1F, 0x00}, //전
  {0x04, 0x1F, 0x04, 0x0A, 0x04, 0x1F, 0x04, 0x00}, //후
 };
 u8 i,j;
 //CG RAM address 00h set
 lcdc(0x40);
 for(i=0;i<3;i++)
  for(j=0;j<8;j++)
   lcdd(a[i][j]);
}

int main(void){
 u8 upkey,downkey,leftkey,rightkey,setkey;
 u8 pupkey,pdownkey,pleftkey,prightkey,psetkey;
 u32 loop=0;
 u8 blink=0;
 
 s8 mm=1,dd=1,h=1,m=0,s=0,wday,hs[]={0x00,0x01}; //초기값
 s16 yy=2011;
 
 u32 timevar;
 char temp[16];
 enum {normal, setyear, setmonth, setday, sethour, setmin, setsec} mode=normal;
 struct tm *now;
 GPIO_InitTypeDef GPIO;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOD,ENABLE);
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR,ENABLE);
 
 GPIO.GPIO_Mode=GPIO_Mode_Out_PP; //출력
 GPIO.GPIO_Speed=GPIO_Speed_2MHz;
 GPIO.GPIO_Pin=0xff;
 GPIO_Init(GPIOA, &GPIO);
 
 GPIO.GPIO_Pin=GPIO_Pin_0;
 GPIO_Init(GPIOB, &GPIO);
 
 GPIO.GPIO_Pin=GPIO_Pin_7;
 GPIO_Init(GPIOE, &GPIO);
 
 GPIO.GPIO_Mode=GPIO_Mode_IN_FLOATING; //입력/ 조이스틱
 GPIO.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_14|GPIO_Pin_12;
 GPIO_Init(GPIOD, &GPIO);
 
 GPIO.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
 GPIO_Init(GPIOE, &GPIO);
 
 delay(1000,1000);
 
 lcdw();
 
 makefont();


 while(1){
  loop++;
  if(loop>3) {
   loop=0;
   blink = ~blink; //blink반전
  }
  timevar = RTC_GetCounter();
  now = localtime(&timevar);
  yy=now->tm_year+2000;
  mm=now->tm_mon+1;
  dd=now->tm_mday;
  h=now->tm_hour;
  m=now->tm_min;
  s=now->tm_sec;
  wday = (now->tm_wday+6)%7;
  
  if(h<12) hs[1]=0x01;
  else {
   hs[1]=0x02;
   h-=12;
  }
  if(h==0) h=12;
  
  
  setkey = READ_SET;
  upkey = READ_UP;
  downkey = READ_DOWN;
  leftkey = READ_LEFT;
  rightkey = READ_RIGHT;
  
  switch(mode) {
  case normal:
   if((setkey != psetkey) && setkey){
    mode = setyear;
   }
   lcdc(0x81);
   sprintf(temp,"%4d/%02d/%02d %s",yy,mm,dd,yoil[wday]);
   String(temp);
   lcdc(0xc3);
   lcdd(hs[0]);//오
   lcdd(hs[1]); //전 /후 
   sprintf(temp,"%2d:%02d:%02d",h,m,s);
   String(temp);
   break;
  case setyear: 
   if((upkey != pupkey) && upkey){
    now->tm_year+=1;
    timeset(mktime(now));
   }
   if((downkey != pdownkey) && downkey){
    now->tm_year-=1;
    timeset(mktime(now));
   }
   if((rightkey != prightkey) && rightkey){
    mode = setmonth;
   }
   if((setkey != psetkey) && setkey){
    mode = normal;
   }
   lcdc(0x81);
   if(blink==0) sprintf(temp,"    /%02d/%02d %s",mm,dd,yoil[wday]);
   else sprintf(temp,"%4d/%02d/%02d %s",yy,mm,dd,yoil[wday]);
   String(temp);
   lcdc(0xc3);
   lcdd(hs[0]);//오
   lcdd(hs[1]); //전 /후 
   sprintf(temp,"%2d:%02d:%02d",h,m,s);
   String(temp);
   break;
  case setmonth:
   if((upkey != pupkey) && upkey){
    now->tm_mon+=1;
    timeset(mktime(now));
   }
   if((downkey != pdownkey) && downkey){
    now->tm_mon-=1;
    timeset(mktime(now));
   }
   if((leftkey != pleftkey) && leftkey){
    mode = setyear;
   }
   if((rightkey != prightkey) && rightkey){
    mode = setday;
   }
   if((setkey != psetkey) && setkey){
    mode = normal;
   }
   lcdc(0x81);
   if(blink==0) sprintf(temp,"%4d/  /%02d %s",yy,dd,yoil[wday]);
   else sprintf(temp,"%4d/%02d/%02d %s",yy,mm,dd,yoil[wday]);
   String(temp);
   lcdc(0xc3);
   lcdd(hs[0]);//오
   lcdd(hs[1]); //전 /후 
   sprintf(temp,"%2d:%02d:%02d",h,m,s);
   String(temp);
   break;
  case setday:
   if((upkey != pupkey) && upkey){
    now->tm_mday+=1;
    timeset(mktime(now));
   }
   if((downkey != pdownkey) && downkey){
    now->tm_mday-=1;
    timeset(mktime(now));
   }
   if((leftkey != pleftkey) && leftkey){
    mode = setmonth;
   }
   if((rightkey != prightkey) && rightkey){
    mode = sethour;
   }
   if((setkey != psetkey) && setkey){
    mode = normal;
   }
   lcdc(0x81);
   if(blink==0) sprintf(temp,"%4d/%02d/   %s",yy,mm,yoil[wday]);
   else sprintf(temp,"%4d/%02d/%02d %s",yy,mm,dd,yoil[wday]);
   String(temp);
   lcdc(0xc3);
   lcdd(hs[0]);//오
   lcdd(hs[1]); //전 /후 
   sprintf(temp,"%2d:%02d:%02d",h,m,s);
   String(temp);
   break;
  case sethour: //시간을설정하는 모드
   if((upkey != pupkey) && upkey){
    now->tm_hour+=1;
    timeset(mktime(now));
   }
   if((downkey != pdownkey) && downkey){
    now->tm_hour-=1;
    timeset(mktime(now));
   }
   if((leftkey != pleftkey) && leftkey){
    mode = setday;
   }
   if((rightkey != prightkey) && rightkey){
    mode = setmin;
   }
   if((setkey != psetkey) && setkey){
    mode = normal;
   }
   lcdc(0x81);
   sprintf(temp,"%4d/%02d/%02d %s",yy,mm,dd,yoil[wday]);
   String(temp);
   lcdc(0xc3);
   lcdd(hs[0]);//오
   lcdd(hs[1]); //전 /후 
   if(blink==0) sprintf(temp,"  :%02d:%02d",m,s);
   else sprintf(temp,"%2d:%02d:%02d",h,m,s);
   String(temp);
   break;
  case setmin:
   if((upkey != pupkey) && upkey){
    now->tm_min+=1;
    timeset(mktime(now));
   }
   if((downkey != pdownkey) && downkey){
    now->tm_min-=1;
    timeset(mktime(now));
   }
   if((leftkey != pleftkey) && leftkey){
    mode = sethour;
   }
   if((rightkey != prightkey) && rightkey){
    mode = setsec;
   }
   if((setkey != psetkey) && setkey){
    mode = normal;
   }
   lcdc(0x81);
   sprintf(temp,"%4d/%02d/%02d %s",yy,mm,dd,yoil[wday]);
   String(temp);
   lcdc(0xc3);
   lcdd(hs[0]);//오
   lcdd(hs[1]); //전 /후 
   if(blink==0) sprintf(temp,"%2d:  :%02d",h,s);
   else sprintf(temp,"%2d:%02d:%02d",h,m,s);
   String(temp);
   break;
  case setsec:
   if((upkey != pupkey) && upkey){
    now->tm_sec+=1;
    timeset(mktime(now));
   }
   if((downkey != pdownkey) && downkey){
    now->tm_sec-=1;
    timeset(mktime(now));
   }
   if((leftkey != pleftkey) && leftkey){
    mode = setmin;
   }
   if((setkey != psetkey) && setkey){
    mode = normal;
   }
   lcdc(0x81);
   sprintf(temp,"%4d/%02d/%02d %s",yy,mm,dd,yoil[wday]);
   String(temp);
   lcdc(0xc3);
   lcdd(hs[0]);//오
   lcdd(hs[1]); //전 /후 
   if(blink==0) sprintf(temp,"%2d:%02d:  ",h,m);
   else sprintf(temp,"%2d:%02d:%02d",h,m,s);
   String(temp);
   break;
  }
  
  pupkey = upkey;
  pdownkey = downkey;
  pleftkey = leftkey;
  prightkey = rightkey;
  psetkey = setkey;
  
  }
}
void String(char *string){
 while(*string != '\0'){
  lcdd(*string);
  string++;
 }
}

void lcdw(void){
  lcdc(0x38); //8bit 2row 5*8dot
  lcdc(0x02); //return home
  lcdc(0x01); //clear display
  lcdc(0x06); //address increment
  lcdc(0x0c); //display on, cursor off, blink off,
}

void lcdc(unsigned char data){
  GPIOA->ODR &= ~0xff;
  GPIOA->ODR |= data;
  GPIOE->ODR &= ~(LCD_RS);
  GPIOB->ODR |= (LCD_E);
  lcds();
  GPIOB->ODR &= ~(LCD_E);
  GPIOE->ODR &= ~(LCD_RS);
  lcdcc();
}

void lcdd(unsigned char data){
  GPIOA->ODR &= ~0xff;
  GPIOA->ODR |= data;
  GPIOE->ODR |= (LCD_RS);
  GPIOB->ODR |= (LCD_E);
  lcds();
  GPIOB->ODR &= ~(LCD_E);
  GPIOE->ODR &= ~(LCD_RS);
  lcds();
}

void lcdcc(void){
  delay(1000,100);
}
void lcds(void){
  delay(1000,10);
}
void delay(u32 d1, u32 d2){
  vu32 i,j;
  for(i=0;i<d1;i++) for(j=0;j<d2;j++);
}
 
void RTC_Config(void){
 PWR_BackupAccessCmd(ENABLE);
 RCC_LSEConfig(RCC_LSE_ON);
 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);
 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
 RCC_RTCCLKCmd(ENABLE);
 RTC_WaitForLastTask();
 RTC_SetPrescaler(32767);
 RTC_WaitForSynchro();
 RTC_WaitForLastTask();
 RTC_ITConfig(RTC_IT_SEC,ENABLE);
 RTC_WaitForLastTask();
}