bahay - Setup ng internet
Mga interrupts sa atmega8. Kursong pagsasanay

Ang isa sa mga bentahe ng ATmega8 microcontroller ay ang malawak na hanay ng iba't ibang mga interrupt.

Makagambala ay isang kaganapan kung saan nasuspinde ang pagpapatupad ng pangunahing programa at tinawag ang isang function na humahawak sa isang interrupt ng isang tiyak na uri.

Ang mga interrupt ay nahahati sa panloob at panlabas. Ang mga pinagmumulan ng mga panloob na interrupts ay kinabibilangan ng mga built-in na microcontroller modules (timer, USART transceiver, atbp.). Ang mga panlabas na interrupt ay nangyayari kapag ang mga panlabas na signal ay dumating sa mga microcontroller pin (halimbawa, mga signal sa RESET at INT pin). Ang likas na katangian ng mga signal na humahantong sa paglitaw ng isang interrupt ay nakatakda sa control register MCUCR, lalo na sa mga bit - ISC00 (bit 0) at ISC01 (bit 1) para sa input INT 0; ISC10 (bit2) at ISC11 (bit3) para sa INT1 input.

Sa ATmega8 microcontroller, ang bawat interrupt ay may sarili matakpan ang vector(address sa simula ng lugar ng memorya ng programa kung saan naka-imbak ang command para sa paglukso sa tinukoy na interrupt routine). Sa mega8, lahat ng mga interrupt ay may parehong priyoridad. Kung maraming interrupts ang nangyari nang sabay-sabay, ang interrupt na may mas mababang vector number ay ipoproseso muna.

Makagambala sa mga vector sa Atmega8

Address I-interrupt ang source Paglalarawan
0x0000 I-RESET I-reset ang signal
0x0001 INT0 Kahilingan sa panlabas na interrupt sa input ng INT0
0x0002 INT1 Panlabas na paghiling ng interrupt sa INT1 input
0x0003 T/C1 Pagkuha ng timer T/C1
0x0004 T/C1 Tugma ang T/C1 Timer Paghambingin ang Register A
0x0005 T/C1 Itugma sa ihambing ang rehistro B ng timer T/C1
0x0006 T/C1 T/C1 counter overflow
0x0007 T/C0 T/C0 counter overflow
0x0008 SPI Nakumpleto ang paglilipat ng data ng SPI
0x0009 UART Nakumpleto na ng UART transceiver ang pagtanggap ng data.
0x000A UART Walang laman ang rehistro ng data ng UART
0x000B UART Nakumpleto ang paghahatid ng data sa pamamagitan ng UART transceiver
0x000C ANA_COMP Makagambala mula sa analog comparator

Makagambala sa pamamahala

4 na rehistro ang may pananagutan sa pamamahala ng mga pagkagambala sa ATmega8:

GIMSK(aka GICR) - ipagbawal/paganahin ang mga interrupt batay sa mga signal sa mga input INT0, INT1

GIFR- pamamahala ng lahat ng panlabas na pagkagambala

TIMSK, TIFR- pamamahala ng mga pagkaantala mula sa mga timer/counter

Magrehistro GIMSK(GICR)

INTFx=1: isang interrupt ang naganap sa input ng INTx. Kapag pumapasok sa interrupt handling routine, ang INTFx ay awtomatikong nire-reset sa log state. 0

Magrehistro TIMSK

7 6 5 4 3 2 1 0
TOIE1
OCIE1A
OCIE1B
-
TICIE
-
TOIE0
-

TOIE1=1: Pinagana ang T/C1 overflow interrupt

OCIE1A=1: interrupt kapag ang rehistro ng paghahambing A ay tumutugma sa mga nilalaman ng counter T/C1 na pinagana

OCIE1B=1: matakpan kapag ang rehistro ng paghahambing B ay tumutugma sa mga nilalaman ng counter T/C1 na pinagana

TICIE=1: pinagana ang interrupt kapag natugunan ang kundisyon ng pagkuha

TOIE0=1: Pinagana ang T/C0 overflow interrupt

Magrehistro TIFR

7 6 5 4 3 2 1 0
TOV1
OCF1A
OCF1B
-
ICF1
-
TOV0
-

TOV1=1: Naganap ang pag-apaw ng T/C1

OCF1A=1: rehistro ng paghahambing A ay kasabay ng mga nilalaman ng counter T/C1 na pinapayagan

OCF1B=1: Ang rehistro ng paghahambing B ay tumutugma sa mga nilalaman ng counter T/C1 na pinapayagan

ICF=1: natugunan ang mga kundisyon sa pagkuha

TOV0=1: T/C0 overflow ang naganap

Kapag pumapasok sa interrupt handling subroutine, ang TIFR register flag na tumutugma sa interrupt ay awtomatikong ire-reset sa log state. 0

Gumagana lamang ang mga interrupt kapag pinagana ang mga pangkalahatang interrupt sa rehistro ng status ng SREG (bit 7 = 1). Kapag may naganap na interrupt, ang bit na ito ay awtomatikong ire-reset sa 0, na hindi pinapagana ang mga kasunod na interrupts.

Sa halimbawang ito, ang INT0 pin ay pinagana sa pull-up input mode. Kapag ang pin ay naka-short sa lupa gamit ang isang pindutan, ang logic 0 ay nakatakda dito (ang gilid ng signal ay bumaba mula sa supply ng boltahe sa 0) at ang interrupt handler ay na-trigger, na i-on ang ilaw na bombilya na konektado sa zero pin ng port B

