Komunikacja mikrokontrolerów STM32 z pamięciami DataFlash
Na listingu 5 zamieszczono funkcję kasującą stronę w pamięci erasePage(). Określenie zajętości układu rozwiązano poprzez sprawdzanie zawartości rejestru statusu. Jednak aby nie wstrzymywać pracy całego systemu mikroprocesorowego na niekrótki przecież czas kilkudziesięciu milisekund, użyty został timer SysTick. Funkcja erasePage() tak konfiguruje timer, żeby ten po upływie 35 ms wygenerował przerwanie. Obsługa przerwania, zamieszczona na listingu 6, oddaje muteks oraz wyłącza przerwanie.
List. 6. Funkcja obsługi timera SysTick
void SysTick_Handler(void) { /* Wyłączenie timera oraz jego przerwania */ SysTick->CTRL = (0<
Rys. 8. Ciągły odczyt pamięci bez użycia bufora
Ciągły odczyt bez użycia bufora
Zasadę działania ciągłego odczytu pamięci bez użycia bufora przedstawiono na rysunku 8. Z rysunku wynika, należy podać adres początkowy bajta w stronie, a odczyt następuje już przez całą przestrzeń adresową. Po osiągnięciu ostatniego bajta w ostatniej stronie układ pamięci automatycznie rozpoczyna odczyt od początku pierwszej strony. Jak już wspomniano, domyślny rozmiar strony wynosi 528 bajtów.
Rys. 9. Adresowanie pierwszego do odczytu bajtu w stronie
Dla tego przypadku adresowanie jest następujące. W pierwszej kolejności należy wysłać do układu pamięci bajt komendy, dla ciągłego odczytu bez bufora będzie to wartość 0xE8, a zaraz po nim trzy bajty adresowe. Podział bajtów adresowych na adres strony oraz na adres bajta w stronie zamieszczono na rysunku 9, natomiast całą funkcję continousRead(), która inicjuje ciągły odczyt przedstawia listing 7. W argumentach do funkcji należy przekazać adres strony, adres bajta w stronie oraz liczbę bajtów, jakie mają zostać odczytane.
List. 7. Funkcja rozpoczynająca ciągły odczyt pamięci
void continousRead(uint16_t pageAddress, uint16_t byteAddress, uint16_t nofBytesToRead) { /* sprawdzanie muteksa */ while(SPI_InUse); /* "weź" muteks */ SPI_InUse = 0x11; SPI_Cmd(SPI1, DISABLE); SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE); SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE); /* Nof_Bytes_To_TxRx = nofBytesToRead + komenda + 3xAdres + 4 bajty nieznaczące */ Nof_Bytes_To_TxRx = nofBytesToRead + 8; /* Komenda "continuous read" */ TxBuf[0] = 0xE8; /* Starsze 7 bitów adresu strony */ TxBuf[1] = (uint8_t) pageAddress>>6; /* Pozostałe (młodsze) 6 bitów adresu strony, * ale wyrównane do lewej strony + dwa starsze bity * adresu bajta w stronie*/ TxBuf[2] = ((uint8_t) pageAddress<<2) | ((uint8_t) byteAddress>>8); /* Młodsze 8 bitów adresu bajta w stronie */ TxBuf[3] = (uint8_t) byteAddress; SPI_Cmd(SPI1, ENABLE); GPIO_SetBits(GPIOA, CS); /* CS w stan niski */ GPIO_ResetBits(GPIOA, CS); }
Bufor odbiorczy RxBuf[] powinien być kopiowany dopiero od bajta o indeksie 8, a to dlatego, że pomiędzy ostatnim bajtem adresowym wysłanym do układu pamięci, a pierwszym odebranym bajtem z danymi muszą wystąpić cztery bajty nieznaczące. Zatem mamy „do przeskoczenia”: komendę (czyli pierwszy bajt), trzy bajty adresowe oraz cztery bajty nieznaczące.