SD kartları abr'a bağlarız. SD hafıza kartını STM32'ye SPI üzerinden bağlıyoruz.

Resmi sd karttan ekranda gösterdik, ancak içinde bazı noktalar gözden kaçırıldı, ilki - kartın kendisinin bağlanması, ikincisi - kütüphane işlevlerinin yalnızca bir kısmı dikkate alındı Küçük Şişmanlar Bu noktalara daha yakından bakalım.

Kart ile iletişim iki arabirimden biri aracılığıyla mümkündür, SPI veya SD.



SD arayüzünün bir bit ve dört bit modlarında çalışabileceğini söylemeliyim.

Kartı SPI ile bağlama şeması standarttır ve şuna benzer, kullanılmayan kart pinleri 10K'lık bir direnç kullanılarak güç kaynağına bağlanmalıdır.


Ancak amatör tasarımlarda, çekme dirençleri genellikle ihmal edilir ve bağlantı şeması basitleştirilir.

SPI ile bağlandığında, kartın besleme voltajı için çok talepte bulunduğuna ve besleme voltajındaki küçük bir düşüşün kartın çalışmamasına yol açtığına dikkat edilmelidir, bu test edilmiştir. kişisel deneyim, SD arayüzü hakkında söylenecek bir şey yok, henüz denemedim. Bütün bunlar için yazılmış güç kaynağı için kondansatörlerin kurulması gerekir. İndüktöre gelince, 100mA'ya kadar akım için derecelendirilmelidir, ancak takılması gerekli değildir.

Yukarıda gösterilen şemalar, kartın çalışması için sırasıyla 3,3 volta ihtiyaç duyduğunu, veri iletim hatlarında voltajın 0 - 3,3 volt aralığının ötesine geçmemesi gerektiğini ve burada MC'ye 5 güç sağlanıyorsa şu soru ortaya çıkıyor: volt?
Cevap basit, veri hatlarını eşleştirmeniz gerekiyor ve bu, geleneksel bir dirençli bölücü kullanılarak yapılabilir.


Diyagram, veriler bu hat üzerinden iletildiği için MISO hattının eşleştirilmesine gerek olmadığını göstermektedir. karttan MK'ye.
Aslında, birkaç kişi kartı doğrudan MK'ye bağlar, bir kart konektörünü MK'ye bağlamak veya bir konektör ve gerekli tüm kablo demetiyle bir kalkan satın almak çok daha uygundur.

Bağlantıyı bulduk, şimdi kütüphaneyi nasıl kullanacağımıza bakalım. Küçük Şişmanlar küçük bellek boyutuna sahip 8 bitlik mikrodenetleyiciler için tasarlanmıştır.

Kütüphane 5 dosyadan oluşur:
tamsayı.h- ana veri türlerini açıklayan bir başlık dosyası.

diskio.h- diskle çalışmak için düşük seviyeli işlevlerin prototiplerini ve bunların döndürdükleri durum kodlarını bildiren bir başlık dosyası.

diskio.c- bu dosyada düşük seviyeli işlevler uygulanmalıdır, başlangıçta "saplamalar" vardır.

pffconf.h- yapılandırma dosyası.

pff.h- disk dosya sistemiyle etkileşim için işlevlerin prototiplerinin bildirildiği başlık dosyası.

pff.c- dosya, disk dosya sistemiyle etkileşime yönelik işlevlerin uygulamalarını içerir.

Görüldüğü gibi kütüphanenin çalışabilmesi için alt seviye fonksiyonların gerçeklenmesi gerekmektedir. Ancak AVR veya PIC'den bahsediyorsak, onlar için dosyayı içeren kitaplık ile çalışmanın bir örneğini siteden indirebilirsiniz. mmc, içinde zaten düşük seviyeli işlevler uygulanmaktadır. Ayrıca pff.h dosyasında kütüphane konfigürasyonunun ayarlanması ve SPI'nin çalışması için gerekli fonksiyonların yazılması gerekmektedir.

Petit FatF'lerin İşlevleri.

FRESULT pf_mount (FATFS*)- işlev diski takar/çıkarır. Bu işlev, diskle çalışmaya başlamadan önce çağrılmalıdır, işlevi bir boş işaretçi ile çağırırsanız, diskin bağlantısı kesilir. Fonksiyon herhangi bir zamanda çağrılabilir.

Seçenekler
FATFS* fs- FATFS tipi bir nesneye işaretçi, bu yapının açıklaması pff.h dosyasında bulunabilir. Sadece bu türden bir değişken bildirmemiz gerekiyor.

Dönüş değerleri:
FR_OK (0)
FR_NOT_READY- cihaz başlatılamadı
FR_DISK_ERR- diskten okunurken bir hata oluştu
FR_NO_FILESYSTEM- sürücünün geçerli bir FAT bölümü yok

FATFS fs;//FATFS türünde bir nesne tanımlayın //Diski bağlayın if (pf_mount(&fs) == FR_OK) ( //Diski bağlayın, onunla çalışın //Diski çıkarın pf_mount(NULL); ) else ( //disk bağlanamadı )

FRESULT pf_open (const char* yolu)- işlev mevcut bir dosyayı açar. Dosya açıldıktan sonra onunla çalışabilir, yani ondan okuyabilir ve ona yazabilirsiniz. Başka bir dosya açılana kadar açık bir dosya ile çalışabilirsiniz. Fonksiyon herhangi bir zamanda çağrılabilir.

Seçenekler
const karakter* yolu- dosyanın yolunu gösteren bir dize işaretçisi. Yol, kök dizine göre tamamen belirtilmelidir ve dizinleri eğik çizgi ile ayırmalıdır.

Dönüş değerleri:
FR_OK (0)- işlevin başarılı bir şekilde yürütülmesi durumunda iade edilir
FR_NO_FILE- dosya bulunamadı
FR_DISK_ERR- disk hatası
FR_NOT_ENABLED- disk takılı değil

FATFS fs;//FATFS türünde bir nesnenin bildirilmesi //diskin bağlanması if (pf_mount(&fs) == FR_OK) ( //kök dizinde bulunan dosyanın açılması if(pf_open("hello.txt") == FR_OK) ) ( //birşey yapıyor ) //new klasöründeki dosyayı aç if(pf_open("new/hello.txt") == FR_OK) ( //birşey yap ) //diski kaldır pf_mount(NULL); ) else ( // disk bağlanamadı)

FRESULT pf_read(void* buff, WORD btr, WORD* br)- işlev, dosyadan belirtilen sayıda baytı okur ve bunları arabelleğe kaydeder. Okunan bayt sayısı belirtilenden azsa, dosyanın sonuna ulaşılmıştır.
#tanımla _USE_READ 1

Seçenekler:
geçersiz * tutkunu- okunan verilerin saklandığı arabelleğe işaretçi
KELİME BTR- okunacak bayt sayısı
KELİME*br- okunan bayt sayısını depolayan bir değişkene işaretçi.

Dönüş değerleri:
FR_OK (0)- işlevin başarılı bir şekilde yürütülmesi durumunda iade edilir
FR_DISK_ERR- disk hatası
FR_NOT_OPENED- dosya açılmadı
FR_NOT_ENABLED- disk takılı değil

FATFS fs;//FATFS BYTE türünde bir nesne bildirir buff;//WORD br dosyasını okumak için arabellek; // bayt sayacı oku // diski bağla if (pf_mount(&fs) == FR_OK) ( // kök dizinde bulunan dosyayı aç if(pf_open("hello.txt") == FR_OK) ( // oku 10 bayt pf_read(buff, 10, &br); if(br != 10) ( //eğer br 10'a eşit değilse //dosyanın sonuna geldik demektir ) ) )

FRESULT pf_write(const void* buff, WORD btw, WORD* bw)- işlev, açık bir dosyaya veri yazmanıza izin verir. Fonksiyonun pffconf.h dosyasında çalışması için şunu yazmanız gerekir:
#define _USE_WRITE 1

Seçenekler:
geçersiz * tutkunu- yazmak istediğimiz arabelleğe işaretçi, sıfır değeri yazmayı sonlandırır
KELİME bu arada- yazmak istediğimiz bayt sayısı
KELİME*bw- yazılabilecek bayt sayısını saklayan bir değişkene işaretçi. Bu değişkeni analiz ederek dosyanın sonuna ulaşılıp ulaşılmadığını öğrenebilirsiniz.

