目次

音出し

 書籍の付録には、スピーカがひとつ入っていました。



 大きくて実験では、扱い難いので¥100ショップで
 売られているスピーカを利用します。



 スピーカのインピーダンスは、4Ωから16Ω程度で
 マイコンの出力ポートにとっては、重い負荷なので
 バッファのトランジスタを入れて電流増幅して使い
 ます。



 スピーカに波形を送れば音がでます。
 PWM波形を与えることで、音色が変化します。



 PWM波形の場合、HとLレベルの時間比率をDuty比として
 定義して処理します。
 実験回路は、以下。



 実験回路の動作テストは、以下のプログラムを利用。

#define OFF 0
#define ON  OFF+1

#define THX 1000

typedef unsigned char UBYTE ;

UBYTE state ;

/* prototype */
void usr_init(void);

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* impress */
    PORTB = state & ON ;
    /* delay */
    Delay_ms(THX);
    /* update state */
    state++ ;
  }
}

void usr_init(void)
{
  /* initial value */
  PORTB = OFF ;
  /* direction */
  TRISB = 0x00 ;
  /* clear state counter */
  state = 0 ;
}

 スイッチを押している間、スピーカから音が出るように
 してみます。




#define OFF 0
#define ON  OFF+1

#define THX 1000

typedef unsigned char UBYTE ;

UBYTE state ;

/* prototype */
void usr_init(void);

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* beep */
    while ( PORTA.FO == OFF ) {
      /* impress */
      PORTB = state & ON ;
      /* delay */
      Delay_ms(THX);
      /* update state */
      state++ ;
    }
  }
}

void usr_init(void)
{
  /* initial value */
  PORTA = OFF ;
  PORTB = OFF ;
  /* direction */
  TRISA = 0xff ;
  TRISB = 0x00 ;
  /* clear state counter */
  state = 0 ;
}

 この回路の応用は、アマチュア無線で利用される
 電鍵と紹介されています。GHD社縦振電鍵が有名。



 モールス符号(CW)は、次のようになっています。

A . -
B - . . .
C - . - .
D - . .
E .
F . . - .
G - - .
H . . . .
I . .
J . - - -
K - . -
L . - . .
M - -
N - .
O - - -
P . - - .
Q - - . -
R . - .
S . . .
T -
U . . -
V . . . -
W . - -
X - . . -
Y - . - -
Z - - . .
1 . - - - -
2 . . - - -
3 . . . - -
4 . . . . -
5 . . . . .
6 - . . . .
7 - - . . .
8 - - - . .
9 - - - - .
0 - - - - -

 電鍵の場合、2個のスイッチを用意してdot(.)
 dash(-)を表現するパドルもあります。
 (写真は、GHD社のパドルです。)



 3箇所のスイッチにより、音色が変化するように
 プログラムすると、次のようになります。

#define OFF 0
#define ON  OFF+1

#define SF0 477
#define SF1 425
#define SF2 380

typedef unsigned char UBYTE ;

UBYTE state ;

/* prototype */
void usr_init(void);

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* SF0 */
    while ( PORTA.FO == OFF ) {
      /* impress */
      PORTB = state & ON ;
      /* delay */
      Delay_ms(SF0);
      /* update state */
      state++ ;
    }
    /* SF1 */
    while ( PORTA.F1 == OFF ) {
      /* impress */
      PORTB = state & ON ;
      /* delay */
      Delay_ms(SF1);
      /* update state */
      state++ ;
    }
    /* SF2 */
    while ( PORTA.F2 == OFF ) {
      /* impress */
      PORTB = state & ON ;
      /* delay */
      Delay_ms(SF2);
      /* update state */
      state++ ;
    }
  }
}

void usr_init(void)
{
  /* initial value */
  PORTA = OFF ;
  PORTB = OFF ;
  /* direction */
  TRISA = 0xff ;
  TRISB = 0x00 ;
  /* clear state counter */
  state = 0 ;
}

 回路は、以下。



 複数のピッチの音を出して、メロディを出すこともできます。
 CDEFGABの各ピッチを生成する関数を定義して、対応します。

