Mikroprocesorski sistemi/K2 2021

Izvor: SI Wiki
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.

CubeMX

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, a zatim u Pinout & Configuration podešeno:

  • PC11..0 su podešeni kao GPIO_Output pinovi.
  • PB0 i PB2 su podešeni kao GPIO_EXTI0 i GPIO_EXTI2 pinovi a u NVIC su uključeni EXTI line0 interrupt i EXTI line2 interrupt.
  • PB1 i PB3 su podešeni kao GPIO_Output pinovi.
  • U TIM1 je kao Clock Source podešen Internal Clock, na Channel1 je podešeno PWM Generation CH1, kao prescaler vrednost je podešeno 7999 (kako bi jedan otkucaj bila jedna milisekunda radi lakšeg računanja) a kao period je podešeno 9 (tako da se prekoračenje brojača, odnosno update event, dešava na svakih deset milisekundi). U PWM podešavanjima puls je podešen na 0 a polaritet na nizak (tako da se motor na početku neće okretati). U NVIC je izabran TIM1 update interrupt.
  • U TIM3 je kao Clock Source podešen Internal Clock, na Channel1 je podešen Input Capture direct mode, kao prescaler vrednost je podešeno 7999 (kako bi jedan otkucaj bila jedna milisekunda radi lakšeg računanja) a kao period je podešeno 65535. Kao polaritet input capture kanala izabrana je uzlazna ivica. U NVIC je izabran TIM3 global interrupt.

Makefile

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.

main.c

Dodato je:

    HAL_TIM_Base_Start_IT(&htim1);
    HAL_TIM_Base_Start_IT(&htim3);
    HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

ispod inicijalizacije periferija.

stm32f1xx_it.c

U odeljku za korisnički kod na dnu fajla je dodato:

uint8_t currentMotorSpeed = 0;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == GPIO_PIN_0) {
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
        if (currentMotorSpeed < 9) {
            ++currentMotorSpeed;
        }
        TIM1->CCR1 = currentMotorSpeed;
    } else if (GPIO_Pin == GPIO_PIN_2) {
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
        if (currentMotorSpeed > 0) {
            --currentMotorSpeed;
        }
        TIM1->CCR1 = currentMotorSpeed;
    }
}

tim.c

U odeljku za korisnički kod na dnu fajla je dodato (komentari dodati naknadno):

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;
    }
}

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.