개발

jackryu 2011. 5. 31. 23:16

펌 - http://blog.paran.com/timy/7562418


그동안 강좌를 너무 오래 쉬었다. ^^

 

이번에는 그동안 했던 내용을 조금 정리해서 응용프로그램을 짜 보도록 한다.

우선 시리얼통신을 통해 PC화면에서 TY52쪽으로 명령을 줄수 있도록 프로그램을 짜본다. 이 내용은 쉽다. 화면엔 명령문구가 출력되도록 하고, 그때 입력받은 값에 따라 일정한 프로그램 코드를 실행시키도록 하면 된다.
한번 소스코드를 살펴보면서 응용해 보면 좋을 것이다. ^^

 

그리고, 이번에는 트랜지스터를 이용한 증폭회로를 하나 사용했다. 우선 집에 가지고 있는 것이 있어서 그것을 그냥 사용했다. ^^ 트랜지스터의 증폭작용에 관해서는 자세히는 몰라도 대충 증폭작용을 한다는 정도는 일반적으로 알려져 있다.

여기서는 8051 의 다리에서 흘러나오는 전류가 적기 때문에 소전력의 LED 를 켜고 끄기는 별 무리가 없지만 고휘도 LED 같은, 그래도 약간 더 전력을 소모하는 경우에는 8051 자체의 전류만으로는 무리가 따른다. 그래서 외부에 증폭회로를 두어야 하는데 여기서는 집에 가지고 있던 NPN 타입의 C3207을 사용하였다. LED 는 고휘도 LED를 사용하였고, LED와 직렬로 연결된 저항은 100오옴이다.


이미지를 클릭하시면 원본크기로 보실수 있습니다.

이미지를 클릭하시면 원본크기로 보실수 있습니다.
그림에서 보이듯이 4개의 LED를 사용한다. 회로는 작은 만능기판에 꾸며보았다.

 

원래 이 회로는 크리스마스때 사용하려고 사두었던 저가의 광섬유로 된 트리를 조금 더 구미에 맞게 개조하려고 꾸민것이다. 바빠서 크리스마스가 지나고서야 이제 꾸미게 되었다. ㅜ.ㅜ

어쨌건 이걸 잘 장식해서 새해맞이용 장식품으로 만들어봐야겠다..

 

이미지를 클릭하시면 원본크기로 보실수 있습니다.

이렇게 생긴 놈이다. 광섬유는 중국산같다. 얇고 가늘고, 빛투과율이 생각보다 작다. 하지만 싸니까...

이미지를 클릭하시면 원본크기로 보실수 있습니다.

광섬유 굵은 것을 옆부분을 깍아서 만들어져 있다. 

이미지를 클릭하시면 원본크기로 보실수 있습니다.

한컷 더...

이미지를 클릭하시면 원본크기로 보실수 있습니다.

회로 구성한 사진 - 카메라폰으로 찍다보니 흔들리고, 해상도가 많이 떨어졌습니다. 오른쪽 검정색과 빨간색은 전원선이고, 위쪽의 4개 선은 LED 로 들어오는 신호선입니다. 각각 P0.0, P0.2, P0.4, P0.6 으로 연결됩니다.

이미지를 클릭하시면 원본크기로 보실수 있습니다.

뒤쪽 배선한 모습...

이미지를 클릭하시면 원본크기로 보실수 있습니다.

고휘도 LED 라 빛이 상당히 강합니다. ^^

이미지를 클릭하시면 원본크기로 보실수 있습니다.

4개가 함께 빛을 내고 있습니다. 사진으로는 잘 모르겠지만, 빨강, 파랑, 녹색, 노랑의 4개 LED가 점멸하고 있습니다.

 

 

사용은 간단하다.
프로그램은 우선 타이머0를 이용해서 10ms 의 타이머를 만들고, 이것을 이용해서 LED의 깜박이는 시간을 조절한다. 보통은 의미없는 for(i=0;i<10000;i++); 이런 식으로 많이 사용하는데, 여기서는 타이머를 배웠으니까 타이머를 이용해서 한번 프로그램을 짜 보았다. 보통은 인터럽트를 남용할 필요는 없으니 위에서 말한 것처럼 for(i=0;i<10000;i++); 식으로 사용해도 좋다.

그다음 시리얼통신을 통해 미리 약속된 문구를 보여주고, 일정한 입력을 받으면 그에 맞는 코드를 실행하도록 하였다.

광섬유 트리의 아래부분에 4개의 LED가 빛을 내도록 붙여두고, 각각을 켜고 끄는 명령을 두었다. 그리고 Help 명령을 통해 각각의 입력값의 의미를 화면에 보여주게 하였고, C 명령은 무한루프를 돌며 빛을 내도록 해 두었다.


참고로 LED 의 불빛의 강도를 세고 약하게 하기 위해서 조금 특별한 방법을 썼다. 이 방법은 보통 모터를 제어할때 많이 사용하는 방법이다. PWM 이라고 불리는 방법이다.

