Ayhan 26 Ocak 2014 ARM
I2C EEPROM

I2C EEPROM

Merhaba Arkadaşlar,
Bugünkü yazımda sizlere daha öceden paylaşmış olduğum STM32F1XX I2C ile Harici EEPROM Kullanımı yazısındaki kütüpanemizin geliştirilmiş halini paylaşacağım.

İlk yazımda sadece EEPROM yazma ve okuma fonksiyonları vardı. Daha sonra düşünüp geliştirmeye karar verdim. Öncelikle EEPROM temizleme fonksiyonunu oluşturmayı istedim. EEPROM adresleri yazım yapılmadığı taktirde 0xFF değerini barındırır. Buna göre bizde EEPROM temizlemek için tüm adreslere 0xFF yazacağız. Mantığımız basit ve işe yarayacaktır.


EEPROM TEMİZLEME:

/********************************************************
Fonksiyon : eeprom_temizle(M24256)
Amac      :24CXX Serisieeprom temizleme fonksiyonudur
           Hangi eeprom kullanilacaksa paremetre girilir
Kullanim  :eeprom_temizle(M24256);
*********************************************************/
void eeprom_temizle(uint8_t Mem_Type)
{
  uint16_t adres=0;
  for(adres=0;adres<=32768;adres++)
  {
    write_24CXX(adres,0xFF,Mem_Type);
  }
}

Diğer yandan ise belkide en gerekli şeylerden biri eeproma istediğimiz yazıyı rahatça yazabilmektir.Amacımız harf harf uğraşmaktan ziyade direk olarak yazıyı yazabilmektir. Bu bize rahatça menüler oluşturma imkanı verebilir.Bunun için C dilinin pointer özelliğini kullanacağız. Yazacağımız yazıyo bir dizi gibi düşünüp içindeki değerleri okuyacağız.Okuduğumu adreslerde veri olduğu sürece yazı bitmemiştir deyip okumaya devam edeceğiz adresimizi arttırarak.

/********************************************************
Fonksiyon :eeprom_sirali_yaz
Amac      :Eeeprom'un istediğimiz başlangıcından itibaren yazılan yazıyı yazar.
Kullanim  :eeprom_siralıi_yaz(0x00,M24256,"AyhanKorkmaz.Net Gururla Sunar");
*********************************************************/
void eeprom_sirali_yaz(uint16_t adres,uint8_t Mem_Type,uint8_t *s)
{
while(*s)
{
write_24CXX(adres++,*s++,M24256);
}

}

Şimdi eeproma sıralı olarak istediğimiz yazıyı yazdık. Akla hemen gelen şey peki nasıl sıralı biçimde okuyacağımızdır. Hemen onuda oluşturalım. Mantığımız yine çok basit.Giriliecek adresten girilecek sayı kadar ileriye eeprom okuyup bir diziye kaydedeceğiz.

/********************************************************
Fonksiyon :eeprom_sirali_oku
Amac      :Eeeprom'un istediğimiz başlangıcından itibaren istenilen kadar oku
Kullanim  :eeprom_siralıi_oku(0x00,30,M24256);
*********************************************************/
void eeprom_sirali_oku(uint16_t adres,uint8_t adet,uint8_t Mem_Type)
{
uint8_t i;
for(i=0;i<adet;i++)
Veri[i]=read_24CXX(adres+i,Mem_Type);

}

Eklediğimiz yeni fonksiyonları da yazdıktan sonra kodumuzun son halini gösteren bir örnek kod yazalım ve bu yazımızı sonlandıralım.

/*************************************************************
* Dosya   : eeprom
* Amaç    : 24CXX serisi eepromlarla ilgili işlemler yapmak
* Yazar   : Ayhan Korkmaz - AyhanKorkmaz.Net
* İletişim: info@ayhankorkmaz.net
* Test    : STM32VLDiscovery Kartı ve 24C256
*           eeprom üstünde test edilmiştir.
**************************************************************/

#include "stm32f10x.h"
#include "stm32f10x_i2c.h"

#define I2C_TIMEOUT_MAX 10000
#define MEM_DEVICE_WRITE_ADDR 0xA0
#define MEM_DEVICE_READ_ADDR 0xA1
#define i2c_speed              100000 // 100 KHz
enum  eepromtype  {M2401,M2402,M2404,M2408,M2416,M2432,M2464,M24128,M24256,M24512};

unsigned char gozlem=0,Veri[30];

/********************************************************
Fonksiyon : _delay
Amac	  : Gecikme Fonksiyonudur.
Kullanim  : _delay(1000)-10ms eder;
*********************************************************/
void _delay(int a){
	int x,y;
	for(x=0;x<750;x++)
		for(y=0;y<a;y++);
}
/********************************************************
Fonksiyon :i2c_setup
Amac	  :i2c1 için ayarlamalar yapar
Kullanim  :i2c_setup();
*********************************************************/
void i2c_setup(void)
{


    GPIO_InitTypeDef  GPIO_InitStructure;
    I2C_InitTypeDef  I2C_InitStructure;


    /*I2C Aktif Ettik*/
    I2C_Cmd(I2C1,ENABLE);
    I2C_DeInit(I2C1);

    /* I2C1 Saat Ayarlarini Yapiyoruz */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);


    /*I2C1 SDA ve SCL pinlerinin ayarlamalarini yaptik*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//OD
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    //SCL PB6 and SDA PB7 I2C1 için

    /* I2C1 Ayarlarini yaptik*/
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = i2c_speed ;
    I2C_Init(I2C1, &I2C_InitStructure);
    I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);  

}