#define OFF 0
#define ON  OFF+1

typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;

UBYTE state ;

/* prototype */
void usr_init(void);
void n_c(void);
void n_d(void);
void n_e(void);
void n_f(void);
void n_g(void);
void n_a(void);
void n_b(void);
void n_cc(void);
void n_r(void);

void main(void)
{
  /* initialize PORT */
  usr_init();
  /* endless loop */
  while (ON) {
    /* */
    n_c();n_c();n_c();n_c();n_c();n_c();n_d();n_d();n_e();n_e();n_d();n_d();
    n_c();n_c();n_r();n_r();n_r();n_r();
    /* */
    n_d();n_d();n_d();n_d();n_d();n_d();n_g();n_g();n_d();n_d();n_g();n_g();
    n_e();n_e();n_r();n_r();
    /* */
    n_e();n_e();n_f();n_f();n_g();n_g();n_g();n_g();n_d();n_d();n_e();n_e();
    n_f();n_f();n_f();n_f();
    /* */
    n_r();n_r();
    /* */
    n_g();n_g();n_g();n_g();n_g();n_g();n_g();n_g();n_g();n_g();n_f();n_f();
    n_e();n_e();n_d();n_d();n_c();n_c();n_c();n_r();n_r();n_r();
  }
}

void usr_init(void)
{
  /* initial value */
  PORTA = OFF ;
  PORTB = OFF ;
  /* direction */
  TRISA = 0xff ;
  TRISB = 0x00 ;
  /* clear state counter */
  state = 0 ;
}

void n_c(void)
{
  UBYTE i ;
  for ( i = 0 ; i < 150 ; i++ ) {
    /* impress */
    PORTB = state & ON ;
    /* delay */
    Delay_ms(477);
    /* update state */
    state++ ;
  }
}

void n_d(void)
{
  UBYTE i ;
  for ( i = 0 ; i < 168 ; i++ ) {
    /* impress */
    PORTB = state & ON ;
    /* delay */
    Delay_ms(425);
    /* update state */
    state++ ;
  }
}

void n_e(void)
{
  UBYTE i ;
  for ( i = 0 ; i < 189 ; i++ ) {
    /* impress */
    PORTB = state & ON ;
    /* delay */
    Delay_ms(379);
    /* update state */
    state++ ;
  }
}

void n_f(void)
{
  UBYTE i ;
  for ( i = 0 ; i < 200 ; i++ ) {
    /* impress */
    PORTB = state & ON ;
    /* delay */
    Delay_ms(358);
    /* update state */
    state++ ;
  }
}

void n_g(void)
{
  UBYTE i ;
  for ( i = 0 ; i < 225 ; i++ ) {
    /* impress */
    PORTB = state & ON ;
    /* delay */
    Delay_ms(318);
    /* update state */
    state++ ;
  }
}

void n_a(void)
{
  UBYTE i ;
  for ( i = 0 ; i < 252 ; i++ ) {
    /* impress */
    PORTB = state & ON ;
    /* delay */
    Delay_ms(284);
    /* update state */
    state++ ;
  }
}

void n_b(void)
{
  UWORD i ;
  for ( i = 0 ; i < 282 ; i++ ) {
    /* impress */
    PORTB = state & ON ;
    /* delay */
    Delay_ms(253);
    /* update state */
    state++ ;
  }
}

void n_cc(void)
{
  UWORD i ;
  for ( i = 0 ; i < 300 ; i++ ) {
    /* impress */
    PORTB = state & ON ;
    /* delay */
    Delay_ms(239);
    /* update state */
    state++ ;
  }
}

void n_r(void)
{
  UWORD i ;
  for ( i = 0 ; i < 567 ; i++ ) {
    /* impress */
    PORTB = OFF ;
    /* delay */
    Delay_ms(126);
  }
}

 ピッチは、単位時間あたりの波の数なので
 for文で繰返回数を決めています。


目次

inserted by FC2 system