Anasayfa Gömülü Sistemler ARM STM32F1xx EEPROM Fonksiyonlarını Geliştirelim
ARM

STM32F1xx EEPROM Fonksiyonlarını Geliştirelim

17 Dakikada Okunur
5
0
42
STM32I2C2
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.

Daha fazla ilgili makale
Yazardan daha fazla Ayhan KORKMAZ
Load More In ARM

5 Yorumlar

  1. fatih başdemir

    28 Ocak 2014 at 9:11 pm

    Ellerinize sağlık açıklayıcı bir yazı olmuş.

    Cevapla

  2. fatih başdemir

    28 Ocak 2014 at 9:38 pm

    Dahili eeproma yazma/okuma olayı sanırım yok stm32 lerde ?

    Cevapla

  3. Ayhan

    29 Ocak 2014 at 8:52 am

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

    Cevapla

  4. turgut

    18 Şubat 2015 at 2:33 pm

    stm32L serisinde dahili eeprom vardır

    Cevapla

    • Ayhan

      21 Şubat 2015 at 7:14 pm

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

      Cevapla

Cevap Yaz