LinkedIn YouTube Facebook
Szukaj

Newsletter

Proszę czekać.

Dziękujemy za zgłoszenie!

Wstecz
Artykuły

Komunikacja mikrokontrolerów STM32 z pamięciami DataFlash

 

Komunikacja pomiędzy układami scalonymi w systemach mikroprocesorowych/mikrokontrolerowych cieszą się wciąż niesłabnącym zainteresowaniem. W artykule przedstawiamy komunikację mikrokontrolera z rodziny STM32F107 z szeregową pamięcią DataFlash.

Współczesne mikrokontrolery mają pamięć Flash o coraz większej pojemności. Popularność zyskują układy z wbudowanym 1 lub nawet 2 MB pamięci nieulotnej. Wydawać by się mogło, że stosowanie zewnętrznych pamięci typu DataFlash nie ma już żadnego sensu. Jest to jednak z dwóch powodów złudny wniosek.
Po pierwsze, niekiedy jednak nawet pojemność rzędu megabajtów jest niewystarczająca. Nie chodzi tutaj o wielkość programu. W zwykłych aplikacjach, bez rozbudowanych systemów operacyjnych, dość trudno jest znaleźć takie, które potrzebowałyby aż tyle pamięci programu. Konieczność stosowania pamięci zewnętrznej może zaistnieć wtedy, kiedy wymagane jest zbieranie i zapisywanie dużej ilości informacji, jak choćby z czujników. Innym przykładem może być urządzenie wyposażone w rozbudowany interfejs użytkownika z wyświetlaczem graficznym. Dodatkowa pamięć nieulotna może w takim przypadku przechowywać bitmapy będące elementami interfejsu.
Po drugie – cena układów. Mikrokontrolery z dużą pamięcią Flash są zazwyczaj wyposażone w wiele układów peryferyjnych, a to bezpośrednio wpływa na ich cenę. Gdy projektowane urządzenie nie będzie musiało wykonywać zbyt skomplikowanych czynności, bardziej opłacalne może okazać się zastosowanie tańszego, a przez to słabiej wyposażonego, mikrokontrolera oraz pamięci zewnętrznej do przechowywania danych.
Nie wgłębiając się już bardziej w czynniki wpływające na decyzję konstruktora o stosowaniu pamięci zewnętrznej, przejdziemy do opisu stosownej aplikacji z wykorzystaniem mikrokontrolera STM32 i szeregowej pamięci DataFlash.

Interfejs komunikacyjny

Wybór pamięci zewnętrznej padł na układ AT45DB321D firmy Atmel. Jest to 32-megabitowa pamięć szeregowa, dostępna w 8-wyprowadzeniowej obudowie typu SOIC8. Wymiana danych z układem pamięci odbywa się przez interfejs SPI, który może pracować z częstotliwością zegarową do 66 MHz. Pamięć do mikrokontrolera STM32 należy dołączyć jak zwykłe urządzenia pracujące z interfejsem SPI. Przykładowy schemat zamieszczono na rysunku 1.

 

Rys. 1. Schemat dołączenia układu AT45DB321D do mikrokontrolera STM32

Rys. 1. Schemat dołączenia układu AT45DB321D do mikrokontrolera STM32

 

 

Układ AT45DB321D może komunikować się z MCU w trybach Mode 0 lub Mode 3. Szablony komunikacji w obydwu trybach przedstawiono na rysunku 2. W Mode 0 linia zegarowa SCK w stanie spoczynkowym znajduje się w na poziomie niskim, natomiast bity zatrzaskiwane są na zboczach narastających. W drugim trybie (Mode 3), gdy dane nie są przesyłane, SCK znajduje się na poziomie wysokim, poszczególne bity są jednak zapisywane również na zboczach narastających.

 

Rys. 2. Obsługiwane przez pamięć AT45DB321D tryby pracy magistrali SPI

Rys. 2. Obsługiwane przez pamięć AT45DB321D tryby pracy magistrali SPI

 

 

Sterownik magistrali SPI wbudowany w mikrokontrolery STM32 można ustawić do pracy w obydwu trybach. Przykładowa aplikacja będzie wykorzystywała Mode 0. Kod konfigurujący MCU do pracy w tym trybie przedstawiono na listingu 1 wraz z funkcją dataflashInit(), która inicjuje niezbędne peryferia.

 

List. 1. Funkcja inicjująca niezbędne do komunikacji z pamięcią peryferia

void dataflashInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Wybranie grupy priorytetów */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    /* Konfiguracja przerwania od SPI1 */
    NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE);

    /* Konfiguracja wyprowadzeń wykorzystywanych przez SPI: SCK(PA5), MISO(PA6), MOSI(PA7) */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Konfiguracja wyprowadzenia chip select */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Wybranie parametrów pracy kontrolera SPI1 */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
    SPI_Init(SPI1, &SPI_InitStructure);

    SPI_CalculateCRC(SPI1, DISABLE);
    SPI_Cmd(SPI1, ENABLE);
}

 

Przedstawiony kod jest wyraźnie uporządkowany w trzy bloki, ich zadaniem jest ustawienie parametrów odpowiednio: kontrolera przerwań NVIC, wykorzystywanych wyprowadzeń oraz samego kontrolera magistrali SPI. Użyto kontroler SPI1 oraz jego domyślne wyprowadzenia:

  • PA5 – SCK,
  • PA6 – MISO,
  • PA7 – MOSI.

Sygnał CS (Chip Select) jest dostarczany programowo poprzez wyprowadzenie PA4. Komunikacja będzie odbywała się w trybie full dupleks, a mikrokontroler będzie oczywiście układem nadrzędnym (Master). Zgodnie z akceptowanym przez układ pamięci formatem ramki danych, jej długość jest ustalana na 8 bitów, przy czym pierwszy na magistralę będzie wystawiany bit najbardziej znaczący (MSB).
Ustalanie trybu pracy SPI (czyli w przypadku układu AT45DB321D będzie to wybór pomiędzy Mode 0, a Mode 3) odbywa się przez wypełnienie pól SPI_CPOL i SPI_CPHA struktury inicjującej. Ostatnim parametrem jest wybranie prędkości przesyłania danych. Maksymalna szybkość komunikacji wynosi dla rodziny układów STM32F107 18 Mb/s. Kontroler SPI jest podłączony do wewnętrznej magistrali APB2, która może pracować z maksymalną częstotliwością 72 MHz. Jeśli właśnie taka jest częstotliwość sygnału taktującego APB2, to preskaler kontrolera SPI musi być ustawiony na 4 (72 MHz/4 = 18 MHz).