Last active
February 28, 2018 14:46
-
-
Save 7m4mon/0d2a13921ad0424b8396bea14056959f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ふみきりのオモチャ | |
* 2018/02/28 7M4MON | |
* Memory usage: ROM=19% RAM=16% - 19% | |
*/ | |
#include <12f683.h> // サーボを使うのでCCPモジュールがある683を選定 | |
#fuses INTRC_IO, NOWDT, PUT, NOPROTECT, NOMCLR, NOBROWNOUT | |
#use Delay(CLOCK=4000000) // 1cycle = 1us | |
#use fast_io(a) | |
#define PIN_LED1 PIN_A0 | |
#define PIN_LED2 PIN_A1 | |
#define PIN_SERVO PIN_A2 | |
#define PIN_EXE PIN_A3 | |
#define PIN_CANCEL PIN_A4 | |
#define PIN_BUZZ PIN_A5 | |
/* タイマの定数は実機での実験結果により10% 早めた値にする */ | |
#define BUZZ_TIME_523 (239) // 523Hz -> 1912us周期、半周期は 938us、タイマの都合で8bit,DIV_4 → 938 ÷ 4 (タイマ2は減算カウンタ) | |
#define BUZZ_TIME_659 (190) // 659Hz -> 1517us周期、半周期は 759us、タイマの都合で8bit,DIV_4 → 759 ÷ 4 (タイマ2は減算カウンタ) | |
#define INTRPT_50MS (255 - 160) /* 約50ms毎*/ | |
#define POST_500MS_DIV 5 /* 250ms ÷ 50ms */ | |
#define EXE_TIMEOUT (20*4) /* 20秒 */ | |
#define SERVO_CYCLE (65535-20000) // 20ms → サーボモーターのサイクル | |
#define SERVO_H_DEG (SERVO_CYCLE + 1100) // 1ms = 0° | |
#define SERVO_V_DEG (SERVO_CYCLE + 2000) // 2ms = 90° | |
#define SERVO_POS_DIV 5 // サーボの動かすポジションの分割数 | |
#define SERVO_MOVE_DEG ((SERVO_V_DEG - SERVO_H_DEG) / SERVO_POS_DIV) | |
#define SERVO_MOVE_ADD 1 // サーボモーターを角度が一致してから何回動作させるか | |
/* グローバル変数 */ | |
unsigned int1 exe = 0; /* 実行中フラグ */ | |
unsigned int8 exe_time = 0; /* 0:L点灯_BUZZ_OFF, 1:0:L点灯_BUZZ_ON, 2:R点灯_BUZZ_OFF, 3:R点灯_BUZZ_ON */ | |
unsigned int8 postscale = POST_500MS_DIV; | |
unsigned int8 buzz_state = 0; | |
signed int8 servo_move = 0; | |
unsigned int16 deg = SERVO_V_DEG; | |
/* TIMER1はサーボモーター制御のため、コンペアモードで使う*/ | |
// 20ms毎にパルスを出力する。 | |
#INT_TIMER1 | |
void timer1_isr(){ | |
set_timer1(SERVO_CYCLE); | |
if(servo_move > 0){ | |
output_high(PIN_SERVO); | |
} | |
} | |
#INT_CCP1 //コンペアマッチ割り込み | |
void ccp1_isr(){ //出力をLowにする | |
output_low(PIN_SERVO); | |
} | |
/* カンカン音の周期での割り込み */ | |
#INT_TIMER2 | |
void set_buzzer(void){ | |
unsigned int8 buzz_time; | |
if(exe && (exe_time & 1) ){ /* 実行中かつexe_timeが奇数だったら */ | |
output_toggle(PIN_BUZZ); | |
buzz_state++; | |
buzz_state &= 3; // 4→0 | |
/* 523Hzと659Hzを交互に鳴らす*/ | |
buzz_time = (buzz_state & 2) ? BUZZ_TIME_523 : BUZZ_TIME_659; | |
set_timer2(buzz_time); | |
}else{ | |
output_low(PIN_BUZZ); | |
} | |
} | |
/* サーボモーターの角度を決める。実行中なら角度上げ、停止中なら角度下げ */ | |
void set_servo(void){ | |
unsigned int16 deg_work; | |
signed int8 servo_move_work; | |
deg_work = exe ? (deg - SERVO_MOVE_DEG) : (deg + SERVO_MOVE_DEG); | |
if((deg_work > SERVO_V_DEG)){ | |
deg_work = SERVO_V_DEG; | |
}else if(deg_work < SERVO_H_DEG){ | |
deg_work = SERVO_H_DEG; | |
} | |
/* 角度が一致して動かす必要がない場合は止める */ | |
servo_move_work = (deg == deg_work) ? (servo_move - 1) : SERVO_MOVE_ADD; | |
servo_move = (servo_move_work < 0) ? 0 : servo_move_work; | |
CCP_1 = deg_work; | |
deg = deg_work; | |
} | |
/* ブザー用の割り込み許可(サーボと排他利用) */ | |
void enable_interrupt_buzz(void){ | |
disable_interrupts(INT_TIMER1); //タイマ1(サーボ)割込み禁止 | |
disable_interrupts(INT_CCP1); //CCP(サーボ)割り込み禁止 | |
set_timer2(BUZZ_TIME_523); | |
enable_interrupts(INT_TIMER2); //タイマ2(ブザー)割込み許可 | |
enable_interrupts(INT_TIMER0); //タイマ0割込み許可 | |
} | |
/* サーボ用の割り込み許可(ブザーと排他利用) */ | |
void enable_interrupt_servo(void){ | |
disable_interrupts(INT_TIMER2); //タイマ2(ブザー)割込み禁止 | |
set_servo(); | |
set_timer1(SERVO_CYCLE); | |
enable_interrupts(INT_TIMER1); //タイマ1(サーボ)割込み許可 | |
enable_interrupts(INT_CCP1); //CCP(サーボ)割り込み許可 | |
enable_interrupts(INT_TIMER0); //タイマ0割込み許可 | |
} | |
/* 50msに一度のタイマ割り込み */ | |
#INT_RTCC | |
void set_cross_state(void){ | |
disable_interrupts(GLOBAL); //グローバル割込み禁止 | |
if(postscale == 0){ /* 250ms */ | |
postscale = POST_500MS_DIV; | |
if(exe){ | |
exe_time++; | |
exe = (exe_time > EXE_TIMEOUT) ? 0 : 1; | |
if(exe_time & 2){ | |
output_low(PIN_LED2); | |
output_high(PIN_LED1); | |
}else{ | |
output_low(PIN_LED1); | |
output_high(PIN_LED2); | |
} | |
if(exe_time & 1){ | |
enable_interrupt_buzz(); | |
}else{ | |
enable_interrupt_servo(); | |
} | |
}else{ // 停止中 | |
output_low(PIN_LED1); | |
output_low(PIN_LED2); | |
exe_time = 0; | |
enable_interrupt_servo(); | |
} | |
}else{ | |
postscale--; | |
} | |
set_timer0(INTRPT_50MS); | |
enable_interrupts(GLOBAL); //グローバル割込み許可 | |
} | |
/* ボタンをチェックして動作状態を決定する。 */ | |
void check_button(void){ | |
/* 三項演算子だとうまく動かないのでベタに書くことにする。 */ | |
//exe = input(PIN_EXE) ? exe : 1; // 実行ボタンが押されたら実行にする | |
//exe = input(PIN_CANCEL) ? exe : 0; // 停止ボタンが押されたら停止にする | |
if(!input(PIN_EXE)){ | |
exe = 1; | |
}else if (!input(PIN_CANCEL)){ | |
exe = 0; | |
} | |
} | |
void main(void){ | |
/*ピンの設定*/ | |
setup_adc_ports(NO_ANALOGS); | |
port_a_pullups(0b00010000); | |
set_tris_a(0b00011000); // 3,4が入力 | |
/* 割り込み設定 */ | |
setup_counters(RTCC_INTERNAL , RTCC_DIV_256); // 256us毎 | |
set_timer0(INTRPT_50MS); // 50ms毎 | |
setup_timer_2(T2_DIV_BY_4,BUZZ_TIME_523,1); // 4us毎 | |
set_timer2(BUZZ_TIME_523); | |
//CCPの設定 | |
CCP_1 = SERVO_H_DEG; //初期化 | |
setup_ccp1(CCP_COMPARE_INT); //CCP1コンペアマッチした時の動作 | |
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); //内部クロック使用 プリスケーラ1倍 | |
set_timer1(SERVO_CYCLE); | |
enable_interrupts(INT_TIMER0); //タイマ0割込み許可 | |
disable_interrupts(INT_TIMER1); //タイマ1割込み許可 | |
disable_interrupts(INT_TIMER2); //タイマ2割込み許可 | |
disable_interrupts(INT_CCP1); //CCP割り込み許可 | |
enable_interrupts(GLOBAL); //グローバル割込み許可 | |
while(true){ | |
check_button(); /* ボタンの状態をチェック */ | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment