Stm32f10xx & OV7670 & Tft

Başlatan yldzelektronik, 27 Mayıs 2013, 03:55:03

Mnemonic

bir denerim ama ben 7670 kullandığım için farklı olacaktır büyük ihtimalle

Mucit23

#106
Kamerayı çalıştırdık çok şükür. Ama O editlenmiş datasheet olmasaydı mümkün değil çalıştıramazdım. Datasheet'te birçok register Reserved olarak ayrılmış. Normalde bu alanlar boş olması gerekirken belliki kameranın çalışmasını etkileyen ayarları kontrol ediyor. Neden böyle birşeye ihtiyaç duymuşlar anlamıyorum. Kameranın PID ve VER registerlerini okuduğumda Kameranın OV9657 olduğu anlaşılıyor. Ama bununla ilgili hiçbir kaynak döküman vs birşey bulamadım. Belliki kamerayı Rev5 diye güncellemişler ama döküman verilmemiş.

Diğer bir yandan kamera omnivision firmasının olmasına rağmen kendi sitesinde böyle bir ürüne denk gelmedim. Firmaya durumla ilgili 2 defa mail attım hiç bir tanesine cevap vermediler. Bu yüzden omnivision firmasında iyice soğudum. Ovt nin yeni ürünlerinde döküman durumu nedir bilmiyorum ama bir daha kamera ile uğraşmam gerekirse teknik döküman problemi yaşamayacağım bir firmanın ürününü kullanırım kesinlikle.

