MCR - Micom Car Rally
大会情報 マイコンカーラリーとは? 今から始めるマイコンカーラリー 技術情報 大会記録 MCRファン倶楽部 お問い合せ
マイコンカーラリートップへ マイコンカーラリートップへ
技術情報 >> R8C/M12A 技術情報
技術情報
各種資料
YouTube情報
R8C/M12A 技術情報
上位入賞マイコンカー
よくある質問(FAQ)
ダウンロード
R8C/M12A 技術情報
圧電サウンダーから音を鳴らす
(PWM波形の出力)

2012.03.30一部修正

内容
R8C/M12Aの内蔵周辺機能のひとつであるタイマRJ2を使って、圧電サウンダーから音を鳴らします。圧電サウンダーに、特定の周波数のパルスを加えることにより音が鳴ります。パルス幅やタイミングをマイコンで制御しています。
今回の「タイマRBJ」の「2」は、Ver.2という意味です。型式の違うR8CマイコンにはタイマRJがありますが、タイマRJ2の方が機能がアップしています!

ワークスペース
開発環境を整える」ページからダウンロードしてください。

回路
回路を下図に示します。

回路図

ブレッドボード実装図
ブレッドボードの実装を下図に示します。
ブレッドボード実装図

実習中のブレッドボード
実習中のブレッドボード

プログラムを開く
ワークスペース「r8cm12a_breadboard」のプロジェクト「04sounder」をアクティブ(有効)にします。「04sounder」が太字になっていない場合は、右画面のように、「アクティブプロジェクトに設定」してください。

「ビルド→ビルド」して、MOTファイルを作成、「ツール→R8C Writer」でプログラムを書き込んで、実行してください。
  プロジェクトを切り替える
プロジェクト「04sounder」を有効にする

実行中の動画
※映像は動きません。音だけ鳴ります。音量は小さめにして、少しずつ上げていってください。

プログラムの説明
タイマRJ2の設定

タイマRJ2の概要(パルス出力モード)を、下図に示します。

タイマRJ2(パルス出力モード) 概要

タイマRJ2を使って、パルスを出力します。タイマRJ2を使ったパルス出力は、ON幅とOFF幅の比率を変えることは出来ず、常にON幅:OFF幅=50%:50%になります。今回のようにON幅とOFF幅を同じでパルス出力する場合は、持ってこいのタイマとなります。
これからタイマRJ2のパルス出力モードについて、説明します。

■TRJO端子の選択
TRJO端子(タイマRJ2を使ったパルス出力モードで、パルスを出力することのできる端子)は、P3_7端子とP1_6端子の2つあります。どちらの端子を使うかは、プログラムで設定します。
P3_7端子からパルスを出力したい場合、ポートP3_7機能選択ビット(P37SEL1,P37SEL0)を下記のように設定します。
    p37sel1 = 1;  /* P3_7をTRJO端子にする */
    p37sel0 = 0;  /* 〃                   */

P1_6端子からパルスを出力したい場合、ポートP1_6機能選択ビット(P16SEL1,P16SEL0)を下記のように設定します。
    p16sel1 = 1;  /* P1_6をTRJO端子にする */
    p16sel0 = 0;  /* 〃                   */

今回は、P3_7をタイマRJ2 パルス出力モードの出力端子にしています。

■タイマRJモードレジスタ(TRJMR)の設定
bit 7 6 5 4 3 2 1 0
設定
内容
0 タイマRJカウントソース
選択ビット
000:f1(20MHz)
001:f8(2.5MHz)
010:fHOCO(20MHz)
011:f2(10MHz)
0 タイマRJ動作モード
選択ビット
000:タイマモード
001:パルス出力モード
010:イベントカウンタモード
011:パルス幅測定モード
100:パルス周期測定モード
設定値 0 0 1 1 0 0 0 1

タイマRJカウントソース選択ビットは、f2(10MHz)を選びます。これは、タイマRJカウンタの値が、100nsごとにカウントダウンしていくことになります。
タイマRJ動作モード選択ビットは、今回は「パルス出力モード」を選びます。

■タイマRJ制御レジスタ(TRJCR)の設定
bit 7 6 5 4 3 2 1 0
設定
内容
0 0 0 0 0 0 0 タイマRJカウント
開始ビット
0:カウント停止
1:カウント開始
設定値 0 0 0 0 0 0 0 x
ビットの
名称
              TSTART_TRJCR

タイマRJカウント開始ビットを"1"にすると、タイマRJカウンタレジスタ(TRJ)の値がタイマRJカウントソース選択ビットで設定した時間ごとに-1していきます。値の変化は、TSTART_TRJCR(タイマRJカウント開始ビット)が"1"のときだけです。"0"だと、値は変化しません。

