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();
}
'컴퓨터 > Cortex-M3(STM32F103)' 카테고리의 다른 글
삼광도트매트릭스 기본 프로그램 (0) | 2011.08.24 |
---|---|
[STM3210B]GLCD 만능달력 (0) | 2011.07.12 |
[STM3210B]TEXT LCD Module MLCD-100 기본 구동 프로그램 (0) | 2011.06.28 |
myCortex(LM3S8962)에서 광전자도트매트릭스 테스트 프로그램 (0) | 2011.05.13 |
STM3210E보드에 있는 LED점멸하기(GPIO) (1) | 2011.05.04 |