Şerefsiz kamera tam iki haftamı aldı. >:( >:(

O editlenmiş datasheetide nerden buldum bilmiyorum. Sanki birisi halimi gördüde "yeter uğraştın al şunuda adam akıllı çalıştır kamerayı" dercesine birden çıktı karşıma. Nerden indirdiğime dair hiçbir fikrim yok.

Kameranın çalışmasına gelince Görüntüde bozukluk yok. Renklerde iyi fakat kamera ortamdaki ışık değişimlerine geç adapte oluyor. Birtek bu hoşuma gitmiyor ama sanırım yapacak birşey yok. Günümüz kameralarıyla karşılaştırmamak gerekir.

Aslında döküman bulabilsem elimde bir hurda tabletlerden söktüğüm kameralar var. Onları bile kullanırız.

Son Test videosu

https://www.youtube.com/watch?v=z7-FOgELcbE

Bu arada Kullandığım TFT 3.5" SSD1289 lu bir TFT. Önceki Testlerde LCD de kaymalar felan oluyordu. Düzgün görüntü elde edebilmek için 3-4 defa kartı resetlemem gerekiyordu. Kamera düzelince buda düzeldi.

@Mnemonic,

Hocam kodları deneyin. Datasheetleri karşılaştırırsanız eğer göreceksinizki birçok register aynı.

kantirici


Mnemonic

Mucit23 hayırlı olsun.
renk tepkilerini geç verme olayını pll değerlerini değiştirerek ayarlayabilirsin diye düşünüyorum ayrıca agc ayarları ile oyna istersen
bende bugün musaitim kodlar üzerinde çalışıcam
öncelikle registerleri doğru okuyabilirsem akabinde senin register tablonu deniycem

Mnemonic

@mucit23 hocam
ben hala reg okuma kısmında takıldım
bir yerde sorun var ama anlamıyorum debug yapıyorum değişkene attığı değer her seferinde farklı okuyor
senin kodları benimle bir paylaşırmısın
nerede hata yapıyorum bir türlü bulamadım

Mucit23

#110
Alıntı yapılan: Mnemonic - 14 Mart 2014, 09:47:48
Mucit23 hayırlı olsun.
renk tepkilerini geç verme olayını pll değerlerini değiştirerek ayarlayabilirsin diye düşünüyorum ayrıca agc ayarları ile oyna istersen
bende bugün musaitim kodlar üzerinde çalışıcam
öncelikle registerleri doğru okuyabilirsem akabinde senin register tablonu deniycem


Hocam evet contrast parlaklık ayarlarını buldum. Ortalama bir değer yakaladım. Şuan kamera gayet iyi görüntü veriyor.

XCLK frekansı 24Mhz deydi. 40Mhz ye çıkardım. Görüntüler dahada akıcılaştı ama ara sıra kameranın şarşırdığı oluyordu. Yine en iyisi 24Mhz.

Alıntı yapılan: Mnemonic - 14 Mart 2014, 12:58:40
@mucit23 hocam
ben hala reg okuma kısmında takıldım
bir yerde sorun var ama anlamıyorum debug yapıyorum değişkene attığı değer her seferinde farklı okuyor
senin kodları benimle bir paylaşırmısın
nerede hata yapıyorum bir türlü bulamadım


Muhtemelen I2C kodlarında problem var. Ben Soft I2C kullanıyorum. Kullandığım kütüphaneyi baştan sona elden geçirdim. Okuma ve yazmada sıkıntı yok.

I2C.c
/**
  ******************************************************************************
  * @file    I2C.c
  * @author  Ferhat YOL
  * @version V0.0.3
  * @date    10/15/2010
  * @brief   Software I2C Program
  *          
  ******************************************************************************/
	/* Includes ------------------------------------------------------------------*/
  #include "stm32f4xx.h"
	#include "I2C.h"
	#include "main.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
	 #define I2C_Port GPIOB
	 #define I2C_SDA  GPIO_Pin_9
	 #define I2C_SCL  GPIO_Pin_8
/* Bits definitions ----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
   #define SDAH GPIO_SetBits(I2C_Port,I2C_SDA)
	 #define SDAL GPIO_ResetBits(I2C_Port,I2C_SDA)
	 #define SCLH GPIO_SetBits(I2C_Port,I2C_SCL)
	 #define SCLL GPIO_ResetBits(I2C_Port,I2C_SCL)
   #define SDAR GPIO_ReadInputDataBit(I2C_Port,I2C_SDA)//GPIOB->IDR & I2C_SDA
   #define SCLR GPIO_ReadInputDataBit(I2C_Port,I2C_SCL)//GPIOB->IDR & I2C_SDA
/* Private variables ---------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

void Soft_I2C_Configuration(void){
  GPIO_InitTypeDef GPIO_InitStructure;
	/* Enable GPIOB clocks */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

	/*SDA Pin Configuration*/
  GPIO_InitStructure.GPIO_Pin = I2C_SDA; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_Init(I2C_Port, &GPIO_InitStructure);
	/*SCL Pin Configuration*/
	GPIO_InitStructure.GPIO_Pin = I2C_SCL; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_Init(I2C_Port, &GPIO_InitStructure);
}


void I2C_Delay(void)
{
   unsigned int i=I2C_Delay_Time;
   while(i)
   {
     i--;
   }
}

uint8_t I2C_Start(void)
{
  SDAH;
	SCLH;
	I2C_Delay();
  SDAL;
	I2C_Delay();
	SCLL;
	I2C_Delay();
 return (0x00);
}

void I2C_Stop(void)
{
 SDAL;
 I2C_Delay();
 SCLH;
 I2C_Delay();
 SDAH;
 I2C_Delay();
}

void I2C_Ack(void)
{
 SCLL;
 I2C_Delay();
 SDAL;
 I2C_Delay();
 SCLH;
 I2C_Delay();
 SCLL;
 I2C_Delay();
}

void I2C_NoAck(void)
{
 SCLL;
 I2C_Delay();
 SDAH;
 I2C_Delay();
 SCLH;
 I2C_Delay();
 SCLL;
 I2C_Delay();
}
 
uint8_t I2C_WaitAck(void)  
{
	SDAH;
  I2C_Delay();
	SCLH;I2C_Delay();  //Clock Uygulaniyor
	if(SDAR) return (0xFF);
	;SCLL;I2C_Delay();
	return(0x00);
}

void I2C_SendByte(unsigned char SendByte)
{
    unsigned char i=0;
    for(i=0;i<8;i++)
		{
      if ((SendByte << i) & 0x80)
			 {
				 SDAH;
       }
			 else
			 {
         SDAL;
       }
			 I2C_Delay();
       SCLH;
			 I2C_Delay();
       SCLL;
			 I2C_Delay();
    }
}
 
unsigned char I2C_ReceiveByte(void)  
{
    unsigned char i=8;
    unsigned char ReceiveByte=0;
 
    SDAH;    
    while(i--)
    {
      ReceiveByte<<=1;      
      SCLL;
      I2C_Delay();
      SCLH;
      I2C_Delay();
      if(SDAR)
      {
        ReceiveByte|=0x01;
      }
    }
    SCLL;
    return ReceiveByte;
}

unsigned char I2C_ReadByte( unsigned char DeviceAddress,unsigned int ReadAddress)
{  
    unsigned char temp;
    if(!I2C_Start())return (0xFF);    
 
    I2C_SendByte((DeviceAddress & 0xFF));
    if(!I2C_WaitAck()){I2C_Stop(); return 0xFF;}
   
    I2C_SendByte((unsigned char)((ReadAddress>>8) & 0xFF));    
    I2C_WaitAck();
    I2C_SendByte((unsigned char)((ReadAddress) & 0xFF));        
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte((DeviceAddress & 0xFE)|0x01);    
    I2C_WaitAck();
   
    temp = I2C_ReceiveByte();
   
    I2C_NoAck();
     
    I2C_Stop();
    return temp;
}


I2C.h
/********************************************************************************
  * @file    I2C.h
  * @author  Ferhat YOL
  * @version V0.0.3
  * @date    10/15/2010
  * @brief   Software I2C Program
  *          
  ******************************************************************************/
#ifndef I2C_H
#define I2C_H
/* Includes ------------------------------------------------------------------*/
   #include "stm32f4xx.h"
	 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/ 
	 #define I2C_Delay_Time 500
/* Bits definitions ----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void Soft_I2C_Configuration(void);
void I2C_Delay(void);
uint8_t I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NoAck(void);
uint8_t I2C_WaitAck(void);
void I2C_SendByte(unsigned char SendByte);
unsigned char I2C_ReceiveByte(void);
unsigned char I2C_ReadByte(unsigned char DeviceAddress,unsigned int ReadAddress);

#endif


SCL Pini Olarak PB8, SDA olarakda PB9 kullanılıyor. Eğer değiştirmek isterseniz Kütüphanenin başındaki tanımlamarı değiştirin.

Kameraya Yazma ve Okuma rutinlerinide bu şekilde yapın.

/**
  * @brief  Writes a byte at a specific Camera register
  * @param  Device: OV9655 write address.
  * @param  Addr: OV9655 register address. 
  * @param  Data: data to be written to the specific register 
  * @retval None
  */
uint8_t DCMI_SingleRandomWrite(uint8_t Device, uint16_t Addr, uint8_t Data)
{
	I2C_Delay();
	
	I2C_Start();
	I2C_SendByte(Device);
	if(I2C_WaitAck()==0xFF) return(0xFF);
	I2C_SendByte(Addr);
	if(I2C_WaitAck()==0xFF) return(0xFF);
	I2C_SendByte(Data);
	if(I2C_WaitAck()==0xFF) return(0xFF);	
	I2C_Stop();
	
  return(0x00);
}
/**
  * @brief  Reads a byte from a specific Camera register 
  * @param  Device: OV9655 write address.
  * @param  Addr: OV9655 register address. 
  * @retval data read from the specific register 
  */
uint8_t DCMI_SingleRandomRead(uint8_t Device, uint16_t Addr)
{
	unsigned char Recieved_Data=0;
        I2C_Delay();
	I2C_Start();
	I2C_SendByte(Device);
	if(I2C_WaitAck()==0xFF) return(0xFF);
	I2C_SendByte(Addr);
	if(I2C_WaitAck()==0xFF) return(0xFF);
	I2C_Stop();
	I2C_Start();
	I2C_SendByte(Device+1);
        if(I2C_WaitAck()==0xFF) return(0xFF);
	Recieved_Data=I2C_ReceiveByte();
	I2C_Stop();
	return Recieved_Data;
}


Bu kodları bir deneyin muhtemelen problem çözülecektir.

Mnemonic

mucit23 hocam
allah senden razı olsun
şu anda registerleri okuyabiliyorum :)
sonraki adımlarla devam edicem

