« 18ピンDIP版 拡張PIC16Fマイコン入手(3) | メイン | STM8Sマイコンで作る警報音 (4) »

STM8Sマイコンで作る警報音 (3)


STM8S-Discoveryに圧電スピーカをつなぐ 割り込みを使って,断続する

 STマイクロエレクトロニクス社(以下ST社)の STM8S-Discovery に接続した圧電スピーカから,割り込みを使って断続的に音を出します.

割り込みって,何だろう
  // Loop forever
  while (1) {
    wait_tim3_update();         // Wait for TIM3 update
    BEEP_Cmd(ENABLE);           // Enable BEEP
    wait_tim3_update();         // Wait for TIM3 update
    BEEP_Cmd(DISABLE);          // Disable BEEP
  }

 前回のプログラムでは,上のように Timer3 モジュールのフラグをソフトウェアが監視していました.フラグの監視をソフトウェアが行うため,監視中はほかの処理を行うことができません.そこで,割り込みを使用して,フラグを監視する必要がないように変更してやります.

割り込みによる刺激の伝達

 割り込みが発生するきっかけは,ハードウェアからの刺激です.今回の場合には, Timer3 モジュールの UPDATE イベント・フラグがセットされたというきっかけで,割り込みが発生します.割り込みが発生したら,割り込み処理ルーチン(Interrupt Service Routine : ISR)と呼ばれる別の処理が動作を始めます.

 今回の例では, ISR で BEEPEN ビットを操作して, Beeper モジュールを ON/OFF させ,警報音を断続させます.

プロジェクトを準備しよう

 まあ,とりあえず,プログラムを作って,試してみることにします.まずは,プロジェクトを作成します.今回は,前回作成した workspace03 ワークスペースを使い, project03a というプロジェクトを "C:\Projects\STVD\ws03\proj03a" というフォルダに作成しました.

ワークスペース・ペイン

 次に,ライブラリをリンクします.今回使用するのは, Timer3 モジュールと Beeper モジュールの二つです.リンクしたファイルは,以下のとおりです.

リンクするファイルリンク先用途
FWLib\library\inc\stm8s.hInclude Files汎用ヘッダ
FWLib\library\inc\stm8s_beep.hInclude FilesBeeper モジュール・ヘッダ
FWLib\library\inc\stm8s_timer3.hInclude FilesTimer3 モジュール・ヘッダ
FWLib\library\src\stm8s_beep.cSource FilesBeeper モジュール・ライブラリ
FWLib\library\src\stm8s_timer3.cSource FilesTimer3 モジュール・ライブラリ


 さらに, "stm8s_conf.h" ファイルをコピーして,コメントになっている二つのマクロ _BEEP と _TIM3 の宣言を非コメント化します.

_BEEPを非コメント化 _TIM3を非コメント化

 変更が終わったら, ctrl+S でファイルを保存します.

ソース・コードを書きなおそう

 "main.c" ファイルを以下のように書き換えます.

//**************************************
//
// main.c : 
//  
// Copyright (c) 2010 noritan.org
//
//**************************************

#include "stm8s.h"

//======================================
// Constant declaration
//======================================
#define PERIOD  (62500)         // timer counter period
#define DUTY    (PERIOD/2)      // PWM duty value

//======================================
// Main procedure
//======================================
main()
{
  // Initialize Beeper module.
  BEEP_Init(BEEP_FREQUENCY_1KHZ);
  
  // Initialize Timer3 module.
  TIM3_TimeBaseInit(            // Configure Timebase
    TIM3_PRESCALER_32,          // divide by 32
    PERIOD-1                    // divide by PERIOD
  );
  TIM3_OC2Init(                 // Configure OC2 output
    TIM3_OCMODE_PWM1,           // PWM mode-1 output
    TIM3_OUTPUTSTATE_ENABLE,    // Enable OC2 output
    DUTY,                       // Activated on count DUTY
    TIM3_OCPOLARITY_LOW         // LOW active output
  );
  
  // Enable UPDATE interrupt.
  TIM3_ITConfig(TIM3_IT_UPDATE, ENABLE);
  // Start Timer3
  TIM3_Cmd(ENABLE);             // Start the Timer
  // Enable global interrupts.
  enableInterrupts();
  // Loop forever
  while (1) {}
}

u8 beep_switch = DISABLE;  // Disable at first

//======================================
// Timer3 UPDATE event's
// Interrupt Service Routine
//======================================
@far @interrupt void Tim3Update_isr(void)
{
  // Clear the update flag
  TIM3_ClearFlag(TIM3_FLAG_UPDATE);
  // Toggle switch variable.
  beep_switch = !beep_switch;
  // Enable of disable BEEP
  BEEP_Cmd(beep_switch);        // Control BEEP
  return;
}

 まだ,アプリケーションは完成していませんが,ビルドして,エラーが発生しないか確認しましょう.

