메뉴 바로가기

서브메뉴 바로가기

본문 바로가기

logo

묻고 답하기
러빙유2008.01.10 14:15

먼저 답변을 드려야죠.^^'  타이머들은 다 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,
스위치 입력값은 정상으로 들어오는데..--

 }
}



정말 힘들었습니다. 꼭 좋은  답변 부탁 드립니다.

사진 및 파일 첨부

여기에 파일을 끌어 놓거나 왼쪽의 버튼을 클릭하세요.

파일 용량 제한 : 0MB (허용 확장자 : *.*)

0개 첨부 됨 ( / )