Mikroprocesorski sistemi/K2 2021

Izvor: SI Wiki
< Микропроцесорски системи
Datum izmene: 15. mart 2024. u 02:24; autor: KockaAdmiralac (razgovor | doprinosi) (Dodavanje jezika u <syntaxhighlight>)
(razl) ← Starija izmena | Trenutna verzija (razl) | Novija izmena → (razl)
Pređi na navigaciju Pređi na pretragu

Prvi kolokvijum 2021. godine nema postavku dostupnu sa stranice predmeta. Nije mnogo poznato o ovom roku, osim zadatka navedenog ispod. Isti zadatak pojavio se i na drugom kolokvijumu 2022. godine.

Zadatak

Postavka

Referentna šema u zadatku.

Koristeći alate arm-none-eabi-*, build-tools i Eclipse CDT, Proteus simulator i CubeMX alat potrebno je ispuniti stavke koje se nalaze u nastavku.

  1. [6 poena] Napraviti CubeMX i Proteus projekte za mikrokontroler STM32F103R6. Dodati dva dugmeta i povezati ih na pinove PB0 i PB2 (pogledati referentnu šemu) tako da se mogu koristiti za generisanje prekida. Izvršiti neophodnu konfiguraciju tako da se generišu zahtevi za obradu prekida ukoliko se na ulaznom signalu ovih pinova prepozna uzlazna ivica. Dodati dve LED (light emitting diode) i povezati ih na pinove PB1 i PB3 (pogledati referentnu šemu). Izvršiti neophodnu konfiguraciju i zatim u okviru prekidne rutine za dugme koje je vezano na pin PB0 napisati programski kod koji vrši promenu stanja na pinu PB1, a u okviru prekidne rutine za dugme koje je vezano na pin PB2 napisati programski kod koji vrši promenu stanju[sic] na pinu PB3 (pogledati referentni snimak).[1]
  2. [6 poena] Dodati sedmosegmentni ekran širine četiri cifara, povezati ga na odgovarajuće pinove prema referentnoj šemi, izvršiti neophodnu konfiguraciju i napisati programski kod za prikaz cifara 1234 na ekranu. Osvežavanje ekrana vršiti u update event prekidnoj rutini tajmera TIM1. Ukoliko se stavka (4) uradi u potpunosti ispravno prikaz na ekranu uskladiti sa zahtevima iz stavke (4) a poeni za stavku (2) biće priznati u celosti.
  3. [6 poena] Dodati elektromotor i osciloskop u skladu sa referentnom šemom. Potrebno je proširiti postojeće prekidne rutine iz stavke (1) na način da se kontroliše brzina rada elektromotra.[sic] Uloga dugmeta povezanog na pin PB0 jeste da poveća brzinu, a uloga dugmeta povezanog na pin PB2 jeste da smanji brzinu (pogledati referentni snimak).[1] Za generisanje signala kojim se kontroliše elektromotor koristiti tajmer TIM1 i njegov kanal CH1. Pojedinačni inkrement odnosno dekrement za koji se menja brzina predstavlja 10% od maksimalne brzine elektromotora.
  4. [6 poena] Potrebno je dodati generator signala prema referentnoj šemi. Implementirati izračunavanje trenutne frekvencije signala sa generatora i prikaz izračunate frekvencije na sedmosegmentnom ekranu iz stavke (2) umesto cifara 1234 (pogledati referentni snimak).[1] Frekvencija prikazana na ekranu treba da bude izražena u Hz. Za implementaciju ove stavke koristiti tajmer TIM3 a moguće je koristiti njegove kanale CH1 i CH2. Ukoliko se stavka (4) uradi u potpunosti ispravno prikaz na ekranu uskladiti sa zahtevima iz stavke (4) a poeni za stavku (2) biće priznati u celosti.

Rešenje

Celo rešenje može se preuzeti odavde.

Svi relevantni izmenjeni fajlovi sa kodom nalaze se u cubemx/code/Core/Src direktorijumu.

Rešenje ispod se može u manjim detaljima razlikovati od rešenja u arhivi iznad, kako je kod ispod dodatno pojednostavljen radi pojašnjenja nekih funckionalnosti.

