プログラムを動かそう
サーボの制御は簡単です。50hz-60hz(16ms-20ms)の周期で信号を送ってやれば動きます。
Hの信号を1.5±0.5msの状態になるようすれば左右に動きます(1.5msのとき真ん中)。
TW.GRB=3000(3000*0.5us=1.5ms)によってちょうどFTIOB端子からサーボを真ん中にする信号が出ます。
ここの値を2000から4000にすればサーボが右へ左へ60度と動きます。
なお、17500から4250程度で使うとサーボが90度左右に動きます。
FTIOB:Port8の2bit目、FTIOC:Port8の3bit目、P84/FTIOD:Port8の4bit目です。
#include "3664f.h"
/*カウンタは2mhz 0.5usec*/
void setTimerW_PWM(int time)
{
TW.TMRW.BYTE=7; /*PWMモードBCDを出力に*/
TW.TCRW.BIT.CCLR=1; /*TCNTはAでクリアする*/
TW.TCRW.BIT.CKS=3; /*クロックはφ/8*/
TW.TCRW.BIT.TOB=1; /*FTIOB=1*/
TW.TCRW.BIT.TOC=1; /*FTIOC=1*/
TW.TCRW.BIT.TOD=1; /*FTIOD=1*/
TW.TIOR0.BIT.IOB=1; /*TCNT=GRBでFTIOB=0*/
TW.TIOR1.BIT.IOC=1; /*TCNT=GRCでFTIOC=0*/
TW.TIOR1.BIT.IOD=1; /*TCNT=GRDでFTIOD=0*/
TW.GRA=time; /*Aは周期*/
TW.GRB=0;
TW.GRC=0;
TW.GRD=0;
TW.TMRW.BIT.CTS=1; /*タイマスタート*/
}
int main(void){
setTimerW_PWM(32000); /*周期は16ms*/
TW.GRB=3000;
TW.GRC=3000;
TW.GRD=3000;
return(0);
}
H8tinyは8つの10bitのA/D変換ポートがあり、常に変換し続けるスキャンモード(最大4ポート)とその都度読み出す必要がある単一モード(最大8ポート)がある。 変換時間は70ステート。スキャンモードの場合A/D変換された値はAD.DRA,AD.DRB,AD.DRC,AD.DRDに収められている。なお上位10bitに値があるので下位6bitはいらない情報。
/*A/Dスキャンモード*/
void setScanAD(int ch)
/*chは0-3まで0の時はAN0だけ*/
{
AD.CSR.BIT.ADIE =0; /*割込を使うかどうか*/
AD.CSR.BIT.ADST =0; /*A/Dストップ*/
AD.CSR.BIT.SCAN =1; /*1スキャンモード 0単一モード*/
AD.CSR.BIT.CKS =1; /*1高速 0低速*/
AD.CSR.BIT.CH =ch; /*an0-3を使う*/
AD.CSR.BIT.ADST =1; /*A/Dスタート*/
while(AD.CSR.BIT.ADF==0); /*一度エンドフラグを待つ*/
}
/*A/D単一モード*/
int getSingleAD(int ch)
{
AD.CSR.BIT.ADIE =0; /*割込を使うかどうか*/
AD.CSR.BIT.ADST =0; /*ADストップ*/
AD.CSR.BIT.SCAN =0; /*1スキャンモード 0単一モード*/
AD.CSR.BIT.CKS =1; /*1高速 0低速*/
AD.CSR.BIT.CH =ch; /*使うチャンネル指定*/
AD.CSR.BIT.ADST=1; /*A/Dスタート*/
while (AD.CSR.BIT.ADF==0); /*A/Dエンドフラグ待ち*/
AD.CSR.BIT.ADF=0; /*A/Dフラグを落とす*/
if(ch==0|ch==4)
return AD.DRA;
else if(ch==1|ch==5)
return AD.DRB;
else if(ch==2|ch==6)
return AD.DRC;
else
return AD.DRD;
}
int getMaskAD(int ch){
int adv;
adv = getSingleAD(ch) >> 11; /*使うのは上位5bit 32段階*/
adv &= 0x001f; /*上位にゴミがあるといけないのでマスクする*/
return adv;
}
5us単位でwaitがかけられる。wait(200)なら1ms待つことになる。
void wait(long msec){
/*0.005*msecだけ待つ*/
long i;
TV.TCRV0.BIT.CKS = 1; /* カウント開始 4Mhz*/
for(i=0;i<msec;i++){
while(TV.TCSRV.BIT.CMFA==0); /*フラグ待ち*/
TV.TCSRV.BIT.CMFA=0;
}
TV.TCRV0.BIT.CKS = 0; /* カウント停止*/
}
void setTimerV_time(){
/*0.005msec数えてくれる*/
TV.TCRV0.BIT.CCLR = 1; /*aでクリア*/
TV.TCRV0.BIT.CKS = 0; /*停止*/
TV.TCRV1.BIT.ICKS = 0; /*φ/4*/
TV.TCSRV.BIT.CMFA = 0; /* フラグクリア*/
TV.TCORA = 20; /*8bitなので255まで 4mhz*20:200khz*/
/*0.005msec:200khz*/
/* 5usec:200khz*/
}
int main(void){
setTimerV_time();
wait(200); /*1ms待つ*/
return(0);
}
TRGV入力からの遅延時間がTCORB、パルス幅が(TCORA−TCORB)の波形をソフト ウェアの介在なしに出力できます。
void setTimerV_out(){
/*0.05msec数えてくれる*/
TV.TCRV0.BIT.CMIEA= 0; /*割込不許可*/
TV.TCRV0.BIT.CCLR = 1; /*コンベアマッチAでクリア*/
TV.TCRV0.BIT.CKS = 1; /*クロックは1/8*/
TV.TCSRV.BIT.OS = 6; /*TCNTV=A 1 TCNTV=B 0*/
TV.TCRV1.BIT.TVEG = 2; /*たち下がり検知*/
TV.TCRV1.BIT.TRGE = 1; /*TRGVによるカウント開始とコンペアマッチによるクリア時のカウント停止を許可*/
TV.TCRV1.BIT.ICKS = 1; /*クロックは1/8*/
TV.TCORA = 200; /*255まで パルス幅0.05msec*/
TV.TCORB = 100; /*255まで 遅延時間0.05msec*/
/*遅延時間をのばしたければクロックを下げる。*/
/*最大1/128までできる(125khz 8usec)(250*8usec=2msecの遅延まではできる)*/
}
int main(void){
IO.PMR1.BIT.IRQ3=1; /*port17はtrgvモード*/
setTimerV_out();
return(0);
}
もう少し整理してから。
熊谷研の資料を見ればうちのサイトなど見なくてもいい気がするな…
e-mail:aoki_ssr@hotmail.com