아날로그 값을 8051 에서는 읽을 수 없다. 그래서 AD 컨버터라는 IC를 통해 아날로그 값을 디지털로 변환해서 8051 에서 값을 읽어오게 된다. 마찬가지로 아날로그 값을 출력할수도 없다. 8051 에서 나가는 값은 1이거나 0이어야 한다. 즉, +5V 거나 아니면 0V가 되어야 한다.

그래서 DA 컨버터라는 것도 있다. 하지만 DA 컨버터를 사용하는 대신 조금 특별한 방법으로 DA 기능을 쓰기도 한다. 여기서 쓰는 것처럼, 일정한 시간동안 on/Off 를 주기적으로 주는 것이다.

이를테면 다음과 같다.

[0000000001] -> 반복한다.

0000000001 0000000001 0000000001 ...

이렇게 되면 9라는 시간동안 0V가 되고, 1이라는 시간동안 5V가 된다. 여기서 10이라는 시간은 10초가 아니라 매우 짧은 시간이어야 한다. 이것을 모터에 적용하면 DC 모터에 9동안은 전류가 흐르지 않고, 1동안만 전류를 흐르게 한다. 그러면 결과적으로 모터에는 아주 작은 전류가 흐르는 것처럼 약하게 구동하게 된다.

마찬가지로 LED에도 이것을 적용해 보았다. ^^

9동안 전류를 주지 않고, 1동안만 전류를 흐르게 했다. 물론 여기서 9와 1이 시간이 충분히 길면... 깜박이는 것이 눈에 보이게 된다. 하지만 TV 화면을 생각해 보자. 1초에 29.7번 깜박이는 화면을 보면서도 사람의 눈에는 깜박이는 것으로 보이지 않고,오히려 움직이는 것으로 보이게 된다.
이런 점을 이용해서 LED의 깜박임을 매우 짧은 시간동안 하도록 한다.
 
slow_light() 라는 함수가 바로 이것을 이용해서 LED를 짧은 시간동안 일정한 Pulse 를 가지고 깜박이도록 해서 눈에는 깜박임이 보이지 않고 빛의 세기가 달라지는 것처럼 보이게 한 함수이다.

다른 곳에서 LED를 가지고 세기를 조절할때 가변저항을 쓰는 경우를 종종 봤다. 하지만 PWM을 사용하면 굳이 그럴 필요가 없다. ^^ 가변저항을 쓰는 대신 가능한 최소의 저항을 사용하면서 PWM으로 깜박이는 간격을 조절해주면 얼마든지 프로그램내부에서 밝기를 조절할 수 있다. ^^

한번 살펴보고 사용해보기를... ^^

 

프로그램 코드는 다음과 같다..^^


#include "at89x52.h"

#define LF   0x0a
#define CR   0x0d
#define MSB_reload_value 0xB1 /* msb reload value exemple */
#define LSB_reload_value 0xE0 /* lsb reload value exemple */

// Timer0 Mode1 10ms 만들기
#define   TH0_VALUE     0xB1
#define   TL0_VALUE     0xDF

#define LED1    P1_0
#define LED2    P1_2
#define LED3    P1_4
#define LED4    P1_6

#define on      1
#define OFF     0

typedef  unsigned char  u08;
typedef  char    s08;
typedef  unsigned int  u16;
typedef  int    s16;

u08 count = 0 ;
volatile u16 cnt;

void putch(u08 c);
u08 getch(void);
void serial9600init(void);
void init_T2 (void);
void put_str(const char *str);
void timer0init(void);
void empty(void);
void delay(u16 number);
void delay1s(void);
void delay100ms(void);
void delay10ms(void);
void slow_light(void);


void timer0init(void) {
    TMOD &= 0xF0;
    TMOD |= 0x01;  // timer0 16비트 설정
    TH0 = TH0_VALUE; // 초기값 설정
    TL0 = TL0_VALUE; //

    ET0=1;    // timer0 가능
    EA=1;     // 인터럽트가능
    TR0=1;    // 타이머0 시작
}

void empty(void)
{
 ;
}
 
void delay(u16 number)
{
 u16 i;
 for(i=0;i<number;i++) delay10ms();
}

void delay1s(void)
{
 cnt = 0;
 while(cnt<100) ;
 cnt = 0;
}

void delay100ms(void)
{
 cnt = 0;
 while(cnt<10) ;
 cnt = 0;
}

void delay10ms(void)
{
 cnt = 0;
    TH0 = TH0_VALUE; // 초기값 설정
    TL0 = TL0_VALUE; //
 while(cnt<1) ;
 cnt = 0;
}

void put_str(const char *str)
{
    int idata i;
    for(i=0;*(str+i)!=0;i++)
    {
     if(*(str+i)=='\n')
     {
        putch(CR);
        //  putch(LF);
        }
    putch(*(str+i));
    }
}


void putch(u08 c)
{
 while (!TI);     // TI 가 1이 될때까지 기다림
    SBUF  = c;
    TI =0;
}

u08 getch(void)
{
      u08 c;
      while(!RI);         // 수신 버퍼 
      c = SBUF;
      RI=0;
      return c;
}