Opšte napomene

  • Potrebno je uraditi Refresh projekta u Eclipse okruženju nakon ponovnog generisanja koda u CubeMX-u kako bi sve radilo ispravno.
  • Za pinove se ostavlja podrazumevana opcija no pull-up, no pull-down za razliku od vežbi.
  • U slučaju problema rada sedmosegmentog displeja dodati GPIOC->ODR &= ~0xFFF pre postavljanja vrednosti na displej.

CubeMX opšte

Prvo je pod Project Manager u Project podešena putanja projekta i Makefile za Toolchain, a zatim u Code Generator štiklirana opcija za generisanje odvojenih izvornih fajlova i zaglavlja za svaku periferiju. Uraditi inicijalno generisanje koda.

Eclipse opšte

  • Otvoriti Eclipse i postaviti radno okruženje na folder CubeMX unutar foldera projekta.
  • Window->Preferences->MCU:
    • Workspace Arm -> postaviti pitanju do interna_putanja_na_vašem_računaru\GNU MCU\arm-none-eabi-gcc-10.2.1-1.1\bin.
    • Workspace BuildTools -> postaviti pitanju do interna_putanja_na_vašem_računaru\GNU MCU\build-tools-4.2.1-2\bin.
  • Putem opcije import uvesti generisan kod iz foldera Code, kao postojeći C/C++ projekat koji koristi makefile. Obavezno označiti Arm Cross GCC.
  • Nakon učitavanja, desni klik na učitani projekat, properties->C/C++ Build->Setting, a zatim Apply and close.
  • Opet desni klik na učitani projekat, properties->C/C++ General->Paths and symbols, i dodati C simbole STM32F103x6 i USE_HAL_DRIVER.

Makefile opšte

U Makefile je pomeren tim.c na dno C_SOURCES promenljive, sledeći blok:

ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif


# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"

je promenjen na:

ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2 -fdebug-prefix-map==../
endif


# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"

CFLAGS += -mlong-calls
CFLAGS += -Wall -Wextra

i startup_stm32f103x6.s je promenjeno na Core/Src/startup_stm32f103x6.s unutar ASM_SOURCES.

Stavka 1

CubeMX
  • Pinove PB0 i PB2 podesiti kao GPIO_EXTI.
  • Pinove PB1 i PB3 podesiti kao GPIO_Output.
  • U NVIC omogućiti prekide po EXTI0 i EXTI2.
  • Generisati kod.
Eclipse

stm32f1xx_it.c

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
	switch (GPIO_Pin) {
	case GPIO_PIN_0:
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
		break;

	case GPIO_PIN_2:
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
		break;
	}
}
Proteus
  • Dodati mikotrokontroler i postaviti signale prema referentnoj šemi.
  • Dioda je LED-YELLOW iz biblioteke ACTIVE. Diode je potrebno postaviti da budu digitalne.
  • Za dugme se koristi BUTTON iz biblioteke ACTIVE. Switching time postaviti na 1n.
  • Postaviti otpornike u skladu sa referentnom šemom.
  • Postaviti .elf ili .hex fajl u mikrokontroleru i testirati ispravan rad.

Stavka 2

CubeMX
  • Tajmer TIM1:
    • Clock Source->Internal clock,
    • Prescaler (PSC)->999
    • Counter Period (AutoReload Register)->79
  • Postavke iznad obezbeđuju na svakih 10ms da se desi update interrupt, 8MHz/PSC je broj taktova u jednoj sekundi, a ARR na koliko taktova se generiše update interrupt.
  • U NVIC omogućiti update interrupt za TIM1.
  • Podesiti pinove PC0-PC11 kao GPIO_Output.
  • Generisati kod.
Eclipse

main.c

     (&htim1)->Instance->SR = ~TIM_SR_UIF;   //  Чисти иницијалани update interrupt flag по покретању пројекта
  	 HAL_TIM_Base_Start_IT(&htim1);		 // Стартује TIM1

tim.c

uint8_t digits[4] = { 1, 2, 3, 4 };
uint8_t sevenSeg[] = { 0x81, 0xCF, 0x92, 0x86, 0xCC, 0xA4, 0xA0, 0x8F, 0x80, 0x84 };
uint8_t currentDigit = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
     if (htim->Instance == TIM1) {
			GPIOC->ODR &= ~0xF00;	                // Чисти приказ свих цифара (чисти пинове за аноде 7seg дисплеја)
			GPIOC->ODR &= ~0xFF;	                //Чисти стару вредност текуће цифре
			GPIOC->ODR |= sevenSeg[digits[currentDigit]];	// Поставља нову вредност текуће цифре
			GPIOC->ODR |= 0x1 << (currentDigit + 8);	// Приказује текућу цифреу активирањем пина аноде на одговарајућој позицији
			currentDigit = (currentDigit + 1) % 4;
		}
	}
