/************************************************
제목 :그래픽형 LCD
보드 : STM3210B
LCD : Dr.Kim GRAPHIC LCD Module MLCD-200
최초작성일 : 2011.06.28
작성자 : 부산직업능력개발원 정보기술 ***
핀연결
1(DB5) : PA5
2(DB4) : PA4
3(DB6) : PA6
4(DB3) : PA3
5(DB7) : PA7
6(DB2) : PA2
8(DB1) : PA1
10(DB0) : PA0
11(E) : PE7
13(RS) : PE9
15(/CS2) : PE11
17(/CS1) : PE13
19(VCC) : 5V
20(GND) : GND
*************************************************/
#include "stm32f10x.h"
#include "font.h"
#include "e_font5x7.h"
#include "txt_128x64.h"
#include <time.h>
#include <stdio.h>
#include <string.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_CTRL GPIOE->ODR
#define LCD_DATA GPIOA->ODR
#define LCD_E GPIO_Pin_7 //e
#define LCD_RS GPIO_Pin_9 //e
#define LCD_CS2 GPIO_Pin_11 //e
#define LCD_CS1 GPIO_Pin_13 //e
void lcdg(void);
void lcdc(u8 ctrl);
void lcdd(u8 se, u8 _data);
void String(char *);
void lcdr(u8 x,u8 y,u8 *string);
void delay(u32 d1, u32 d2);
void RTC_Config(void);
void timeset(s32 t){
RTC_Config();
RTC_WaitForLastTask();
RTC_SetCounter(t);
RTC_WaitForLastTask();
}
void fill_screen(char c){ //화면전체 체움
u8 i,j;
for(j=0;j<8;j++) {
//set page
lcdc(0xb8+j);
for(i=0;i<64;i++){
//set y addr.
lcdc(0x40+i);
lcdd(1,c); //left lcd
}
}
for(j=0;j<8;j++) {
//set page
lcdc(0xb8+j);
for(i=0;i<64;i++){
//set y addr.
lcdc(0x40+i);
lcdd(2,c); //right lcd
}
}
}
void fill_byte_screen(u8 x, u8 y, u8 c) {//1byte 채움
u8 lcd;
if(y>=64) lcd=2;
else lcd=1;
y = y % 64;
//set page
lcdc(0xb8+x);
//set y addr.
lcdc(0x40+y);
lcdd(lcd,c); //left or right
}
void fill_eng(u8 x, u8 y, char c) { //1글자 채움
u8 i;
for(i=0;i<5;i++) {
fill_byte_screen(x, y+i, font5x7[(c-' ')*5+i]);
}
}
void fill_eng_inv(u8 x, u8 y, char c) { //1글자 역상으로 채움
u8 i;
for(i=0;i<5;i++) {
fill_byte_screen(x, y+i, ~font5x7[(c-' ')*5+i]);
}
}
void fill_dd(u8 x, u8 y) { //요일출력
u8 i;
for(i=0;i<112;i++) {
fill_byte_screen(x, y+i, ~(TextFontTbl[i]));
fill_byte_screen(x+1, y+i, ~(TextFontTbl[112+i]));
}
}
void makecal(u16 year, u8 month, u8 day, u8 yoilstart, u8 dayend)
{
char temp[3],px,py;
fill_dd(0,8); //요일출력
px=2; py=10;
for(u8 i=0;i<yoilstart;i++) { //공백으로 채우기.
fill_eng(px,py,' ');
fill_eng(px,py+5,' ');
py += 16;
}
px=2; py=10+yoilstart*16;
for(u8 j=1;j<=37;j++){
sprintf(temp,"%2d",j);
if(j>dayend) {//공백채우기
fill_eng(px,py,' ');
fill_eng(px,py+5,' ');
}
else if(j==day) {//역상으로 채우기
fill_eng_inv(px,py,temp[0]);
fill_eng_inv(px,py+5,temp[1]);
}
else { //정상적으로 숫자 채우기..
fill_eng(px,py,temp[0]);
fill_eng(px,py+5,temp[1]);
}
py += 16;
if((j+yoilstart)%7==0) {
px++;
py=10;
}
if(px==7 && py==(10+16+16+16)) break;
}
}
int main(void){
GPIO_InitTypeDef GPIO;
char temp[10];
u8 m2[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
u8 upkey,downkey,leftkey,rightkey,setkey;
u8 pupkey,pdownkey,pleftkey,prightkey,psetkey;
u32 loop,tmp;
u8 blink=0;
u8 h,m,s,mm,dd; //초기값
u8 wd1,dispmm,wd2;
u16 yy,dispyy;
u32 timevar;
//char temp[16];
enum {normal, setyear, setmonth, setday, sethour, setmin, setsec, caldisp} mode=normal;
struct tm *now;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|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_7|GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13;
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);
LCD_CTRL &= ~(GPIO_Pin_7|GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13);
LCD_DATA &= ~(0xff);
delay(30,100);
lcdg(); //초기화
while(1){
//px=7; py=80;
//시계
loop++;
if(loop>0){
loop=0;
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;
m2[2]=28; //초기화 필요.
if(yy % 4 == 0) m2[2]=29;
if(yy % 100 == 0) m2[2]=28;
if(yy % 400 == 0) m2[2]=29;
tmp = 0;
tmp += (yy-1); //전년도까지 년수
tmp += ((yy-1)/4);
tmp -= ((yy-1)/100);
tmp += ((yy-1)/400);
for(u8 i=0;i<mm;i++) tmp += m2[i]; //전월까지 일수
wd1 = (tmp+1) % 7; //1일자 요일
setkey = READ_SET;
upkey = READ_UP;
downkey = READ_DOWN;
leftkey = READ_LEFT;
rightkey = READ_RIGHT;
switch(mode) {
case normal: //현재실시간모드
if((upkey != pupkey) && upkey){
dispyy = yy+1;
dispmm = mm;
mode=caldisp;
}
if((downkey != pdownkey) && downkey){
dispyy = yy-1;
dispmm = mm;
mode=caldisp;
}
if((leftkey != pleftkey) && leftkey){
dispmm = mm-1;
dispyy = yy;
mode=caldisp;
}
if((rightkey != prightkey) && rightkey){
dispmm = mm+1;
dispyy = yy;
mode=caldisp;
}
if((setkey != psetkey) && setkey){
mode = setyear;
}
makecal(yy,mm,dd,wd1,m2[mm]);
sprintf(temp,"%4d",yy);
fill_eng(7,40,temp[0]);
fill_eng(7,45,temp[1]);
fill_eng(7,50,temp[2]);
fill_eng(7,55,temp[3]);
fill_eng(7,60,'/');
sprintf(temp,"%2d",mm);
fill_eng(7,65,temp[0]);
fill_eng(7,70,temp[1]);
sprintf(temp,"%2d:%02d:%02d",h,m,s);
for(u8 i=0;i<8;i++) fill_eng(7,78+5*i,temp[i]);
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;
}
makecal(yy,mm,dd,wd1,m2[mm]);
sprintf(temp,"%4d",yy);
if(blink) {
fill_eng_inv(7,40,temp[0]);
fill_eng_inv(7,45,temp[1]);
fill_eng_inv(7,50,temp[2]);
fill_eng_inv(7,55,temp[3]);
}
else {
fill_eng(7,40,temp[0]);
fill_eng(7,45,temp[1]);
fill_eng(7,50,temp[2]);
fill_eng(7,55,temp[3]);
}
fill_eng(7,60,'/');
sprintf(temp,"%2d",mm);
fill_eng(7,65,temp[0]);
fill_eng(7,70,temp[1]);
sprintf(temp,"%2d:%02d:%02d",h,m,s);
for(u8 i=0;i<8;i++) fill_eng(7,78+5*i,temp[i]);
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;
}
makecal(yy,mm,dd,wd1,m2[mm]);
sprintf(temp,"%4d",yy);
fill_eng(7,40,temp[0]);
fill_eng(7,45,temp[1]);
fill_eng(7,50,temp[2]);
fill_eng(7,55,temp[3]);
fill_eng(7,60,'/');
sprintf(temp,"%2d",mm);
if(blink){
fill_eng_inv(7,65,temp[0]);
fill_eng_inv(7,70,temp[1]);
}
else{
fill_eng(7,65,temp[0]);
fill_eng(7,70,temp[1]);
}
sprintf(temp,"%2d:%02d:%02d",h,m,s);
for(u8 i=0;i<8;i++) fill_eng(7,78+5*i,temp[i]);
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;
}
makecal(yy,mm,dd,wd1,m2[mm]);
sprintf(temp,"%4d",yy);
fill_eng(7,40,temp[0]);
fill_eng(7,45,temp[1]);
fill_eng(7,50,temp[2]);
fill_eng(7,55,temp[3]);
fill_eng(7,60,'/');
sprintf(temp,"%2d",mm);
fill_eng(7,65,temp[0]);
fill_eng(7,70,temp[1]);
sprintf(temp,"%2d:%02d:%02d",h,m,s);
for(u8 i=0;i<8;i++) fill_eng(7,78+5*i,temp[i]);
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;
}
if(blink==0) sprintf(temp,"%02d: : ",h);
else sprintf(temp,"%2d:%02d:%02d",h,m,s);
for(u8 i=0;i<8;i++) fill_eng(7,78+5*i,temp[i]);
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;
}
if(blink==0) sprintf(temp," :%02d: ",m);
else sprintf(temp,"%2d:%02d:%02d",h,m,s);
for(u8 i=0;i<8;i++) fill_eng(7,78+5*i,temp[i]);
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;
}
if(blink==0) sprintf(temp," : :%02d",s);
else sprintf(temp,"%2d:%02d:%02d",h,m,s);
for(u8 i=0;i<8;i++) fill_eng(7,78+5*i,temp[i]);
break;
case caldisp:
if((upkey != pupkey) && upkey){
dispyy++;
}
if((downkey != pdownkey) && downkey){
dispyy--;
}
if((leftkey != pleftkey) && leftkey){
dispmm--;
if(dispmm==0) {
dispmm=12;
dispyy--;
}
}
if((rightkey != prightkey) && rightkey){
dispmm++;
if(dispmm==13) {
dispmm=1;
dispyy++;
}
}
if((setkey != psetkey) && setkey){
mode = normal;
}
m2[2]=28; //초기화 필요.
if(dispyy % 4 == 0) m2[2]=29;
if(dispyy % 100 == 0) m2[2]=28;
if(dispyy % 400 == 0) m2[2]=29;
tmp = 0;
tmp += (dispyy-1); //전년도까지 년수
tmp += ((dispyy-1)/4);
tmp -= ((dispyy-1)/100);
tmp += ((dispyy-1)/400);
for(u8 i=0;i<dispmm;i++) tmp += m2[i]; //전월까지 일수
for(u8 i=40;i<=70;i++) fill_eng(7,i,' ');
wd2 = (tmp+1) % 7; //1일자 요일
makecal(dispyy,dispmm,0,wd2,m2[dispmm]);
sprintf(temp,"%4d/%02d/",dispyy,dispmm);
for(u8 i=0;i<8;i++) fill_eng(7,78+5*i,temp[i]);
break;
}
pupkey = upkey;
pdownkey = downkey;
pleftkey = leftkey;
prightkey = rightkey;
psetkey = setkey;
}
}
void String(char *string){
while(*string != '\0'){
//lcdd(*string);
string++;
}
}
void lcdr(u8 x, u8 y, u8 *string){
u8 i,a,y_aes;
if(y<=7){
a=1;
y_aes=y*8;
}
else {
a=2;
y_aes=(y-8)*8;
}
lcdc(0xb8+x*2);
lcdc(0x40+y_aes);
for(i=0;i<=15;i++){
lcdd(a,*string);
string++;
}
lcdc(0xb8+x*2+1);
lcdc(0x40+y_aes);
for(i=0;i<=15;i++){
lcdd(a,*string);
string++;
}
}
void lcdg(void){
u8 i,j,x,y;
lcdc(0x3f);
lcdc(0xc0);
x=0xb8;
y=0x40;
for(i=0;i<8;i++){
lcdc(x);
lcdc(y);
for(j=0;j<64;j++) lcdd(0,0);
x++;
}
}
void lcdc(u8 ctrl){
LCD_CTRL |= LCD_E;
delay(10,1);
LCD_DATA &= ~0xff;
LCD_DATA |= ctrl;
delay(10,1);
LCD_CTRL &= ~(GPIO_Pin_7|GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13);
delay(100,10);
}
void lcdd(u8 se, u8 _data){
switch(se){
case 0:
LCD_CTRL |= LCD_E|LCD_RS;
LCD_CTRL &= ~(LCD_CS2|LCD_CS1);
delay(10,1);
LCD_DATA &= ~0xff;
LCD_DATA |= _data;
delay(10,1);
LCD_CTRL &= ~(GPIO_Pin_7|GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13);
break;
case 1:
LCD_CTRL |= LCD_E|LCD_RS|LCD_CS2;
LCD_CTRL &= ~(LCD_CS1);
delay(10,1);
LCD_DATA &= ~0xff;
LCD_DATA |= _data;
delay(10,1);
LCD_CTRL &= ~(GPIO_Pin_7|GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13);
break;
case 2:
LCD_CTRL |= LCD_E|LCD_RS|LCD_CS1;
LCD_CTRL &= ~(LCD_CS2);
delay(10,1);
LCD_DATA &= ~0xff;
LCD_DATA |= _data;
delay(10,1);
LCD_CTRL &= ~(GPIO_Pin_7|GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13);
break;
}
delay(100,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)' 카테고리의 다른 글
[STM3210B] MFND-100 7-SEGMENT MODULE 구동 (0) | 2011.09.30 |
---|---|
삼광도트매트릭스 기본 프로그램 (0) | 2011.08.24 |
[STM3210B]RTC를 이용하여 TEXT LCD에 날짜가 표시되는 시계 (0) | 2011.06.30 |
[STM3210B]TEXT LCD Module MLCD-100 기본 구동 프로그램 (0) | 2011.06.28 |
myCortex(LM3S8962)에서 광전자도트매트릭스 테스트 프로그램 (0) | 2011.05.13 |