Temat 2: Konfiguracja uniwersalnych portów wejścia/wyjścia (GPIO), obsługa prostych wyświetlaczy Celem ćwiczenia jest prezentacja sposobu konfiguracji i sterowania uniwersalnych portów GPIO μc z serii STM32 oraz utworzenie bibliotek obsługi wyświetlaczy: alfanumerycznego LCD oraz siedmiosegmentowego LED. 1. Budowa portu ogólnego przeznaczenia, funkcje alternatywne Układy STM32F1xx udostępniają maksymalnie 8 portów GPIO (General Purpose Inputs/Outputs) o długości 16-u bitów każdy (do 128 pinów dostępnych w μc produkowanych w obudowach z 144-oma wyprowadzeniami). Struktura bitu (pinu) portu jest zilustrowana na Rys.1. Rys.1 Budowa bitu portu GPIO [5] W celu uaktywnienia wybranego portu, przede wszystkim należy włączyć jego sygnał taktujący za pomocą funkcji RCC_APB2PeriphClockCmd(), w której argumentach podajemy identyfikator GPIOA. GPIOB,.., GPIOG. Konfiguracji portów GPIO można dokonać z użyciem funkcji GPIO_Init(), która wymaga podania identyfikatora portu (GPIOA. GPIOB,.., GPIOG) i referencji do struktury typu GPIO_InitTypeDef zawierającej następujące pola: GPIO_Pin (GPIO_Pin_0,.., GPIO_Pin_15) GPIOMode (tryb pracy opisany poniżej), GPIO_Speed(GPIO_Speed_2MHz, GPIO_Speed_10MHz, GPIO_Speed_50MHz). Tryb pacy każdego bitu portu może być ustalony programowo na: wejściowy cyfrowy o wysokiej impedancji (GPIO_Mode_IN_FLOATING), wejściowy cyfrowy z rezystorem podciągającym do stanu wysokiego (GPIO_Mode_IPU), wejściowy cyfrowy z rezystorem podciągającym do stanu niskiego (GPIO_Mode_IPD), wejściowy analogowy (GPIO_Mode_AIN), wyjściowy typu otwarty dren (GPIO_Mode_Out_OD),
wyjściowy przeciwsobny (GPIO_Mode_Out_PP), funkcji alternatywnej typu otwarty dren (GPIO_Mode_AF_OD), funkcji alternatywnej typu przeciwsobnego (GPIO_Mode_AF_PP). Oprócz typowego wykorzystywania portów, jego piny mogą spełniać funkcje alternatywne opisane w specyfikacji danego układu mikrokontrolera. Fragment zestawienia funkcji wyprowadzeń dla STM32F103RBT6 jest umieszczony poniżej (ze specyfikacji podawanej przez producenta). Rys.2. Fragment zestawienie funkcji pinów μc [6]. Przykładowo, bit na pozycji 6 portu GPIOA (PA6) może pełnić funkcje wejścia kanału numer 6 przetwornika A/C, linię MISO interfejsu SPI lub wyjście kanału 1 licznika 3. Dodatkowo, możliwe jest przemapowanie jego funkcji za pomocą GPIO_PinRemapConfig()na wejście sygnału sterującego pracą licznika 3 (Break IN). Warto również zwrócić uwagę na to, że wybrane piny układu są kompatybilne z sygnałem TTL na poziomie 5V (oznaczone na Rys.2 jako FT, 5 V tolerant). Funkcje obsługi interfejsu GPIO są zgromadzone w module stm32f10x_gpio.c, gdzie umieszczono również krótkie opisy ułatwiające ich wykorzystywanie we własnym programie. Kontekstowy dostęp do opisu danej funkcji jest możliwy po wskazaniu kursorem nazwy funkcji w kodzie źródłowym i wciśnięciu przycisku Ctrl lub po wybraniu przycisku F3 (Open Declaration). Nagłówki podstawowych funkcji realizujące operacje na portach GPIO zostały zgromadzone poniżej: uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin_y) odczyt bitu GPIO_Pin_y (y=1..15) portu GPIOx (x=a..e), uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx) odczyt słowa 16-to bitowego portu GPIOx (x=a..e),
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) odczyt aktualnego stanu bitu GPIO_Pin_y (y=1..15) portu GPIOx (x=a..e), uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx) odczyt aktualnego stanu wyjść portu GPIOx (x=a..e), voidgpio_setbits(gpio_typedef* GPIOx, uint16_t GPIO_Pin) ustawienie bitu GPIO_Pin_y (y=1..15) portu GPIOx (x=a..e), voidgpio_resetbits(gpio_typedef* GPIOx, uint16_t GPIO_Pin) wyzerowaniebitu GPIO_Pin_y (y=1..15) portu GPIOx (x=a..e), voidgpio_writebit(gpio_typedef* GPIOx, uint16_t GPIO_Pin, BitActionBitVal) zapis danych do bitu GPIO_Pin_y (y=1..15) portu GPIOx (x=a..e), voidgpio_write(gpio_typedef* GPIOx, uint16_t PortVal) zapis danych do portu GPIOx (x=a..e). 2. Obsługa wyświetlacza alfanumerycznego LCD1602 ze sterownikiem HD44780 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Vss Vdd Vo RS R/W E D0 D1 D2 D3 D4 D5 D6 D7 LED+ LED- Rys.3 Wyprowadzenia modułu LCD Na Rys.3 zostały przedstawione wyprowadzenia modułu LCD1602 : Vss, Vdd ujemny i dodatni terminal zasilania, Vo regulacja napięcia polaryzującego (kontrast), RS wybór trybu transmisji (komenda dla L lub znak do wyświetlenia dla H), R/W kierunek transmisji (zapis dla L lub odczyt dla H), E sygnał sterujący (enable) odczytem/zapisem (aktywacja stanem H), D0..D7 bity danych (D0=LSB, D7=MSB), LED+, LED- anoda i katoda diody podświetlającej. Wyprowadzenia niezbędne do uruchomienia LCD w zestawie uruchomieniowym są dostępne na złączu CHAR_LCD płyty ZL30ARM. Przed wyświetlaniem znaków należy wykonać inicjalizację modułu LCD, w trakcie której określane są jego parametry pracy. Podczas laboratorium będzie wykorzystywany czterobitowy tryb komunikacji (bity D4..D7) bez kontroli bitu zajętości (R/W na stałe
połączone z GND, niedostępna operacja czytania ze sterownika LCD). W trybie tym wymagana jest minimalna liczba linii do komunikacji pomiędzy μc i LCD. Schemat połączeń został umieszczony na Rys.4. b5 b4 b0 b1 b2 b3 Rys.4 Połączenia wymagane do sterowania LCD w trybie czterobitowym Inicjalizacja LCD do pracy w opisanym trybie polega na przesłaniu do modułu ustalonego zestawu rozkazów zgodnie z Rys.5. Podane kody rozkazów obowiązują przy założeniu, że linia D3 połączona jest z bitem LSB portu, a pozostałe z odpowiednimi kolejnymi bitami (b0..b3). Przy czym, zapisanie ciągu cztero-bitowego do sterownika wymaga ustalenia stanu L na linii RS oraz podania stanu wysokiego na linię E na około 100μs (bity b4, b5). Po włączeniu zasilania odczekać >15ms Inicjalizacja 0x3 Czekaj >5ms Inicjalizacja 0x3 Czekaj >0,1ms Inicjalizacja 0x3 Interfejs 4 bity Tryb 2 wiersze, matryca 5x7 0x2 0x2 0x8 Inkrementacja poz., bez przes. okna 0x6 Wyłącz LCD 0x8 Włącz LCD bez kursora 0xC Wyczyść LCD 0x1 Rys.5 Komendy inicjalizujące moduł LCD do pracy w trybie czterobitowym Po dokonaniu inicjalizacji można już wyświetlać znaki alfanumeryczne poprzez przesłanie ich kodów ASCII do kontrolera LCD (rozpoczynając od starszej czwórki bitów). Szerszy opis sterowania modułem LCD wraz z tabelą obsługiwanych komend można znaleźć np. w [4]. Zadanie 1 Napisać program sterujący diodami LED0,..,LED7 z portu GPIOA w opisany poniżej sposób: a) krążąca jedynka, b) krążące zero, c) wahadło.
Następnie rozbudować program o możliwość zmniejszania (przycisk S0) i zwiększania (przycisk S1) prędkości zmian efektu wizualnego. Połączenia na płycie ZL30ARM: Anody LED D0..D7 Przyciski SW0, SW1 GPIO PA0..PA7 GPIO PA8, PA9 Przydatne fragmenty kodu źródłowego: void GPIO_Configuration(void) GPIO_InitTypeDefGPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* Configure LED outputs */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 GPIO_Pin_1 GPIO_Pin_2 GPIO_Pin_3 GPIO_Pin_4 GPIO_Pin_5 GPIO_Pin_6 GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure switch inputs */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); Zadanie 2 Zbudować bibliotekę zawierającą funkcje inicjalizacji voidlcd_ini(void)oraz wyświetlania voidlcd_txt(char znaki[])do 32-óch znaków alfanumerycznych dla dwuwierszowego wyświetlacza LCD1602z zestawu uruchomieniowego. Przyjąć założenie, że ciąg jest zakończony znakiem '\n' oznaczającym koniec linii. Połączenia na płycie ZL30ARM: CHAR_LCD D4..D7 CHAR_LCD RS CHAR_LCD EN CHAR_LCD R/W GPIO PB8..PB11 GPIO PB12 GPIO PB13 GND Przydatne fragmenty kodu źródłowego: #include "stm32f10x.h" uint16_t wy; void Delay_lcd( IO uint32_t ncount) uint8_t i; for(; ncount!= 0;nCount--) i=ncount;
void wyslij_4(uint8_t rozkaz) GPIO_ResetBits(GPIOB, GPIO_Pin_12); wy=gpio_readoutputdata(gpiob); wy&=0xf0ff; wy =((rozkaz<<8)&f00); GPIO_Write(GPIOB,wy); GPIO_SetBits(GPIOB, GPIO_Pin_13); Delay_lcd(5000); GPIO_ResetBits(GPIOB, GPIO_Pin_13); Delay_lcd(5000); //odczyt aktualnego stanu portu GPIOB //wyzerowanie bitów danych LCD //ustalenie bitów danych //ustawienie linii Enable //ok.1ms Zadanie 3 Zbudować bibliotekę zawierającą funkcję void led7(uint16_t liczba)realizującą multipleksowe wyświetlanie cyfr liczby całkowitej liczba z zakresu 0..9999 na wyświetlaczach siedmiosegmentowych LED zestawu uruchomieniowego. Przyjąć czas wyświetlania cyfry około 4ms. Następnie, wywołując sekwencyjnie zbudowaną funkcję wyświetlać aktualną wartość zmiennej inkrementowanej w pętli w podanym zakresie. Połączenia na płycie ZL30ARM: Anody wyświetlaczy DS0..DS3 Segmenty wyświetlaczy a..g GPIO PA8,PA9,PA10,PB15 GPIO PB8..PB14 Przydatne fragmenty kodu źródłowego: Literatura #include "stm32f10x.h" void Delay_led( IO uint32_t ncount) uint8_t i; for(; ncount!= 0;nCount--) i=ncount; uint8_t segmenty[]=0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 2, 0x78, 0, 0x10; uint16_t wy, reszta; void led7(uint16_t liczba) : wy=gpio_readoutputdata(gpiob); wy&=0x80ff; GPIO_Write(GPIOB,(segmenty[reszta/1000]<<8) wy); Delay_led(20000); reszta%=1000; : [1] http://platforma.polsl.pl/rau3/ [2] Marek Galewski, "STM32 - Aplikacje i ćwiczenia w języku C", ISBN 978-83-60233-82-5, Wydawnictwo BTC, Legionowo 2011.
[3] Krzysztof Paprocki, "Mikrokontrolery STM32 w praktyce", ISBN 978-83-60233-52-8, Wydawnictwo BTC, Legionowo 2009, 2011 wyd. I poprawione. [4] http://en.wikipedia.org/wiki/hitachi_hd44780_lcd_controller [5] Reference Manual-RM0008 [6] www.st.com