UMEHOSHI ITA TOP PAGE COMPUTER SHIEN LAB
このページは、UMEHOSHI ITA のCN6とCN7のPWD制御の一部をROM化して、
しかもRAM領域に「UME専用Hexコマンド」文字列を送信することで、プログラム送信や実行もでききる状態を維持する変更を
紹介しています。
まず、以前に紹介したPWM操作用のハードのリンクがここにあり、
ここで示したハードを制御するROM化が目標です。
また、このページで紹介した[UMEHOSHI ITA]のプログラムを利用しています。
この制御で必要な[UMEHOSHI ITA]のAPIは、このリンクの呼び出しを使っています。
// app_pwm_esp32.c // _RB15のLED制御はstartで点灯し、beepで点灯状態を反転しています。他の制御ではコメントにしています。 #include <xc.h> #include "common.h" #define BASE_FUNC 0x9D020000 // EEPROM領域配置用(パワーONでないリセット操作の実行アドレス) //#define BASE_FUNC 0x80005000 // RAM領域配置用 #define AdrStart (BASE_FUNC+0x0010) // アプリの起動時の初期ルーチンのアドレス #define AdrForward (BASE_FUNC+0x0200) // モータ前進ルーチンのアドレス #define AdrGoBack (BASE_FUNC+0x0300) // モータ後進ルーチンのアドレス #define AdrRight (BASE_FUNC+0x0400) // モータ右回転ルーチンのアドレス #define AdrLeft (BASE_FUNC+0x0500) // モータ左回転ルーチンのアドレス #define AdrUpLeft (BASE_FUNC+0x0600) // モータ左デューティ幅アップ #define AdrDownLeft (BASE_FUNC+0x0700) // モータ左デューティ幅ダウン #define AdrUpRight (BASE_FUNC+0x0800) // モータ右デューティ幅アップ #define AdrDownRight (BASE_FUNC+0x0900) // モータ右デューティ幅ダウン #define AdrStop (BASE_FUNC+0x0A00) // モータ停止 #define AdrTimer2 (BASE_FUNC+0x0B00) // 指定時間後にモータ停止のTimer2用アドレス #define AdrBeep (BASE_FUNC+0x0D00) // ビープ音 #define AdrSetCN6 (BASE_FUNC+0x0E00) // CN6(左側) コネクタの制御 #define AdrSetCN7 (BASE_FUNC+0x0F00) // CN7(右側) コネクタの制御 #define UPDAOWN 0x1000 // デューティ幅の変更で使う値(この値を加算又は減算) typedef struct { int cn6PWM; // 現在の左デューティ幅で、初期設定 int cn7PWM; // 現在の右デューティ幅で、初期設定 int time2Count;//Timer2割り込みでカウントアップ(下記stopCountまでカウント) int stopCount; // time2CountがstopCount以上で、time2CountがをゼロにしてモータをOFF } MortorCtrl; #define MT ((MortorCtrl *)0xA0009000;) // ram_area3領域の絶対アドレスで、グローバル変数を定義 __attribute__((address( AdrStart ))) void start (void); void start() { // 左右のモータで、進行にバラツキがある場合、下記初期設定を調整して合わせる。 MT->cn6PWM = 0x04FFF; // 現在の左デューティ幅で、初期設定 MT->cn7PWM = 0x04FFF; // 現在の右デューティ幅で、初期設定 MT->time2Count = 0;//Timer2割り込みでカウントアップ(下記stopCountまでカウント) MT->stopCount = 0x500;// time2CountがstopCount以上で、time2CountがをゼロにしてモータをOFF PORTBCLR = 0b0110000000001100;//モータ関連ポート(14,13,3,2)をゼロにする IEC0CLR = 0x00000200;//T2IE Timer2 Enable(割込み不可)"); // 初期化ルーチン(リセット時の処理)を設定 ( (uint32_t *)_HANDLES)[_IDX_INIT_SUB_FUNC] = (uint32_t ) AdrStart; __asm__ ("NOP"); // Timer2の割り込み処理を置き換える ( (uint32_t *)_HANDLES)[_IDX_TIMER_2_FUNC] = (uint32_t ) AdrTimer2; PR2=0x09c3F; // Timer2の周期設定 _set_pwd_mode(1); // PWM モードへ変更 T2CONbits.ON = 1; //Timer2の機能を有効 MT->time2Count =0; _RB15 = 1; // LED D1点灯 _clear_beep_code(); _set_beep_code((uint8_t)0b00000100);//音パターン[・・・・]の登録 _UM_PTR_GOTO_BEEP = NULL;//ループ生成OFF } // モータを停止する。(割り込み不可も行う) __attribute__((address( AdrStop))) void stop(void); void stop() { IEC0CLR = 0x00000200;//T2IE Timer2 Enable(割込み不可)"); OC5RS = OC1RS = OC4RS = OC3RS = 0;// モータすべてをOFF MT->time2Count = 0; } // タイマーで(stopCount 値に達するまで)の時間ごとに、モータを停止する。 // モータがオンで、移動し続けないようにする考慮で、stop内で割り込みを不可にしている。 __attribute__((address( AdrTimer2))) void timer2(void); void timer2() { IFS0CLR = 0x00000200; // Clear the timer interrupt status flag if( ++MT->time2Count >= MT->stopCount ){ stop();// PWM パルス幅を0 //_RB15 = 0; // LED1消灯 } } // CN6(左側) コネクタの制御 dの値 0停止, 1:正転, -1:逆転 __attribute__((address( AdrSetCN6 ))) void setCN6(int); void setCN6( int d){ OC5RS = 0x0; // CN6[1-2]制御(RB2) OC1RS = 0x0; // CN6[3-4]制御(RB3) if(d==1){ OC5RS = MT->cn6PWM; // CN6[1-2]制御(RB2) OC1RS = 0x0; // CN6[3-4]制御(RB3) } else if(d==-1){ OC5RS = 0x0; // CN6[1-2]制御(RB2) OC1RS = MT->cn6PWM; // CN6[3-4]制御(RB3) } } // CN7(右側) コネクタの制御 dの値 0停止, 1:正転, -1:逆転 __attribute__((address( AdrSetCN7 ))) void setCN7(int); void setCN7( int d){ OC4RS = 0x0; // CN7[3-4]制御(RB13) OC3RS = 0x0; // CN7[1-2]制御(RB14) if(d==1){ OC4RS = MT->cn7PWM; // CN7[3-4]制御(RB13) OC3RS = 0x0; // CN7[1-2]制御(RB14) } else if(d==-1){ OC4RS = 0x0; // CN7[3-4]制御(RB13) OC3RS = MT->cn7PWM; // CN7[1-2]制御(RB14) } } __attribute__((address( AdrBeep ))) void beep (void); void beep() { _clear_beep_code(); _set_beep_code((uint8_t)0b000000100);//音パターン[・・・・]の登録 _UM_PTR_GOTO_BEEP = NULL;//ループ生成OFF _RB15 = ! _RB15;//確認用のLED1点灯反転 } // モータ前進ルーチン __attribute__((address( AdrForward ))) void forward(void); void forward() { MT->time2Count = 0; MT->stopCount = 300; setCN6( 1 );// 左正転 setCN7( 1 );// 右正転 //_RB15 = ! _RB15;//確認用のLED1点灯反転 IEC0SET = 0x00000200;//T2IE Timer2 Enable(割込み許可)"); } // モータ後進ルーチン __attribute__((address( AdrGoBack ))) void goback(void); void goback() { MT->time2Count = 0; MT->stopCount = 200; setCN6( -1 );// 左逆転 setCN7( -1 );// 右逆転 //_RB15 = ! _RB15;//確認用のLED1点灯反転 IEC0SET = 0x00000200;//T2IE Timer2 Enable(割込み許可)"); } // モータ右回転ルーチン __attribute__((address( AdrRight ))) void right(void); void right() { MT->time2Count = 0; MT->stopCount = 100; setCN6( 1 );// 左正転 setCN7( -1 );// 右逆転 //_RB15 = ! _RB15;//確認用のLED1点灯反転 IEC0SET = 0x00000200;//T2IE Timer2 Enable(割込み許可)"); } // モータ左回転ルーチン __attribute__((address( AdrLeft ))) void left(void); void left() { MT->time2Count = 0; MT->stopCount = 100; setCN6( -1 );// 左逆転 setCN7( 1 );// 右正転 //_RB15 = ! _RB15;//確認用のLED1点灯反転 IEC0SET = 0x00000200;//T2IE Timer2 Enable(割込み許可)"); } // モータ左デューティ幅アップルーチン __attribute__((address( AdrUpLeft ))) void upleft(void); void upleft() { //_send_hex_low( cn6PWM ); if( MT->cn6PWM +UPDAOWN <= 0x0ffff){ MT->cn6PWM += UPDAOWN ; //_send_string(" Left UP\r\n"); } else { beep(); //_send_string(" Left FULL\r\n"); } //_RB15 = ! _RB15;//確認用のLED1点灯反転 } // モータ左デューティ幅ダウンルーチン __attribute__((address( AdrDownLeft ))) void downleft(void); void downleft() { //_send_hex_low( MT->cn6PWM ); if( MT->cn6PWM - UPDAOWN >= 0){ MT->cn6PWM -= UPDAOWN ; //_send_string(" Left DOWN\r\n"); } else { beep(); //_send_string(" Left Minimum\r\n"); } //_RB15 = ! _RB15;//確認用のLED1点灯反転 } //モータ右デューティ幅アップ __attribute__((address( AdrUpRight ))) void upright(void); void upright() { //_send_hex_low( MT->cn7PWM ); if( MT->cn7PWM +UPDAOWN <= 0x0ffff){ MT->cn7PWM += UPDAOWN ; //_send_string(" Right UP\r\n"); } else { beep(); //_send_string(" Right FULL\r\n"); } //_RB15 = ! _RB15;//確認用のLED1点灯反転 } // モータ右デューティ幅ダウン __attribute__((address( AdrDownRight ))) void downright(void); void downright() { //_send_hex_low( MT->cn7PWM ); if( MT->cn7PWM -UPDAOWN >= 0){ MT->cn7PWM -= UPDAOWN ; //_send_string(" Right DOWN\r\n"); } else { beep(); //_send_string("Right Minimum\r\n"); } //_RB15 = ! _RB15;//確認用のLED1点灯反転 }以上のコードをumehoshiEditの開発ツールで作成し、 できた「UME専用Hexコマンド」を転送するだけで、EEPROM領域(0x9D020010〜)に書き込まれます。
#include <xc.h> #include "common.h" #define BASE_FUNC 0x9D020000 // EEPROM領域配置用(パワーONでないリセット操作の実行アドレス) //#define BASE_FUNC 0x80005000 // RAM領域配置用 #define AdrStart (BASE_FUNC+0x0010) // アプリの起動時の初期ルーチンのアドレス #define AdrForward (BASE_FUNC+0x0200) // モータ前進ルーチンのアドレス #define AdrGoBack (BASE_FUNC+0x0300) // モータ後進ルーチンのアドレス #define AdrRight (BASE_FUNC+0x0400) // モータ右回転ルーチンのアドレス #define AdrLeft (BASE_FUNC+0x0500) // モータ左回転ルーチンのアドレス #define AdrTimer2 (BASE_FUNC+0x0B00) // 指定時間後にモータ停止のTimer2用アドレス #define AdrBeep (BASE_FUNC+0x0D00) // ビープ音 typedef struct { int cn6PWM; // 現在の左デューティ幅で、初期設定 int cn7PWM; // 現在の右デューティ幅で、初期設定 int time2Count;//Timer2割り込みでカウントアップ(下記stopCountまでカウント) int stopCount; // time2CountがstopCount以上で、time2CountがをゼロにしてモータをOFF } MortorCtrl; #define MT ((MortorCtrl *)0xA0009000) // ram_area3領域の絶対アドレスで、グローバル変数を定義 void WaitBeep() //音出して、1秒待つ { ( (void (*)(void) )AdrBeep)();//音パターン[−−−−]の登録、ループ無し MT->time2Count = 1000; IEC0SET = 0x00000200;//T2IE Timer2 Enable(割込み許可) } void timer2_interrupt()// 割り込み関数 { static int step=0; static void (*funcs[])(void)={ // 実行する順番で関数を登録(各関数内で、Timer2割り込みをイネーブルにする必要がある) WaitBeep, // 音を出して一時停止 (void *)AdrForward, // 前進関数 (void *)AdrRight, // 右回転関数 WaitBeep, // 音を出して一時停止 (void *)AdrLeft, // 左回転関数 (void *)AdrGoBack, // 後進関数 }; ( (void (*)(void) )AdrTimer2 )(); // 内部でMT->time2Count++を行って、MT->stopCount以上なら0になり、Timer2割り込みがディセーブルになる。 if( MT->time2Count != 0) return; // time2Countまだ動作中 if( step >= 6 ) step = 0; funcs[step++]();// 上記で配列に登録した関数を、順番に実行する。 } // RAM領域の起動アドレス __attribute__((address( 0x80005000 ))) void start (void); void start() { ( (void (*)(void) )AdrStart)();// Timer2のON、割り込み処理デフォルト関数登録、割り込み不可 ( (uint32_t *)_HANDLES)[_IDX_TIMER_2_FUNC] = (uint32_t ) timer2_interrupt;// Timer2の割り込み処理を置き換える __asm__ ("NOP"); MT->stopCount = 3000;// 最初の割り込み内のstop()タイミング (3秒後) IEC0SET = 0x00000200;//T2IE Timer2 Enable(割込み許可) }なお、USBケーブルを接続したままで実行すると雑音で誤動作しがちなので、実行スタートを3秒に設定しています。
Beep R009D020D00003B
StartInit R009D020010004E
Forward R009D020200004D
Back R009D020300004C
Right R009D020400004B
Left R009D020500004A