Dönüş değerleri:
FR_OK (0)- işlevin başarılı bir şekilde yürütülmesi durumunda iade edilir
FR_DISK_ERR- disk hatası
FR_NOT_OPENED- dosya açılmadı
FR_NOT_ENABLED- disk takılı değil

Kitaplığın az miktarda belleğe sahip mikrodenetleyiciler için tasarlanmış olması nedeniyle, bu işlevin bir takım sınırlamaları vardır:

  • yeni dosyalar oluşturamazsınız ve yalnızca mevcut olanlara yazabilirsiniz
  • dosya boyutu artırılamaz
  • zaman damgası güncellenemiyor
  • yazma işlemi yalnızca bir sektör sınırında başlatılabilir/durdurulabilir
  • salt okunur dosya özniteliği yazmayı engelleyemez

Sondan bir önceki noktayı anlamak için, kartın hafızasının 512 baytlık bloklara (sektörlere) bölündüğünü ve kayıt sadece sektörün başından itibaren başlatılabilir. Böylece 1000 byte yazmak istersek o zaman birinci sektör tamamen yazılacak ve ikinciye sadece 488 byte yazılacak ve kalan 24 byte sıfırlarla doldurulacaktır.

Açık bir dosyaya yazmak için aşağıdakileri yapın:

  • işaretçiyi sektör sınırına ayarlayın, sınıra ayarlanmazsa işaretçi alt sektör sınırına yuvarlanır
  • yazma işlevini istediğiniz sayıda çağırın
  • işlevi bir boş işaretçi ile çağırarak girişi sonlandırın

Kayıt fonksiyonunun çalışmasına örnek vermek için bir fonksiyonu daha ele almak gerekir.

FRESULT pf_lseek(DWORD ofseti)- okuma/yazma işaretçisini şuna ayarlar: açık dosya. İmleci mutlak veya göreli bir ofsetle ayarlayabilirsiniz; mutlak bir ofset için işleve bir sayı iletmelisiniz.
pf_lseek(5000);
göreli için, işaretçinin değerini geçerli konuma iletin fs.fptr ve yer değiştirme miktarı
pf_lseek(fs.fptr + 3000);
Fonksiyonun pffconf.h dosyasında çalışması için şunu yazmanız gerekir:
#define _USE_LSEEK 1

Seçenekler:
DWORD ofseti işaretçinin kaydırılacağı bayt sayısıdır.

Dönüş değerleri:
FR_OK (0)- işlevin başarılı bir şekilde yürütülmesi durumunda iade edilir
FR_DISK_ERR- disk hatası
FR_NOT_OPENED- dosya açılmadı

Bir dosyaya aşağıdaki şekilde veri yazabilirsiniz.
FATFS fs;//FATFS BYTE türünde bir nesne bildirir buff;//WORD br dosyasını okumak için arabellek; // bayt sayacı oku // diski bağla if (pf_mount(&fs) == FR_OK) ( // kök dizinde bulunan dosyayı aç if(pf_open("hello.txt") == FR_OK) ( // set ilk sektörün işaretçisi pf_lseek(0); //write pf_write(buff, 10, &br); //yazmayı sonlandır pf_write(0, 0, &br); ) )

Ayrıca burada, yukarıda açıklanan tüm işlevleri kullanan, gerçekten çalışan bir kod parçası bırakıyorum.
#define F_CPU 8000000UL #define buff_size 10 #include #katmak #include "diskio.h" #include "pff.h" #include "spi.h" FATFS fs;//FATFS BYTE türünde bir nesne bildirmek read_buff;//dosyayı okumak için tampon BYTE write_buff = "hello word"; /// UINT br dosyasına yazmak için arabellek; // bayt sayacı oku int main(void) ( // diski bağla if (pf_mount(&fs) == FR_OK) ( // dosyayı new klasöründe aç if(pf_open("new/hello.txt") =) = = FR_OK) ( //yazma işaretçisini ayarla pf_lseek(0); //write pf_write(write_buff, buff_size, &br); //yazmayı sonlandır pf_write(0, 0, &br); //okuma işaretçisini ayarla pf_lseek(0); / /yazdığımızı oku pf_read(read_buff, buff_size, &br); if(br != buff_size) ( //eğer br, buff_size'ye eşit değilse // dosyanın sonuna geldik demektir ) ) //bağla disk pf_mount(NULL); ) while(1) ( ) )

FRESULT pf_opendir(DIR* dp, const char * yol)- işlev varolan bir dizini açar ve açık dizindeki dosyaların listesini almak için kullanılacak olan DIR türünde bir nesneye işaretçi oluşturur.
Fonksiyonun pffconf.h dosyasında çalışması için şunu yazmanız gerekir:
#define _USE_DIR 1

Seçenekler:
YÖN *dp- DIR türünde bir değişkene işaretçi.

const char *yol- dizine giden yolu içeren bir dizeye işaretçi, dizinler eğik çizgi ile ayrılır

Dönüş değerleri:
FR_OK (0)- işlevin başarılı bir şekilde yürütülmesi durumunda iade edilir
FR_NO_PATH- yol bulunamadı
FR_NOT_READY- Disk başlatılamadı
FR_DISK_ERR- disk hatası
FR_NOT_ENABLED- disk takılı değil

//fatfs fs değişkenlerinin bildirilmesi; YÖN dir; //diski bağla pf_mount(&fs); //dizin aç pf_opendir(&dir, "Klasörüm");

FRESULT pf_readdir(DIR* dp, FILINFO* fno)- işlev, dizinin içeriğini okumanızı sağlar. Bunu yapmak için, pf_opendir() işleviyle bir dizin açın ve pf_readdir()'i çağırın. İşlev her çağrıldığında, belirtilen dizinde bulunan nesnenin (klasör/dosya) adını döndürür. Tüm nesneleri gözden geçirdiğinde, fno.fname dizi öğesindeki boş dizgiyi döndürür.
Fonksiyonun pffconf.h dosyasında çalışması için şunu yazmanız gerekir:
#define _USE_DIR 1

Seçenekler:
YÖN *dp- önceden bildirilmesi gereken DIR tipi bir değişkene işaretçi

FILINFO *fno- önceden bildirilmesi gereken FILINFO tipi bir değişkene işaretçi.

Dönüş değerleri:
FR_OK- işlevin başarıyla tamamlanması
FR_DISK_ERR- disk hatası
FR_NOT_OPENED- dizin açık değil

FATFS; FRESULT çözünürlüğü; FILINFO fno; YÖN dir; //diski bağla pf_mount(&fs); //res dizini aç = pf_opendir(&dir, KLASÖRÜM); //dizinin içeriğini oku for(;;)( res = pf_readdir(&dir, &fno); //okuma sırasında herhangi bir hata olup olmadığını ve belirtilen dizinde hala dosyalar olup olmadığını kontrol edin if ((res ! = FR_OK) || ( fno.fname == 0))( break; ) //fno.fname usart_sendStr(fno.name); usart_sendStr(/r); )

Son olarak, çalışma projesini burada bırakacağım.

Ders 33

Bölüm 1

SPI. Hafıza kartı. YAĞ

Bugün SPI arayüzünde en sevdiğimiz konuya devam edeceğiz. Bu veri yolu ile Atmega8a ve ATTtiny2313 kontrolörlerini birbirimize bitirdik. Ve bugün bu arayüzü kullanarak bu veri yolu üzerinden mikrodenetleyiciye bir hafıza kartı bağlamayı deneyeceğiz. SD (Güvenli Dijital).

Bu kart SDIO arabirimi üzerinden de bağlanabilmektedir ancak böyle bir arabirim denetleyici donanımımız tarafından desteklenmediği için bu dersimizde ona dokunmayacağız. Otobüs bağlantısının türüyle ilgileniyoruz SPI, çünkü bu konuda zaten iyi bir bilgi birikimine ve programladığımız denetleyicide donanım desteğine sahibiz.

Bununla birlikte, her iki tür için de kart ayaklarının pin çıkışını göreceğiz.

Peki, ikinci tiple ilgilendiğimiz için onunla ilgileneceğiz.

Ve burada gerçekten anlaşılacak bir şey yok. Bütün bu kısaltmalar bizim tarafımızdan bilinmektedir. İşte SPI arayüzünün tüm standart ayakları ve burada gereksiz hiçbir şey yok.

