メインプログラム:T_CONT.c
プロセッサーエキスパート(PE)で設定した結果、下図の様なソースファイルが生成されます。初期設定は全て完了していますのでMAIN関数の含まれているT_CONT.cのみを記述します。
【宣言部】
Types definition
今まで使っていたchar型やint型などのデータ型をunsibned intと書くのは長いのでwordとする宣言文です。
MAS_CON:マスコンVRをAD変換した結果を格納するレジスタです。
SPEED:モーターの回転数を制御するレジスタです。
BREAK_CON:ブレーキVRをAD変換した結果を格納するレジスタです。
PRESSURE:圧力計サーボの指示値レジスタです。
ATCPOS: ATCセンサー番号レジスタです。
ATCFLG: ATCモードフラグです。
STOPFLG:停止可能フラグです。
/* Types definition */
typedef unsigned char byte;
typedef unsigned int word;
typedef unsigned long dword;
typedef unsigned long dlong[2];
/***** 宣言部 *****/
word MAS_CON; // マスコンレバーの位置レジスタ
word SPEED; // 電車の現在速度レジスタ
word BREAK_CON; // ブレーキレバーの位置レジスタ
word BREAK; // 電車の現在のブレーキレジスタ
word PRESSURE; // 圧力計値レジスタ
byte ATCPOS; // ATCセンサー番号レジスタ
byte ATCFLG; // ATCモードフラグ
byte STOPFLG; // 停止可能フラグ
【ATC割込み関数】
PORTBの立下りで割込みが発生すると、この関数が呼び出されます。割込みフラグをクリアして、どのポートが原因かでATCPOS(ATCポジション)を設定します。
//*********************************************************
//* ATC割込み関数
//*********************************************************
ISR(ATC) // PTB割込み処理
{
PTBSC_PTBACK = 1; // 割込みフラグのクリア
if(PTBD_PTBD0 == 0) ATCPOS = 1; // センサー1
if(PTBD_PTBD1 == 0) ATCPOS = 2; // センサー2
if(PTBD_PTBD2 == 0) ATCPOS = 3; // センサー3
}
【ATC運転関数】
関数名はATCMODEです。この関数はATC運転の処理を行います。
SPEEDもBREAK_CONもMAS_CONも0〜1023の可変範囲です。これらをプログラムで制御します。まずSPEEDが300以上の場合はBREAK_CONを800として速度を落とします。
SPEEDが300以下になったらブレーキを解除し、マスコンを140に設定します。電車は慣性走行を行いながら徐々に速度が低下し、SPEEDが140になった時点で定速度走行となります。
SPEEDが300以下でセンサー1が検出されるとATCPOSは1となり、SPEEDは徐行運転速度の120となり、停止可能フラグをセットしてATCPOSが2になるまで維持されます。
停止可能フラグが1でセンサー2が検出されるとATCPOSは2となり、SPEEDを0として停止します。ATCPOSが2でSPEEDが0の状態は乗降待ちとなり5秒間停車した後、自動運転終了のため、ATCフラグとATCPOSをクリアします。停止可能フラグが0の場合はそのまま通過して次の駅のセンサーまで走行が維持されます。
//*********************************************************
//* ATC運転関数
//*********************************************************
void ATCMODE(void)
{
int i;
/***** 速度300以上 *****/
if(SPEED >=300)
{
BREAK_CON = 800; // ブレーキを800
MAS_CON = 140; // マスコンを140(徐行)
}
/***** 速度300以下 *****/
if(SPEED < 300)
{
BREAK_CON = 100; // ブレーキ解除
}
/***** センサー1検出(速度300以下) *****/
if(ATCPOS == 1 & SPEED <= 300)
{
SPEED = 120; // 徐行運転
BREAK_CON = 100; // ブレーキ解除
ATCPOS = 0; // センサー番号レジスタをクリア
STOPFLG = 1; // 停止可能フラグをセット
}
/***** 乗降待ち *****/
if(ATCPOS == 2 & SPEED == 0)
{
for(i=1;i<6;i++)
{
Cpu_Delay100US(10000);
}
/***** 自動運転終了 *****/
ATCFLG = 0; // 自動運転フラグをクリア
ATCPOS = 0; // センサー番号フラグをクリア
}
/***** センサー2検出(停止可能) *****/
if(ATCPOS == 2 & STOPFLG)
{
MAS_CON = 0; // マスコンを停止位置に設定
SPEED = 0; // 停止
STOPFLG = 0; // 停止可能フラグクリア
}
}
【初期設定】
TRIM設定はお馴染みの内臓クロックトリムの設定です。初期設定はポートB割込み用の設定です。
//*********************************************************
//* メイン関数
//*********************************************************
void main(void)
{
/* Write your local variable definition here */
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/
/* Write your code here */
/* For example: for(;;) { } */
//*********************************************************
//* 初期設定
//*********************************************************
/***** TRIM設定 *****/
ICSTRM = 0x9E;
ICSSC_FTRIM = 1;
/***** 初期設定 *****/
PTBPS = 7; // PORTB0〜PORT2を割込み要因に設定
PTBES = 0; // 立下りで割込み発生に設定
PTBSC_PTBMOD = 0; // 割込みはエッジのみ検出に設定
PTBSC_PTBIE = 1; // 割込み許可
ATCPOS = 0; // ATCセンサー番号レジスタをクリア
【メインループ】
ATC自動運転スイッチが押されているかチェックし、押されていればATCFLG(ATCフラグ)を反転します。次にATCフラグにより手動運転かATC運転かに分岐します。ATCフラグが1ならばATC運転関数にジャンプします。
モーター制御PWMの可変幅は0〜20000、SPEEDレジスタの値は0〜1023なのでSPEEDレジスタの値を20倍してモーター制御PWMのパルス幅を可変します。
手動運転の時はマスコンとブレーキのボリュームをAD変換します。
SPEEDに対してMAS_CONが大きいとSPEEDをインクリメントして加速します。MAS_CONがSPEEDより小さい時はSPEEDからBREAKの値を減算して減速します。BREAKは最低値が1なのでブレーキをかけなくても徐々に減速します。(慣性走行)BREAKの値が大きいとそれだけ減速率が上がり早く速度が低下します。
圧力計表示はBREAK_CONの可変範囲0から1023をサーボの動作範囲2.375mS〜1.53mSに変換して出力しています。サーボにより可変できる範囲が違いますので注意してください。
速度計表示はSPEEDの可変歯に0〜1023をサーボの動作範囲2.375mS〜0.67mSに変換して出力しています。
ブレーキのAD変換する時に100を加算するのは、AD変換値が100を超えるまでBREAK値が慣性走行時と同じ1になってしまうのでブレーキを操作しても速度が低下しない事を防いでいます。
ボリューム値のオフセットと思えば良いでしょう。
//*********************************************************
//* メインループ
//*********************************************************
for(;;)
{
/***** 自動運転スイッチチェック *****/
if(PTBD_PTBD6 == 0)
{
Cpu_Delay100US(100);
if(PTBD_PTBD6 == 0) ATCFLG = !ATCFLG;
while(!PTBD_PTBD6){}
}
/***** ATC運転/手動運転分岐 *****/
if(ATCFLG == 1)
{
ATCMODE(); // 自動運転
}
else
{
/***** 手動運転 *****/
STOPFLG = 0; // 停止可能フラグクリア
ATCPOS = 0; // センサー番号レジスタクリア
ADCSC1 = 11; // AD変換スタート
while (!ADCSC1_COCO); // AD変換終了待ち
MAS_CON = ADCR; // 変換値をレジスタに格納
Cpu_Delay100US(10);
ADCSC1 = 10; // AD変換スタート
while (!ADCSC1_COCO); // AD変換終了待ち
BREAK_CON = ADCR + 100; // 変換値にOFFSETを付けてレジスタに格納
}
/***** 圧力計制御 *****/
PRESSURE = 9500-BREAK_CON*6; // 2.375mS〜1.53mS
TPM1C1V = PRESSURE; //
BREAK = (BREAK_CON / 100); // BREAK=1〜11
/***** 速度制御 *****/
if(MAS_CON>SPEED) //
{
Cpu_Delay100US(200);
SPEED = SPEED + 1; // 加速
}
else
{
if(SPEED) // 速度が0でない
{
if(SPEED > BREAK) // 速度がブレーキより大きい
{
SPEED = SPEED - BREAK; // 減速
}
else // 速度がブレーキより小さい
{
SPEED = 0; // 停止
}
Cpu_Delay100US(1000);
}
}
/***** 速度計制御 *****/
if(SPEED > 50)
{
TPM1C0V = 9500 - ((SPEED - 50) * 7); // 2.375mS〜0.67mS
}
else
{
TPM1C0V = 9500;
}
/***** 線路出力電圧制御 *****/
if(PTBD_PTBD7) // 進行方向スイッチ
{ //
TPM2C1V = 0; // SPEED 比 タイマー値
Cpu_Delay100US(1); // 停止 = 0 0% 0
TPM2C0V = SPEED * 20; // 全速 = 1023 100% 20000
}
else
{
TPM2C0V = 0;
Cpu_Delay100US(1);
TPM2C1V = SPEED * 20;
}
}
/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;){}
/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/
/* END T_CONT */