Komentator Napisano Maj 31, 2018 Udostępnij Napisano Maj 31, 2018 Poznaliśmy już jeden interfejs szeregowy, który był asynchroniczny. Oczywiście chodzi o UART. Teraz dla odmiany pora na bardzo popularny, interfejs synchroniczny, którym jest SPI.W tej części kursu STM32 wykorzystamy go do podłączenia ekspandera portów. UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.Przeczytaj całość »Poniżej znajdują się komentarze powiązane z tym wpisem. Cytuj Link do komentarza Share on other sites More sharing options...
ArczerMX Czerwiec 27, 2018 Udostępnij Czerwiec 27, 2018 Podobieństwo do UART bywa mylące. MISO powinno zostać skonfigurowane na pinie PA6, natomiast pin PA3 jest podpięty pod RX z UART. Ten sam błąd pojawia się w następnej części części kursu. 1 Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Lipiec 1, 2018 Udostępnij Lipiec 1, 2018 ArczerMX, gratuluję czujności i dziękuję za zgłoszenie. Właśnie poprawiłem oba teksty 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
beszt Styczeń 17, 2019 Udostępnij Styczeń 17, 2019 Ja mam pytanie z kolei o "Identyfikator urządzenia" po co go w ogóle wysyłać do ekspandera? Czy to jest po prostu ułatwienie dla czytelności kodu? Nigdzie nie zauważyłem, aby było to wyjaśnione, a sprawa ciekawa 🙂 W dokumentacji scalaka też cisza jeśli chodzi o wartości 0x40 i 0x41. Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
Popularny post Treker (Damian Szymański) Styczeń 18, 2019 Popularny post Udostępnij Styczeń 18, 2019 @beszt, witam na forum 😉 Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start: Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników. Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć? Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości. 16 godzin temu, beszt napisał: Ja mam pytanie z kolei o "Identyfikator urządzenia" po co go w ogóle wysyłać do ekspandera? Czy to jest po prostu ułatwienie dla czytelności kodu? Nigdzie nie zauważyłem, aby było to wyjaśnione, a sprawa ciekawa 🙂 W dokumentacji scalaka też cisza jeśli chodzi o wartości 0x40 i 0x41. Adres/identyfikator urządzenia ustawia się za pomocą wejść opisany jako A0 oraz A1. Adres zależy również od tego czy zapisujemy, czy odczytujemy dane - jest to opisane w dokumentacji: Jest tam podana informacja na temat sposobu '"obliczenia" identyfikatora: dla odczytu mamy binarnie 01000001, co daje 0x41 dla zapisu mamy binarnie 010000000, co daje 0,40 Gdzie pogrubione 00 to wartości ustawione za pomocą pinów A0 oraz A1 🙂 3 Cytuj Link do komentarza Share on other sites More sharing options...
beszt Styczeń 18, 2019 Udostępnij Styczeń 18, 2019 @Treker Serdecznie dziękuję za odpowiedź! Teraz wszystko jasne - po za CS, musi iść bajt kontrolny do samego układu. Dziękuję za wyjaśnienie i pokazanie w instrukcji - jak to często u mnie bywa, zbyt szybko ją przewertowałem 🙂 1 Cytuj Link do komentarza Share on other sites More sharing options...
MaciejZyskowski Luty 1, 2019 Udostępnij Luty 1, 2019 Cześć! Zrobiłem zadanie 9.3 Oto mój kod (działa na 4 diodach, bo ciasno mi było montować wszystkie... ;p): /** ****************************************************************************** * @file main.c * @author Ac6 * @version V1.0 * @date 01-December-2013 * @brief Default main function. ****************************************************************************** */ #include "stm32f1xx.h" #define MCP_IODIR 0x00 #define MCP_IPOL 0x01 #define MCP_GPINTEN 0x02 #define MCP_DEFVAL 0x03 #define MCP_INTCON 0x04 #define MCP_IOCON 0x05 #define MCP_GPPU 0x06 #define MCP_INTF 0x07 #define MCP_INTCAP 0x08 #define MCP_GPIO 0x09 #define MCP_OLAT 0x0a SPI_HandleTypeDef spi; void mcp_write_reg(uint8_t addr, uint8_t value) { uint8_t tx_buf[] = {0x40, addr, value}; HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); HAL_SPI_Transmit(&spi, tx_buf, 3, HAL_MAX_DELAY); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); } uint8_t mcp_read_reg(uint8_t addr) { uint8_t tx_buf[] = {0x41, addr, 0xff}; uint8_t rx_buf[3]; HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(&spi, tx_buf, rx_buf, 3, HAL_MAX_DELAY); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); return rx_buf[2]; } int main(void) { SystemCoreClock = 8000000; HAL_Init(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_SPI1_CLK_ENABLE(); /* SPI I/O config */ /* SCK & MOSI */ GPIO_InitTypeDef gpio; gpio.Mode = GPIO_MODE_AF_PP; gpio.Pin = GPIO_PIN_5 | GPIO_PIN_7; gpio.Pull = GPIO_NOPULL; gpio.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &gpio); /* MISO */ gpio.Mode = GPIO_MODE_AF_INPUT; gpio.Pin = GPIO_PIN_6; HAL_GPIO_Init(GPIOA, &gpio); /* CS */ gpio.Mode = GPIO_MODE_OUTPUT_PP; gpio.Pin = GPIO_PIN_0; HAL_GPIO_Init(GPIOC, &gpio); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); /* idle state of the conection with slave */ spi.Instance = SPI1; spi.Init.Mode = SPI_MODE_MASTER; spi.Init.NSS = SPI_NSS_SOFT; spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; /* 1MHz */ spi.Init.Direction = SPI_DIRECTION_2LINES; spi.Init.CLKPhase = SPI_PHASE_1EDGE; spi.Init.CLKPolarity = SPI_POLARITY_LOW; spi.Init.DataSize = SPI_DATASIZE_8BIT; spi.Init.FirstBit = SPI_FIRSTBIT_MSB; spi.Init.TIMode = SPI_TIMODE_DISABLE; spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; spi.Init.CRCPolynomial = 7; HAL_SPI_Init(&spi); __HAL_SPI_ENABLE(&spi); mcp_write_reg(MCP_IODIR, ~0x0F); mcp_write_reg(MCP_GPPU, 0x10); while(1) { if ((mcp_read_reg(MCP_GPIO) & 0x10) == 0) { for (int i = 0x00; i<=0x0F; ++i) { mcp_write_reg(MCP_OLAT, i); HAL_Delay(1000); } } else { for (int i = 0x0F; i>=0x00; --i) { mcp_write_reg(MCP_OLAT, i); HAL_Delay(1000); } } } } Niby działa, ale nie jest to najwspanialsze rozwiązanie, gdyż odczyt stanu pinu ekspandera odbywa się po skończeniu pętli. Chciałbym użyć przerwań, aby wykrywać zmianę stanu tego pinu, lecz nie wiem jak się za to zabrać. :< Czy moglibyście mi pomóc? Dać jakieś wskazówki? 1 Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Luty 2, 2019 Udostępnij Luty 2, 2019 Dnia 1.02.2019 o 15:52, MaciejZyskowski napisał: Chciałbym użyć przerwań, aby wykrywać zmianę stanu tego pinu, lecz nie wiem jak się za to zabrać. :< Czy dobrze rozumiem, że chciałbyś wyzwalać przerwanie w mikrokontrolerze po zmianie stanu na pisanie ekspandera "bez" ciągłego odpytywania ekspandera o stan jego pinów? Cytuj Link do komentarza Share on other sites More sharing options...
MaciejZyskowski Luty 4, 2019 Udostępnij Luty 4, 2019 Dnia 2.02.2019 o 17:29, Treker napisał: Czy dobrze rozumiem, że chciałbyś wyzwalać przerwanie w mikrokontrolerze po zmianie stanu na pisanie ekspandera "bez" ciągłego odpytywania ekspandera o stan jego pinów? Dokładnie to mam na myśli. Obecnie zmiana "kierunku" pracy licznika może obyć się dopiero po zakończeniu pętli. Chciałbym, żeby mogła nastąpić natychmiast po zmianie stanu pinu wejściowego. Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Luty 4, 2019 Udostępnij Luty 4, 2019 @MaciejZyskowski przy takim standardowym podłączeniu nie będzie raczej takiej opcji, bo mikrokontroler nie ma pojęcia co dzieje się na pinach ekspandera (jeśli ich ciągle nie sprawdza). W Twoim przypadku rozwiązaniem może być chyba wykorzystaniu pinu INT, który należałoby osobno podłączyć do STM32. Fragment z noty katalogowej: Jeśli będziesz chciał zabrać się za ten temat to załóż proszę osobny temat na forum, aby nie "mieszać" tutaj w komentarzach do kursu 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
danielll Październik 2, 2019 Udostępnij Październik 2, 2019 if ((mcp_read_reg(MCP_GPIO) & 0x02) == 0) Po co tutaj koniunkcja i jak ona dziala? chyba nie mozna w taki sposob odczytac wartosci z rejestru Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Październik 2, 2019 Udostępnij Październik 2, 2019 @danielll witam na forum 🙂 Dlaczego uważasz, że taki zapis nie jest poprawny? Porównujemy zwyczajnie dwie wartości za pomocą operatora logicznego i sprawdzamy wynik. Co dokładnie wydaje Ci się tutaj nieodpowiednie? Cytuj Link do komentarza Share on other sites More sharing options...
danielll Październik 3, 2019 Udostępnij Październik 3, 2019 (edytowany) Nie za bardzo rozumiem o co w tym chodzi Gdy przewod laczacy PIN1 z masa jest zwarty to funkcja mcp_read_reg zwraca stan wysoki na tym pinie czyli wartosc 0x02 (00000010). Po co nastepnie ta koniunkcja. Sluzy moze do tego zeby wyzerowac najmlodszy bit gdy dioda jest zaswiecona (bo wtedy tez jest na niej stan wysoki wiec zostanie odczytana wartosc 0x03) ? Edytowano Październik 3, 2019 przez danielll Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Październik 3, 2019 Udostępnij Październik 3, 2019 1 godzinę temu, danielll napisał: Gdy przewod laczacy PIN1 z masa jest zwarty to funkcja mcp_read_reg zwraca stan wysoki na tym pinie czyli wartosc 0x02 (00000010). Po co nastepnie ta koniunkcja W wyniku działania funkcji otrzymujemy cały bajt, a nas interesuje tylko wartość z konkretnego bitu (drugi od prawej). Taki zapis pozwala uzyskać właśnie taki efekt. Załóżmy, że funkcja zwraca bajt 01011011, porównujemy go więc z bajtem 00000010. W wyniku działania tego operatora otrzymamy liczbę, w której jedynki będą jedynie na tych pozycjach, na których jedynka wystąpiła w obu porównywanych liczbach. W wyniku operacji: "010110X1 & 00000010" otrzymujemy więc: 000000X0, czyli wyciągamy z całego bajta tylko jeden, interesujący nas bit. Pozostały bity nie wpłyną na wynik i o to nam właśnie chodzi, bo w programie chcemy sprawdzić stan jednego I/O. Pozostałe nas w tym przypadku nieinteresującą. Czy teraz jest to trochę jaśniejsze? To nie jest bezpośrednio związane z STMami, ani nawet tym przykładem, to ogólne zagadnienie z logiki. Warto potrenować korzystanie z różnych operatorów logicznych, ponieważ przy mikrokontekstach bardzo często się z tego korzysta 😉 1 Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Październik 3, 2019 Udostępnij Październik 3, 2019 (edytowany) Poza tym warto odróżnić koniunkcję (czyli operację na wartościach logicznych) od operacji na bitach. Ot, taka niewielka różnica między && i & Edytowano Październik 3, 2019 przez ethanak 1 Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!