Şimdi genel olarak harita hakkında. Bu kart veri depolamamıza izin verir, hafıza tipi FLASH'dır, bu da EEPROM tipi hafızaya kıyasla uçucu değildir, yani güç kapatıldığında veriler hiçbir yerde kaybolmaz, ancak kayıtlı kalır. Ayrıca bu hafızanın farklılıkları var, programlama sürecinde onlarla tanışacağız. Temel farklardan biri, bu belleğe EEPROM belleğindeki gibi bir bayt yazamamamızdır. Teorik olarak, elbette yapabiliriz, ancak FLASH - NOR veya NAND türüne bağlı olarak oraya yalnızca baytımızdan birler veya yalnızca sıfırlar yazılacaktır. Yani bir baytı yazmadan önce onu silmeniz gerekir ve bu belleğin organizasyonu nedeniyle yalnızca bloklar halinde silebiliriz ve bu nedenle sadece bloklar halinde yazabiliriz. Ancak EEPROM'dan en büyük fark var - bu fiyat. Depolanan bir bilgi birimi için (megabayt başına, gigabayt başına) bazen büyüklük derecelerine göre bile birçok kez daha ucuzdur. Bu nedenle, FLASH bellek genellikle çok daha büyük miktarda bilgiye sahiptir.

4 tip SD vardır, ancak bunu biraz sonra inceleyeceğiz.

Proteusdayken bu kartı bağlayalım

Burada her şey basit. Aslında pek öyle değil. Daha fazla dirence ihtiyaç var

Kart 3.3 volt ile beslendiği için uygun seviyelerin sağlanabilmesi için bu dirençlere ihtiyaç duyulmaktadır. Genel olarak, teknik belgelere göre 2,7 ila 3,6 volt.

Ayrıca proteusta belirtilmemiş ama aslında kartımıza 5 voltu 3.3 volta çeviren bir mikro devre kurarak ayrı bir güç kaynağından güç vereceğiz.

Aksine, hiçbir şey kurmayacağız, ancak her şeyin kurulu olduğu hazır bir modül kullanacağız.

Ayrıca, ekran kitaplığının işlevselliğini genişletirken olduğu gibi, bağlı bir ekranımız var.

pratikte böyle görünüyor

Tutuculu modül böyle görünür

Böyle bir modülü her yerde bulabilirsiniz, bir kuruşa mal olur. SDIO üzerinden bağlanan modülün maliyeti daha fazladır. Ayrıca voltajı 3,3 volta düşürmek için modüle bir mikro devrenin takılı olduğunu görüyoruz. Ve gücü yalnızca 5 volt kontağına bağlarız ve 3.3'e hiçbir şey bağlamayız.

Ayrıca, seviyeler için tüm bölücüler modül üzerine kuruludur, yani bu modül özellikle 5 voltluk cihazlara bağlantı için tasarlanmıştır.

Ve 32 megabaytlık testler için bir flash kart çıkardım, tam olarak bir megabayt ve bir gigabayt değil

Bu flash kart, bir tür kamera ile birlikte bağışlandı ve testlerimiz için bize en çok yakışacak, en azından kartta çok fazla bellek olması nedeniyle şu ya da bu aksaklık olduğunu düşünmeyeceğiz.

Kod da display library ile birlikte son dersten alınmıştır son derste oluşturduğumuz fonksiyonu çok aktif kullanacağımız için sadece tabi ki yeni bir proje oluşturulup buna göre isimlendirilmiştir. MYSD_SPI.

Gereksiz satırları silin, main() içinde sadece buna sahip olacağız

intana( geçersiz)

imzasızintBen;

port_ini();

LCD_ini(); // ekranı başlat

açık lcd(); // ekranı temizle

setpos(0,0);

str_lcd( "Dize 1");

setpos(2,1);

str_lcd( "dize2");

setpos(4,2);

str_lcd( "dize 3");

setpos(6,3);

str_lcd( "dize 4");

Gecikme_ms(2000);

// for (i=0; i<=22;i++) {str80_lcd(buffer2+i*20);_delay_ms(1000);}

Sırasında(1)

Yazıyı karakter karakter göstermeyeceğimiz için değişkendeki char tipi ile idare etmek mümkün olacaktır.

imzasızkarakter Ben;

Şimdi bir nüans daha.

Proteus'ta bir SD kart ile çalışabilmemiz için kartın kendisi ile tutucuyu eklememiz yeterli değil, özelliklerinde bir flash kart görüntü dosyası da eklememiz gerekiyor.

Bunu oluşturmak zor değil. Bunun bir yolu, onu WinImage programını kullanarak oluşturmaktır.

Dosya -\u003e Yeni menü öğesini kullanarak standart olarak yeni bir dosya oluştururuz. İletişim kutusundaki son öğeyi seçin ve "Tamam"a tıklayın

Proteus'taki test için 4 megabayt boyutu bizim için yeterli, bu nedenle bir sonraki iletişim kutusundaki alanı sektör sayısıyla değiştireceğiz ve ayrıca FAT12 / 16 biçimini seçeceğiz çünkü 32 bitlik bir dosya ile sistem biraz farklı çalışma özellikleri ve ayrıca "Tamam" ı tıklayın

Genel olarak tabii ki henüz dosya sistemi ile çalışmadığımız için FAT32'den de ayrılabiliriz ama dersin ilerleyen bölümlerinde dosya sistemi ile çalışacağız ve 12/16 ile çalışacağız.

Daha sonra oluşturulan dosyamızı Dosya -> Farklı Kaydet menü öğesini kullanarak kaydediyoruz. Ve onu, kaydedilmiş proteus projemizin olduğu klasöre kaydediyoruz. Dosyayı adlandırın ve "Kaydet"i tıklayın

Ayrıca, bu dosyayı "salt okunur" özniteliğiyle almadığımızdan emin olmanız gerekecek ve bundan sonra onu proteus'a zaten bağlayabiliriz. Proteus bir tür kendi formatını gerektirdiğinden ve dosyamız görünemeyeceğinden, dosya adını manuel olarak girmek gerekecektir.

Dosyayı proje klasöründe bulundurduğumuz için herhangi bir yola ihtiyacımız yok. "Tamam"a basıyoruz.

Veri yolunu başlatmamıza gerek yok, çünkü bir yazılım SPI'mız olacak, tüm flash kartlar donanım flash kartlarıyla düzgün çalışmıyor, o zaman herhangi bir kayıt kullanmamıza gerek kalmayacak. Elbette donanımsal olan daha iyi ama protokolün işleyişini tam olarak anlamak için yazılımla da çalışmanız yani portların ayaklarını sallamanız gerekiyor. Genel olarak, şemaya bakıldığında, donanımda her şeye sahipmişiz gibi görünebilir, çünkü tam da bu tür ayakları seçtim, çünkü daha sonra, bir gün, belki birileri donanım uygulama lastikleriyle çalışmaya devam edecek şekilde seçtim. .

Bağlantı noktası pimleri için makro ikameleri ekleyin

#katmak"ana.h"

#tanımlamakMOSİ3

#tanımlamakMİSO4

#tanımlamakSCK5

#tanımlamakSS2

Port başlatma işlevine bacakları başlatma kodunu ekleyelim

geçersizport_ini( geçersiz)

PORTD=0x00;

DDRD=0xFF;

PORTB|=(1<< SS)|(1<< MİSO)|(1<< MOSİ);

DDRB|=(1<< SS)|(1<< MOSİ)|(1<< SCK);

MISO bacağını girişte bırakıyoruz, çünkü varsayılan olarak kayıttaki tüm bitler sıfırdır ve ona dokunmayız. Ayrıca MOSI ve SS'de hemen yüksek bir seviye açıyoruz ve MISO'ya bir direnç çekiyoruz.

SPI veri yolu üzerinden bir bayt aktarmak için bir işlev yazalım

geçersizSPI_SendByte( imzasızkarakterbayt)

{

}

Döngü ve döngünün kendisi için bir değişken ekleyin

geçersizSPI_SendByte( imzasızkarakterbayt)

imzasızkarakterBen;

için( Ben=0; Ben<8; Ben++) // bir baytın bitleri ile hareket et

{

}

Tam olarak 8 bit ilettiğimiz için neden 8'e kadar saymamız anlaşılabilir olduğunu düşünüyorum.

