カメラモジュールから液晶ディスプレイに。 何か映ったけど・・・
仕様は決まった。 さっそくプログラムを書いてみた。
とりあえずはこんな感じ。
#include <Wire.h> #include <FspTimer.h> static FspTimer fsp_timer; long putcnt = 0; void Cam_Write_Reg(uint8_t reg, uint8_t dat){ Wire.beginTransmission(0x21); Wire.write(reg); // Sends value byte Wire.write(dat); // Sends value byte if(Wire.endTransmission(true)){ Serial.print("error write reg "); Serial.println(reg, HEX); } delay(20); } void Cam_Init(void){ uint8_t error; R_PORT0->PDR = 0x0000; R_PORT3->PDR = 0x0010; //XCLKだけ出力 R_PORT2->PDR = 0x0000; //OV7670 XCLK用PWM生成 5MHz D8ポート fsp_timer.begin(TIMER_MODE_PWM,0,7, 5000000.0 ,50.0); fsp_timer.open(); R_PFS->PORT[3].PIN[4].PmnPFS_b.PMR = 0; //D8を汎用入出力に設定 R_PFS->PORT[3].PIN[4].PmnPFS_b.PSEL = 0x03; //D8をGPT端子として使用 R_PFS->PORT[3].PIN[4].PmnPFS_b.PMR = 1; //D8を周辺機能用の端子に設定 R_GPT7->GTIOR_b.GTIOA = 0x06; //GTIOCA端子機能選択 R_GPT7->GTIOR_b.OAE = 1; //GTIOCA端子出力許可 fsp_timer.start(); //PWM出力開始 Wire.begin(); //IIC起動 while(1){ Wire.beginTransmission(0x21); //OV7670と接続 error = Wire.endTransmission(); if (error == 0){ //接続確認 break; }else{ Serial.print("OV7670 conect error : "); Serial.println(error); } } //ov7670基本設定 Cam_Write_Reg(0x12, 0x80); //REG_COM7 SCCB reset delay(100); Cam_Write_Reg(0x3a, 0x04); //REG_TSLB Cam_Write_Reg(0x11, 0x0f); //CLKRC クロック1/15倍 //解像度設定 QVGA Cam_Write_Reg(0x17, 0x16); //HSTART Cam_Write_Reg(0x18, 0x04); //HSTOP Cam_Write_Reg(0x32, 0x00); //HREF QVGA Cam_Write_Reg(0x19, 0x02); //VSTART Cam_Write_Reg(0x1a, 0x7a); //VSTOP Cam_Write_Reg(0x03, 0x0a); //VREF Cam_Write_Reg(0x0c, 0x04); //REG_COM3 Cam_Write_Reg(0x3e, 0x19); //REG_COM14 QVGA Cam_Write_Reg(0x70, 0x3a); //SCALING_XSC QVGA Cam_Write_Reg(0x71, 0x35); //SCALING_YSC QVGA Cam_Write_Reg(0x72, 0x11); //Scaling DCWCTR QVGA Cam_Write_Reg(0x73, 0xf1); //Scaling PCLK_DIV QVGA Cam_Write_Reg(0xa2, 0x02); //SCALING_PCLK_DELAY QVGA //色データ RGB565 Cam_Write_Reg(0x12, 0x04); //REG_COM7 RGB mode Use QVGA Cam_Write_Reg(0x8c, 0x00); //REG_RGB444 RGB444 diseble Cam_Write_Reg(0x40, 0xd0); //REG_COM15 RGB565 Cam_Write_Reg(0x04, 0x00); //REG_COM1 Cam_Write_Reg(0x14, 0x38); //REG_COM9 Cam_Write_Reg(0x4f, 0xb3); //Color Saturation 0 Cam_Write_Reg(0x50, 0xb3); Cam_Write_Reg(0x51, 0x00); Cam_Write_Reg(0x52, 0x3d); Cam_Write_Reg(0x53, 0xa7); Cam_Write_Reg(0x54, 0xe4); Cam_Write_Reg(0x3d, 0x08); //COM13 Cam_Write_Reg(0x15, 0x20); //COM10 //PCLK does not toggle on HBLANK. } void Lcd_Writ_Bus(unsigned char d) { R_PORT4->PODR_b.PODR8 = 0; R_PORT1->PODR = d << 2; R_PORT4->PODR_b.PODR8 = 1; } void Lcd_Write_Com(unsigned char VH) { R_PORT4->PODR_b.PODR9 = 0; Lcd_Writ_Bus(VH); } void Lcd_Write_Data(unsigned char VH) { R_PORT4->PODR_b.PODR9 = 1; Lcd_Writ_Bus(VH); } void Lcd_Init(void) { R_PFS->PORT[1].PIN[8].PmnPFS_b.PMR = 0; R_PFS->PORT[1].PIN[9].PmnPFS_b.PMR = 0; R_PORT1->PDR = 0x03fc; //Data Port R_PORT4->PDR = 0x0f00; //Cont Port R_PORT4->PODR_b.PODR8 = 1; //WR R_PORT4->PODR_b.PODR9 = 1; //RS R_PORT4->PODR_b.PODR11 = 1; //Reset delay(5); R_PORT4->PODR_b.PODR11 = 0; delay(15); R_PORT4->PODR_b.PODR11 = 1; delay(15); R_PORT4->PODR_b.PODR10 = 0; Lcd_Write_Com(0x36); // Memory Access Control Lcd_Write_Data(0x38); //横表示 BGR Lcd_Write_Com(0x21); //Display Inversion ON Lcd_Write_Com(0x3A); Lcd_Write_Data(0x55); //Data 18bit Lcd_Write_Com(0xB1); //Frame Rate Control Lcd_Write_Data(0x00); Lcd_Write_Data(0x1b); Lcd_Write_Com(0xB6); // Display Function Control Lcd_Write_Data(0x08); Lcd_Write_Data(0x82); Lcd_Write_Data(0x27); Lcd_Write_Com(0x11); //Exit Sleep delay(120); Lcd_Write_Com(0x29); //Display on } void setup(){ Serial.begin(9600); while (!Serial); //LCD初期化 Serial.println("LCD init"); Lcd_Init(); //OV7670カメラとの通信開始 Serial.println("OV7670 init"); Cam_Init(); Serial.println("Init Finish"); } void loop(){ int i1; while(!R_PORT3->PIDR_b.PIDR2); //VSYNCが立ち上がるまで待ち Lcd_Write_Com(0x2a); //描画領域 幅 Lcd_Write_Data(0x00); Lcd_Write_Data(0x00); Lcd_Write_Data(0x01); Lcd_Write_Data(0x3f); Lcd_Write_Com(0x2b); //描画領域 高さ Lcd_Write_Data(0x00); Lcd_Write_Data(0x00); Lcd_Write_Data(0x00); Lcd_Write_Data(0xEF); Lcd_Write_Com(0x2c); //画面のドットの数だけ繰り返す for(i1 = 0; i1 < 76800; i1++){ while(!R_PORT3->PIDR_b.PIDR1); //PCLKが立ち上がるまで待ち Lcd_Write_Data(R_PORT0->PIDR | (R_PORT2->PIDR << 1)); //LCDへデータ転送 上位 while(R_PORT3->PIDR_b.PIDR1); //PCLKが立ち下がるまで待ち while(!R_PORT3->PIDR_b.PIDR1); //PCLKが立ち上がるまで待ち Lcd_Write_Data(R_PORT0->PIDR | (R_PORT2->PIDR << 1)); //LCDへデータ転送 下位 while(R_PORT3->PIDR_b.PIDR1); //PCLKが立ち下がるまで待ち } }
まだ最初なので、デバックも兼ねた作りとなっている。
シリアルモニターが開かれないとプログラムがスタートしないようになっているので、実行したらシリアルモニターを開くこと。
また、1枚の画像が表示されるのに3秒くらいかかるよう処理をわざと遅くしている。
まずは綺麗に画像を取得して表示させることが大切だからだ。
で、プログラムを実行すると・・・何やら顔が映ってる・・・
いや、私キャッスルの顔なのだが、おかしい。 顔じゃなくて色がね。
怖いよ。 ホラーだよ。 子供は泣くよ。
でも、とりあえずカメラから取得した画像が液晶ディスプレイに出力されたことは確かだ。
このプログラムをベースにいろいろいじって改良していこうと思う。