Mucit23

24Mhz de 30FPS de çalıştığını sanıyordum ama öyle değilmiş. 24Mhz de tam olarak 15FPS alabiliyorum. XCLK frekansını 48'e çıkarınca 30FPS yi gördüm.

Mnemonic

mucit hocam
registerlerini ve register yukleme rutinini gonderebilirmisin ?
ayrıca dcmi interruptı nasıl yazdın ?

Mucit23

#114
Edit;

Buraya yükleyecektim ama olmuyor nedense. Yazının yarısı çıkmıyor.
http://yadi.sk/d/BcjDHq9aKZW82
Neyse kütüphaneyi buradan indirebilirsiniz.

Hocam Kesme oluşması için DCMI modülünün init edildiği bölümde DCMI frame kesmesini aktif ettim. Kesmenin oluşması içinde stm32f4xx_it.c içerisine aşağıdaki kodları ekleyin

void DCMI_IRQHandler(void)
{  	   
	if (DCMI_GetITStatus(DCMI_IT_VSYNC) != RESET) 
	{	 		   	
		DCMI_ClearITPendingBit(DCMI_IT_VSYNC);	  
	}
	
	if (DCMI_GetITStatus(DCMI_IT_LINE) != RESET) 
	{
	  STM_EVAL_LEDToggle(LED3);
		DCMI_ClearITPendingBit(DCMI_IT_LINE); 			  
	}
	
	if (DCMI_GetITStatus(DCMI_IT_FRAME) != RESET) 
	{
		LCD_SetDisplayWindow(0, 0, 319, 239);
	  LCD_WriteRAM_Prepare();
		DCMI_ClearITPendingBit(DCMI_IT_FRAME);
	}
	if (DCMI_GetITStatus(DCMI_IT_ERR) != RESET) 
	{
		DCMI_ClearITPendingBit(DCMI_IT_ERR);
	}
}