Pekala, onları sinsice geçmeye başlayalım.

Önce en soldaki biti kontrol edelim, tüm bayttan maskeleyerek seçelim ve eğer 1'e eşitse, MOSI veriyolunda 1'e ayarlayalım ve 0 ise veri yoluna dokunmayız.

için( Ben=0; Ben<8; Ben++) // bir baytın bitleri ile hareket et

Herkese iyi günler! Bugün hakkında konuşacağız bir SD hafıza kartı bağlama STM32 mikrodenetleyicisine.

Görünüşe göre STM32F10x denetleyicilerinin çok fazla belleği var, neden ek bir bellek var, ancak bu izlenim aldatıcı) Örneğin, ekranda birkaç farklı görüntü - 320 * 240 formatında - yani, Her biri 2 bayta kadar karşılık gelen 76800 piksel. Böylece resim başına yaklaşık 150 kB elde ederiz. Ve bu, bir mikrodenetleyicinin standartlarına göre çok fazla ve Flash belleğine iki farklı resmin doldurulabileceği bir gerçek değil. Ya da büyük miktarda bilgiyi, örneğin bazı sensörlerden gelen verileri depolamamız gerekiyor. Ayrıca, güç kapatıldıktan sonra bile bu verilerin kullanılabilir olması için. Harici belleğin kullanışlı olduğu yer burasıdır. Ve harika bir çözüm hafıza kartı veya MMC'yi seçin. Bu arada, bu yazıda üzerinde deneyler yapacağız. Mikro SD kart.

İlk olarak, hafıza kartının kendisi veya daha doğrusu pin çıkışı hakkında birkaç söz. Her şey şuna benziyor:

Peki burada neyimiz var? Pekala, sekiz adede kadar sonucu olduğunu hemen görebilirsiniz. Pim atamaları aşağıdaki gibidir (soldan sağa):


SPI Modu sütunu, SPI arayüzünü kullanarak mikrodenetleyici ile etkileşime girdiğini bize ima eder. ANCAK! Farklı bir yol izleyeceğiz 😉 Mesele şu ki, STM32'de hafıza kartlarıyla çalışmak için hazır bir çevre birimi modülü var ve buna SDIO deniyor.

Genel olarak, hafıza kartlarıyla etkileşim, onlara belirli komutların aktarılmasından oluşur. Bazı komutlar argüman gerektirir, bazıları gerektirmez. Komutlar, belirli bir kartın resmi belgelerinde bulunabilir. Böylece yerleşik SDIO modülü, komutları iletme sürecini ve aslında harici hafıza kartlarıyla çalışma sürecini büyük ölçüde basitleştirmeyi mümkün kılar. Örneğin, işte kayıt SDIO_CMD- orada sadece karta aktarmak istediğimiz komutun kodunu yazıyoruz. Veya burada durum kaydı SDIO_STA- her hapşırma için, yani çok sayıda olay için 24 adede kadar bayrak vardır.

Bu arada STM, her şey için iyi bir dokümantasyondan da memnun. Burada, örneğin, bir SD hafıza kartı için başlatmanın ayrıntılı bir açıklaması bulunmaktadır (diğer kart türleri için her şey benzer şekilde açıklanmıştır):

Aslında, pratik bir örneğe geçmenin zamanı geldi. Standart Çevre Birim Kitaplığı'nı inceleyelim.

Dosyada stm32f10x_sdio.h geleneksel olarak, her tür ayar için yapılar buluruz - yani, saat sinyalinin kaynağını, SDIO denetleyicisinin frekansını seçmek ve iletilen bayt sayısını ayarlamak için. Orada her şey o kadar cömertçe yorumlanmış ki, ayrı ayrı tekrarlamak bile istemiyorum)) Sadece bakın:

typedef yapısı ( uint32_t SDIO_ClockEdge; /* Bit yakalamanın yapıldığı saat geçişini belirtir. Bu parametre bir @ref SDIO_Clock_Edge */ değeri olabilir. uint32_tSDIO_ClockBypass; /* SDIO Saat bölücü atlamanın etkin mi yoksa devre dışı mı olduğunu belirtir. Bu parametre bir @ref SDIO_Clock_Bypass */ değeri olabilir. uint32_tSDIO_ClockPowerSave; /* Veri yolu boştayken SDIO Saat çıkışının etkin mi yoksa devre dışı mı olduğunu belirtir. Bu parametre bir @ref SDIO_Clock_Power_Save */ değeri olabilir. uint32_tSDIO_BusWide; /* SDIO veri yolu genişliğini belirtir. Bu parametre bir @ref SDIO_Bus_Wide */ değeri olabilir. uint32_t SDIO_HardwareFlowControl; /* SDIO donanım akış kontrolünün etkin mi yoksa devre dışı mı olduğunu belirtir. Bu parametre bir @ref SDIO_Hardware_Flow_Control değeri olabilir */ uint8_tSDIO_ClockDiv; /* SDIO denetleyicisinin saat frekansını belirtir. Bu parametre 0x00 ile 0xFF arasında bir değer olabilir. */) SDIO_InitTypeDef; typedef yapısı ( uint32_t SDIO_Argument; /* Bir komut mesajının parçası olarak bir karta gönderilen SDIO komut bağımsız değişkenini belirtir. Bir komut bir argüman içeriyorsa, komutu komut kaydına yazmadan önce bu kayda yüklenmelidir */ uint32_t SDIO_CmdIndex; /* SDIO komut dizinini belirtir. 0x40'tan küçük olmalıdır. */ uint32_t SDIO_Response; /* SDIO yanıt türünü belirtir. Bu parametre bir @ref SDIO_Response_Type */ değeri olabilir. uint32_tSDIO_Bekle; /* SDIO kesinti için bekleme isteğinin etkin mi yoksa devre dışı mı olduğunu belirtir. Bu parametre bir @ref SDIO_Wait_Interrupt_State değeri olabilir */ uint32_t SDIO_CPSM; /* SDIO Komut yolu durum makinesinin (CPSM) etkin mi yoksa devre dışı mı olduğunu belirtir. Bu parametre bir @ref SDIO_CPSM_State değeri olabilir */) SDIO_CmdInitTypeDef; typedef yapısı ( uint32_t SDIO_DataTimeOut; /* Kart veriyolu saat periyotlarında veri zaman aşımı periyodunu belirtir. */ uint32_tSDIO_DataLength; /* Aktarılacak veri bayt sayısını belirtir. */ uint32_tSDIO_DataBlockSize; /* Blok aktarımı için veri bloğu boyutunu belirtir. Bu parametre bir @ref SDIO_Data_Block_Size */ değeri olabilir. uint32_tSDIO_TransferDir; /* Veri aktarım yönünü, aktarımın okuma mı yoksa yazma mı olduğunu belirtir. Bu parametre bir @ref SDIO_Transfer_Direction değeri olabilir */ uint32_tSDIO_TransferModu; /* Veri aktarımının akış modunda mı yoksa blok modunda mı olduğunu belirtir. Bu parametre bir @ref SDIO_Transfer_Type */ değeri olabilir. uint32_t SDIO_DPSM; /* SDIO Veri yolu durum makinesinin (DPSM) etkin mi yoksa devre dışı mı olduğunu belirtir. Bu parametre bir @ref SDIO_DPSM_State */ değeri olabilir.) SDIO_DataInitTypeDef;

SPL'nin komutların hafıza kartına aktarımını nasıl uyguladığına dikkat edin. Bu amaçlar için ayrı bir yapı oluşturulmuştur. SDIO_CmdInitTypeDef. sahada SDIO_CmdIndex alana komut kodunu girin SDIO_Argüman- komut bağımsız değişkeni, kalan alanları da doldurun. Bu verileri bir şekilde bir mikro SD karta aktarmaya devam ediyor 😉 Ve bunun için bir işlev hazırladık:

SDIO_SendCommand (SDIO_CmdInitTypeDef *SDIO_CmdInitStruct)

Argüman olarak, ona yarattığımız yapının aynısını aktarıyoruz. Veri yazmak için bir işlev var - SDIO_WriteData(uint32_t Verileri). Bu işlevi çağırdıktan sonra, veriler özel olarak tasarlanmış bir kayıt defterinde olacaktır - SDIO_FIFO.

STM32F10x'te SDIO modülü ile çalışma bu şekilde yapılır)

