発表用タイマー

  1. 目的

     研究発表などでは、進行時間を通知するため独自のルールがあります。

      一人発表の場合時間は8分とする
      終了2分前に予鈴を鳴らす
      質問は5分

    この時間を知らせるため、タイムキーパーが必要になりますが。ここでは、タイムキーパーの処理を行うタイマーを制作します。

  2. システム構成

    1. 構成

       人手で行うなう場合、ストップウオッチ(時計)とベルを利用します。ここでは、時計はPIC内部のターマーを利用します。まだ、ベルの替わりにスピーカを利用します。
       開始時に、スタートボタンを押します。これで、計時を開始します。計時は発表時間を減らします。残り2分で、スピーカに信号を送ります。

    2. 手法

       スタートボタンはext割り込みを利用します。実行中でもスタートボタンが有効になります。計時にはタイマー0割り込みを利用します。ブザー音にはタイマー割り込み1を利用します。

    3. 回路構成

       ポートBの1〜7を7素子数字素子C535のa〜gに接続します。ポートAの0〜2で、7素子の各桁をドライブします。ポートAの第3ビット(PA3)にはソフトウエアでブザー音を発振し、これをブザーに接続します。
       ポートBの0端子には押しボタンスイッチを接続し、外部割込みとして利用します。タイマーのスタートや進行に利用し、最初の押し下げで、発表モードに入ります。発表時間中に押し下げた場合は質問モードに移行します。
       発表者の人数(一人/二人)で、発表時間が異なります。この切り替えは、PA3に接続された切り替えスイッチを利用します。他に。発信用セラミック振動子(20MHz、osc端子)、CLR端子(5Vに接続)、への接続が必要です。


      電源は、1.5Vの乾電池2本を利用します。仕様では、3vで、20MHzのクロックは保証外ですが、テストでは動作しました。クロックを4MHzに下げる方が安全です。その場合、タイマーの設定値を1/5に下げる必要があります。

  3. プログラム構成


    1. プログラム:3種の割り込み

       プログラムでは3種の割り込みを利用します。一つは、PB0端子からのスイッチによる外部割込みで、開始や終了など次のフェーズに進むための信号として利用します。
       外部割込み#int_ext は、押しボタンスイッチの押し下げで発生します。発表モード(prs==1)での押し下げは、質問モードに移行します。質問モードで押し下げた場合、発表モードに移行します。
       タイマー0の割り込みは、時間進行を行います。タイマー0は 10mS で割り込みます。時刻は3桁の分単位で表示します。031 は3.2分の意味で、これは、3分12秒に相当します(0.1分は6秒単位)。発表モードでは残り時間を減算表示し、質問モードでは増加計数をします。
       タイマー1の割り込みは、ブザー音の生成に利用します。prd で周期を設定し、PIN_A3 を反転します。ブザー音は、発表残り2分で1回、発表終了で2回、質問5分経過で3回鳴ります。音の高さも変更しています。

    2. プログラムソース

      #include <16f88.h>
      #include <stdlib.h>
      
      #fuses HS,NOWDT,NOLVP//内部クロック、WDT,LVPなし
      #use delay(CLOCK=20000000) //クロック4MHz
      #use fast_io(B)
      
      //PB7..PB1に7素子のg..aを接続
      //PA2,PA1,PA0に7素子の桁信号を接続
      //PA3:スピーカ
      //PB0:スタートスイッチ
      //PA4:人数設定スイッチ
      
      //int ct;//数字の更新間隔
      long val;//表示する数字
      int digit;//表示する桁
      
      //7素子表示パターン
      int segment_data[]={0x7E,0x0C,0xB6,0x9E,0xCC,0xDA,0xFA,0xE,0xFE,0xCE};
      char st[3];
      int prs;
      long cnt0=600;
      int buz,flag,buzcnt,seq;
      int pt=80;
      long prd;
      long tunit=600;
      
      
      #int_ext
      void extisr(){
       //押しボタン処理
        val=0;
        prs=1;
       
       if (input_a() & 0x10){
              val=80;
        }
         else {
             val=150;
        }
      
        //val=80;
        //開始の音
        prd=64500;
        buzcnt=0;
        enable_interrupts(INT_TIMER1);
        buz=1;
        seq=0;
        //output_bit(PIN_C0,0);
      }
      
      #int_rtcc   //タイマ0割込み
      void rtcc_isr() 
      {
         //時間処理    
        if(cnt0 == 0){         
          if(val==0) prs=0;//発表/質問切り替え         
          if(prs) val--;
          else val++;
                          
          if(prs && val==20){//予鈴
                  prd=64500;//ブザー音開始
                  set_timer1(prd);
                  enable_interrupts(INT_TIMER1);
                  buz=1;
                  buzcnt=0;
              }
              
              if( val==0){//発表終了
                  prd=65000;//ブザー音開始
                  set_timer1(prd);
                  enable_interrupts(INT_TIMER1);
                  buz=1;
                  buzcnt=1;//続けて1回ならす
              }
              
              if( !prs && (val==50)){//質問終了
                  prd=65200;//ブザー音開始
                  set_timer1(prd);
                  enable_interrupts(INT_TIMER1);
                  buz=1;
                  buzcnt=2;//続けて2回ならす
              }
                      
          if(val==1000) val=0;
        
          st[2]=val/100;
          st[1]=val/10-st[2]*10;
          st[0]=val%10;
         }
       
         cnt0++; 
         if(cnt0==tunit) cnt0=0;
      
         //ブザーを止める
         if(cnt0 % 100 ==0 ){
                if(buz) {
                  buz =0;
                  if(buzcnt>0) seq=1;
                  disable_interrupts(INT_TIMER1);
                  buzcnt--;
                }
            if(seq==2 ){//ブザー再開
                  set_timer1(prd);
                  enable_interrupts(INT_TIMER1);
                  buz=1;
                  seq=0;
                  output_bit(PIN_C0,1);
               }      
             if(seq==1) seq=2;
         }
       
        set_timer0(60);//10mS
      }
      
      #int_timer1
      void timer1_isr()
      {//ブザー音の生成
           output_bit(PIN_A3,flag);
           if (flag==1) flag=0; else flag=1;
           set_timer1(prd);
      
      }
      
      void main(){
      
        set_tris_b(0b00000001);//Bポート下位4bit出力
        //set_tris_a(0b11111100);
        digit=0;
        cnt0=0;
        buz=0;
        prs=1;
        buzcnt=0;
      
        val=80;//表示する値
        set_timer0(60);
        output_bit(PIN_C0,0);
        
        setup_counters(RTCC_INTERNAL,RTCC_DIV_256);
        setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);
        
        enable_interrupts(INT_EXT);
        enable_interrupts(INT_TIMER0);
        enable_interrupts(GLOBAL);
      
        while(1){
                
         if(digit== 2){//第3桁の表示
              output_b( segment_data[st[2]]);
              output_bit(PIN_A2,1);//3桁表示開始
              delay_ms (5);        //表示期間(ミリ秒)
              output_bit(PIN_A2,0);//表示を消す
              delay_us(100);
            }
      
          if(digit== 1){
              output_b( segment_data[st[1]]);
              output_bit(PIN_A1,1);
              delay_ms (5);
              output_bit(PIN_A1,0);
              delay_us(100);
            }
      
          if(digit == 0){
              output_b( segment_data[st[0]]);
              output_bit(PIN_A0,1);
              delay_ms (5);
              output_bit(PIN_A0,0);
              delay_us(100);
            }
      
          digit ++;//表示桁を変更
          if(digit ==3 ) digit=0;
        }
      
      }