void lampON()
{
PORTB.0=1;
DDRB.0=1;
}

interrupt void ext_int0_isr(void)
{
lampON();
}

DDRD.2=0;
PORTD.2=1;

SREG|= (1 habang(1) (

Ipinapakita rin ng halimbawa sa itaas kung paano nakatakda ang mga interrupt na vector sa Code Vision AVR (interrupt void ext_int0_isr(void)). Ang mga interrupt na vector ay nakatakda nang katulad para sa iba pang mga kaso:

EXT_INT0 2
EXT_INT1 3
TIM2_COMP 4
TIM2_OVF 5
TIM1_CAPT 6
TIM1_COMPA 7
TIM1_COMPB 8
TIM1_OVF 9
TIM0_OVF 10
SPI_STC 11
USART_RXC 12
USART_DRE 13
USART_TXC 14
ADC_INT 15
EE_RDY 16
ANA_COMP 17
TWI 18
SPM_READY 19

Una sa lahat, ano ang pagkagambala?
Ang interrupt ay isang uri ng function na isasagawa kapag may dumating na signal sa ilang input ng controller.
Kapag nagtatrabaho sa AVR Studio, ginagawa ang mga interrupt gamit ang mga macro ISR() , SIGNAL() At INTERRUPT(). Minarkahan nila ang ilang function bilang isang interrupt handler. Ang pagkakaiba nila ay iyon INTERRUPT() At ISR() tukuyin ang isang handler function para sa kaso kapag ang pangkalahatang pagkagambala ay pinagana (ang handler ay maaaring maantala), at SIGNAL() para sa kaso kapag ang pangkalahatang pagkagambala ay hindi pinagana.

Sa pamamagitan nito, tapusin natin ang teorya at magpatuloy sa pagsasanay (bagaman magkakaroon ng higit pang teorya sa ibaba).
Pagsama-samahin natin ang sumusunod na diagram sa ISIS:

Tulad ng malamang na nahulaan mo na, magsusulat kami ng isang interrupt (na nabuo sa pamamagitan ng isang pindutan) na sisindi at papatayin ang diode.
Kaya, buksan ang studio at lumikha ng isang karaniwang proyekto.
Para gumamit ng mga interrupts, isama ang header file:

#isama

Sumang-ayon tayo na ang interrupt (pisikal) ay hindi i-on o i-off ang kapangyarihan sa controller leg (tulad ng naisip ko nang tapos na ito), ngunit babaguhin lamang ang bandila. Sa ilang mga halaga kung saan ang diode ay i-on at off.
Itakda natin ang flag na ito sa buong mundo:

Int num = 1;

Ngayon, magdeklara tayo ng pagkagambala:

ISR(SIG_INTERRUPT1)( kung (num == 1) num = 0; else num = 1; )

Tulad ng nakikita mo, ang tinatawag na interrupt vector ay ipinahiwatig sa mga macro bracket. Sinasabi ng vector na ito sa compiler kung saan bubuo ang input ng interrupt. Para sa INT1 ito ay SIG_INTERRUPT1. Para sa isang ADC, halimbawa, ito ay SIG_ADC. (ang buong listahan ay perpektong inilarawan sa aklat na "Shpak Yu.A. Programming sa C para sa AVR at PIC microcontrollers.")
Ngayon ay lumipat tayo sa pangunahing pag-andar ng aming "programa".
Kailangan nating paganahin ang mga pagkagambala sa pangkalahatan at para sa INT1 sa partikular:

Sei(); // sa pangkalahatan GIMSK |= (1<

Kapag tapos na ito, kailangan mong i-configure ang interrupt na gawi. Maaari itong mabuo sa iba't ibang paraan.
I-download ang datasheet (may link kapag lumilikha ng proyekto) at hanapin ang sumusunod na talahanayan sa seksyon ng interrupt:

Sa tingin ko ay mauunawaan mo kung paano ito isalin.
Itakda natin ang estado ng interrupt generation para sa bawat "lohikal na pagbabago sa INT1".

MCUCR = (0<

Ngayon itakda natin ang buong port C bilang output:

DDRC = 0xff; // port C - output

Well, ito ay dapat na malinaw:

Habang (1)( if (num == 1) PORTC |= 1; // i-on ang unang output C else PORTC &= ~1; // patayin ang unang output C _delay_ms(100); // maghintay ng 100ms )

Hindi na kailangang maghintay. Bukod dito, binabawasan nito ang pagganap. Pero gusto ko ganyan.
Buong programa:

#define F_CPU 8000000UL // 8MHz #include #isama #isama int num = 1; ISR(SIG_INTERRUPT1)( if (num == 1) num = 0; else num = 1; ) int main (walang bisa)( sei(); GIMSK |= (1<

Kino-compile namin ang hex at i-assemble ang circuit sa Proteus. Nasisiyahan kami sa interrupt function kapag binabago ang posisyon ng button.

Madalas na nangyayari na ang isang microcircuit ay dapat gumana at gumana nang tahimik, ngunit para sa ilang mga kaganapan, i-drop ang lahat at gumawa ng iba pa. At pagkatapos - bumalik muli sa orihinal na gawain... Ito ay tulad ng isang relo, halimbawa - ipinapakita nito ang oras hanggang sa dumating ang oras ng alarm clock. At tila walang mga panlabas na impluwensya - pagpindot sa isang pindutan, i-reset - at ang microcircuit ay lumipat mismo.

Maaari itong ipatupad gamit ang mga interrupts - mga signal na nagpapaalam sa processor tungkol sa paglitaw ng isang kaganapan.

Narito ang isang halimbawa mula sa pang-araw-araw na buhay - nakaupo ka sa kusina, umiinom ng tsaa na may raspberry jam at masasarap na pagkain, at naghihintay ng mga bisita. Paano mo malalaman na may dumating na? Mayroong dalawang mga pagpipilian: alinman ay magpapahinga kami mula sa jam, ang ibig kong sabihin ay tsaa, bawat limang minuto at tumakbo upang makita kung may nakatayo sa pintuan, o bumili ng doorbell at mahinahong maghintay sa isang mainit na lugar hanggang sa may mag-ring.

Kaya, kapag tumawag ang isang bisita, ito ay isang kaganapan. Alinsunod dito, humiwalay kami at nagmamadaling pumunta sa pinto.

Kaya, ang microcircuit ay may mga interrupts. At hindi lang isa. Ang mga interrupt ay nahahati sa panlabas - ang mga ito ay na-trigger sa isang tiyak na boltahe sa ilang mga pin ng microcircuit (INT0, INT1 at kung minsan din ang buong PCINT port) - at panloob - kapag ang counter ay umapaw, ang watchdog timer ay na-trigger, kapag gumagamit ng USART, kapag ang isang analog comparator, ADC at iba pang mga peripheral ay nagambala .

Alinsunod dito, lumitaw ang isang priyoridad na problema. Parang nakaupo pa rin kami at umiinom ng tsaa, pero hindi lang sila nagdo-doorbell, pati na rin sa telepono... At hindi ka mapupunit, may kailangan munang gawin. Samakatuwid, ang datasheet ay naglalaman ng isang talahanayan ng mga interrupt na vector. Kung mas mababa ang interrupt na numero, mas mataas ang priyoridad nito.

Mayroong ilang mga subtleties dito ...

Isang kaganapan ang naganap - isang interrupt request ang ipinadala, iyon ay, ang tinatawag na "interrupt request flag" ay nakatakda. Kung ang lahat ay maayos, ang pagkagambala ay nalutas, kung gayon ang buhay ay kahanga-hanga at ito ay naproseso.

Ngunit kung hindi pinagana ang isang interrupt - halimbawa, pinoproseso na ang isang mas mataas na priyoridad na interrupt - mananatiling nakabitin ang flag ng kahilingang ito hanggang sa paganahin ang mga interrupt. Pagkatapos nito, sinusuri ng chip ang rehistro ng kahilingan sa pagkakasunud-sunod ng priyoridad, at kung mayroong bandila, iproseso ito.

PERO! Kahit na naproseso na ang interruption ay hindi katotohanan na buhay pa rin ang pangyayaring nagdulot nito... Parang sabay ring tumunog ang doorbell at telepono, sinagot mo ang telepono, at ang mga bisita na. nagpasya na walang tao sa bahay at umalis. At parang may event - tumunog ang doorbell, pero walang tao sa likod ng pinto.

Ang isa pang problema ay habang ang isa pang interrupt ay pinoproseso at nakataas na ang flag ng kahilingan, maaaring mangyari ang kaganapan nang maraming beses. Sinagot namin ang tawag sa telepono, binuksan ang pinto - at mayroon nang isang buong grupo ng mga bisita doon! Nakakatakot? Nakakatakot...

Ang isa pang tampok ng paggamit ng mga interrupt - at hindi lamang nakakagambala: reentrantness (o re-entry).

Ang reentrant program ay isa na maaaring tawagan ng maraming user (o mga proseso) nang hindi, sa pinakamababa, nagdudulot ng error at, sa maximum, nang hindi sinasayang ang pag-compute—halimbawa, hindi na kailangang patakbuhin muli ng ibang user ang code.

Sa madaling salita, kung sa kusina habang binabati mo ang mga bisita, walang nagnakaw ng ilang mga goodies, kung gayon ang lahat ay reentrant)

Sa pangkalahatan, ito ay isang seryosong bagay - kung hindi mo ito isasaalang-alang, maaari kang magdusa ng mahabang panahon sa "bakit hindi ito gumagana?!" Kailangan itong isaalang-alang, halimbawa, kung maraming mga interrupt ang naproseso, at bawat isa ay nagbabago ng ilang global variable...

Ang mga pagkaantala ay karaniwang HINDI muling pagpasok. Ibig sabihin, sa oras na tumatakbo ang interrupt, hindi mo na matatawag muli ang parehong interrupt. Ito ay upang maprotektahan laban sa paulit-ulit na pagpasok sa handler na awtomatikong ipinagbabawal ang mga interrupt sa oras ng pagproseso nito (kung gusto mong paganahin ang mga interrupt sa interrupt pamamaraan ng paghawak, kailangan mong mag-isip ng sampu, dalawampung beses bago gumawa ng gayong pantal na hakbang).

Isaalang-alang natin ang pagtatrabaho sa mga panlabas na interrupts: kailangan natin, una, upang i-configure kung aling kaganapan ang magti-trigger ng pagkaantala, at, pangalawa, upang payagan ang chip na iproseso ang mismong pagkaantala na ito.

Ang rehistro ng MCUCR ay responsable para sa una sa ATmega8 chip - mga bit na ISC11-ISC10, responsable para sa INT1, at ISC01-ISC00, na responsable para sa INT0.

Talahanayan 1. Kahulugan ng mga kaganapan para sa pagbuo ng isang interrupt sa pamamagitan ng INT1

Alinsunod dito, pareho sa INT0.

Ngayon ang lahat na natitira ay upang paganahin ang mga interrupts sa pin na kailangan namin - ang GIGR register ay may bits INT0 at INT1; nakatakda sa gustong "1" - at naka-enable ang panlabas na pagkaantala! Ngunit masyadong maaga upang magalak - bilang karagdagan sa mga panlabas na pagkagambala, ang mga pagkagambala sa pangkalahatan ay dapat paganahin - itakda ang pinakakaliwang bit I ng rehistro ng SREG sa "1". Ang parehong ay maaaring gawin sa assembler command: asm sei;

Tingnan natin ang isang simpleng halimbawa: ang isang pindutan ay nakakabit sa INT0 (D.2) pin ng ATmega8 chip (sa pin at sa zero); pindutin - may naganap na interrupt at ang LED sa pin B.0 ay bubukas. Ang LED, nang naaayon, ay konektado sa binti at sa yunit:

//program para sa ATmega8 kapag pinindot mo ang isang button sa pin INT0 (D.2) - konektado sa 0 - //i-on ang LED sa pin B.0 sa pamamagitan ng external interrupt - konektado sa 1 //redefine type typedef unsigned char byte; sbit ddrButton at ddD2_bit; //generation button sbit pinButton at pinD2_bit; sbit portButton sa portD2_bit; sbit ddrLight at ddB0_bit; //output para sa LED, sa pull-up na output, i-0 ang sbit button na portLight sa portB0_bit; byte flagButton = 0; //button click flag; pinindot - 1 void INT0_interrupt() org IVT_ADDR_INT0 //kailangan mong magsulat ng kahit isang walang laman na function - //dahil ang compiler ay hindi gumagawa nito mismo. Kung hindi man ay hindi ito gagana ( flagButton = 1; ) //pagproseso ng pagpindot sa pindutan - isinasaalang-alang ang bounce void buttonLight() ( if(flagButton) //kung pinindot ang button ( portLight = 0; //i-on ang LED delay_ms(500); portLight = 1; //i-off ang LED flagButton = 0; ) ) void main() ( // inisyal ang lahat ng ginamit na port ddrB = 0; portB = 0; ddrD = 0; portD = 0; // pagsisimula ng button - sa input na may pull-up portButton = 1; ddrButton = 0; //pagsisimula ng LED, na naka-on sa 0 at pagpindot sa button - sa output at sa 1 portLight = 1; ddrLight = 1; / /configuring external interrupts MCUCR.ISC00 = 0; //interrupt ay nabuo ng logical 0 sa INT0 MCUCR.ISC01 = 0; GICR.INT0 = 1; //enable external interrupt INT0 asm sei;//SREG.B7 = 1; / / paganahin ang mga interrupts sa prinsipyo (bit I); ang mga utos ay katulad ng while(1) ( buttonLight() ; ) )

Medyo tungkol sa syntax. Ang interrupt function ay nakasulat tulad nito: void function_name() org IVT_ADDR_INT0.

Isinasaad ng keyword ng org na susunod na darating ang interrupt address mula sa datasheet. Mayroon kaming pangalan ng interrupt mula sa aklatan: nagta-type kami ng IVT at pagkatapos ay pindutin ang Ctrl + Space (Gusto ko ang mga ganoong bagay ˆˆ). Maaari mo ring gamitin ang iv sa halip na ang salitang org, batay sa tulong ng compiler.

Isa pang maliit na tala: una, ang pagkaantala ay hindi dapat maging mahirap - ilang mga linya at iyon na. Ito ay dahil sa ang katunayan na habang pinoproseso ang isang interrupt, ang microcircuit ay hindi maaaring makagambala sa anumang bagay, na nangangahulugang kung mayroon tayong ilang mga pagkagambala, maaari nating makaligtaan ang paglitaw ng ilang kaganapan.

Maaari rin itong lumabas na hindi namin kailangan ang pag-abala sa pagproseso - halimbawa, sapat na ang circuit ay nagising mula sa sleep mode. Ngunit sa kasong ito, kailangan mo pa ring magsulat ng isang interrupt function, kahit isang walang laman - ang tinatawag na "stub". Sa prinsipyo, ang ilang mga compiler ay awtomatikong nagsusulat ng mga walang laman na pag-andar para sa bawat pagkagambala, ngunit hindi ito ang aming kaso - kailangan naming gawin ito nang manu-mano.

Ngayon ay titingnan natin ang konsepto ng pagkagambala at kung paano ito gamitin. Naturally, hindi namin gagawin nang walang programa sa pagsasanay, ngunit sa pagkakataong ito ay hindi namin kukurap ang mga LED. Buti na lang. Gumawa tayo ng parang doorbell.

Gawain: gawin ang microcontroller na naglalabas ng beep kapag pinindot ang isang pindutan.
Diagram para sa aming halimbawa. Mga file ng proyekto.

Gumagawa kami ng ring project sa lumang workspace.
Itakda ang mga setting ng proyekto para sa pagsasaayos ng Paglabas:

Piliin ang uri ng microcontroller.
Mga Pangkalahatang Opsyon > Target > Configuration ng processor
Mayroon akong ATmega8535 na ito.

Payagan ang paggamit ng mga bit name na tinukoy sa header file
Sa General Options > System, lagyan ng check ang kahon na Paganahin ang mga bit definition sa I/O-Include files
Hindi pa kami gumagamit ng kaunting mga pangalan sa ngayon, ngunit ngayon ay kakailanganin namin ang mga ito.

Baguhin ang uri ng output file.
Linker > Output.
Sa field ng Output file, lagyan ng check ang Override default box at palitan ang d90 extension ng hex
Sa field na Format, piliin ang Iba at sa drop-down na menu ng Output format, piliin ang uri ng file na intel-standart

I-save ang proyekto at workspace.

______________________________ Pagputol ______________________________

Isipin ang sitwasyon. Nakaupo ka sa trabaho at pinag-aaralan ang isa pang microcontroller program. Lumapit sa iyo ang boss at sinabing: “Makinig, Pash, bumili kami ng mga oscilloscope para sa aming departamento - Tektronix, four-channel. Tulungan si Vasya na hilahin sila." Sa tingin mo: "Buweno, naku, ang pag-iisip lang ang humadlang... at sa iyo." At ganyan ang tingin sa iyo ng amo, at ang kanyang mga mata ay napakabait, napakabait. Paano mo siya matatanggihan? Buweno, ibinabagsak mo ang lahat at sumama sa isang kaibigan upang bumili ng mga oscilloscope. Dinala nila ito. Nagreport na kami. At muli silang umupo sa kanilang programa. Ito ay tinatayang kung ano ang hitsura ng interrupt mechanism.

Medyo simple, ngunit mayroong isang bilang ng mga pangunahing punto.
una:
- ginawa mo ang iyong trabaho
- kasabay nito, may bumibili ng mga oscilloscope
- sa paglitaw ng kaganapang "nabili ng mga oscilloscope" - naaantala mo ang iyong trabaho
- sa loob ng ilang panahon ay gumagawa ka ng iba pang gawain - nagdadala ng mga oscilloscope
- pagkatapos ay bumalik ka sa iyong lugar ng trabaho at magpatuloy sa paggawa ng iyong trabaho mula sa kung saan ka tumigil

Pangalawa:
- madali mong ipadala ang iyong boss at hindi pumunta kahit saan
- pagkatapos umalis para sa mga oscilloscope, maaari kang manatili doon ng mahabang panahon, o kahit na hindi na bumalik
- kapag bumalik ka sa iyong lugar ng trabaho, maaaring nakalimutan mo na ang iyong mga mahuhusay na ideya

Ang lahat ng ito ay halos kapareho sa kung ano ang nangyayari sa isang microcontroller. Kasama sa mga AVR microcontroller ang isang buong bungkos ng mga peripheral device (mga timer/counter, analog-to-digital converter, analog comparator, asynchronous transceiver... atbp.). Ang kapangyarihan ng microcontroller ay ang lahat ng mga aparatong ito ay maaaring gumana nang magkatulad at independiyente sa bawat isa, pati na rin sa parallel sa programa na isinasagawa. Maaaring mag-trigger ng interrupt ang bawat peripheral device kapag may nangyaring partikular na kaganapan. Ang pagkagambala ay magaganap lamang kung ito ay pinagana. Nakatakda ang interrupt enable para sa bawat device nang hiwalay. Bilang karagdagan, mayroong isang pandaigdigang paganahin/paganahin ang bandila para sa lahat ng mga pagkagambala - ito ang I flag sa rehistro ng SREG. Kapag naganap ang isang interrupt, iniimbak ng microcontroller ang mga nilalaman ng PC program counter sa stack, iyon ay, naaalala nito ang lokasyon kung saan ito nagambala. Nilo-load ang address ng kaukulang interrupt vector sa program counter at tumalon sa address na iyon. Ito ay tumama sa isang unconditional jump command, na napupunta sa interrupt processing subroutine. Hindi pinapagana ang mga interrupt sa pamamagitan ng pag-reset ng I flag, isinasagawa ang subroutine. Ang pagkakaroon ng naisakatuparan ang interrupt handling routine, ang microcontroller ay nagbibigay-daan sa mga interrupts sa pamamagitan ng pagtatakda ng I flag at pagpapanumbalik ng mga nilalaman ng program counter, iyon ay, ito ay bumalik sa parehong lugar sa program kung saan ito naantala.

Sa teorya, ang interrupt handler ay hindi dapat makapinsala sa mga nilalaman ng microcontroller registers, dahil maaaring naglalaman ang mga ito ng data mula sa program na isinasagawa sa sandaling iyon. Upang gawin ito, sa simula ng interrupt handling subroutine, ang mga nilalaman ng microcontroller registers ay naka-imbak sa stack, at sa dulo ng subroutine sila ay naibalik. Kaya, pagkatapos lumabas sa interrupt, ang microcontroller ay magagawang ipagpatuloy ang pagpapatupad ng programa na parang walang nangyari. Kapag nagprograma sa assembler, ang programmer mismo ay nagrereseta ng pag-save ng rehistro; sa C, ginagawa ito ng compiler.

_______________________________________________________________

Ngayon pag-usapan natin ang timer. Ang ATmega8535 ay may tatlong timer/counter na nakasakay - dalawang eight-bit (T0, T2) at isang labing-anim na bit (T1). Gagamit kami ng eight-bit timer/counter T0. Ang timer na ito ay binubuo ng tatlong rehistro - ang control register TCCR0, ang counting register TCNT0 at ang paghahambing na register OCR0. Kapag nagsimula ang timer, ang counter register na TCNT0 ay nagdaragdag ng halaga nito ng isa para sa bawat gilid ng orasan. Ang dalas ng orasan ay pinili mula sa ilang posibleng mga halaga sa control register TCCR0. Gayundin, gamit ang rehistrong ito, nakatakda ang operating mode ng timer. Ang timer T0 ay maaaring mag-trigger ng isang interrupt sa paglitaw ng isang "overflow" na kaganapan - ito ay kapag ang pagbibilang ng rehistro ng TCNT0 ay umapaw, at kapag ang paglitaw ng isang "nagkataon" na kaganapan - ito ay kapag ang halaga ng pagbibilang na rehistro TCNT0 ay naging katumbas ng halaga ng rehistro ng paghahambing na OCR0. Ang mga flag na nagbibigay-daan sa mga interrupt na ito ay matatagpuan sa rehistro ng TIMSK.
Iko-configure namin ang T0 timer/counter para mag-trigger ng "match" event interrupt sa 5 kHz. Sa pag-andar ng handler, ibabalik natin ang estado ng output ng microcontroller kung saan nakakonekta ang piezo speaker. Kaya, ang dalas ng tunog ng piezo ay magiging katumbas ng 2.5 kHz. (Ito ay ang piezospeaker na konektado! Huwag malito ito. Ang resistensya ng isang piezospeaker ay nakasalalay sa dalas at sa 2.5 KHz ito ay karaniwang mga yunit ng Com, kaya maaari itong direktang konektado sa output ng microcontroller, nang walang nililimitahan na risistor) .

Ngayon tungkol sa programa. Hindi na posible na isulat ang programa sa bawat linya, kaya ibibigay ko kaagad ang teksto nito. Sa ibaba ay susuriin namin ang lahat ng mga linya nito nang paisa-isa, at magiging malinaw ang lahat. Sinadya kong hindi gumamit ng mga macro; maliit ang programa at ayaw kong kalat ito.

int pangunahing( walang bisa )
{
//set up ang mga I/O port
DDRD = (0<PORTD = (1<

//set up ang timer T0
TCCR0 = (1<TCNT0 = 0;
OCR0 = 0xc8;

//paganahin ang mga pagkagambala
__enable_interrupt();

//pangunahing programa loop - botohan ang pindutan
habang(1){
kung((PIND at (1<TIMSK = (1<iba pa
TIMSK = 0;
}
bumalik 0;
}

//interrupt handler para sa timer T0

__abala walang bisa Timer0CompVect( walang bisa)
{
PORTD ^= (1<}

Mga setting ng port

Sa aming circuit, nakakonekta ang isang button at isang piezo speaker sa port D. Ang pin kung saan nakakonekta ang pindutan ay dapat na i-configure bilang isang input at ang pull-up na risistor ay dapat na naka-on. Ang pin kung saan nakakonekta ang piezo speaker ay dapat itakda sa output.

DDRD = (0<PORTD = (1<

Pagtatakda ng timer

Ang T0 timer operating mode ay CTC (reset on coincidence), clock signal ay clk/8. Sinasalamin namin ito sa rehistro ng TCCR0

TCCR0 = (1<

Kung sakali, ni-reset namin ang rehistro ng pagbibilang na TCNT0

Isulat ang 0xc8 sa rehistro ng paghahambing na OCR0. Bakit? Dahil naiilang ako calculator. Well, sa papel ganito ang kalkulasyon.
Microcontroller clock frequency 8 MHz
Ang signal ng orasan ng timer ay 8000000 Hz/8 = 1000000 Hz.
Oras ng isang timer clock 1/1000000 = 1 µs
Ang oras ng isang cycle ng dalas na kailangan namin ay 1/5000 Hz = 200 μs
Ilang timer ticks ang pasok sa 200 µs? 200/1 = 200 ticks
200 sa hexadecimal = 0xс8

Para sa isang detalyadong paglalarawan ng T0 timer, tingnan ang dokumentasyon para sa ATMega8535.

Na-configure namin ang timer at pinagana ang isang pangkalahatang interrupt gamit ang built-in na function.

__enable_interrupt();

Button ng botohan

Kapag hindi pinindot ang pindutan, ang output ng microcontroller ay konektado sa kapangyarihan sa pamamagitan ng isang panloob na pull-up resistor, iyon ay, mayroong isa sa output; kapag pinindot ang pindutan, ang output ay pinaikli sa lupa, iyon ay, doon ay isang zero sa output. Upang matukoy kung ang isang pindutan ay pinindot, kailangan mong basahin ang mga nilalaman ng rehistro ng PIND at suriin ang halaga ng zero bit (isang pindutan ay konektado sa PD0). I-poll namin ang button sa isang walang katapusang loop.

habang (1)
{
kung((PIND at (1<//kung pinindot ang button, dapat tumili ang microcontroller
}
iba pa {
//kung hindi, tumahimik ka na parang isda
}
}

Huwag kalimutan == ay hindi isang assignment operator =.

Pindutan sa paghawak/pagbitaw

Sa pamamagitan ng pagpindot sa pindutan ay paganahin namin ang pagkagambala ng timer T0, at sa pamamagitan ng paglabas nito ay hindi namin ito papaganahin. Upang gawin ito, manipulahin namin ang OCIE0 bit ng rehistro ng TIMSK

TIMSK = (1<// payagan ang pagkaantala ng timer T0 dahil sa coincidence event

TIMSK = 0; //iwasan ang pagkaantala

Dahil isang timer lang ang ginagamit namin, hindi na kailangang itakda o i-reset ang mga indibidwal na bit.

Pag-andar ng interrupt

_____________________ I-interrupt ang function syntax _____________________

Tinukoy ang interrupt function gamit ang #pragma vector= directive at isang function word __abala. Ang function ay dapat na may uri na walang bisa at hindi dapat kumuha ng anumang mga parameter.

#pragma vector = Address
__abala walang bisa Pangalan( walang bisa)
{
//ang aming code ay matatagpuan dito
}

Pangalan– pangalan ng function, piliin sa aming paghuhusga
Address– interrupt vector address, maaaring tukuyin sa pamamagitan ng numero, o sa pamamagitan ng mga pangalan na tinukoy sa microcontroller header file (iom8535.h – Interrupt Vector Definition section)

______________________________________________________________

Para sa aming gawain, ganito ang hitsura ng interrupt handler function

#pragma vector = TIMER0_COMP_vect
__abala walang bisa Timer0CompVect( walang bisa)
{
PORTD ^= (1<// baligtarin ang signal sa pin PD1
}

Well, yun lang. Sana malinaw na ang lahat.
Sa susunod na artikulo gagawin natin ang microcontroller na tumugtog ng isang melody.

Interrupt - isang kaganapan na nangangailangan ng agarang tugon mula sa processor. Ang tugon ay naantala ng processor ang pagproseso ng kasalukuyang programa ( nagambalang programa) at nagpapatuloy na magsagawa ng ilang iba pang programa ( nakakaabala sa programa), espesyal na idinisenyo para sa kaganapang ito. Sa pagkumpleto ng program na ito, ang processor ay babalik sa pagsasagawa ng nagambalang programa.

Ang bawat kaganapan na nangangailangan ng pagkaantala ay sinamahan ng putol na signal, inaabisuhan ang computer tungkol dito, at tinawagan humiling ng interrupt.

Katayuan ng programa kumakatawan sa isang hanay ng mga estado ng lahat ng mga elemento ng imbakan sa kaukulang punto ng oras (halimbawa, pagkatapos maisagawa ang huling utos). Kapag nagkaroon ng interrupt, iniimbak ng microcontroller ang mga nilalaman ng program counter sa stack at nilo-load dito ang address ng kaukulang interrupt vector. Ang huling utos ng interrupt service routine ay dapat na isang command na babalik sa pangunahing program at ibinabalik ang dating nakaimbak na program counter. Habang nagsasagawa ng interrupt handler, maaaring magbago ang ilang impormasyon. Samakatuwid, kapag lumipat sa interrupt handler, kinakailangang i-save ang mga elemento na binabago. Ang hanay ng mga naturang elemento ay vector ng estado ng programa. Sa kasong ito, ang ibang impormasyon tungkol sa estado ng mga cell ng memorya ay hindi makabuluhan o maaaring maibalik sa pamamagitan ng program.

Paunang vector ng estado naglalaman ng lahat ng kinakailangang impormasyon para sa paunang paglulunsad ng programa. Sa maraming mga kaso, ang paunang state vector ay naglalaman lamang ng isang elemento - ang panimulang address ng programa na inilulunsad.

I-interrupt ang vector ay ang vector ng paunang estado ng nakakaabala na programa (handler) at naglalaman ng lahat ng kinakailangang impormasyon para sa paglipat sa handler, kasama ang panimulang address nito. Ang bawat uri ng interrupt ay may sariling interrupt vector, na nagpasimula ng pagpapatupad ng kaukulang handler. Karaniwan, ang mga naka-interrupt na vector ay iniimbak sa mga espesyal na inilaan na nakapirming lokasyon ng memorya na may mga maiikling address, na kumakatawan matakpan ang vector table. Upang lumipat sa naaangkop na interrupt program, ang processor ay dapat may isang interrupt vector at ang address ng vector na ito. Sa address na ito, bilang panuntunan, mayroong isang walang kundisyong jump command sa interrupt handling subroutine.

Bilang isang patakaran, ang kontrol sa pag-iimbak at pagbabalik ay itinalaga sa humahawak ng interrupt. Sa kasong ito, ang handler ay binubuo ng tatlong bahagi - paghahanda (prologue) at pangwakas (epilogue), na tinitiyak ang paglipat ng programa, at ang aktwal na nakakaabala na programa, na nagsasagawa ng mga operasyon na hiniling ng kahilingan. Ang oras ng pagtugon ay tinukoy bilang ang agwat ng oras mula sa sandaling natanggap ang isang interrupt na kahilingan hanggang sa magsimulang ipatupad ang nakakaabala na programa.


t p– oras ng pagtugon ng system sa pagkagambala;
t z– oras para sa pag-iimbak ng estado ng naantalang programa;
t ppr– oras ng aktwal na nakakaabala na programa;
t sa– oras upang ibalik ang estado ng naantala na programa

Kung mayroong ilang mga mapagkukunan ng mga kahilingan, isang tiyak na pagkakasunud-sunod ng paglilingkod sa mga papasok na kahilingan ay dapat na maitatag, na tinatawag mga relasyong priyoridad o disiplina sa paglilingkod. Ang hanay ng lahat ng posibleng uri ng pagkagambala ng processor ay interrupt system microcontroller. Tinutukoy ng disiplina sa serbisyo kung alin sa ilang mga kahilingang natanggap nang sabay-sabay ang unang naproseso, at kung ito o ang humahawak ng interrupt na iyon ay may karapatang matakpan ang kahilingang ito.
Kung natanggap ang isang kahilingan sa mas mataas na priyoridad na interrupt habang pinoproseso ang isang interrupt, ililipat ang kontrol sa mas mataas na priyoridad na interrupt handler at ang mas mababang priority interrupt handler ay masususpinde. Bumangon matakpan ang pagpupugad. Tinatawag ang maximum na bilang ng mga programa na maaaring magsuspinde sa isa't isa lalim ng mga pagkagambala.

Kung ang interrupt request ay hindi naserbisyuhan sa oras na dumating ang isang bagong kahilingan mula sa parehong pinagmulan (parehong priyoridad), kung gayon matakpan ang saturation ng system. Sa kasong ito, mawawala ang ilang mga kahilingan sa interrupt, na hindi katanggap-tanggap para sa normal na operasyon ng microcontroller.

Mga katangian ng interrupt system ay:

  • kabuuang bilang ng mga kahilingan sa interrupt bilang ng mga mapagkukunan ng mga kahilingan sa interrupt;
  • uri ng interrupt na representasyon - bilang panuntunan, ang isang kahilingan sa pag-abala ay kinakatawan ng isang antas ng lohikal na signal;
  • interrupt priority - tinutukoy ang pagkakasunud-sunod kung saan ang bawat interrupt na kahilingan ay naproseso; mas mataas ang priyoridad, mas maikli ang pagkaantala sa pagpapatupad ng nakakaabala na programa para dito;
  • oras ng pagtugon - ang agwat ng oras sa pagitan ng paglitaw ng kahilingan sa pag-abala at pagsisimula ng pagpapatupad ng nakakaabala na programa;
  • pagkaantala sa pagkaantala - tinutukoy ng kabuuang oras para sa pag-iimbak at pagpapanumbalik ng programa;
  • depth, kadalasang tumutugma sa bilang ng mga antas ng priyoridad sa interrupt system;
  • matakpan ang saturation ng system;
  • pinahihintulutang mga sandali ng pagkagambala ng programa (karaniwan ay ang pagtatapos ng pagpapatupad ng susunod na utos).

I-interrupt ang masking ginagamit upang sabihin sa microcontroller na tumugon sa bawat uri ng pagkagambala o huwag pansinin ito. Ang interrupt mask ay kumakatawan sa isang binary code na ang mga bit ay nakatalaga sa mga pinagmumulan ng interrupt request. Ang isang bit sa binary code ay nagsasabi sa microcontroller na pangasiwaan ang ganitong uri ng interrupt. Ang isang zero bit, sa kabaligtaran, ay hindi pinapayagan ang microcontroller na magpatuloy sa pagproseso ng mga pagkagambala ng tinukoy na uri.
Bilang isang patakaran, bilang karagdagan sa pag-mask ng mga interrupts, mayroon ding global interrupt enable bit, ang zero value na hindi pinapagana ang lahat ng interrupt handler (maliban sa pag-reset ng hardware at tumalon sa simula ng executing program).
Bilang karagdagan sa interrupt mask binary code, mayroon ding binary code makagambala sa mga bandila, na nagpapahintulot sa interrupt handler na itakda ang pinagmulan ng interrupt kung mayroong ilang mga source na may tinukoy na kahilingan sa microcontroller.



 


Basahin:



Mga Klase at Namespace na Gumagamit at Nagdedeklara ng mga Namespace

Mga Klase at Namespace na Gumagamit at Nagdedeklara ng mga Namespace

Mga Klase at Namespace .NET Framework Mga Klase Marahil ang pinakamalaking pakinabang ng pagsulat ng pinamamahalaang code - hindi bababa sa mga tuntunin ng...

Booklet sa paksang "computer at mga bata" Tamang posisyon ng kamay

Booklet sa paksa

Gumawa ng mga espesyal na ehersisyo para sa iyong mga mata! 1. Matinding pagpisil at pagkurap ng mga mata nang mabilis at madalas na pagkurap ng mga mata. 2. galaw ng mata...

Snowboarding: paano nagsimula ang lahat?

Snowboarding: paano nagsimula ang lahat?

Ang snowboarding ay isang Olympic sport na kinabibilangan ng pagbaba mula sa mga slope na natatakpan ng niyebe at mga bundok sa isang espesyal na kagamitan - isang snowboard. Orihinal na taglamig...

Larawan kung saan ito matatagpuan sa mapa ng mundo, paglalarawan

Larawan kung saan ito matatagpuan sa mapa ng mundo, paglalarawan

Mula noong sinaunang panahon hanggang sa kasalukuyan, maraming daluyan ng tubig - mga artipisyal na kanal - ang nalikha sa mundo. Ang mga pangunahing gawain ng naturang mga artipisyal ay upang mapadali...

feed-image RSS