Şimdi son olarak uygulamaya geçelim. İyi Çinliler, üzerine bir mikro SD hafıza kartı yuvası takarak şaşkına döndüklerinden, Mini STM32 kartıyla tekrar çalışacağım. Kart konektörünü mikrodenetleyiciye bağlamanın bir şeması aşağıdadır:

Bir program yazmak için, Keil için hazır bir örnek kullanacağız - oradan, kartlarla çalışmak için bir sürücü gibi bir şeyin uygulandığı iki dosya çalacağız - bunlar dosyalar sdcard.c Ve sdcard.h Yeni bir proje oluşturuyoruz, bu dosyaları oraya bağlıyoruz ve ayrıca tabii ki CMSIS ve SPL dosyaları. İşte her şeyin zaten eklendiği bitmiş proje - sadece ana () işlevin kodunu yazmak için kalır)

sdcard.c dosyası bir hafıza kartıyla çalışmak için her türlü işlevi uygular, şimdi sadece onları kullanmamız gerekiyor 😉 Kodu yazalım! Örneğin, micro SD'ye 512 bayt test verisi yazalım ve ardından bunları okumaya çalışalım:

// Gerekli dosyaların bağlanması#include "stm32f10x.h" #include "sdcard.h" /*******************************************************************/ // Girdi ve çıktı verileri dizileri ve verileri depolamak için bir değişken// haritamız hakkında uint8_t writeBuffer[ 512 ] ; uint8_t readBuffer[ 512 ] ; SD_CardInfo SDCardInfo; /*******************************************************************/ int ana() ( // Yazılacak veriyi test et için (uint16_t ben = 0 ; ben< 512 ; i++ ) { writeBuffer[ i] = i % 256 ; readBuffer[ i] = 0 ; } // Harita başlatma SD_Init() ; // Harita bilgilerini al SD_GetCardInfo(& SDCardInfo) ; // Bir haritanın seçilmesi ve çalışma modunun ayarlanması SD_SelectDeselect((uint32_t ) (SDCardInfo.RCA<< 16 ) ) ; SD_SetDeviceMode(SD_POLLING_MODE) ; // Ve son olarak, yazma ve okuma SD_WriteBlock(0x00 , writeBuffer, 512 ) ; SD_ReadBlock(0x00 , readBuffer, 512 ) ; iken (1 ) ( ) ) /*******************************************************************/

Lütfen SD kartın 512 baytlık bloklar halinde yazmayı desteklediğini unutmayın.

Programı bir hata ayıklayıcı altında çalıştırırsak, okunan verilerin yazılan verilere karşılık geldiğini göreceğiz =) Dolayısıyla deney başarılı sayılabilir. Bugünlük bu kadar, görüşmek üzere!

Mihail Russkikh

SD kartlar hakkında kısaca bilgi verilir, SD bus işleyişinin temelleri verilir, STM32 ailesi mikrodenetleyicilerin SD kartlar ile haberleşmesini kolaylaştırmak için tasarlanmış stm324xg_eval_sdio_sd sürücüsünün kullanım prosedürü anlatılır.

Bazı gömülü sistemler büyük miktarda bilgi depolayabilmelidir. Örneğin, çeşitli fiziksel miktar ve parametrelerin (akım, voltaj, sıcaklık, coğrafi koordinatlar) kayıt cihazları, sensörlerden alınan okumaları daha sonra cihazdan çıkarılabilecek ve verileri görüntülemek için bir bilgisayara bağlanabilecek belirli bir ortamda saklamalıdır. kullanıcı dostu bir biçimde. Bu sorunu çözmek için en bariz olanı USB flash sürücülerin kullanılması gibi görünüyor. Piyasada yaygın olarak dağıtılırlar ve büyük miktarda bilgi depolamanıza izin verirler. Ancak bazı küçük gömülü sistemler için kompaktlık çok önemlidir ve bu sürücüler çok büyük olabilir. Ek olarak, tüm mikrodenetleyiciler bir USB modülü ile donatılmamıştır ve sistem tasarımcısı, proje süresini artırabilen USB yığınıyla uğraşmak için oldukça fazla zaman harcayabilir. Bu bağlamda, USB'ye iyi bir alternatif, çok kompakt olan ve ortak SPI arabirimi veya SD kartlar için özel bir arabirim kullanılarak veri alışverişine izin veren SD kartları kullanmaktır.

SD (Secure Digital) hafıza kartları, öncelikle taşınabilir cihazlarda kullanılmak üzere tasarlanmıştır. Bugün piyasada, SanDisc gibi şirketler tarafından sağlanan, sınıfa bağlı hızlarda 8 MB'tan 2 TB'a kadar veri kaydedebilen çok sayıda model bulunmaktadır. SD kartlar, MMC kartlarından farklı olarak, normal veri depolama alanına ek olarak, ortalama bir kullanıcının erişemeyeceği özel bir korumalı alana sahiptir. Cihazın SD karta dosya şeklinde kaydedilen bilgileri okuyabilmesi için bu kartın belirli bir dosya sistemine sahip olması gerekir. Bu durumda en çok tercih edilen sistem FAT sistemidir, çünkü SD kartlar için yazma / okuma döngü sayısı sınırlıdır ve NTFS ve ext gibi sistemler günlüklenir, yani sık sık yoklama içerirler.

Veri iletimi ve alımı, SPI arayüzü veya SD veri yolu üzerinden gerçekleştirilir. Şekil 1, farklı SD kart türleri için pin atamalarını gösterir ve Tablo 1, bu pinlerin işlevselliğini gösterir.

Tablo 1. SD kart pinlerinin işlevsel amacı

SPI arayüzü

SD arayüzü

SDC kartları

miniSD kartlar

microSD kartlar

Ana bilgisayar denetleyicisi, SPI kullanarak kartla iletişim kurabilse de, SD veri yolu yine de daha fazla seçenek sunar ve dört veri hattının varlığı nedeniyle bilgileri daha yüksek hızda aktarmanıza olanak tanır. Bu nedenle, aşağıda tam olarak bu SD kartla çalışma yöntemini daha ayrıntılı olarak ele alacağız.

SD veri yolu üzerinden veri aktarımı

SD kart ile iletişim 6 bilgi hattı üzerinden gerçekleştirilir: 4 veri hattı (DAT0, DAT1, DAT2, DAT3), senkronizasyon hatları (CLK), komut iletim hatları (CMD). Denetleyiciye bağlandığında, veri hattı ve komut satırı Şekil 2'de gösterildiği gibi güce çekilmelidir.