Ben dediğim gibi frame kesmesini aktif ettim. Görüntünün tamamı geldiğinde kesme oluşuyor. Bende kesmeye gidip ekranın başlangıç kordinatlarını veriyorum.

Edit; Dosyaları Güncelledim. İndirdiyseniz tekrar indirin.

Mnemonic

hocam teşekkür ederim
büyük ihtimalle registerler farklıdır ama birşeyler bulmaya çalışıcaz artık
ben henüz net bir görüntü elde edemedim

Mucit23

Hocam sizinde %98 ihtimalle ayarlarınızda problem var. Yani şuanda farklı init kodları denemekten başka çareniz yok gibi. Arduinocuların kütüphanelerinede bakın hocam.

Birde şunu söyliyeyim. DCMI ile görünütüyü direk ekrana gönderirken kesme kullanıp her kesme geldiğinde yeni pencere açmaya gerek yoktur. Siz Capture_Start işlemini yapmadan önce pencerenizi açarsınız sonra gelen datalar sırasıyla ekrana dizili. Ekran dolunca zaten baştan yazmaya başlanır. Benim kesme kullandım çünkü bendeki geri zekalı SSD1289'a beyaz pixel gelince eli ayağı birbirine dolanıyor. Herzaman olmuyor ama ara sıra oluyor. Durum böyle olunca ekranın toparlanması için yeniden pencere açmak gerekiyor. Bende her görüntü geldiğinde kesme oluşturup yeniden pencere açıyorum.

kimlenbu

Daha önce verdim sanırım tekrar vereyim proje dosyasını. 3.2" lcd ve OV7670 keil proje dosyası :

http://dfiles.eu/files/59w15afkf

kamera dcmi'den bağlanıyor. Dosya içinde geliştirme kartına ait pin bağlatı şeması da var. LCD ve DCMI port pinlerine bakarak gerekli bacak bağlantıları yapabilirsiniz. Kendim denedim, çalışıyor.

Mnemonic

#118
mucit23 hocam
LCD_WriteRAM_Prepare(); içeriği nedir ben ssd1963 kullandığım için benim kütüphanede bu komut yok
benim kendi lcdme uyarlama yapayım


mesaj birleştirme:: 15 Mart 2014, 14:25:10

@kimlenbu
aynı kart bende de var bende discovery kartı ve ov7670i bu geliştirme kartına takıyorum ama
cdsinden çıkan bu dosyalar doğru çalışmadı

Mucit23

Sıralı yazmadan önce LCD ye aşağıdaki komutu gönderin.

LCD_WriteCommand(0x002c);


Ben SSD1963 Kütüphanemde bunu kullanıyorum. Siz Window fonksiyonun içine bir bakın. Fonksiyonun sonunda bu komut olması gerekir. Eğer varsa tekrardan göndermenize gerek yok.