Proteus
  • Koristi se 7SEG-MPX4-CAiz biblioteke DISPLAY.
  • Povezati sedmosegmenti displej u skladu sa referentnom šemom.
  • Testirati ispravan rad.

Stavka 3

CubeMX
  • Tajmer TIM1:
    • Channel1->IPWM Generation CH1,
    • Counter Period (AutoReload Register)->9
    • Pulse->0
    • CH Polarity->Low
  • U NVIC omogućiti capture compare interrupt.
  • Generisati kod.
Eclipse

main.c

     HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

stm32f1xx_it.c

     void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
		switch (GPIO_Pin) {
		case GPIO_PIN_0:
			HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
	
			if (power < 9) {
				power++;
			}
			htim1.Instance->CCR1 = power;

			break;

		case GPIO_PIN_2:
			HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);	

			if (power > 0) {
				power--;
			}
			htim1.Instance->CCR1 = power;

			break;
		}
	}
Proteus
  • Postaviti kolo sa motorom u skladu sa referentnom šemom.
  • Za bateriju se koristi CELL iz biblioteke DEVICE, a za motor MOTOR iz biblioteke ACTIVE.
  • Dioda ovde ne treba da bude digitalna.
  • Obratiti pažnju da je napon baterija 12V.

Stavka 4

CubeMX
  • Tajmer TIM3:
    • Clock Source->Internal clock,
    • Channel1->Input Capture direct mode,
    • Prescaler (PSC)->7999
    • Counter Period (AutoReload Register)->65565
    • Polarity Selection kanala 1->Rising edge
  • U NVIC omogućiti general interrupt od TIM3.
  • Generisati kod.
Eclipse

main.c

    (&htim3)->Instance->SR = ~TIM_SR_UIF;
	HAL_TIM_Base_Start_IT(&htim3);
  	HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);

tim.c

uint8_t digits[4] = { 1, 2, 3, 4 };
uint8_t sevenSeg[] = { 0x81, 0xCF, 0x92, 0x86, 0xCC, 0xA4, 0xA0, 0x8F, 0x80, 0x84 };
uint8_t currentDigit = 0;
uint32_t timestamp = 0;
uint32_t overflowCounter = 0;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance != TIM3 && htim->Channel != HAL_TIM_ACTIVE_CHANNEL_1) {
        return;
    }
    uint32_t currentTimestamp = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
    // Прво мерење не треба да ажурира дисплеј, већ само измери време.
    if (timestamp != 0) {
        // Број откуцаја који су прошли од претходног мерења, а један откуцај је
        // једна милисекунда.
        uint32_t periodMs = currentTimestamp - timestamp + overflowCounter * 65536;
        // фреквенција = 1 / периода у секундама = 1000 / периода у милисекундама
        uint32_t frequency = 1000 / periodMs;
        digits[0] = frequency / 1000;
        digits[1] = frequency / 100 % 10;
        digits[2] = frequency / 10 % 10;
        digits[3] = frequency % 10;
    }
    timestamp = currentTimestamp;
    overflowCounter = 0;
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM1) {
        // У нижих осам битова (PC7..0) иду битови тренутне цифре, а у виших четири
        // (PC11..8) иде један бит који каже на коју цифру тренутно исписујемо.
        GPIOC->ODR = sevenSeg[digits[currentDigit]] | (1 << (8 + currentDigit));
        currentDigit = (currentDigit + 1) % 4;
    } else if (htim->Instance == TIM3) {
        ++overflowCounter;
    }
}
Proteus
  • Postaviti preostale komponente u skladu sa referentnom šemom.
  • Na DCLOCK-u se isprobavaju frekvencije manje od 8000.

Napomene

  1. 1,0 1,1 1,2 Referentni snimak nije dostupan sa vikija, ali možete pokrenuti rešenje kako bi videli kako ceo sistem radi.