目次

7セグメントLED表示器

 7セグメントLEDには、1パッケージに個別LEDを8本封入されています。




 電源の高い方を共通にするか、低い方を共通にするかで
 アノードコモン、カソードコモンに分けられます。

 教材用に入っていた7セグメントLEDは、カソードコモンでした。

 点灯は正論理で考えればよく、'1'で点灯、'0'で消灯になります。

 7セグメントLEDの点灯実験回路は、以下。



 スイッチを押すたびに、表示される数字が変化していきます。

 7セグメントLEDの点灯パターンは、switch文を利用して
 関数で定義します。

typedef unsigned char UBYTE ;

UBYTE conv7segment(UBYTE x)
{
  UBYTE result ;

  switch ( number ) {
    case 1  : result = 0x06 ; break;
    case 2  : result = 0x5b ; break;
    case 3  : result = 0x4f ; break;
    case 4  : result = 0x66 ; break;
    case 5  : result = 0x6d ; break;
    case 6  : result = 0x7d ; break;
    case 7  : result = 0x07 ; break;
    case 8  : result = 0x7f ; break;
    case 9  : result = 0x6f ; break;
    default : result = 0x3f ; break;
  }

  return result ;
}

 定義した関数の動作を調べるコードは、時間をおいて
 点灯パターンを変更していきます。

#define OFF 0
#define ON  OFF+1

#define FIVE 500

typedef unsigned char UBYTE ;

/* prototype */
void  usr_init(void);
UBYTE conv7segment(UBYTE x);

void main(void)
{
  UBYTE tmp;
  /* initialize PORT */
  usr_init();
  /* endless loop */
  tmp = 0 ;
  while (ON) {
    /* impress */
    PORTB = conv7segment( tmp );
    /* delay */
    Delay_ms(FIVE);
    /* update */
    tmp++ ;
    if ( tmp == 10 ) { tmp = 0 ; }
  }
}

void usr_init(void)
{
  /* disable analog comparator */
  CMCON = 0x07 ;
  /* initial value */
  PORTB = OFF ;
  /* direction */
  TRISB = 0x00 ;
}

UBYTE conv7segment(UBYTE x)
{
  UBYTE result ;

  switch ( number ) {
    case 1  : result = 0x06 ; break;
    case 2  : result = 0x5b ; break;
    case 3  : result = 0x4f ; break;
    case 4  : result = 0x66 ; break;
    case 5  : result = 0x6d ; break;
    case 6  : result = 0x7d ; break;
    case 7  : result = 0x07 ; break;
    case 8  : result = 0x7f ; break;
    case 9  : result = 0x6f ; break;
    default : result = 0x3f ; break;
  }

  return result ;
}

 スイッチを押すたびに、表示数字が変化するコードは以下。

#define OFF 0
#define ON  OFF+1

#define FIVE 500

#define LAST 10

typedef unsigned char UBYTE ;

/* prototype */
void  usr_init(void);
UBYTE conv7segment(UBYTE x);

void main(void)
{
  UBYTE tmp;
  /* initialize PORT */
  usr_init();
  /* endless loop */
  tmp = 0 ;
  while (ON) {
    /* impress */
    PORTB = conv7segment( tmp );
    /* delay */
    Delay_ms(FIVE);
    /* increment*/
    if ( PORTA.F0 == OFF ) { tmp++ ; }
    /* judge */
    if ( tmp == LAST ) { tmp = 0 ; }
  }
}

void usr_init(void)
{
  /* disable analog comparator */
  CMCON = 0x07 ;
  /* initial value */
  PORTA = 0xff ;
  PORTB = OFF ;
  /* direction */
  TRISA = 0xff ;
  TRISB = 0x00 ;
}

UBYTE conv7segment(UBYTE x)
{
  UBYTE result ;

  switch ( number ) {
    case 1  : result = 0x06 ; break;
    case 2  : result = 0x5b ; break;
    case 3  : result = 0x4f ; break;
    case 4  : result = 0x66 ; break;
    case 5  : result = 0x6d ; break;
    case 6  : result = 0x7d ; break;
    case 7  : result = 0x07 ; break;
    case 8  : result = 0x7f ; break;
    case 9  : result = 0x6f ; break;
    default : result = 0x3f ; break;
  }

  return result ;
}

 7セグメントLED点灯パターンを、配列に格納する方法もあります。

  UBYTE segment_pat[10];

  *(segment_pat+0) = 0x3f ;
  *(segment_pat+1) = 0x06 ;
  *(segment_pat+2) = 0x5b ;
  *(segment_pat+3) = 0x4f ;
  *(segment_pat+4) = 0x66 ;
  *(segment_pat+5) = 0x6d ;
  *(segment_pat+6) = 0x7d ;
  *(segment_pat+7) = 0x07 ;
  *(segment_pat+8) = 0x7f ;
  *(segment_pat+9) = 0x6f ;

 この場合、初期化関数usr_initの中に、上のコードを含めます。

