研究発表などでは、進行時間を通知するため独自のルールがあります。
一人発表の場合時間は8分とする
終了2分前に予鈴を鳴らす
質問は5分
この時間を知らせるため、タイムキーパーが必要になりますが。ここでは、タイムキーパーの処理を行うタイマーを制作します。
人手で行うなう場合、ストップウオッチ(時計)とベルを利用します。ここでは、時計はPIC内部のターマーを利用します。まだ、ベルの替わりにスピーカを利用します。
開始時に、スタートボタンを押します。これで、計時を開始します。計時は発表時間を減らします。残り2分で、スピーカに信号を送ります。
スタートボタンはext割り込みを利用します。実行中でもスタートボタンが有効になります。計時にはタイマー0割り込みを利用します。ブザー音にはタイマー割り込み1を利用します。
ポート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種の割り込みを利用します。一つは、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回鳴ります。音の高さも変更しています。
#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;
}
}