プログラムの解説

 大まかな構成は,前回の「警報音を断続的に鳴らす」アプリケーションと同じなので,違いについて確認していきます.

  // Enable UPDATE interrupt.
  TIM3_ITConfig(TIM3_IT_UPDATE, ENABLE);
  // Start Timer3
  TIM3_Cmd(ENABLE);             // Start the Timer
  // Enable global interrupts.
  enableInterrupts();
  // Loop forever
  while (1) {}

 タイマを起動する部分と無限ループが変更されています.まず, TIM3_Cmd 関数でタイマを起動する前に TIM3_ITConfig 関数で UPDATE イベントによる割り込みを許可しています.この設定を行うと Timer3 モジュールは UPDATE イベント割り込みを発することができるようになります.

 TIM3_Cmd 関数でタイマを起動したら, enableInterrupts 擬似関数で CPU に対する割り込みを許可します. enableInterrupts は,マクロとして宣言されていて,実際には, Reset Interrupt Mask (RIM) 命令が実行されます.

u8 beep_switch = DISABLE;  // Disable at first

//======================================
// Timer3 UPDATE event's
// Interrupt Service Routine
//======================================
@far @interrupt void Tim3Update_isr(void)
{
  // Clear the update flag
  TIM3_ClearFlag(TIM3_FLAG_UPDATE);
  // Toggle switch variable.
  beep_switch = !beep_switch;
  // Enable of disable BEEP
  BEEP_Cmd(beep_switch);        // Control BEEP
  return;
}

 Tim3Update_isr が,割り込みサービス・ルーチン (ISR) です. ISR であることを示すために, @interrupt というディレクティブが追加されています.このディレクティブは, COSMIC社のコンパイラに特有の記述方法なので, RESONANSE社のコンパイラを使う場合には,適宜変更してください.

 ISR では, beep_switch という変数を使って, Beeper モジュールの ON/OFF を行っています.この変数は, ISR 内部でしか使用されないので,大域変数にする必要はありません.ここでは,ある目的のために後で使えるように大域変数としてあります.

 処理の中身は,前回作成したフラグを監視するプログラムとほぼ同じです.異なっているのは,現在の Beeper の発音状態を大域変数で記憶していることだけです.

割り込みベクタの設定

 main.c は,書き換えましたが,まだ,重要な変更が残っています. ISR の処理内容は書きましたが,割り込みイベントが発生したときにどの処理を行うべきか,を関連付けていません.この関連付けのために使用されるのが,割り込みベクタです.

 割り込みベクタは, stm8s_interrupt_vector.c というファイルに記述されています.ワークスペース・エクスプローラにある, stm8s_interrupt_vector.c ファイルをダブル・クリックすると,エディタが開きます.必要な変更は,2か所です.

割り込みサービスルーチンの宣言

 第一の変更点は, ISR の宣言です. ISR は, main.c ファイルに記述したため,そのままでは, stm8s_interrupt_vector.c ファイルからは参照することができません.そのため, stm8s_interrupt_vector.c ファイルで ISR を外部参照できるように extern 宣言しておきます.

割り込みベクタを割り当てる

 もうひとつの変更点は,割り込みイベントと ISR を関連付けるための割り込みベクタ・テーブルの変更です. Timer3 モジュールの UPDATE イベントは,15番目の割り込みとして処理されます.そのため,テーブルの irq15 と書いてある行を変更します.

 それぞれの割り込みイベントと割り込み番号の関係は, STM8S105xx データシート(ドキュメント番号14771)の "Interrupt vector mapping" (割り込みベクタ割り当て表)に記述されています.

 アプリケーションは,以上で完成です.ビルドして,エラーが発生しないか確認しましょう.

ST社のファームウェア・ライブラリ(FWLib)には,割り込みベクタ・テーブルを提供するもうひとつの方法が用意されています.それは,ライブラリの project ディレクトリに配置されている二つのファイル stm8s_it.hstm8s_it.c をコピーして使うことです.これらのファイルには,割り込みイベント別に ISR が定義されており,ファイル stm8s_it.c を変更するだけで使用することができます.また,ライブラリに付属しているプロジェクト例でも多用されています.

ところが, stm8s_it.c ファイルの関数から、たとえば main.c ファイルにある変数や関数などを使用するときには,それらの外部参照宣言を stm8s_it.c ファイルに記述しなくてはなりません.ヘタをすると,二つのファイルに記述が分散してしまう恐れがあります.そのため,この例では, stm8s_interrupt_vector.c ファイルを使用して, main.c ファイルにある ISR を呼び出す方式をとりました.筆者は,こちらのほうがわかりやすいと考えましたが,みなさんはいかがでしょうか.

プログラムを書き込んで,実行しよう

 ハードウェアは,今までと同じです.そのまま,メニューから「Debug → Start Debugging」を選択し,デバッガを起動します.そして,メニューの「Debug → Run」を選択すると,プログラムの実行が開始されます.

メニューの「Debug → Stop Program」を選択すると,音の断続が停止し,さらに,「Debug → Restart」を選択するとプログラムをリセット直後の状態で停止させます.

 次回は,プログラムの動作状態をデバッガで監視してみます.

田中範明(noritan.org)

カテゴリ:

トラックバック

このエントリーのトラックバックURL:
http://www.eleki-jack.com/mt/mt-tb.cgi/4236





カテゴリ

会社案内
情報セキュリティおよび個人情報の取り扱いについて

コメントとトラックバックは、spamを予防するために、編集担当が公開の作業をするまで非公開になっています。
コメントはそれぞれ投稿した人のものです。

Powered by
Movable Type 4.1
/*yahoo remove*/