#define OFF 0
#define ON  OFF+1

#define FIVE 500

#define LAST 10

typedef unsigned char UBYTE ;

volatile UBYTE segment_pat[10];

/* prototype */
void  usr_init(void);

void main(void)
{
  UBYTE tmp;
  /* initialize PORT */
  usr_init();
  /* endless loop */
  tmp = 0 ;
  while (ON) {
    /* impress */
    PORTB = *(segment_pat+tmp);
    /* delay */
    Delay_ms(FIVE);
    /* increment*/
    if ( PORTA.F0 == OFF ) { tmp++ ; }
    /* judge */
    if ( tmp == LAST ) { tmp = 0 ; }
  }
}

void usr_init(void)
{
  /* disable analog comparator */
  CMCON = 0x07 ;
  /* initial value */
  PORTA = 0xff ;
  PORTB = OFF ;
  /* direction */
  TRISA = 0xff ;
  TRISB = 0x00 ;
  /* set bit pattern */
  *(segment_pat+0) = 0x3f ;
  *(segment_pat+1) = 0x06 ;
  *(segment_pat+2) = 0x5b ;
  *(segment_pat+3) = 0x4f ;
  *(segment_pat+4) = 0x66 ;
  *(segment_pat+5) = 0x6d ;
  *(segment_pat+6) = 0x7d ;
  *(segment_pat+7) = 0x07 ;
  *(segment_pat+8) = 0x7f ;
  *(segment_pat+9) = 0x6f ;
}

 配列の利用で、関数内部にある判定を省けるため
 動作は少し高速になります。

 利用する7セグメントLEDが、アノードコモンに変更に
 なったときは、論理演算を応用して正論理から負論理に
 変更します。

 関数の場合は、次のように1行で対応できます。

UBYTE conv7segment(UBYTE x)
{
  UBYTE result ;

  switch ( number ) {
    case 1  : result = 0x06 ; break;
    case 2  : result = 0x5b ; break;
    case 3  : result = 0x4f ; break;
    case 4  : result = 0x66 ; break;
    case 5  : result = 0x6d ; break;
    case 6  : result = 0x7d ; break;
    case 7  : result = 0x07 ; break;
    case 8  : result = 0x7f ; break;
    case 9  : result = 0x6f ; break;
    default : result = 0x3f ; break;
  }

  return( result ^ 0xff );
}

 排他的論理和を利用して、1と0を反転します。

 配列の場合は、「~」を利用して「1の補数」で対応できます。

  /* set bit pattern */
  *(segment_pat+0) = ~0x3f ;
  *(segment_pat+1) = ~0x06 ;
  *(segment_pat+2) = ~0x5b ;
  *(segment_pat+3) = ~0x4f ;
  *(segment_pat+4) = ~0x66 ;
  *(segment_pat+5) = ~0x6d ;
  *(segment_pat+6) = ~0x7d ;
  *(segment_pat+7) = ~0x07 ;
  *(segment_pat+8) = ~0x7f ;
  *(segment_pat+9) = ~0x6f ;

 どちらの場合でも、ポートBへの出力や数字を更新する
 処理に手を加えていない点に注意します。

 値を増やすことから、減らすように変更してみます。

#define OFF 0
#define ON  OFF+1

#define FIVE 500

#define LAST 10

typedef unsigned char UBYTE ;

volatile UBYTE segment_pat[10];

/* prototype */
void  usr_init(void);

void main(void)
{
  int tmp;
  /* initialize PORT */
  usr_init();
  /* endless loop */
  tmp = LAST-1 ;
  while (ON) {
    /* impress */
    PORTB = *(segment_pat+tmp);
    /* delay */
    Delay_ms(FIVE);
    /* increment*/
    if ( PORTA.F0 == OFF ) { tmp-- ; }
    /* judge */
    if ( tmp < 0 ) { tmp = LAST-1 ; }
  }
}

void usr_init(void)
{
  /* disable analog comparator */
  CMCON = 0x07 ;
  /* initial value */
  PORTA = 0xff ;
  PORTB = OFF ;
  /* direction */
  TRISA = 0xff ;
  TRISB = 0x00 ;
  /* set bit pattern */
  *(segment_pat+0) = 0x3f ;
  *(segment_pat+1) = 0x06 ;
  *(segment_pat+2) = 0x5b ;
  *(segment_pat+3) = 0x4f ;
  *(segment_pat+4) = 0x66 ;
  *(segment_pat+5) = 0x6d ;
  *(segment_pat+6) = 0x7d ;
  *(segment_pat+7) = 0x07 ;
  *(segment_pat+8) = 0x7f ;
  *(segment_pat+9) = 0x6f ;
}

 初期値と状態値の更新が−1になるようにしています。
 さらに、境界値を判定して範囲外になったとき、範囲内
 に戻す操作を加えます。


目次

inserted by FC2 system