În cele din urmă este timpul să încercăm să lucrăm cu întreruperi externe. Această lecție, în primul rând, a fost foarte solicitantă, deși pare la prima vedere să fie simplă. Au fost multe cereri și nu am putut să nu răspund. În al doilea rând, lucrăm acum cu modulul LAN ENC28J60. există o ieșire, prin care putem obține întreruperi după finalizarea anumitor operații, pe care am vrut să le proces. De asemenea, dacă reușesc, aș dori să vă împărtășesc acest lucru cu dvs., dar fără ideea inițială de întreruperi externe în controlerul STM32, este greu de înțeles acest lucru, cred, pentru al face ușor. De aceea, această lecție sa maturizat.
Ca microcontroler vom lua același STM32F103RCT6. situat pe o placă ieftină, cu care suntem angajați în procesul de programare a modulului LAN, și ca programator este, de asemenea, un ieftin mic ST-Link V2.
Pe scurt despre întreruperile externe. Întreruperile externe sunt întreruperi care sunt procesate din cauza apariției anumitor evenimente pe un anumit picior al portului microcontrolerului. Pot exista mai multe astfel de evenimente în ciuda a numai 2 stări logice. O varietate de astfel de evenimente pot fi ușor de văzut prin deschiderea listei lor în Cube MX în configurația picioarelor portului
Puteți împărți aceste tipuri în 2 grupe în jumătate. Primul grup, External Interrupt, este procesarea întreruperilor externe. Și al doilea este manipularea evenimentelor. Singura diferență este că, în primul caz, se cheamă mânerul de întrerupere, iar în cel de-al doilea caz se ridică numai steagul corespunzător. Fiecare grup este deja împărțit în trei tipuri de evenimente:
1. A fost detectată o față în sus (o schimbare în nivelul de la 0 la 1)
2. Se detectează o față descendentă (schimbarea nivelului la 0);
3. Se detectează oricare dintre fronturile de mai sus.
De asemenea, există tipuri de programe de întreruperi, dar nu le vom avea nevoie cu siguranță.
Asta e tot prin tipuri de întreruperi.
Există mai multe registre pentru tratarea întreruperilor externe:
EXTI_IMR. Registrul măștilor de întreruperi,
EXTI_EMR. Registrul măștilor de evenimente,
EXTI_RTSR. Registrul de declanșare pe marginea în creștere,
EXTI_FTSR: Registrul de declanșare pe marginea cădere,
EXTI_SWIER. Registrul întreruperii software-ului începe,
EXTI_PR. registrul de steaguri de eveniment pentru care apar apeluri de întrerupere.
Toate aceste registre sunt detaliate în documentația tehnică a manualului de referință pentru toate controlerele STM. Nu le vom examina în detaliu, să lăsăm-o la conștiința bibliotecii HAL.
Iată schema logică a dispozitivului de preluare a întreruperii din controler
Aici vedem toate registrele noastre și care este legătura logică dintre ele.
De asemenea, puteți vedea diagrama organizării liniei de întreruperi externe
Aici vedem 16 linii conectate prin multiplexoare la aceleași pinii tuturor porturilor. Adică, putem procesa simultan 16 picioare ale controlorului, dar, așa cum se poate observa din organizația multiplexă, că toate acestea ar trebui să aibă numere diferite. Asta este, putem procesa picioarele PA1 și PC2 în același timp, dar nu putem procesa PA1 și PC1.
Există și 4 linii care nu sunt conectate la porturile cu scop general, ci la anumite tipuri de periferie
Celelalte patru linii EXTI sunt conectate după cum urmează:
• Linia EXTI 16 este conectată la ieșirea PVD
• Linia EXTI 17 este conectată la evenimentul de alarmă RTC
• Linia EXTI 18 este conectată la evenimentul Wakeup USB
• Linia EXTI 19 este conectată la evenimentul Wakeup Ethernet (disponibil numai în dispozitivele de conectivitate)
Adică, putem procesa evenimente externe de la detectorul de tensiune programabil, de la ceasul de alarmă RTC, de la "trezirea" USB și Ethernet.
Asta e cât de mult pentru întreruperi, și asta nu e tot. Pe acest subiect, în documentația tehnică scrisă de până la 18 pagini, astfel încât oricine interesat - să fie sigur că pentru a citi.
Sarcina noastră este să procesăm corect aceste întreruperi în codul nostru utilizând funcțiile bibliotecii HAL.
Creați un nou proiect în generatorul de proiect Cube MX selectând controlorul nostru
Porniți rezonatorul de cuart
Alegeți un programator pentru interfața SWD
Activați piciorul responsabil pentru LED
Porniți întreruperile externe pe piciorul PA1
Vom seta divizoare și multiplicatori pentru performanță maximă în secțiunea "Configurarea ceasului" (faceți clic pe imagine pentru a mări imaginea)
Sa mergem la "Configuration" si in sectiunea GPIO vom regla PC13 pentru viteza medie
Pentru picioare PA1 de strângere aplicabile înregistrați pentru un autobuz comun, astfel încât să nu este agățat în aer, ca și întreruperea, vom prinde butonul, iar butonul oriunde nu trage, în caz contrar, starea va fi incert. Tipul de întrerupere externă va fi lăsat în mod implicit - marginea în creștere
Aplicați setările de port și treceți la setările de întreruperi globale de pe butonul "NVIC", porniți acolo întrerupe EXTI1
Aplicați de asemenea aceste setări.
Vom configura proiectul prin atribuirea numelui EXTI01 și selectarea mediului de dezvoltare SW4STM32
Generați proiectul, deschideți-l în sistemul de lucru System Workbench. ca întotdeauna, și să ștergeți fișierul de depanare în setările de depanator.
Vom colecta proiectul, vom incerca sa-l incepem, dar cel mai probabil nu vom reusi si vom vedea in consola un astfel de mesaj ca controlerul nu a putut fi flashat datorita faptului ca nu a reusit sa reporneasca
Desigur, puteți ține și elibera butonul RESET de pe placă la timp. Dar vom merge în altă direcție. Am citit o serie de forumuri și nu am găsit nimic acolo, cu excepția editării fișierelor de configurare. Deschideți fișierul de depanare în proprietățile proiectului
În dialogul care se deschide, accesați fila "Debugger" și faceți clic pe "Afișați opțiunile generatorului"
În câmpul "Reset mode", deschis în partea de jos, selectăm elementul "Resetare sistem software"
Vom salva setările, acum totul trebuie făcut.
Deschideți main.c și dezactivați LED-ul nostru în funcția principal (). deoarece știm că este conectat inversat (puteți face acest lucru în Cube MX, dar este atât de clar)
/ * CODUL UTILIZATORULUI ÎNCEPE 2 * /
HAL_GPIO_WritePin (GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
/ * USER CODE END 2 * /
Apoi, în main.c, adăugați un handler de întrerupere externă
/ * CODUL UTILIZATORULUI BEGIN 4 * /
void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
/ * USER CODE END 4 * /
Apoi vom urmări întreruperea de la 1 rând aici și aprinde LED-ul
void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
HAL_GPIO_WritePin (GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
/ * USER CODE END 4 * /
Conectați butonul între PA1 și cablul de alimentare (faceți clic pe imagine pentru a mări imaginea)
Vom colecta proiectul, vom impune controlorul. Apoi faceți clic pe butonul - LED-ul ar trebui să fie aprins (faceți clic pe imagine pentru a mări imaginea)
Să diversificăm puțin proiectul nostru, astfel încât să nu fie atât de plictisitor. Pentru a face acest lucru, vom merge la Cube MX, și din moment ce nu avem Keil, nu este nevoie să închidem proiectul și vom porni întreruperile externe și pe piciorul PA2
Și vom include un alt tip - operația de întrerupere pe partea inferioară a coborârii și vom trage rezistența, dimpotrivă, la sursa de tensiune. Pentru aceasta, efectuați următoarele setări în "Configurare" din GPIO pentru piciorul PA2
Aplicați setările, generați proiectul, reveniți la System Workbench și efectuați proiectul Refresh.
Să adăugăm mânerul nostru după cum urmează, astfel încât prin întreruperea piciorului PA1 LED-ul se aprinde, iar în cazul PA2 - se stinge
void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
dacă (GPIO_Pin == GPIO_PIN_1)
HAL_GPIO_WritePin (GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
> altfel dacă (GPIO_Pin == GPIO_PIN_2)
HAL_GPIO_WritePin (GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
Conectăm încă un buton, dar deja pe PA2, iar cel de-al doilea este deja la firul comun (faceți clic pe imagine pentru a mări imaginea)
Acum, dacă colectăm codul și coșem controlerul, primul buton va fi pentru noi să aprindem LED-ul și cel de-al doilea să stingem.
Se pare că există un astfel de lucru? Și faptul că acest lucru se întâmplă indiferent de progresul programului în sine, nu într-o buclă infinită, când în timpul unui handler scris cu un clic pe buton nu putem fi deloc și nu va fi clar dacă evenimentul nostru va fi procesat. Prin urmare, după studierea întreruperilor externe, am făcut un mare pas înainte spre independența procesării anumitor evenimente de pe picioarele porturilor microcontrolerului. Desigur, având în vedere experiența noastră deja foarte bogată, nu a fost foarte dificil pentru noi să facem acest lucru.
Mulțumesc tuturor pentru atenție!