/**********************************************************/ /* */ /* CMOS-EYE 色判定サンプルプログラム */ /* Target:H8Tiny/3687F(BestTechnorogy BTC065) */ /* Environment:GDL1.5.0.52 */ /* Since:2006.8.18 */ /* (c) AsakusaGiken Co., LTD. */ /* */ /**********************************************************/ /*----------------------------------------------------------------------------------- ピンアサイン (CMOS-EYE<-H8/3687) A0 P30 A1 P31 A2 P32 A3 P33 A4 P34 A5 P35 A6 P36 A7 P37 A8 P10 A9 P11 A10 P12 A11 P14 A12 P15 A13 P16 A14 P17 A15 P70 A16 P74 A17 P75 A18 P76 D0 P60 D1 P61 D2 P62 D3 P63 D4 P64 D5 P65 D6 P66 D7 P67 M0 P53 M1 P54 M2 P55 CE P50 WE P51 OE P52 ST P24 BSY P23 (PC<-H8/3687)*プログラム転送用(BTC065は標準でSCI3経由でPGをダウンロード) RX P21/RXD TX P22/TXD (オシロ<-H8/3687)*TESTは処理時間測定用、オシロスコープで波形を計測 TEST P20 (AGB65<-H8/3687)*CMOS-EYEシリアル命令及び、AGB65シリーズを動かす用 RX P71/RXD_2 TX P72/TXD_2 (その他空き) P56/SDA P57/SCL PB0/AN0-PB7/AN7 ------------------------------------------------------------------------------------------*/ /*-----------------------------------------------*/ /* インクルード */ /*-----------------------------------------------*/ #include <3687.h> /* H8 Tinyの内部I/O定義をインクルード(GDL付属のヘッダファイル) */ /*-----------------------------------------------*/ /* 名称定義 */ /*-----------------------------------------------*/ /*---ピン---*/ #define ADDR1 IO.PDR3.BYTE #define ADDR2 IO.PDR1.BYTE #define ADDR3 IO.PDR7.BYTE #define DATA IO.PDR6.BYTE #define M0 IO.PDR5.BIT.B3 #define M1 IO.PDR5.BIT.B4 #define M2 IO.PDR5.BIT.B5 #define CE IO.PDR5.BIT.B0 #define WE IO.PDR5.BIT.B1 #define OE IO.PDR5.BIT.B2 #define ST IO.PDR2.BIT.B4 #define BSY IO.PDR2.BIT.B3 #define TEST IO.PDR2.BIT.B0 #define RX_2 IO.PDR7.BIT.B1 #define TX_2 IO.PDR7.BIT.B2 /*---IO方向---*/ #define DATA_DIR IO.PCR6 #define INPUT 0 #define ALL_INPUT 0x00 #define OUTPUT 1 #define ALL_OUTPUT 0xFF /*---その他---*/ #define LOW 0 #define HIGH 1 /*-----------------------------------------------*/ /* アドレスセット関数 */ /*-----------------------------------------------*/ void set_address(unsigned long myAddr) { /*3687はビット3が抜けているポートが多いので、アドレッシングは少し面倒です。*/ /*今回はポート1、3、7を使って19ビットのアドレスを出力しています。*/ /*引数は19ビット以上必要なのでlong long 型(32ビット)*/ ADDR1 = (unsigned char)(0x000000FF & myAddr); ADDR2 = (unsigned char)( ((0x00000700 & myAddr)>>8) + ((0x00007800 & myAddr)>>7) ); ADDR3 = (unsigned char)( ((0x00008000 & myAddr)>>15) + ((0x00070000 & myAddr)>>12) ); } /*-----------------------------------------------*/ /* IO初期化関数 */ /*-----------------------------------------------*/ void init_io(void) { /*---アドレスバス---*/ IO.PCR3 = ALL_OUTPUT; /*P30-P37を出力へ*/ IO.PCR1 = ALL_OUTPUT; /*P10-P17を出力へ*/ IO.PCR7 = ALL_OUTPUT; /*P70-P76を出力へ*/ /*---データバス---*/ IO.PCR6 = ALL_INPUT; /*P60-P67をとりあえず入力へ*/ /*---シリアルポート---*/ IO.PMR1.BIT.TXD = 1; /*TXDをシリアル端子に設定*/ SCI3.SCR3.BIT.RE = 1; /*RXDを有効(P21をシリアル端子に設定)*/ IO.PMR1.BIT.TXD2 = 1; /*TXD_2をシリアル端子に設定*/ SCI3_2.SCR3.BIT.RE = 1; /*RXDを有効(P21をシリアル端子に設定)*/ /*---SCI3_2のシリアル設定---*/ SCI3_2.SMR.BIT.COM = 0; /*調歩同期(非同期)*/ SCI3_2.SMR.BIT.CHR = 0; /*データ長8ビット*/ SCI3_2.SMR.BIT.PE = 0; /*パリティなし*/ SCI3_2.SMR.BIT.STOP = 0; /*ストップビット1*/ SCI3_2.SMR.BIT.CKS = 0; /*クロック分周 0:0 1:CLK/4 2:CLK/16 3:CLK/64*/ SCI3_2.BRR = 64; /*ボーレート設定、クロック20MHz時9600bpsの設定値=64(データシートより) H8で"クロック20MHzの場合"は正確な115200bpsは出ません。*/ SCI3_2.SCR3.BIT.TE = 1; /*SCI3_2送信有効*/ /*---コントロール線---*/ IO.PMR5.BYTE = 0x00; /*PORT5を全て汎用IOへ*/ IO.PCR5 = ALL_OUTPUT; /*P50-P55(M0-2,CE.OE.WE)を出力へ*/ IO.PCR2 = 0x15; /*P24,P22,P20(ST,TXD,TEST)を出力へ、P23,P21(BSY,RXD)を入力へ*/ /*---タイマ設定(ウェイト用)---*/ TV.TCRV0.BIT.CCLR = 1; // コンペアマッチAでTCNVクリア TV.TCRV0.BIT.CKS = 0; // 停止 TV.TCRV1.BIT.ICKS = 1; // 上記CKS=3と併用で φ/128=156.25kHz TV.TCSRV.BIT.CMFA = 0; // フラグクリア TV.TCNTV = 0; // タイマカウンタクリア TV.TCORA = 156-1; // タイムコンスタントレジスタA設定 156.25kHz/125≒1ms /*---初期値---*/ set_address(0); M0 = LOW; M1 = LOW; M2 = LOW; CE = HIGH; WE = HIGH; OE = HIGH; ST = HIGH; } /*-----------------------------------------------*/ /* msウェイト関数 */ /*-----------------------------------------------*/ void wait_ms(unsigned long num) { long i; TV.TCRV0.BIT.CKS = 3; // カウント開始 for (i = 0; i < num; i++) { while (!TV.TCSRV.BIT.CMFA) ; // TCNTV=TCORAフラグ待ち TV.TCSRV.BIT.CMFA = 0; // フラグクリア } TV.TCRV0.BIT.CKS = 0; // カウント停止 } /*-----------------------------------------------*/ /* 1ピクセルデータ読み込み関数 */ /*-----------------------------------------------*/ /*この関数前に、 CE=LOW; と DATA_DIR = ALL_INPUT; を実行する必要あり*/ /*gpAddr:読み取りアドレス*/ unsigned char getPixData(unsigned long gpAddr) { unsigned char result; /*結果一時保存用変数*/ set_address(gpAddr); /*アドレスセット*/ OE = LOW; /*OE=LOWでデータバスにデータが表れる*/ result = DATA; /*データを変数へ保存*/ OE = HIGH; /*読み込みが終わったらOEをHIGHに戻す*/ return result; /*結果をリターン*/ } /*-----------------------------------------------*/ /* 1ピクセルデータ書き込み関数 */ /*-----------------------------------------------*/ /*この関数前に、 CE=LOW; と DATA_DIR = ALL_OUTPUT; を実行する必要あり*/ /*spAddr:書き込みアドレス spData:書き込みデータ*/ void setPixData(unsigned long spAddr, unsigned char spData) { set_address(spAddr); /*アドレスセット*/ DATA = spData; /*データバスに値を出力*/ WE = LOW; /*WEをLOWで書き込み*/ WE = HIGH; /*終わったらHIGHに戻す*/ } /*-----------------------------------------------*/ /* 撮影関数 */ /*-----------------------------------------------*/ void shatter(void) { while (BSY == LOW){}; /*CMOS-EYEがBUSYなら待つ*/ ST = LOW; /*シャッターを切る*/ wait_ms(1); ST = HIGH; wait_ms(1); /*撮影が開始されるまで少し待つ*/ while (BSY == LOW); /*撮影が終了するまで待つ(約70-100msかかる)*/ } /*-----------------------------------------------*/ /* 可変しきい値二値化 */ /*-----------------------------------------------*/ void twoValue(unsigned long stAddr, unsigned long toAddr, int mySize, int threRef, int myDiff) { int cnt; unsigned char data, myThre_hi,myThre_lo; /* data:画素読み取り一時データ myThre:しきい値(Threshold)*/ if (myDiff > threRef) myThre_lo = 0; /* しきい値下限値設定 */ else myThre_lo = threRef - myDiff; if ( (threRef+myDiff) > 255) myThre_hi = 255; /* しきい値上限値設定 */ else myThre_hi = threRef + myDiff; data = 255; /* 開始時は「前処理が白」に設定 */ cnt = 0; /* 相対アドレスを0(320x240の場合はlong型でないとNG)*/ CE = LOW; /* SRAMを有効 */ for (cnt=0; cnt myThre_hi) data = 255; /* しきい値=しきい値+許容値 */ else data = 0; }else{ /* 前回処理結果が白(255)だった場合 */ if (getPixData(stAddr + cnt) > myThre_lo) data = 255; /* しきい値=しきい値-許容値 */ else data = 0; } DATA_DIR = ALL_OUTPUT; /* データバスを出力へ */ setPixData(toAddr + cnt, data); /* 結果(白か黒)を書き込み */ } DATA_DIR = ALL_OUTPUT; /* データバスを入力へ(出力衝突回避) */ CE = HIGH; /* SRAMを無効 */ } /*-----------------------------------------------*/ /* メイン関数 */ /*-----------------------------------------------*/ void main(void) { /*---初期設定---*/ init_io(); /*IO初期化*/ wait_ms(3000); /*CMOS-EYEが立ち上がるまで待つ*/ M0 = LOW; /*80x60白黒モード*/ M1 = LOW; M2 = LOW; wait_ms(200); /*設定が終わるまで待つ*/ CE = HIGH; /*SRAMコントロール端子初期状態*/ WE = HIGH; OE = HIGH; TEST = LOW; /*TEST端子初期状態*/ int diff,x,y,length; /*-----------------------------*/ /* メインループ */ /*-----------------------------*/ diff = 50; /*誤差*/ x = 80; /*画面幅*/ y = 60; /*画面縦*/ length = 4800; /*画面サイズ*/ unsigned long picAddr; picAddr = 0; /*撮影開始アドレス*/ /*---5秒ごとに指定色を抽出(ニ値化画像作成)---*/ while(1){ /*無限ループ開始*/ wait_ms(5000); set_address(picAddr); /*アドレスを指定*/ shatter(); /*撮影*/ TEST = HIGH; /*時間計測開始*/ twoValue(picAddr, 4800, length, 80, 0); /* しきい値80、幅5でニ値化(結果は4800番地-) */ TEST = LOW; /*時間計測修了*/ } }