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