void serial9600init(void)         //initialie serial and timer
{  
    ET1 = 0;
    TMOD = 0x25;
    SCON = 0x52;
    PCON = 0x80;
    TH1 = 243;
    TR1 = 1;
}

void init_T2 (void)        // 24MHz X-TAL
{
 T2MOD &= 0xFC; /* T2OE=0;DCEN=1; */
 T2MOD |= 0x01;
 EXF2=0; /* reset flag */
 TCLK=0;RCLK=0; /* disable baud rate generator */
 EXEN2=0; /* ignore events on T2EX */
 TH2=MSB_reload_value;/* Init msb_value */
 TL2=LSB_reload_value;/* Init lsb_value */
 RCAP2H=MSB_reload_value;/* reload msb_value */
 RCAP2L=LSB_reload_value;/* reload lsb_value */
 C_T2=0; /* timer mode */
 CP_RL2=0; /* reload mode */
 EA=1; /* interupt enable */
 ET2=1; /* enable timer2 interrupt */
 TR2=1; /* timer2 run */

}


void help(void) {
 
     put_str("\n====================\n");
     put_str("LED Light Program\n");
     put_str("Select LED Number\n");
     put_str("LIGHT on  : (1)   (2)   (3)   (4)\n");
     put_str("LIGHT OFF : (5)   (6)   (7)   (8)\n");
     put_str("LIGHT Blink : (B)   \n");
        put_str("Slow Light on & Off : (S) \n");
        put_str("Repeat Light on & Off : (C) \n");
     put_str("Help(H) ALL on(A)  ALL OFF(F)\n");

}

void it_timer2(void) interrupt 5 /* interrupt address is 0x002b */
{
 count++;
 TF2 = 0; /* reset interrupt flag */
}

void it_timer0(void) interrupt 1 /* interrupt address is 0x000b */
{
    TH0 = TH0_VALUE;
    TL0 = TL0_VALUE;
    cnt++;
}

void slow_light(void) {
 u08 i,j,k;
    for(k=0;k<4;k++) {
     P1=0x00; delay(10);
     for(i=0;i<200;i++)  { LED1=ON;for(j=0;j<i;j++) empty();
           LED1=OFF;for(j=0;j<200-i;j++) empty();}
     for(i=0;i<200;i++)  { LED1=OFF;for(j=0;j<i;j++) empty();
           LED1=ON;for(j=0;j<200-i;j++) empty();}
       
     P1=0x00; delay(10);
     for(i=0;i<200;i++)  { LED2=ON;for(j=0;j<i;j++) empty();
           LED2=OFF;for(j=0;j<200-i;j++) empty();}
     for(i=0;i<200;i++)  { LED2=OFF;for(j=0;j<i;j++) empty();
           LED2=ON;for(j=0;j<200-i;j++) empty();}
       
     P1=0x00; delay(10);
     for(i=0;i<200;i++)  { LED3=ON;for(j=0;j<i;j++) empty();
           LED3=OFF;for(j=0;j<200-i;j++) empty();}
     for(i=0;i<200;i++)  { LED3=OFF;for(j=0;j<i;j++) empty();
           LED3=ON;for(j=0;j<200-i;j++) empty();}

     P1=0x00; delay(10);
     for(i=0;i<200;i++)  { LED4=ON;for(j=0;j<i;j++) empty();
           LED4=OFF;for(j=0;j<200-i;j++) empty();}
     for(i=0;i<200;i++)  { LED4=OFF;for(j=0;j<i;j++) empty();
           LED4=ON;for(j=0;j<200-i;j++) empty();}
     P1=0x00;
 }
}

void main(void){

 u08 c;
 u16 i,j;

    serial9600init();
    init_T2 () ;                     // initialize timer
    timer0init();
    
 help();
    while(1) {
//     c=(getch()-'0');

     put_str("\nHelp(H) / [A F] [1 2 3 4] [5 6 7 8] [B S C] \n");
     put_str("Enter the Number = ");

  c=getch();
        put_str("\n");
     
//     if(c==0) {P1=0xff; delay(20);}

     if(c=='H') {help();}
     if(c=='A') {P1=0xff; delay(10);}
     if(c=='F') {P1=0x00; delay(50);}
     
     if(c=='B') {
      for(c=0;c<4;c++) {
       
      P1=0x00;
      LED1 = on; delay(50); P1 = 0x00;
      LED2 = on; delay(50); P1 = 0x00;
      LED3 = on; delay(50); P1 = 0x00;
      LED4 = on; delay(50); P1 = 0x00;
      }
     }

     if(c=='S') slow_light();
     if(c=='C') while(1) {slow_light();}
     
     if(c=='1') LED4=ON;
     if(c=='2') LED3=ON;
     if(c=='3') LED2=ON;
     if(c=='4') LED1=ON;
    
     if(c=='5') LED4=OFF;
     if(c=='6') LED3=OFF;
     if(c=='7') LED2=OFF;
     if(c=='8') LED1=OFF;
    }
}

 

TY52_RS_LED4.C

TY52_RS_LED4.ihx