/********************************************************
Fonksiyon :write_24CXX
Amac	  :24CXX Serisi için yazma fonksiyonudur
	   Hangi eeprom kullanuulacaksa paremetre girilir
Kullanim  :i2c_read(0x0000,0x41,M24256);
*********************************************************/
uint8_t write_24CXX (uint16_t Addr,uint8_t Data,uint8_t Mem_Type)
{

    uint32_t timeout = I2C_TIMEOUT_MAX;//Zaman Aşimi
    uint8_t upper_addr,lower_addr;//EEPROM Adres_H ve Adres_L
    lower_addr = (uint8_t)((0x00FF)&Addr);//Düşük değerlikli Adres_L

    if(Mem_Type== M24256 || Mem_Type ==M24512)//16 bit adrese sahip eeprom mu?
    {
            Addr = Addr>>8;
            upper_addr = (uint8_t)((0x00FF)&Addr);//Yüksek değerli kismi bul Adres_H
    }
    /*I2C Başlat Komutu*/
    I2C_GenerateSTART(I2C1, ENABLE);

    /*Yazma Komutu gönder*/
    timeout = I2C_TIMEOUT_MAX; 
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
    {
           
            if ((timeout--) == 0) return 0xFF;	
    }

    
    I2C_Send7bitAddress(I2C1, MEM_DEVICE_WRITE_ADDR, I2C_Direction_Transmitter);

   
    timeout = I2C_TIMEOUT_MAX;
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
    {
            
            if ((timeout--) == 0) return 0xFF;
    }
    /*********************************************************************/
    if(Mem_Type==M24256 || Mem_Type ==M24512)
    {
          
            I2C_SendData(I2C1, upper_addr);//Adres_H Gonder
           
            timeout = I2C_TIMEOUT_MAX;// Zaman Asimi Ayarla
            while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
            {
                    
                    if ((timeout--) == 0) return 0xFF;
            }
    }	
    /* Adres_L Gonder */
    I2C_SendData(I2C1, lower_addr);

    /*Zaman asimi ayarla*/
    timeout = I2C_TIMEOUT_MAX; 
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
            
            if ((timeout--) == 0) return 0xFF;
    }

    /*Data Gonder*/
    I2C_SendData(I2C1, Data);

    /*Zaman asimi ayarla */
    timeout = I2C_TIMEOUT_MAX; 
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
            
            if ((timeout--) == 0) return 0xFF;
    }  

    /* Durdur komutu yolla*/
    I2C_GenerateSTOP(I2C1, ENABLE);
    _delay(10);
 
    return 0;
}

/********************************************************
Fonksiyon :read_24CXX
Amac	  :24CXX Serisi için okuma fonksiyonudur
		   Hangi eeprom kullanilacaksa paremetre girilir
Kullanim  :i2c_read(0x0000,M24256);
*********************************************************/
uint8_t read_24CXX(uint16_t Addr, uint8_t Mem_Type)
{

  uint32_t timeout = I2C_TIMEOUT_MAX;//Zaman Asimi Ayarla
  uint8_t Data = 0;
  uint8_t upper_addr,lower_addr;

  lower_addr = (uint8_t)((0x00FF)&Addr);

  if(Mem_Type==M24256 ||Mem_Type==M24512 )
  {
          Addr = Addr>>8;
          upper_addr = (uint8_t)((0x00FF)&Addr);//Adres_H bul
}
  /* Baslat komutu yolla*/
  I2C_GenerateSTART(I2C1, ENABLE);

  /*Zaman Asimi Ayarla */
  timeout = I2C_TIMEOUT_MAX; 
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
  {
    
		if ((timeout--) == 0) return 0xFF;
  } 
  
 
  I2C_Send7bitAddress(I2C1, MEM_DEVICE_WRITE_ADDR, I2C_Direction_Transmitter);
 

  timeout = I2C_TIMEOUT_MAX;
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    
		if ((timeout--) == 0) return 0xFF;
  } 

	if(Mem_Type==M24256)//256
	{
		/* Adres_H*/
		I2C_SendData(I2C1,upper_addr);

		/*Zaman Asimi Ayarla */
		timeout = I2C_TIMEOUT_MAX;
		while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
		{
			
			if ((timeout--) == 0) return 0xFF;
		}
	}		
	
	  /* Adres_L Yolla*/
  I2C_SendData(I2C1, lower_addr);

  /* Zaman Asimi Ayarla */
  timeout = I2C_TIMEOUT_MAX; /* Initialize timeout value */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    
		if ((timeout--) == 0) return 0xFF;
  } 
  
 
 

  /* Start Komutu Yolla */
  I2C_GenerateSTART(I2C1, ENABLE);
  
  /* Zaman Asimi Ayarla */
  timeout = I2C_TIMEOUT_MAX;
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
  {
    
		if ((timeout--) == 0) return 0xFF;
  } 
  
  
  I2C_Send7bitAddress(I2C1, MEM_DEVICE_READ_ADDR, I2C_Direction_Receiver);
   
 
  timeout = I2C_TIMEOUT_MAX; 
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
  {
   
		if ((timeout--) == 0) return 0xFF;
  }  
 
	
  I2C_AcknowledgeConfig(I2C1, DISABLE);  

  
  timeout = I2C_TIMEOUT_MAX; 
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))
  {
    
		
    if ((timeout--) == 0) return 0xFF;
  }   


    
  /* Stop Komutu Yolla */
  I2C_GenerateSTOP(I2C1, ENABLE);

  /* Data Al */
  Data = I2C_ReceiveData(I2C1);

  /* Data Dondur */
  return Data;
}
/********************************************************
Fonksiyon : eeprom_temizle(M24256)
Amac      :24CXX Serisieeprom temizleme fonksiyonudur
           Hangi eeprom kullanilacaksa paremetre girilir
Kullanim  :eeprom_temizle(M24256);
*********************************************************/
void eeprom_temizle(uint8_t Mem_Type)
{
  uint16_t adres=0;
  for(adres=0;adres<=32768;adres++)
  {
    write_24CXX(adres,0xFF,Mem_Type);
  }
}

