여섯개의 FND와 8개의 LED 그룹1과 또다른 5개의 LED 그룹에 d0~d7로 버스방식으로 다 연결되어 잇습니다. 따라서 fnd와 LED 출력인
SEGM = 값을 쓰면 fnd나 led그룹들로 값이 나갑니다. 그 전에 몇번째 fnd와 몇번째 LED 그룹에다 값을 쓸 것인지를 지정해줘야 되겠죠. 그것이 바로 DIGM 주소입니다. fnd와 led가 다 common anode로 연결 되어 있어 common을 잡아 주는 IC의 맵핑 주소가 DIGM 입니다.
따라서, 예를 들면 DIGM = 0X01; 첫번째 fnd선택 SEGM = 값; 하면 첫번째 fnd로만 시그널이 나갑니다. 나머지는 빠르게 DIGM을 업카운트 시키면 되겠죠.
여기서, 중요한 사실은
DIGM = 0 DIGM = 1 DIGM = 2 FND 3개
DIGM = 3 LED 첫번째 그룹(LED 8개)
DIGM = 4 DIGM = 5 DIGM = 6 나머지 FND 3개
DIGM = 7 LED 두번째 그룹(LED 5개)로 회로적으로 맵핑되어 있다는 것입니다.
그리고, 스위치 입력은 그냥 KEYM (*(volatile unsigned char *)0x9000 이주소로
key = KEYM 으로 받으면 됩니다.
따라서 ,여기서 요구되는 것은 fnd와 led를 계속 업데이트 시켜 주면서 sw 스캔을 하여 특정 입력시 특정 led그룹의 특정 led를 제어해야 한다는 사실입니다.
----------------------------------------------------------------------------------------------- 위에 근거한 제가 첨부한 코드 설명 ---------------------------------------------------------------------------------------------- void Disp_operation(void) {
if(Disp_timer>0) return; Disp_timer =2;
if(++icounter ==8) icounter=0; DIGM = 1<<icounter; //이부분이 바로 fnd와 led를 빠르게 순차적으로 선택해주는 것입니다. 값을 쓰기전에 선택하 는 것이죠. 0x01=1st fnd선택, 0x02=2nd fnd 선택...등. if(icounter == 3){ //위에서 언급했다 시피 DIGM = 0x08 이면 1st LED 그룹(8개)를 선택합니다. if(blink_flag ==0 && blink_flag < 9) return; //blink_flag 는 아래 LED 함수에서 설명 드리겠습니다. else { SEGM = Led_one; } // Led_one은 volatile unsigned char로 선언되어 있으며, 바로 첫번째 LED 그룹의 변수입니다. 여기서 출력을 내보냅니다. } ////////////////////////////// else if(icounter == 7){ //바로 마지막 LED그룹을 선택하는 것입니다. if(blink_flag >8) return; //blink_flag를 왜 이렇게 비교하는지는 밑에 led 함수에서 설명.. else { SEGM = Led_two; } //위와 마찬가지로 두번째 그룹의 led값을 출력합니다. }
//////////////////////////////// else{SEGM =fnd_data[icounter];} //그리고 3 과 7이 아닌 나머지들은 바로 fnd들인 것입니다. 여기서 fnd_data[ ]는 밑의 fnd 함수를 보시면 아 실 수 있으십니다. }
void Disp_suboperation(void) {
if(LED_timer>0) return; LED_timer =2;
//////////////////////////// if(icounter == 3){ DIGM = 1<<icounter; // 첫번째 led 그룹으로 출력을 내보내려고 선택했습니다. if(blink_flag >0 && blink_flag < 9){ //blink_flag 비교값이 왜 이런지, 뭔지는 led 함수에서....
LED_timer = 800; //첫번째 LED 그룹, 8개의 LED들 중 특정 LED의 깜빡 주기. 250us * 800 if(LEDST[blink_flag-1]==1){ //LEDST는 volatile unsigned char LEDST[13]; 이라고 선언되어 있습니다. LEDST[0] = 첫번재 led 그룹의 첫번재led 의 상태값, LEDST[12] = 두번재 LED 그룹의 LED 마지막 LED의 상태값 여기서는 1 이면 OFF입니다. Led_one = Led_one & ~(1<<(blink_flag-1));// 따라서 이렇게 하면 0으로 마스킹하여 ON 시킵니다. SEGM = Led_one;} // 그리고 출력. else if(LEDST[blink_flag-1]==0) { // 이제는 위와 반대겠죠. Led_one = Led_one | (1<<(blink_flag-1));//OFF SEGM = Led_one;} } else return; }
////////////////////////////// else if(icounter== 7){ //이제는 두번째 LED그룹(5개 LED)을 선택하는 것입니다. DIGM = 1<<icounter; if(blink_flag >8){ //왜 이값을 비교하는지는 밑의 LED 함수에서..
LED_timer = 800; //이제부터는 icounter==3 의 위와 유사합니다. if(LEDST[blink_flag-1]==1){ //LED OFF 상태입니다. Led_two = Led_two & ~(1<<(blink_flag-9));//ON SEGM = Led_two;} else if(LEDST[blink_flag-1]==0) { //LED ON 상태입니다. Led_two = Led_two | (1<<(blink_flag-9));//OFF SEGM = Led_two;} //마지막 LED 그룹으로 출력. } else return; }
//////////////////////////////// }
//FND WRITE 함수입니다.메인에서 호출하여 배열에 값을 넣어 두게 합니다. //numb 는 fnd 넘버입니다. 0,1,2,4,5,6. 입니다, 여기서 3,7은 led이므로 여기서 입력자체를 안합니다. //datafnd는 값입니다. 이미 상수 배열로 다 선언해놓았기 때문에, 여기는 걍 0~9만 쓰면 됩니다. //그리고 마지막으로 dotp 는 dot 유무입니다. void FndDisp(unsigned char numb,unsigned char datafnd, unsigned char dotp){ if(dotp == 1) {fnd_data[numb]=(0x7f & fnd_pattern[datafnd]);} //dot 넣을 거면 masking~~! 그리고 값 넣습니다. else {fnd_data[numb] = fnd_pattern[datafnd];} //아니면 그냥 값 넣습니다. }
//바로 메인에서 호출하여 led_one, led_two에 값을 써 두는 함수입니다. //Lnum은 LED 넘버입니다. LED가 총 13개이므로 0~12로 정의하여 입력받습니다. //Ldata 는 일종의 모드입니다. 0이면 off, 1이면 on, 2이면 블링크입니다. void LedDisp(unsigned char Lnum, unsigned char Ldata){ switch(Ldata) { case 0: //off LEDST[Lnum] =1;//LED[13] 이라고 선언된 배열에 상태를 입력 if(Lnum <8) { //만약 LED가 첫번재 그룹이라면 0~7. Led_one = (Led_one | (1<<Lnum)); }// 바로 led_one에 값을 masking 하여 off 시킵니다. else { Led_two = (Led_two | (1<<(Lnum-8))); } //아니면 8을 빼주면 되겠쬬. 가령, Lnum=8 이면 두번째 그룹의 첫번째 LED입니다. 그럼, DIGM = 7 일때, SEGM = 0000 0001 의 '1' 이죠. 그렇기 때문에, (Lnum-8) == 0 이 되면 되는 것입니다. 그래서 8을 뺍니다. blink_flag =0; //그리고 블링크 모드 플래그는 리셋시킵니다. break;
case 1://on LEDST[Lnum] =0; // ON 입니다. 여기서는 ON 을 '0'으로 간주합니다. if(Lnum <8) { //마스킹만 틀리지 위와 똑같습니다. Led_one = (Led_one & ~(1<<Lnum)); }//set else { Led_two = (Led_two & ~(1<<(Lnum-8))); } blink_flag =0; break;
case 2://blink //바로 여기입니다, blink 모드를 입력하면, blink_flag 에 LED 넘버(Lnum) +1 을 넣어 둡니다. 왜냐하면 led가 첫번째 led이면 Lnum =0이기 때문에 1을 더해 주어야 합니다. blink_flag == 0 은 reset 에 사용하기 때문입니다.
따라서 위에서 본 if(blink_flag >0 && blink_flag < 9) 는 첫번째 LED 그룹의 8개의 LED들을 가리키는 것입니다. 그리고, LEDST[blink_flag-1]==0 에서 1을 다시 빼는 이유도 다 여기 때문입니다.
blink_flag = Lnum +1; break; } }
main() { led_one = 0x00; //all 출력 on led_two = 0x00; //all 출력 on
FndDisp(0,2,0); //초기에 6개의 fnd와 13개 led에 값을 줍니다. FndDisp(1,2,0); FndDisp(2,3,0); FndDisp(4,4,0); FndDisp(5,5,0); FndDisp(6,7,0); LedDisp(0,1); LedDisp(1,1); LedDisp(2,1); LedDisp(3,2); LedDisp(4,1); LedDisp(5,1); LedDisp(6,1); LedDisp(7,1); LedDisp(8,1); LedDisp(9,1); LedDisp(10,1); LedDisp(11,1); LedDisp(12,2);
먼저 답변을 드려야죠.^^' 타이머들은 다 unsigned int로 했씁니다. 그리고, 위에 제가 첨부한 코드들로 했을 때
fnd 6개는 다 잘들어옵니다. led들이 문제이죠.
회로와 로직에 대해설 설명을 드리고, 코딩에 대해서 주석을 달아 드리겠습니다.
먼저 회로를 여기에 다 올려서 설명하기 그렇고..
일단 외부 io 제어 방식을 사용합니다. 그리고, 회로적으로 아래와 같은 주소에
값을 쓰면, 입출력이 됩니다.
#define SEGM (*(volatile unsigned char *)0x8000)//WR0
#define DIGM (*(volatile unsigned char *)0x8200)//WR1
#define KEYM (*(volatile unsigned char *)0x9000)//RD0
여섯개의 FND와 8개의 LED 그룹1과 또다른 5개의 LED 그룹에 d0~d7로 버스방식으로 다 연결되어 잇습니다.
따라서 fnd와 LED 출력인
SEGM = 값을 쓰면 fnd나 led그룹들로 값이 나갑니다. 그 전에 몇번째 fnd와 몇번째 LED 그룹에다 값을 쓸 것인지를
지정해줘야 되겠죠. 그것이 바로 DIGM 주소입니다. fnd와 led가 다 common anode로 연결 되어 있어 common을 잡아
주는 IC의 맵핑 주소가 DIGM 입니다.
따라서, 예를 들면 DIGM = 0X01; 첫번째 fnd선택 SEGM = 값; 하면 첫번째 fnd로만 시그널이 나갑니다.
나머지는 빠르게 DIGM을 업카운트 시키면 되겠죠.
여기서, 중요한 사실은
DIGM = 0
DIGM = 1
DIGM = 2 FND 3개
DIGM = 3 LED 첫번째 그룹(LED 8개)
DIGM = 4
DIGM = 5
DIGM = 6 나머지 FND 3개
DIGM = 7 LED 두번째 그룹(LED 5개)로 회로적으로 맵핑되어 있다는 것입니다.
그리고, 스위치 입력은 그냥 KEYM (*(volatile unsigned char *)0x9000 이주소로
key = KEYM 으로 받으면 됩니다.
따라서 ,여기서 요구되는 것은 fnd와 led를 계속 업데이트 시켜 주면서 sw 스캔을 하여 특정 입력시
특정 led그룹의 특정 led를 제어해야 한다는 사실입니다.
-----------------------------------------------------------------------------------------------
위에 근거한 제가 첨부한 코드 설명
----------------------------------------------------------------------------------------------
void Disp_operation(void) {
if(Disp_timer>0) return;
Disp_timer =2;
if(++icounter ==8) icounter=0;
DIGM = 1<<icounter; //이부분이 바로 fnd와 led를 빠르게 순차적으로 선택해주는 것입니다. 값을 쓰기전에 선택하
는 것이죠. 0x01=1st fnd선택, 0x02=2nd fnd 선택...등.
if(icounter == 3){ //위에서 언급했다 시피 DIGM = 0x08 이면 1st LED 그룹(8개)를 선택합니다.
if(blink_flag ==0 && blink_flag < 9) return; //blink_flag 는 아래 LED 함수에서 설명 드리겠습니다.
else {
SEGM = Led_one; } // Led_one은 volatile unsigned char로 선언되어 있으며, 바로 첫번째 LED 그룹의 변수입니다.
여기서 출력을 내보냅니다.
}
//////////////////////////////
else if(icounter == 7){ //바로 마지막 LED그룹을 선택하는 것입니다.
if(blink_flag >8) return; //blink_flag를 왜 이렇게 비교하는지는 밑에 led 함수에서 설명..
else {
SEGM = Led_two; } //위와 마찬가지로 두번째 그룹의 led값을 출력합니다.
}
////////////////////////////////
else{SEGM =fnd_data[icounter];} //그리고 3 과 7이 아닌 나머지들은 바로 fnd들인 것입니다.
여기서 fnd_data[ ]는 밑의 fnd 함수를 보시면 아 실 수 있으십니다.
}
void Disp_suboperation(void) {
if(LED_timer>0) return;
LED_timer =2;
////////////////////////////
if(icounter == 3){
DIGM = 1<<icounter; // 첫번째 led 그룹으로 출력을 내보내려고 선택했습니다.
if(blink_flag >0 && blink_flag < 9){ //blink_flag 비교값이 왜 이런지, 뭔지는 led 함수에서....
LED_timer = 800; //첫번째 LED 그룹, 8개의 LED들 중 특정 LED의 깜빡 주기. 250us * 800
if(LEDST[blink_flag-1]==1){ //LEDST는 volatile unsigned char LEDST[13]; 이라고 선언되어 있습니다.
LEDST[0] = 첫번재 led 그룹의 첫번재led 의 상태값, LEDST[12] = 두번재 LED 그룹의 LED
마지막 LED의 상태값 여기서는 1 이면 OFF입니다.
Led_one = Led_one & ~(1<<(blink_flag-1));// 따라서 이렇게 하면 0으로 마스킹하여 ON 시킵니다.
SEGM = Led_one;} // 그리고 출력.
else if(LEDST[blink_flag-1]==0) { // 이제는 위와 반대겠죠.
Led_one = Led_one | (1<<(blink_flag-1));//OFF
SEGM = Led_one;}
}
else return;
}
//////////////////////////////
else if(icounter== 7){ //이제는 두번째 LED그룹(5개 LED)을 선택하는 것입니다.
DIGM = 1<<icounter;
if(blink_flag >8){ //왜 이값을 비교하는지는 밑의 LED 함수에서..
LED_timer = 800; //이제부터는 icounter==3 의 위와 유사합니다.
if(LEDST[blink_flag-1]==1){ //LED OFF 상태입니다.
Led_two = Led_two & ~(1<<(blink_flag-9));//ON
SEGM = Led_two;}
else if(LEDST[blink_flag-1]==0) { //LED ON 상태입니다.
Led_two = Led_two | (1<<(blink_flag-9));//OFF
SEGM = Led_two;} //마지막 LED 그룹으로 출력.
}
else return;
}
////////////////////////////////
}
//FND WRITE 함수입니다.메인에서 호출하여 배열에 값을 넣어 두게 합니다.
//numb 는 fnd 넘버입니다. 0,1,2,4,5,6. 입니다, 여기서 3,7은 led이므로 여기서 입력자체를 안합니다.
//datafnd는 값입니다. 이미 상수 배열로 다 선언해놓았기 때문에, 여기는 걍 0~9만 쓰면 됩니다.
//그리고 마지막으로 dotp 는 dot 유무입니다.
void FndDisp(unsigned char numb,unsigned char datafnd, unsigned char dotp){
if(dotp == 1) {fnd_data[numb]=(0x7f & fnd_pattern[datafnd]);} //dot 넣을 거면 masking~~! 그리고 값 넣습니다.
else {fnd_data[numb] = fnd_pattern[datafnd];} //아니면 그냥 값 넣습니다.
}
//바로 메인에서 호출하여 led_one, led_two에 값을 써 두는 함수입니다.
//Lnum은 LED 넘버입니다. LED가 총 13개이므로 0~12로 정의하여 입력받습니다.
//Ldata 는 일종의 모드입니다. 0이면 off, 1이면 on, 2이면 블링크입니다.
void LedDisp(unsigned char Lnum, unsigned char Ldata){
switch(Ldata) {
case 0: //off
LEDST[Lnum] =1;//LED[13] 이라고 선언된 배열에 상태를 입력
if(Lnum <8) { //만약 LED가 첫번재 그룹이라면 0~7.
Led_one = (Led_one | (1<<Lnum)); }// 바로 led_one에 값을 masking 하여 off 시킵니다.
else {
Led_two = (Led_two | (1<<(Lnum-8))); } //아니면 8을 빼주면 되겠쬬. 가령, Lnum=8 이면 두번째 그룹의 첫번째
LED입니다. 그럼, DIGM = 7 일때, SEGM = 0000 0001 의 '1' 이죠.
그렇기 때문에, (Lnum-8) == 0 이 되면 되는 것입니다. 그래서 8을 뺍니다.
blink_flag =0; //그리고 블링크 모드 플래그는 리셋시킵니다.
break;
case 1://on
LEDST[Lnum] =0; // ON 입니다. 여기서는 ON 을 '0'으로 간주합니다.
if(Lnum <8) { //마스킹만 틀리지 위와 똑같습니다.
Led_one = (Led_one & ~(1<<Lnum)); }//set
else {
Led_two = (Led_two & ~(1<<(Lnum-8))); }
blink_flag =0;
break;
case 2://blink //바로 여기입니다, blink 모드를 입력하면, blink_flag 에 LED 넘버(Lnum) +1 을 넣어
둡니다. 왜냐하면 led가 첫번째 led이면 Lnum =0이기 때문에 1을 더해 주어야 합니다.
blink_flag == 0 은 reset 에 사용하기 때문입니다.
따라서 위에서 본 if(blink_flag >0 && blink_flag < 9) 는 첫번째 LED 그룹의 8개의 LED들을
가리키는 것입니다. 그리고, LEDST[blink_flag-1]==0 에서 1을 다시 빼는 이유도 다 여기
때문입니다.
blink_flag = Lnum +1;
break;
}
}
main() {
led_one = 0x00; //all 출력 on
led_two = 0x00; //all 출력 on
FndDisp(0,2,0); //초기에 6개의 fnd와 13개 led에 값을 줍니다.
FndDisp(1,2,0);
FndDisp(2,3,0);
FndDisp(4,4,0);
FndDisp(5,5,0);
FndDisp(6,7,0);
LedDisp(0,1);
LedDisp(1,1);
LedDisp(2,1);
LedDisp(3,2);
LedDisp(4,1);
LedDisp(5,1);
LedDisp(6,1);
LedDisp(7,1);
LedDisp(8,1);
LedDisp(9,1);
LedDisp(10,1);
LedDisp(11,1);
LedDisp(12,2);
while(1) {
Disp_operation();
Disp_suboperation();
SW_operation();
if(SwInput()==4)LedDisp(12,2); //스위치 입력값이 4이면, 12번째 led만 깜빡 깜빡해라.. fnd,
스위치 입력값은 정상으로 들어오는데..--
}
}
정말 힘들었습니다. 꼭 좋은 답변 부탁 드립니다.