마지막 프로젝트로 7segment를 이용한 간단한 전자시계를 만들었다.
사용된 기능은 GPIO, Timer interrupt, Switch interrupt, ADC 기능이다.
먼저 7segment 핀 이용을 위한 정의이다.
#define DIG1 1
#define DIG2 2
#define DIG3 6
#define DIG4 8
#define SEG1 14
#define SEG2 4
#define SEG3 13
#define SEG4 3
#define SEG5 5
#define SEG6 11
#define SEG7 10
#define SEG8 7 //dot
#define DOT 17
#define PTC12 12
#define PTC13 13
#define PTD15 15
#define PTD16 16
#define PTD0 0
volatile int timer = 0;
volatile int setmode = 0;
int digpin[4] = {DIG1,DIG2,DIG3,DIG4};
int segpin[8] = {SEG1,SEG2,SEG3,SEG4,SEG5,SEG6,SEG7,SEG8};
가장 기본적인 port초기화에 대한 내용이다.
사용하고자 하는 pin들을 모두 GPIO설정 해주었다.
void PORT_init(void){
PCC -> PCCn[PCC_PORTC_INDEX] = PCC_PCCn_CGC_MASK;
PORTC ->PCR[12] = PORT_PCR_MUX(1);
PTC ->PDDR &= ~(1<<PTC12);
PORTC->PCR[12] |= (9<<16);
PCC->PCCn[PCC_PORTD_INDEX] |=PCC_PCCn_CGC_MASK;
for(int i=0;i<4;i++){
PORTD->PCR[digpin[i]] &= ~PORT_PCR_MUX_MASK;
PORTD->PCR[digpin[i]]|= PORT_PCR_MUX(1);
PTD->PDDR |= 1<<digpin[i];
}
for(int i=0;i<8;i++){
PORTD->PCR[segpin[i]] &= ~PORT_PCR_MUX_MASK;
PORTD->PCR[segpin[i]]|= PORT_PCR_MUX(1);
PTD->PDDR |= 1<<segpin[i];
}
PORTD->PCR[17] &= ~PORT_PCR_MUX_MASK;
PORTD->PCR[17]|= PORT_PCR_MUX(1);
PTD->PDDR |= 1<<DOT;
PORTD->PCR[0] &= ~PORT_PCR_MUX_MASK;
PORTD->PCR[0] |= PORT_PCR_MUX(1);
PTD->PDDR |= 1<<PTD0; /////Blue
}
setTime 함수는 앞으로 타이머 인터럽트가 들어올때마다 계속해서 호출될것이다.
7segment의 원리상 4개의 digit을 가지고있고, 이를 모두 동시에 켤순는 없다.
자리수마다 한개씩 매우 빠르게 번갈아 숫자를 갱신하는 원리이므로, setTime은 그때마다 호출되게된다.
void setTime(int dig_num, int n){
for(int i=0;i<8;i++){
PTD->PSOR |= 1<<segpin[i]; //pin clear
}
PTD-> PSOR |= 1<<digpin[dig_num];
switch(n){
case 0:
PTD->PCOR |= 1<<SEG1;
PTD->PCOR |= 1<<SEG2;
PTD->PCOR |= 1<<SEG3;
PTD->PCOR |= 1<<SEG4;
PTD->PCOR |= 1<<SEG5;
PTD->PCOR |= 1<<SEG6;
break;
case 1:
PTD->PCOR |= 1<<SEG2;
PTD->PCOR |= 1<<SEG3;
break;
case 2:
PTD->PCOR |= 1<<SEG1;
PTD->PCOR |= 1<<SEG2;
PTD->PCOR |= 1<<SEG4;
PTD->PCOR |= 1<<SEG5;
PTD->PCOR |= 1<<SEG7;
break;
case 3:
PTD->PCOR |= 1<<SEG1;
PTD->PCOR |= 1<<SEG2;
PTD->PCOR |= 1<<SEG3;
PTD->PCOR |= 1<<SEG4;
PTD->PCOR |= 1<<SEG7;
break;
case 4:
PTD->PCOR |= 1<<SEG2;
PTD->PCOR |= 1<<SEG3;
PTD->PCOR |= 1<<SEG6;
PTD->PCOR |= 1<<SEG7;
break;
case 5:
PTD->PCOR |= 1<<SEG1;
PTD->PCOR |= 1<<SEG3;
PTD->PCOR |= 1<<SEG4;
PTD->PCOR |= 1<<SEG6;
PTD->PCOR |= 1<<SEG7;
break;
case 6:
PTD->PCOR |= 1<<SEG1;
PTD->PCOR |= 1<<SEG3;
PTD->PCOR |= 1<<SEG4;
PTD->PCOR |= 1<<SEG5;
PTD->PCOR |= 1<<SEG6;
PTD->PCOR |= 1<<SEG7;
break;
case 7:
PTD->PCOR |= 1<<SEG1;
PTD->PCOR |= 1<<SEG2;
PTD->PCOR |= 1<<SEG3;
PTD->PCOR |= 1<<SEG6;
break;
case 8:
PTD->PCOR |= 1<<SEG1;
PTD->PCOR |= 1<<SEG2;
PTD->PCOR |= 1<<SEG3;
PTD->PCOR |= 1<<SEG4;
PTD->PCOR |= 1<<SEG5;
PTD->PCOR |= 1<<SEG6;
PTD->PCOR |= 1<<SEG7;
break;
case 9:
PTD->PCOR |= 1<<SEG1;
PTD->PCOR |= 1<<SEG2;
PTD->PCOR |= 1<<SEG3;
PTD->PCOR |= 1<<SEG4;
PTD->PCOR |= 1<<SEG6;
PTD->PCOR |= 1<<SEG7;
break;
}
PTD-> PCOR |= 1<<digpin[dig_num];
}
main에서는 기본적으로 무한루프내에서 시간의 최대, 즉 24:00을 넘어가게 되면 0으로 초기화되게 된다.
초로 환산하면 86400초이다.
또한 ADC기능을 추가한부분, timer가 홀수와 짝수일때로 나누어 시계의 : 부분이 깜빡이도록 하는 부분까지 확인할 수 있다.
int main(void){
PORT_init();
SOSC_init_8MHz();
SPLL_init_160MHz();
NormalRUNmode_80MHz();
NVIC_init_IRQs();
ADC_init();
LPIT0_init();
int hour, min, sec, adc_num;
for(int i=0;i<8;i++){
PTD->PSOR |= 1<<segpin[i]; //pin clear
}
for(;;){
convertAdcChan(12);
if(setmode){
while(adc_complete()==0){}
timer = read_adc_chx()*(17.28);
}
if(timer == 86400)
timer = 0;
if(((timer >=0) && (timer <5) )|| ((timer >= 43200) && (timer < 43205)))
PTD-> PCOR |= 1<<PTD0;
else PTD-> PSOR |= 1<<PTD0;
if((timer % 2) == 0)
PTD->PCOR |= 1<<DOT;
else PTD->PSOR |= 1<<DOT;
hour = timer/3600;
min = (timer%3600)/60;
sec = ((timer%3600)%60)%60;
setTime(0,hour/10);
setTime(1,hour%10);
setTime(2,min/10);
setTime(3,min%10);
}
}
포스팅내 모든 소스코드는 아래사이트에서 확인할 수 있습니다.
github.com/MinkiJo/NXP-S32DesignStudio-Project/tree/main
'NXP&S32DesignStudio' 카테고리의 다른 글
PWM (0) | 2021.01.17 |
---|---|
ADC (0) | 2021.01.17 |
Timer Interrupt (0) | 2021.01.17 |
GPIO & Switch (0) | 2021.01.17 |