■タイマRJカウンタレジスタ(TRJ)
bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
TSTART_TRJCR="1"なら、タイマRJカウントソース選択ビットで設定した時間(今回は100ns)ごとに-1します。1の次は0、0の次が設定した値です。
TSTART_TRJCR="0"なら、値は変化しません。

TRJが「・・・→2→1→0→設定した値→・・・」と、0から設定した値に変わる瞬間に波形が反転します。TRJには、ON幅(またはOFF幅)をTRJに設定しておきます。
例えば、周期1msのパルスを出力したいときの計算方法は次のようになります。
  出力したい周期/タイマRJカウントソース
=(1×10-3)/(100×10-9)= 10000

タイマRJカウンタ(TRJ)に設定する値は、ON幅です。周期の1/2なので、
 10000 / 2 = 5000

最後に1引いた値が、タイマRJカウンタ(TRJ)に設定する値になります。
 TRJ = 5000 - 1 = 4999

■タイマRJ2の設定プログラム
今回のinit関数内でのタイマRJ2の初期化プログラムを下記に示します。
 259 :      /* タイマRJ2の設定 */
 260 :      p37sel1 = 1;        /* P3_7をTRJO端子にする         */
 261 :      p37sel0 = 0;        /* 〃                           */
 262 :      msttrj  = 0;        /* タイマRJ2を有効にする        */
 263 :      trjmr   = 0x31;     /* パルス出力モードに設定       */
 264 :      trj     = 0;       /* TRJ×1/20M*2の時間でON/OFFする*/
 265 :      //tstart_trjcr = 1; /* タイマスタート(今回はまだしない)    */

※265行はコメントです。今回はタイマスタートはここでは実行しません。
 他のプログラムでこの部分を使って、タイマスタートする場合は、
 「//」をとってこの行のプログラムを実行してください。

「msttrj」は、タイマRJ2スタンバイビットで、タイマRJ2を有効にするか、無効にするかを選択するビットです。0で有効です。初期はタイマRJ2が無効になっているので、タイマRJ2を使う前にこのビットを0にしてください。
波形出力は、次で説明するsounder関数で行うので、ここではまだタイマRJカウンタのカウントはしません。すなわち、tstart_trjcrを1にはまだしません。

sounder関数

sounder関数を説明する前に、音階について説明します。
音階とは、「ドレミファソラシド」のことです。この音階の周波数が分かれば周期が分かりますので、デューティ比50%のPWMをブザーに出力すれば、「ドレミファソラシド」と音を鳴らすことができます。
音階は、「ド」から次の高い「ド」まで「ド、ド#、レ、レ#、ミ、ファ、ファ#、ソ、ソ#、ラ、ラ#、シ」の12段階あります。12段階を1オクターブといいます。
4オクターブ目のドの音の周波数は261.6Hzです。12段階の周波数は、次の式で求めることができます。

  周波数=261.6×2(x/12) [Hz]

音階と周期についての計算を、下表に示します。
オク
ターブ
音階 x 計算式 周波数[Hz] 周期[ms]
0 -48 261.6×2(-48/12) 16.4 61.16
1 -36 261.6×2(-36/12) 32.7 30.58
2 -24 261.6×2(-24/12) 65.4 15.29
3 -12 261.6×2(-12/12) 130.8 7.65
4 0 261.6×2(0/12) 261.6 3.82
4 ド# 1 261.6×2(1/12) 277.2 3.61
4 2 261.6×2(2/12) 293.6 3.41
4 レ# 3 261.6×2(3/12) 311.1 3.21
4 4 261.6×2(4/12) 329.6 3.03
4 ファ 5 261.6×2(5/12) 349.2 2.86
4 ファ# 6 261.6×2(6/12) 370.0 2.70
4 7 261.6×2(7/12) 392.0 2.55
4 ソ# 8 261.6×2(8/12) 415.3 2.41
4 9 261.6×2(9/12) 440.0 2.27
4 ラ# 10 261.6×2(10/12) 466.1 2.15
4 11 261.6×2(11/12) 493.8 2.02
5 12 261.6×2(12/12) 523.2 1.91
6 24 261.6×2(24/12) 1049.4 0.96

これで周期が分かりました。あとはタイマRJカウンタ(TRJ)に設定する数値を計算するだけです。例として、4オクターブ目の「ド」を鳴らすときの値を計算します。

TRJ=ドの周期/タイマRJカウントソース/2−1
  =(3.82×10-3)/(100×10-9)/ 2 − 1
  =38200 / 2 − 1
  =19099

タイマRJカウンタ(TRJ)に設定する値は、ON幅です。周期の1/2なので、
   38200/2=19100