Veri yazma ve okuma blok blok yapılır. Tipik olarak, bir blok 512 bayttan oluşur. Verilerin ve hizmet bilgilerinin aktarımı, "komut-yanıt" etkileşim modeline dayalıdır. Veri iletmeden veya almadan önce, ana bilgisayar denetleyicisi CMD satırında uygun komutu göndermelidir. Aynı satır boyunca SD karttan bir yanıt gelmeli ve ardından gerekli işlem yapılabilir. SD standardı, ana bilgisayar denetleyicisinin komutları yayın yoluyla gönderebileceği durumda, veri yolunda birden çok kölenin varlığını destekler. Komut 48 bitten oluşan net bir yapıya sahiptir: 1 başlangıç ​​biti, 1 iletim biti (1'e set), 6 bit komut dizini, 32 bit argüman, 7 bit sağlama toplamı ve 1 durdurma biti. Yanıt, aynı 48 bitlik yapıya sahip olabilir (bu durumda iletim biti 0'a ayarlanır) veya 136 bitten (uzun yanıt formatı olarak adlandırılır) oluşabilir: 1 başlangıç ​​biti, 1 iletim biti (0'a ayarlanır), 6 ayrılmış bitler, 127 bit CID (Kart Kimlik Kaydı) veya CSD (Karta Özel Veri Kaydı) içeriği ve sağlama toplamı, 1 durdurma biti.

Kartla çalışmanın başlangıcında, ana bilgisayar denetleyicisi komutları kullanarak kartı yeniden yükler. GO_IDLE_STATE(CMD0) Ve IO_RW_DIRECT (CMD52). Açıklamaları olan komutların tam listesi (Ek A) içinde bulunabilir. Yeniden başlatmanın ardından, kart varsayılan ayarlarını geri yükleyecek ve adresi RCA = 0x0001'e eşit olacaktır. Ana bilgisayara birkaç kart bağlıysa, komutu kullanarak SET_RELATIVE_ADDR (CMD3) her karta kendi adresini verir. Ayrıca işe başlarken karta uygulanan voltaj kontrol edilir. Kartın voltajı, 2,7 ila 3,6 V arasında kesin olarak belirlenmiş bir aralıkta olmalıdır. Bu bağlamda, komutu kullanan ana bilgisayar denetleyicisi SEND_OP_COND (CMD1 veya ACMD41) karttaki mevcut voltajı bulmalı ve gerekli aralıkta değilse onunla çalışmayı bırakmalıdır. Bu, kartın türüne (MMC, SD, SD I / O) bağlı olarak diğer komutların ve ek adımların kullanılabileceği kart başlatmanın genel ilkesidir, bu nedenle düşük seviyeli bir arayüz uygularken yapmanız gerekenler kartın belgelerini dikkatlice okuyun ve CMD komutlarını inceleyin.

Yazma sırasında, ana bilgisayar komutu kullanarak karta bir veya daha fazla blok gönderir. WRITE_BLOCK (CMD24) veya WRITE_MULTIPLE_BLOCK (CMD25) sırasıyla, her bloğun sonunda ana bilgisayar bir sağlama toplamı yazar. Yazma özellikli bir kart her zaman blokları alabilir, ancak sağlama toplamı eşleşmezse, kart bir hata bildirir ve mevcut bloğu hafızasına yazmaz ve patlama durumunda, aşağıdaki bloklar göz ardı edilecektir.

Komutu kullanarak ana bilgisayara bilgi aktarabilir, yani tek bir blokta okuyabilirsiniz. READ_SINGLE_BLOCK (CMD17) veya komutu kullanarak birkaç bloktan oluşan bir grup READ_MULTIPLE_BLOCK (CMD18). Seri iletim durumunda, ana bilgisayar komutu göndererek okumayı istediği zaman iptal edebilir. İLETİMİ DURDUR (CMD12). Birkaç bloğun aktarımı sırasında kartın dahili denetleyicisi bir hatayı düzeltirse, ana denetleyiciye veri göndermeyi durdurur, ancak kartı veri aktarım modunda bırakır. Bu durumda, ana bilgisayarın okumayı komutla bitirmeye zorlaması gerekecektir. CMD12, bu komuta yanıt olarak kart bir okuma hatası bildirecektir.

SD veri yolunun doğru çalışmasının organizasyonu oldukça zahmetli bir süreçtir, çünkü yukarıda açıklanan genel durumlara ek olarak, kartın davranışında çeşitli nüanslar sağlamak ve ek hata işleyicileri uygulamak gerekir. Bu nedenle, en akılcı çözüm, geliştiricinin donanım düzeyinde veri aktarımının ayrıntılarına girmemesine izin veren ve geliştirme süresini önemli ölçüde azaltan özel kitaplıklar kullanmak olacaktır. Aşağıda tartışılacak olan bu kitaplıklardan biri de sürücü kitaplığıdır. stm324xg_eval_sdio_sd SD kartlarla etkileşime geçmek için tasarlanmış SDIO modülü ile çalışmayı önemli ölçüde basitleştirmenizi sağlayan popüler mikrodenetleyiciler için.

stm324xg_eval_sdio_sd sürücüsü

Bu sürücü, bir SD kart ile iletişim kurmak için üst düzey bir arabirim uygulayabileceğiniz bir işlevler kitaplığıdır. Sürücü, STM324VG hata ayıklama kartı (UtilitiesSTM32_EVALSTM3240_41_G_EVAL) ile çalışacak şekilde sağlanır, ancak bu kitaplığı düşük seviyeli SDIO arabirimine bağlayan işlevleri değiştirdikten sonra, bir SDIO modülü içeren STM32 ailesinin birçok mikro denetleyicisiyle çalışabilir. Önceki cümleden, standart kitaplıktaki dosyaların projeye dahil edilmesi gerektiği anlaşılmaktadır. Standart Çevre Kitaplığı, SDIO modülünün düşük seviyede çalışmasını sağlayan. Örneğin, STM32F4xx serisinin mikrodenetleyicileri için bunlar dosyalar olacaktır. stm32f4xx_sdio.c Ve stm32f4xx_sdio.h.

Sürücü işlevlerini kullanmadan önce, programcının bu sürücüyü donanımla ilişkilendirmesi, yani SDIO modülünün hatlarını yapılandırması gerekir. Bunu yapmak için, main.c programının ana dosyasında işlevler oluşturması gerekir. SD_LowLevel_Init() (SDIO modülünü etkinleştirmek için) ve SD_LowLevel_DeInit() (SDIO modülünü devre dışı bırakmak için) bu hatların yapılandırılması gerekir. Programcı, SD kartla çalışma hızını artırmak için doğrudan bellek erişim modülünü kullanmak istiyorsa, ayrıca işlevler oluşturması gerekecektir. SD_LowLevel_DMA_TxConfig() Ve SD_LowLevel_DMA_RxConfig() PDP modülünü kullanarak veri iletmek ve almaktan sorumludur. Belirtilen dört işlevin başlatılmasına örnek olarak, dosyada bulunan kodu alabiliriz. stm324xg_eval.c(UtilitiesSTM32_EVALSTM3240_41_G_EVAL) kaynağından.

Şimdi bu sürücü tarafından sağlanan SD kartla çalışmanın ana işlevlerine bakalım. Haritayı başlatmak için işlevi çağırmanız gerekir. SD_Init() başvurarak SDIO modülünü yapılandıran SD_LowLevel_Init() , SD kart tipini kontrol eder, CID ve CSD kayıtlarından servis bilgilerini alır, baud hızını ayarlar (varsayılan olarak 24 MHz) ve veri yolu genişliğini (4 bit) ayarlar. Fonksiyonları kullanarak karttan alınan verileri okuyabilirsiniz. SD_ReadBlock() (bir bloğu okumak için) ve SD_ReadMultiBlocks() (birden çok bloğu okumak için). Karta veri yazmak için işlevleri kullanın. SD_WriteBlock() (bir blok yazmak için) ve SD_WriteMultiBlocks() (birden fazla blok yazmak için). Bu okuma ve yazma işlevleri üç bağımsız değişken alır: tampon(okuma ve yazma verilerinin yerleştirilmesi gereken tampon değişkeni), adres(SD kart bellek konumunun adresi) ve blok boyutu(her zaman 512 çünkü bu işlevler yalnızca 512 bayt uzunluğundaki bloklarda çalışır). Kartın hafızasının belirli bir alanını silmek için bir fonksiyon var. SD_Erase() . Argüman olarak startaddr ve endaddr'yi alır. Birincisi silme işleminin başlayacağı bellek hücresinin adresini, ikincisi ise silme işleminin tamamlanacağı hücrenin adresini belirtir.

SDIO modülü ile mikrodenetleyici belleği arasındaki veri aktarımı, hem merkezi işlemci aracılığıyla olağan şekilde hem de doğrudan bellek erişim birimi aracılığıyla gerçekleştirilebilir. Gerekli modu seçmek için dosyada ihtiyacınız var stm324xg_eval_sdio_sd.h yorumu kaldır veya satır #define SD_POLLING_MODE(normal mod) veya hat #SD_DMA_MODE'u tanımla(PDP modu). Herhangi bir yazma veya okuma işleminden sonra, işlevi kullanmanız gerekir. SD_GetStatus() kartın mevcut işlemi tamamlayıp tamamlamadığını ve yeni veri almaya veya göndermeye hazır olup olmadığını kontrol edin. Bu işlev SD_TRANSFER_OK döndürürse, aktarım başarıyla tamamlandı, SD_TRANSFER_BUSY, aktarım kanalının meşgul olduğunu ve SD_TRANSFER_ERROR bir aktarım hatası döndürür. Tüm bu değerler yapıda tanımlanmıştır SD Aktarım Durumu, kaydedilmiş stm324xg_eval_sdio_sd.h. Bilgi aktarımı PDP bloğu aracılığıyla gerçekleştirildiyse, ek olarak PDP denetleyicisinin tüm veri aktarım işlemlerini tamamlayıp tamamlamadığını kontrol etmek gerekir. Bu, işlev kullanılarak yapılır. SD_ReadWaitOperation() . DMA bloğu üzerinden aktarımın bir kesinti ile sona erdiğini de belirtmek gerekir, bu nedenle programcının bir işlev çağrısı düzenlemesi gerekir. SD_ProcessIRQ() modülün kesme işleyicisinde SDIO SDIO_IRQHandler() ve işlev çağrısı SD_ProcessDMAIRQ() kesme işleyicisinde DMA2 DMA2_Streamx_IRQHandler() .

Sürücünün nasıl çalıştığını daha iyi anlamak için stm324xg_eval_sdio_sdçalışma örneğini klasörden kullanabilirsiniz SDIOSDIO_uSDCard(ProjectSTM32F4xx_StdPeriph_ExamplesSDIO). Bu test programını kullanarak, kartın hafızasının belirli bir alanını silebilir, belirli bir adrese veri yazabilir, aynı adrese verileri okuyabilir ve ardından gönderilen ve alınan bilgileri karşılaştırabilirsiniz. Alma arabelleğinin ve gönderme arabelleğinin kimliği, SDIO modülünün, iletişim veri yolunun ve SD kartın normal şekilde çalıştığının bir göstergesidir.

Bu nedenle, büyük miktarda veri depolama gerektiren küçük gömülü sistemlerin tasarlanması söz konusu olduğunda, SD kartların USB flash sürücülerin değerli rakipleri olduğunu söyleyebiliriz. SPI arabirimini kullanarak veya bu amaç için tasarlanmış ve yüksek aktarım hızı sağlayan SD bus aracılığıyla karttan ve karta bilgi aktarabilirsiniz. Kartla iletişimin uygulanması, donanımla çalışmayı kolaylaştıran ve programcılara kullanımı kolay işlevler sunan özel sürücüler kullanılarak büyük ölçüde basitleştirilmiştir. Ancak maalesef rastgele sırayla yazılan veriler herhangi bir işletim sistemi, örneğin Windows tarafından kabul edilmeyecektir, bu nedenle bir sonraki bölümde FAT dosya sistemi olan bir SD kartla nasıl çalışılacağı tartışılacaktır.

Kaynak listesi

SD ve microSD kartlar, büyük miktarda veriyle çalışan Arduino projelerinin yeteneklerini önemli ölçüde artırabilir: veri kaydediciler, hava durumu istasyonları, akıllı ev sistemleri. Arduino kartları, hem flash bellek hem de EEPROM dahil, yalnızca 4 kilobayta kadar nispeten küçük bir dahili bellekle donatılmıştır. Bu hafıza, özellikle kart sürekli kapanıyor veya kapanıyorsa, büyük miktarda veri yazmak için yeterli olmayacaktır. Bir Arduino SD kartını harici bir sürücü olarak bağlamak, herhangi bir bilgi için depolama alanını çoğaltmanıza olanak tanır. Çıkarılabilir SD sürücüler ucuzdur, bağlanması ve kullanımı kolaydır. SD kartın Arduino'ya doğru bağlanması makalede ele alınacaktır.

Arduino'da SD bellekle çalışmak özellikle zor değil. En kolay yol, hazır bir modül bağlamak ve standart kitaplığı kullanmaktır. Bu seçenekle başlayacağız.

Hazır bir modül kullanmanın çeşitli avantajları vardır. Bu, büyük miktarda veriyle çalışmak için oldukça basit ve kullanışlı bir araçtır. Bağlantıda özel beceri gerektirmez, tüm konektörler doğrudan kart üzerinde imzalanır. Kolaylık için ödeme yapmanız gerekiyor, ancak modülün maliyeti nispeten düşük, Rus ve yabancı çevrimiçi mağazalarda uygun fiyatlarla kolayca bulunabilir.

Üniversal modül, üzerine bir kart yuvası, dirençler ve voltaj regülatörünün yerleştirildiği sıradan bir karttır. Aşağıdaki teknik özelliklere sahiptir:

  • Çalışma voltajı aralığı 4,5-5 V;
  • 2GB'a kadar SD kart desteği;
  • akım 80 mA;
  • FAT 16 dosya sistemi.

SD kart modülü, mikrodenetleyici tabanlı cihazın normal çalışması için gerekli olan bilgilerin kartta saklanması, okunması ve yazılması gibi işlevleri gerçekleştirir.


Doğal olarak, ucuz hafıza kartı modüllerinin de dezavantajları vardır. Örneğin, en ucuz ve en yaygın modeller yalnızca 4 GB'a kadar kartları destekler ve neredeyse tüm modüller, bir SD kartta iki gigabayta kadar dosya depolamanıza izin verir - bu, çoğu modelde kullanılan FAT dosya sisteminin bir sınırlamasıdır.

Hafıza kartlarının bir başka dezavantajı, nispeten uzun kayıt süresidir, ancak onunla çalışmanın hızını artırmanıza izin veren yolları vardır. Bunun için, veriler önce RAM'de biriktirildiğinde ve ardından bir seferde hafıza kartına döküldüğünde bir önbellekleme mekanizması kullanılır.

SD ile çalışmak için Arduino kartları

Bir SD kartla çalışmak için birkaç farklı kart vardır:

  • Arduino Ethernet - Bu kart, veri çıkışı için özel bir modül ile donatılmıştır. Pin 4 CS çıkışı için kullanılır.Doğru işlem için SD.begin(4) komutu kullanılmalıdır.
  • Adafruit Micro-SD, Micro-SD kartlarla çalışırken kullanılan bir geliştirme kartıdır.
  • Sparkfun SD - Arduino'nun üstüne monte edilmiştir, CS çıkış için pin 8'i kullanır. Kartın yeni versiyonunda 3.3V bağlantı ve yerleşik altı bitlik bir invertör bulunur.

SD ve microSD'yi Arduino'ya bağlama

İki tür kart vardır - microSD ve SD. Bağlantı, yapı ve program bakımından aynıdırlar, ancak yalnızca boyut olarak farklılık gösterirler. Kullanmadan önce, SD kartın formatlanması tavsiye edilir. Genellikle yeni kartlar zaten biçimlendirilmiştir ve kullanıma hazırdır, ancak eski bir kart kullanıyorsanız, onu Arduino dosya sisteminde biçimlendirmek daha iyidir. Prosedürü gerçekleştirmek için, bilgisayarda SD kitaplığının, tercihen FAT16'nın yüklü olması gerekir. Windows'ta biçimlendirme için, kart simgesine tıklamanız ve "Biçimlendir" seçeneğine tıklamanız gerekir.

Kartı bağlamak için 6 kontak kullanılır, etkileşim SPI arayüzü üzerinden gerçekleştirilir. Tahtada altı pimli bir konektöre benziyor. Kartı bağlamak için kontrolörün kendisine, kart modülüne ve 6 kabloya ihtiyacınız var. SPI'ye ek olarak, bir SDIO modu vardır, ancak uygulanması zordur ve Arduino ile zayıf uyumludur. SPI, tüm mikrodenetleyicilerle çalışacak şekilde kolayca yapılandırılır, bu nedenle kullanılması tavsiye edilir.

Dijital pinler şu şekilde bağlanır: Arduino Nano veya Uno kartı için MOSI pini D11'e, MISO'dan D12'ye, SCK'den D13'e, CS'den 4'e, VCC'den +5 V'a, .GND'den GND'ye bağlanır. Kartın 3,3 ve 5 volta bağlanmak için konektörleri vardır. Kartın kendi güç kaynağı 3,3 volttur, bu nedenle aynı güç kaynağıyla bir mikrodenetleyici kullanmak daha kolaydır, aksi takdirde voltaj seviyesi dönüştürücülere ihtiyacınız vardır. En yaygın Arduino kartlarında böyle bir çıkış var.

Bir SD kartı bağlarken, farklı Arduino kartları türleri için SPI pinlerinin karşılıklarını dikkate almanız gerekir:

SD ve microSD ile çalışmak için Arduino kütüphanesi

Harici veri sürücüleri ile çalışma kolaylığı için Arduino IDE'de hazır kitaplıklar mevcuttur. Çoğu durumda herhangi bir şey indirmeniz veya yüklemeniz gerekmez.

Bir çizime bir kitaplık dahil etmek için include deyimini kullanın:

#katmak #katmak

SPI üzerinden bağlanan cihazların doğru çalışması için SPI kütüphanesine ihtiyaç vardır.

Karta veri okumak ve yazmak için kütüphane işlevlerine ihtiyaç vardır. Kütüphane, SD ve SDHC kartlarını destekleyebilir.

İsimler 8.3 formatında yani isim için 8, uzantı için 3 karakter olacak şekilde yazılır. Dosyanın yolu eğik çizgi "/" kullanılarak yazılır.

Gömülü SD Kitaplığı Örnekleri

Arduino IDE, kitaplığın işlevlerini hızlı bir şekilde öğrenmek için yerleşik örneklere sahiptir:

  • Kart Bilgisi, bir SD kartta saklanan bilgilerin çıkarılmasıdır. Yardımı ile kartın hangi dosya sisteminde biçimlendirildiğini, boş alan miktarını, hangi verilerin kaydedildiğini öğrenebilirsiniz.
  • Yun Datalogger - karttaki üç sensörden günlük verilerini kaydetmenizi sağlar.
  • Datalogger - sensörden alınan verileri karta kaydeder ve kaydeder.
  • Döküm Dosyası - karttan veri okuyun, seri bağlantı noktasına aktarın.
  • Dosyalar - verileri oluşturur ve siler. Yazılı verileri bir arabelleğe koyan bir file.write() işlevi vardır. Bilgilerin haritaya taşınması, flush() veya close() işlevleri çağrılırken gerçekleşir, bu nedenle her dosya açılışından sonra onu kapatmak önemlidir, aksi takdirde veriler kaybolur.
  • Oku Yaz - karttaki dosyaları yazar ve okur.

SD kütüphane işlevleri

Arduino SD kitaplığı, verileri işlemek için kullanılabilecek çeşitli işlevler içerir. SD sınıfı işlevleri:

  • begin() - işlev kitaplığı başlatır, sinyal için bir kişi atar.
  • var() - haritanın gerekli bilgilere sahip olup olmadığını kontrol etmek için tasarlanmıştır.
  • mkdir() - hafıza kartında istediğiniz klasörü oluşturmanıza olanak sağlar.
  • rmdir() - Bu işlevle bir klasörü silebilirsiniz. Silinecek klasörün boş olması önemlidir.
  • open() - yazmanız veya okumanız gereken bir dosyayı açmanıza izin verir. Gerekli dosya haritada yoksa oluşturulacaktır.
  • remove() - herhangi bir dosyayı kaldırır.

Tüm bu işlevlere yanıt olarak, değerlerden biri gelmelidir - işlemin başarıyla tamamlanması durumunda doğru ve başarısızlık durumunda yanlış.

Dosyaları oluşturun, düzenleyin ve silin.

Arduino'da dosyalarla çalışmak için bir File sınıfı vardır. Karttan bilgi yazmak ve okumak için tasarlanmış işlevleri içerir:

  • available() - Dosyanın okunabilir bayt içerip içermediğini kontrol eder. Yanıt, okumak için kullanılabilecek alan miktarıdır.
  • close() - dosyayı kapatır, bunlardan önce verilerin karta kaydedilip kaydedilmediğini kontrol eder.
  • flush() - işlev, verilerin karta yazıldığından emin olmanızı sağlar.
  • name() - isme bir işaretçi döndürür.
  • peek() - işaretçiyi bir sonraki karaktere taşımadan bayt veri okur.
  • pozisyon() - işaretçinin dosyadaki geçerli konumunu bulur.
  • print() - verileri ayrı bir dosyaya çıkarır.
  • println() - verileri bir satır başı ve boş bir satırın göründüğü noktaya kadar bir dosyaya yazdırır.
  • search() - dosyadaki geçerli konumun konumunu değiştirir.
  • size() - verilerin boyutu hakkında bilgi görüntüler.
  • read() - bilgileri okur.
  • write() - bir dosyaya yazar.
  • isDirectory() - bu yöntemi kullanarak dosyanın bir dizin mi, yani bir dizin mi yoksa bir klasör mü olduğunu kontrol eder.
  • openNextFile() - sonraki dosyanın adını görüntüler.
  • rewindDirectory() - dizindeki ilk dosyaya döner.

Kartın düzgün çalışması için SS çıkışının yapılandırıldığından emin olmanız gerekir.

Arduino SD kitaplığıyla çalışmanın bir örneğinin taslağı

Aşağıda, bellek kartı modülüyle çalışmanın bir örneğini gösteren bir çizim bulunmaktadır.

/* SD kartlar kullanılarak veri kaydedici Analog bağlantı noktalarından alınan verilerin bir SD kartta saklanmasına bir örnek. Veriler, "," sembolü biçiminde bir alan ayırıcı ile bir dizi satır olarak dosyaya kaydedilecektir, ** CLK - pin 13 ** CS - pin 4 */ #include #katmak sabit int PIN_CHIP_SELECT = 4; void setup() ( Serial.begin(9600); Serial.print("SD kart başlatılıyor..."); // Bu pin OUTPUT olarak tanımlanmalıdır pinMode(10, OUTPUT); // Eğer modül başlatılmaya çalışılıyorsa) ( !SD.begin(PIN_CHIP_SELECT)) ( Serial.println("Kart başarısız veya mevcut değil"); // Bir şeyler ters giderse, çıkış: dönüş; ) Serial.println("kart başlatıldı."); ) geçersiz döngü () ( // Dosyaya koyacağımız verileri içeren string: String logStringData = ""; // Portlardan veri oku ve for için stringe yaz (int i = 0; i< 5; i++) { int sensor = analogRead(i); logStringData += String(sensor); if (i < 4) { logStringData += ","; } } // Открываем файл, но помним, что одновременно можно работать только с одним файлом. // Если файла с таким именем не будет, ардуино создаст его. File dataFile = SD.open("datalog.csv", FILE_WRITE); // Если все хорошо, то записываем строку: if (dataFile) { dataFile.println(logStringData); dataFile.close(); // Публикуем в мониторе порта для отладки Serial.println(logStringData); } else { // Сообщаем об ошибке, если все плохо Serial.println("error opening datalog.csv"); } }

Bir dosya oluşturma ve arduino SD kartı için bir isim seçme

Bir dosya oluşturmak, Arduino'da SD kartlarla çalışırken en yaygın görevlerden biridir. Önceki çizimde gördüğümüz gibi, bir dosya oluşturmak için onu açmanız yeterlidir. Böyle bir dosyanın var olup olmadığını kontrol etmek istiyorsak, aren() işlevini kullanabiliriz:

  • SD.exists("veri günlüğü.csv");

Dosya varsa, işlev DOĞRU değerini döndürür.

Veri kaydedici projeleri oluştururken popüler bir uygulama, büyük dosyaları güncellemek ve bir bilgisayarda açmak için daha uygun olan daha küçük dosyalara bölmektir. Örneğin, SD kartta çok büyük bir datalog.csv dosyası yerine, sonuna sırayla bir sayı ekleyerek birkaç küçük dosyaya sahip olabilirsiniz: datalog01.csv, datalog02.csv, vb.
İşte işi bitirmenize yardımcı olacak örnek bir eskiz:

char dosya adı = "datalog00.csv"; // (uint8_t i = 0; i) için başlangıç ​​adı< 100; i++) { filename = i / 10 + "0"; filename = i % 10 + "0"; if (! SD.exists(filename)) { // Проверяем наличие logfile = SD.open(filename, FILE_WRITE); break; // Дальше продолжать смысла нет } }

Çözüm

Gördüğümüz gibi bir SD hafıza kartını Arduino'ya bağlamak ve bunu bir projede kullanmak çok da zor değil. Bunun için Arduino IDE içerisinde hazır kütüphaneler ve çok çeşitli modül seçenekleri bulunmaktadır. Herhangi bir elektronik mağazasından bir hafıza kartı satın alabilirsiniz, ucuzdurlar ve aynı zamanda Arduino kartının potansiyelini önemli ölçüde artırabilirler. Hafıza kartlarının kullanılmasıyla, daha sonra analiz edilmek üzere büyük miktarda veri toplanabilir ve saklanabilir. Yazımız sayesinde araştırma projelerimize hafıza kazandırabileceğiz, akıllı ev için sesli anons sistemleri kurabileceğiz, basit bir wav oynatıcı oluşturabileceğiz ve çok daha fazlasını yapabileceğiz.

benzer makaleler

2023 dvezhizni.ru. Tıbbi portal.