/********************************************************
Fonksiyon :eeprom_sirali_yaz
Amac      :Eeeprom'un istediğimiz başlangıcından itibaren yazılan yazıyı yazar.
Kullanim  :eeprom_siralıi_yaz(0x00,M24256,"AyhanKorkmaz.Net Gururla Sunar");
*********************************************************/
void eeprom_sirali_yaz(uint16_t adres,uint8_t Mem_Type,uint8_t *s)
{
while(*s)
{
write_24CXX(adres++,*s++,M24256);
}

}

/********************************************************
Fonksiyon :eeprom_sirali_oku
Amac      :Eeeprom'un istediğimiz başlangıcından itibaren istenilen kadar oku
Kullanim  :eeprom_siralıi_oku(0x00,30,M24256);
*********************************************************/
void eeprom_sirali_oku(uint16_t adres,uint8_t adet,uint8_t Mem_Type)
{
uint8_t i;
for(i=0;i<adet;i++)
Veri[i]=read_24CXX(adres+i,Mem_Type);

}
/********************************************************
Fonksiyon :Main
Amac	  :Ana Fonksiyondur
Kullanim  : -
*********************************************************/
int main(void)
{
 i2c_setup();

  while (1) 
  {

 //write_24CXX(100,0x41,M24256);
  //eeprom_temizle(M24256);
 eeprom_sirali_yaz(0x00,M24256,"AyhanKorkmaz.Net Gururla Sunar");
 eeprom_sirali_oku(0,30,M24256);
 //gozlem=read_24CXX(100,M24256);
  }
}

Sonuç ise aşağıdaki gibidir.

Debug Sonucu

Debug Sonucu


Bu yazımı burada sonlandırıyorum.Eğer sizin de aklınızda kullanışlı olacağını düşündüğünüz fonksiyonlar var ise yorumlar kısmından iletebilirsiniz.

Yazar :

Elektrik-Elektronik mühendisiyim. 2 yıldır bu blogda yazıyorum. Ve 6 aydır aktif olarak internet siteleri yönetiyorum. Kişisel olarak da teknoloji ve fotoğrafçılıkla ile ilgileniyorum.



Beni sosyal medya hesaplarım üzerinden takip edin:

YORUMLAR

  1. Ayhan

    3 sene ago  

    Yorumunuz için teşekkürler.STM32’lerde dahili EEPROM bulunmuyor.Bu nedenle harici eeprom kullanımı çok önemli hale geldi.

  2. turgut

    2 sene ago  

    stm32L serisinde dahili eeprom vardır

    • Ayhan

      2 sene ago  

      Kullanmadığım için bilemiyorum. Kondu ise güzel bir ekleme olmuş.Bazen 10 byte için eeprom kullanmak zorunda kalıyorduk.

Daha fazla ARM
STM32I2C2
STM32F1xx I2C ile Harici EEPROM Kullanımı

Merhaba arkadaşlar bugünkü yazımda internette çok fazla örneği olmayan bir konuya değinmek istiyorum. Aslında bir çok onuda eeprom ele alınmış...

timer
STM32f1xx Delay Fonksiyonları Yazalım!

Merhaba Arkadaşlar bu yazımda STM32VLDiscovery kartında kullanmak için Delay(gecikme) fonksiyonlarını yazacağız. Öncelikle bu yazımda bir kez söyleyeyim ki kitin üzerinde...

Kapat