となります。答えに1引いた値である「19099」が、タイマRJカウンタ(TRJ)に設定する値です。
毎回計算するのは大変なので、プログラムではあらかじめdefine定義しています。
今回の定義部分(抜粋)を下記に示します。
※計算したときの有効数字が違うため、プログラムでは4オクターブ目のドは、19113になっています。
  44 :  /* 4オクターブ目の音階 */
  45 :  #define DO_4        19113   /* ド       */
  46 :  #define DOU_4       18040   /* ド#     */
  47 :  #define RE_4        17028   /* レ       */
  48 :  #define REU_4       16072   /* レ#     */
  49 :  #define MI_4        15170   /* ミ       */
  50 :  #define FA_4        14319   /* ファ     */
  51 :  #define FAU_4       13515   /* ファ#   */
  52 :  #define SO_4        12756   /* ソ       */
  53 :  #define SOU_4       12041   /* ソ#     */
  54 :  #define RA_4        11365   /* ラ       */
  55 :  #define RAU_4       10727   /* ラ#     */
  56 :  #define SI_4        10125   /* シ       */

いよいよ、sounder関数の説明をします。この関数で、圧電サウンダーにパルスを出力します。
 285 :  void sounder( unsigned int tone, int time )
 286 :  {
 287 :      if( tone == 0 ) {
 288 :          tstart_trjcr = 0;       /* タイマ停止         */
 289 :      } else {
 290 :          trj = tone;
 291 :          tstart_trjcr = 1;       /* タイマ開始         */
 292 :      }
 293 :      if( time != 0 ) {
 294 :          timer( 15000L * time / tempo );
 295 :      }
 296 :  }

引数の1つ目には、音階を設定します。2つ目には、長さを指定します。
音階が0なら、288行でタイマRJ2を停止させてパルス出力を停止します。
音階が0以外なら、タイマRJカウンタ(TRJ)に音階データをセット、タイマを開始します。
長さは、4分音符=4として、2分音符なら4分音符の2倍の長さなので8、8分音符なら4分音符の1/2倍の長さなので2を設定します。休符も同様です。音符名、休符名と値の関係を下表に示します。
音符、休符 説明 四分音符を4としたときの長さ テンポが60のときの時間[秒]
全音符 4分音符の4倍に当たる長さの音を表現する音符。 4 16 4
2分音符 4分音符の2倍に当たる長さの音を表現する音符。 2 8 2
4分音符 基準となる長さの音。便宜上、この音の長さを1拍とする。 1 4 1
8分音符 4分音符の1/2に当たる長さの音を表現する音符。 1/2 2 0.5
16分音符 4分音符の1/4に当たる長さの音を表現する音符。 1/4 1 0.25
32分音符 4分音符の1/8に当たる長さの音を表現する音符。 1/8 0.5 0.125

main関数

volume.cのmain関数のプログラムを、下記に示します。
  82 :  int  tempo = 60;  /* テンポ                  */
中略
  87 :  void main( void )
  88 :  {
  89 :      init();       /* 初期化                   */
  90 :
  91 :  /*
  92 :  長さは、四分音符を4として、
                    二分音符は8、八分音符は2となります。
  93 :  休符も同様に、四分休符を4として、
                    二部休符は8、八分休符は2となります。
  94 :  */
  95 :  /*           音階,   長さ    */
  96 :      sounder( DO_4,   4 );
  97 :      sounder( RE_4,   4 );
  98 :      sounder( MI_4,   4 );
  99 :      sounder( FA_4,   4 );
 100 :      sounder( SO_4,   4 );
 101 :      sounder( RA_4,   4 );
 102 :      sounder( SI_4,   4 );
 103 :      sounder( DO_5,   4 );
 104 :      sounder( 0,      0 );
 105 :      while( 1 );

82行で、テンポを指定します。四分音符を1分間に何回演奏するかの指定です。今回は60なので、4分音符を1分間に60回鳴らす早さです。
96〜103行で、「ドレミファソラシド」を鳴らします。
104行で、音を止めます。

課題
1.「大きな古時計」を演奏するよう、プログラムを改造しなさい。

2.チャルメラの音楽(ドレミ〜レド、ドレミレドレ〜〜)を演奏しなさい。

3.R8C/M12Aマイコンと圧電サウンダーの接続をP1_6端子にして、音楽が鳴るようプログラムを改造しなさい。
※P1_6端子につながっているLEDは外してよい。
※圧電サウンダーが繋がっていると書き込みができない場合があります。その時は、書き込み時のみ圧電サウンダーを外して書き込みをしてください。

課題の回答例
1.の回答例
sounder_answer_1.c

2.の回答例
sounder_answer_2.c

3.の回答例
sounder_answer_3.c

BACK