/* 24系統RCサーボパルス発生システム 15μsecのインターバルタイマ割り込みを用いて, ソフトウェアで24系統のパルスをポートから出力する。 ITU1のインターバルタイマを用いる。 PWM周期:20msec。
OUTPORT0 bit0 : 系統0 OUTPORT0 bit1 : 系統1 OUTPORT0 bit2 : 系統2 OUTPORT0 bit3 : 系統3
: OUTPORT1 bit0 : 系統8 OUTPORT1 bit1 : 系統9 OUTPORT1 bit2 : 系統10 OUTPORT1 bit3 : 系統11
: OUTPORT2 bit0 : 系統16 OUTPORT2 bit1 : 系統17 OUTPORT2 bit2 : 系統18 OUTPORT2 bit3 : 系統19
: OUTPORT2 bit7 : 系統23
このプログラムでのシリアル通信制御テスト A,B,C,...V,W,Xの入力
系統0〜24のパルスをそれぞれ50μsec長くする a,b,c,...v,w,xの入力
系統0〜24のパルスをそれぞれ50μsec短くする 0の入力
系統0〜24のパルスをすべて1500μsecの長さにする 1の入力
系統0〜24のパルスをすべて異なる長さにする */
#include "3048f.h" #include
"h8_3048.h"
#define OUTPORT0 P1 #define OUTPORT1
PA #define OUTPORT2 PB
#define PERIOD 20000 /*PWM周期(=20msec)*/ #define
INTERVAL 15 /*割り込み周期15μsec*/
typedef struct { unsigned
char bytedata[3]; } tribyte_t;
typedef struct { int
pulseWidth; int bitnum; }
pulsewidth_t;
/*パルス幅は最初1000,1000,1200,1000,1000,1000,2000,2000μsec*/ /*
1200,1100,2000,1200,1800,1700,1700,2000μsec*/ /*
1500,1100,2000,1300,1400,1500,2000,1600μsec*/ /*とする*/ /*★注意1 使用していない系統の値は1500に固定すること*/ /*★注意2 値は1000〜2000とする*/ int
pulseWidth[24]={ /*単位μsec*/
1000,1000,1200,1000,1000,1000,2000,2000,
1200,1100,2000,1200,1800,1700,1700,2000,
1500,1100,2000,1300,1400,1500,2000,1600 };
tribyte_t tribyte[26]; /*切り替えビットパタン*/ int
switchtime[26]; /*INTERVAL μsecで数えての切り替え時刻*/ int switchindex;
/*ポインタ*/ volatile int switchtimecurrent; /*次の切り替え時刻(INTERVAL
μsecで数える)*/ volatile int tick; /*現在時刻(INTERVAL μsecで数える)*/ int
period; /*PWM周期(INTERVAL μsecで数える)*/
pulsewidth_t b_pulseWidth[24]; tribyte_t
b_tribyte[26]; int b_switchtime[26]; const tribyte_t
initstate={{0xff,0xff,0xff}}; /*初期状態*/ const tribyte_t
mask[24]={
{0xfe,0xff,0xff},{0xfd,0xff,0xff},{0xfb,0xff,0xff},{0xf7,0xff,0xff},
{0xef,0xff,0xff},{0xdf,0xff,0xff},{0xbf,0xff,0xff},{0x7f,0xff,0xff},
{0xff,0xfe,0xff},{0xff,0xfd,0xff},{0xff,0xfb,0xff},{0xff,0xf7,0xff},
{0xff,0xef,0xff},{0xff,0xdf,0xff},{0xff,0xbf,0xff},{0xff,0x7f,0xff},
{0xff,0xff,0xfe},{0xff,0xff,0xfd},{0xff,0xff,0xfb},{0xff,0xff,0xf7},
{0xff,0xff,0xef},{0xff,0xff,0xdf},{0xff,0xff,0xbf},{0xff,0xff,0x7f}, };
void turndownBit(tribyte_t *p,int
bitnum) { int i; for
(i=0;i<3;i++) {
p->bytedata[i]&=mask[bitnum].bytedata[i];
} }
/*スイッチング情報を作成するb_のついた変数に作る*/ /*有効データ数を返す*/ int
makeSwitchInfo(void) { int
i,j; pulsewidth_t tmp; for
(i=0;i<24;i++) {
b_pulseWidth[i].pulseWidth=(pulseWidth[i]+(INTERVAL>>1))/INTERVAL;
b_pulseWidth[i].bitnum=i; }
/*小さい順に並べ替え*/ for (i=0;i<24-1;i++)
{ for (j=i+1;j<24;j++)
{ if
(b_pulseWidth[j].pulseWidth<b_pulseWidth[i].pulseWidth)
{
tmp=b_pulseWidth[j];
b_pulseWidth[j]=b_pulseWidth[i];
b_pulseWidth[i]=tmp;
} }
} b_tribyte[0]=initstate;
b_switchtime[0]=0; j=0; for
(i=0;i<24;i++) { if
(b_pulseWidth[i].pulseWidth==b_switchtime[j])
{
turndownBit(&b_tribyte[j],b_pulseWidth[i].bitnum);
} else
{
j++;
b_tribyte[j]=b_tribyte[j-1];
turndownBit(&b_tribyte[j],b_pulseWidth[i].bitnum);
b_switchtime[j]=b_pulseWidth[i].pulseWidth;
} }
b_switchtime[++j]=0;
b_tribyte[j]=b_tribyte[j-1]; return j+1; }
/*スイッチング情報を実使用データ領域にコピーする*/ void moveSwitchingData(int
num) { int i; for
(i=0;i<num;i++) {
tribyte[i]=b_tribyte[i];
switchtime[i]=b_switchtime[i]; } }
/*スイッチング情報の生成と書き換え*/ /*スイッチング情報の書き換えはこの関数で行う*/ void
renewSwitchingData(void) { int
num; num=makeSwitchInfo();
/*パルス生成作業中はスイッチング情報書き換えは行わず,待ちになる*/ while
(tick<1500/INTERVAL && switchtimecurrent &&
period-100<tick);
moveSwitchingData(num); }
main() { int num; char
ch; int i;
initLed(); initSCI1();
initTimer1Int(INTERVAL);
/*INTERVALμsecのインターバルタイマ割り込み*/ OUTPORT0.DDR=0xff;
/*ポートの出力設定*/ OUTPORT1.DDR=0xff;
/*ポートの出力設定*/ OUTPORT2.DDR=0xff;
/*ポートの出力設定*/
switchindex=switchtimecurrent=tick=0;
period=PERIOD/INTERVAL;
num=makeSwitchInfo();
moveSwitchingData(num);
E_INT(); startTimer1();
turnOnLed(0); while (1)
{
ch=getCharSCI1(); if
('A'<=ch && ch<='X')
{
i=ch-'A';
pulseWidth[i]+=50;
if (2000<pulseWidth[i])
pulseWidth[i]=2000; } else
if ('a'<=ch && ch<='x')
{
i=ch-'a';
pulseWidth[i]-=50;
if (pulseWidth[i]<1000)
pulseWidth[i]=1000; } else
if (ch=='0')
{
for (i=0;i<24;i++)
pulseWidth[i]=1500; } else
if (ch=='1')
{
for (i=0;i<24;i++)
pulseWidth[i]=1000+40*i;
}
renewSwitchingData(); } }
#pragma asm .SECTION MYVEC,
DATA, LOCATE=H'000070
.ORG H'000070
;IMIA1 .DATA.L
_TimerIntFunc .SECTION
P,CODE,ALIGN=2 ;これを忘れてはいけない #pragma endasm #define clearTimer1Flag()
(ITU1.TSR.BIT.IMFA=0)
#pragma interrupt (TimerIntFunc) void TimerIntFunc()
/*タイマ割り込みルーチン*/ { static int
cnt=0,blink=0; char *p; if
(tick++==switchtimecurrent)
{ p=(char
*)&tribyte[switchindex];
OUTPORT0.DR.BYTE=*p++;
OUTPORT1.DR.BYTE=*p++;
OUTPORT2.DR.BYTE=*p;
switchtimecurrent=switchtime[++switchindex]; } else
if (tick==period) {
switchindex=switchtimecurrent=tick=0;
if (++cnt==25)
{
cnt=0;
P5.DR.BIT.B1=blink=1-blink;
} } clearTimer1Flag();
/*タイマステータスフラグのクリア 忘れないこと*/ } |