LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

STM32Butterfly2: obsługa kart SD w trybie SPI

Poniżej przedstawiono program główny.

int main(void)
{

  //Initialize system timer
  time_init();
  //Initialize nokia display
  nlcd_init();
  //register putc handler
  register_printf_putc_handler(putc_lcd,NULL);
  //Card insertion init
  card_insert_init();
  for(;;)
  { 
   nlcd_clear();
   printp(0,"Insert Card");
   //Wait4 card insert
   card_wait4insert();
   //Clear disp
   nlcd_clear();
   //Initialize the mmc
   int mmc_code = mmcInit();
   printp(0,"Card: %s",card_type(mmc_code));
   if(mmc_code<0) for(;;); //If error not process
   printp(1,"Cap: %d MB",(int)(mmcCapacity()/MB));
   //Print partrecord info
   print_partrecord(); 
   //Wait for card remove
   card_wait4remove();
  }
  return 0;
}

 

W pierwszym kroku programu głównego znajduje się funkcja realizująca inicjalizację licznika SysTick. Operacja ta konfiguruje priorytet przerwania wywoływanego przez licznik, ustawienie częstotliwości występowania przerwania. Po przeprowadzeniu konfiguracji następuje uruchomienie licznika.

W kolejnym kroku inicjalizowany jest wyświetlacz bazujący na sterowniku PCD8544 lub zgodnym (wyświetlacz z telefonu Nokia 3310). Ze względu na fakt, iż złącze SPI jest używane do komunikacji z kartą SD, magistrala SPI do komunikacji z wyświetlaczem jest emulowana programowo. Funkcja nlcd_init() inicjalizująca wyświetlacz konfiguruje linie używane w komunikacji, ustawia na nich odpowiedni stan oraz przeprowadza inicjalizację wyświetlacza poprzez przesłanie do niego listy komend. Na koniec przeprowadzane jest wyczyszczenie ekranu w celu usunięcia „śmieci”, które mogą wystąpić w wyniku nieokreślonego stanu poszczególnych bitów w pamięci wyświetlacza.

Następnie wywoływana jest funkcja register_printf_putc_handler, która tworzy wskaźnik na funkcję wyświetlającą znak na wyświetlaczu. Wskaźnik ten wykorzystywany jest w dalszej części programu przez bibliotekę formatującą tekst i dane wyświetlane na wyświetlaczu.

Przed przejściem do nieskończonej pętli wywoływana jest funkcja card_insert_init(), która konfiguruje linię wykrywającą włożenie karty do gniazda jako wejściową. W nieskończonej pętli for, pierwszym poleceniem jest wyczyszczenie zawartości wyświetlacza. Później wywoływana jest funkcja card_wait4insert(), wymusza ona oczekiwanie na włożenie karty do gniazda. Poniżej przedstawiono listing funkcji.

static void card_wait4insert(void)
{
  bool pin, pin1; 
  do
  {
   	pin = io_get(CARD_INSERT_PORT,CARD_INSERT_PIN);
	wait_ms(DEBOUNCE_TIME);
	pin1 = io_get(CARD_INSERT_PORT,CARD_INSERT_PIN);
  } 
   while( pin || pin1);
  wait_ms(INSDELAY_TIME);
}

 

Działanie funkcji card_wait4insert() polega na zapętleniu w pętli do..while, w czasie której odczytywany jest stan linii wykrywającej włożenie karty pamięci do gniazda. Odczyt stanu linii jest wykonywany dwukrotnie, z pewnym opóźnieniem w celu eliminacji drgań styków. Sam odczyt stanu realizowany jest przez funkcję io_get, która jako pierwszy parametr przyjmuje wartość określającą port, natomiast jako drugi parametr podawany jest numer odczytywanej linii. Funkcja kończy działanie gdy jeden z odczytów przyjmie inną wartość niż 0.

Po wykryciu włożenia karty SD do gniazda następuje wyczyszczenie wyświetlacza oraz inicjalizacja karty pamięci, która zwraca kod do zmiennej io_get. Zwrócony kod informuje o rodzaju karty lub o wystąpieniu błędu. Za inicjalizację odpowiada funkcja mmcInit(), w pierwszej części funkcji realizowana jest konfiguracja linii, do których podłączone jest gniazdo kart pamięci oraz włączenie zegarów portów używanych w transmisji oraz SPI, konfiguracja odbywa się przez wywołanie funkcji mmcHwInit(), której listing przedstawiono poniżej.

static void mmcHwInit(void)
{
	RCC->APB2ENR |= APB2ENR_SPI_PORT | APB2ENR_SSEL_PORT | RCC_APB2Periph_SPI1;
	//SPI MISO (Output)	
	io_config(SPI_PORT,MISO_BIT,GPIO_MODE_INPUT,GPIO_CNF_IN_FLOAT);
	//SPI MOSI (Output)
	io_config(SPI_PORT,MOSI_BIT,GPIO_MODE_50MHZ,GPIO_CNF_ALT_PP);
	//SPI SCK (Output)
	io_config(SPI_PORT,SCK_BIT,GPIO_MODE_50MHZ,GPIO_CNF_ALT_PP);
	//SSEL
	io_config(SSEL_PORT,SSEL_BIT,GPIO_MODE_50MHZ,GPIO_CNF_GPIO_PP);
	ssel(1);
	spi_cfg(SPI_BaudRatePrescaler_16);
}