Vizitator marian_i Postat Ianuarie 12, 2010 Partajează Postat Ianuarie 12, 2010 Buna seara!As dori sa realizez o aplicatie cu PIC16f628A.Voi folosi intreruperile provenite de la TMR0, INT ext side la PORTB(RB7-RB4).Sa presupunem ca apare o intrerupere de la TMR0.In timp ce rulam codul de tratare a acestei intreruperi ,mai apar inca doua evenimente ce genereaza int.1.Aceste ultime doua intreruperi vor fi memorate si tratate ulterior sau trebuie sa fac un artificiu, ceva in acest sens?2.In ce ordine vor fi solutionate intreruperile ultime?Va multumesc anticipat! Link spre comentariu
cirip Postat Ianuarie 12, 2010 Partajează Postat Ianuarie 12, 2010 1.Aceste ultime doua intreruperi vor fi memorate si tratate ulterior sau trebuie sa fac un artificiu, ceva in acest sens? Vor fi memorate in flagurile de intrerupere asociate fiecarei surse, dar nu vor fi achitate cat timp esti in intrerupere datorita blocarii globale prin GIE. Ai doua optiuni:1)Fie iesi din intrerupere, dar vei intra imediat datorita existentei flagurilor setate si autorizate.2)Inainte sa iesi din intrerupere te uiti daca mai ai flaguri setate si faci procesarea asociataIndiferent cum ar fi, trebuie sa te uiti la flaguri ca sa determini cine a intrerupt. Eu am facut ceva cu 4 surse de intrerupere, dar am optat ptr varianta 1. La intrarea in intr ma uitam cine a determinat cererea de intrerupere, apoi ieseam. Daca mai era ceva setat, intra din nou.2.In ce ordine vor fi solutionate intreruperile ultime?In ordinea decisa de tine. Dat fiind ca picul 16 are un singur vector (adresa de restart) de intrerupere, detectia sursei si ordinea achitarii este la latitudinea programatorului.In principiu exista si posibilitatea acceptarii unei noi intreruperi in timpul in care esti deja in intrerupere, dar procedura este descurajata la picul 16 datorita arhitecturii simple, stivei mici, etc. Link spre comentariu
Vizitator marian_i Postat Ianuarie 12, 2010 Partajează Postat Ianuarie 12, 2010 Cirip, multumesc tare mult.O seara buna! Link spre comentariu
cirip Postat Ianuarie 12, 2010 Partajează Postat Ianuarie 12, 2010 Cirip, multumesc tare mult.O seara buna!Pentru putin,Am uitat sa precizez ca eu utilizez extensiv simulatorul din MPLAB. Este lipsit de briz-brizuri si, cu mici exceptii declarate in clar la "limitari", simuleaza meserias aproape toate cipurile. Majoritatea proiectelor mele sunt simulate la greu si cand le "torn" in cipan, merg aproape din prima.Un exemplu: Mi-am facut un incarcator de LiPo. La un moment dat am observat ca are un bug. Il foloseam deja de 6 luni si problema a aparut dintr-o data, dar era neconsistenta. Nu o puteam reproduce sistematic. Era o greseala de calcul. Scapa un carry din cand in cand. Ei bine, singura posibilitate de a-l prinde a fost simulatorul.Alta chestie. Din cand in cand ma joc de-a DSP. Cand un algoritm nu merge, singura varianta sa-l prinzi este sa rulezi pas cu pas fiecare etapa de calcul. Simulatorul face minuni si in cazul asta ptr ca poti sa vezi simultan o multime de variabile si SFRuri.Sugestia mea este sa creezi toate scenariile posibile in simulator si sa vezi cum face. Mie nu mi s-a intamplat pana acum ca simulatorul sa nu reproduca intocmai comportarea cipanului.Spor!Cirip Link spre comentariu
Vizitator Xplicit Postat Iulie 27, 2010 Partajează Postat Iulie 27, 2010 Baieti eu sunt mai incepator in programare, dar m-ati spart, scuze expresia!. Cirip cu explicatia si Marian cu multumirile ca a inteles. Sincer eu nu am inteles cum e cu intreruperile astea cumulate. Ca sa fiu mai "Xplicit", pana cum am programat o singura intrerupere, ori pe Timer0 ori pe Timer1, in limbaj PROTON BASIC si merge OK. Dar nu am inteles cum sa fac sa folosesc doua intreruperi diferite, in acelasi soft si sa beneficiez de ambele in functii diferite, adica Timer0 sa faca o clipire de LED de ex, iar INT-ext sa supravegheze un switch si sa dea o comanda la actionare. Daca poate cineva sa ma ajute dar in PROTON BASIC deoarece nu cunosc C sau alte limbaje de programare, pot sa pun o mostra de program si poate vorbim pe marginea lui. Cele bune. Link spre comentariu
francezu Postat Iulie 27, 2010 Partajează Postat Iulie 27, 2010 Fiecare tip de intrerupere are un flag asociat. De exemplu : Intreruperea generata de overflow la TMR0 are asociat flagul T0IF- se afla in registru INTCON la bit-ul 2; Intreruperea generata de tranzitia nivelului logic de la pinul INT are asociat flagul INTF- se afla tot in registru INTCON la bit-ul 1. Pentru a serviza mai multe tipuri de intreruperi, trebuie sa vezi cine a generat intreruperea curenta. Pentru asta , in rutina de intreruperi, verifici flag-urile de mai sus. Daca T0IF este setat apelezi o subfunctie care este legata de acest tip de intrerupere ( cazul tau- schimba starea pinului la care este legat led-ul), daca nu este setat T0IF, ci in schimb este setat INTF, atunci apelezi o alta subfunctie care se ocupa de acest tip de intrerupere( cazul tau- comanda spre actionare, etc).Chestia asta o faci cu instructiuni de genul :if ..... then, else Inainte de iesirea din fiecare subfunctie , trebuie sa resetezi flag-ul care a condus la sa, altfel imediat dupa iesirea din rutina de intreruperi, va fi generata o noua intrerupere de acelasi tip, dar ea deja a fost servizata. Toate astea sunt scrise foarte clar in datasheet, iti sugerez sa citesti cu atentie sectiunea de intreruperi. Link spre comentariu
Vizitator Xplicit Postat Iulie 28, 2010 Partajează Postat Iulie 28, 2010 Francezule multumesc de explicatie. Am facut o proba de cod pentru a vedea daca am inteles bine ce ai spus despre intreruperile concomitente. Asta e codul de test: Device 16F877Xtal 4On_Hardware_Interrupt GoTo Interrupt_routine '---------------------- interrupt variables --------------------------Symbol T1CKPS1 = T1CON.5 ' TIMER1 Input Clock Prescale Select bitsSymbol T1CKPS0 = T1CON.4 ' Symbol T1OSCEN = T1CON.3 ' TIMER1 Oscillator Enable bitSymbol TMR1CS = T1CON.1 ' TIMER1 Clock Source Select bitSymbol TMR1ON = T1CON. 0 ' TIMER1 On bitSymbol GIE = INTCON.7 ' Global Interrupt Enable bitSymbol PEIE = INTCON.6 ' Peripheral Interrupt Enable bitSymbol TMR1IF = PIR1.0 ' TIMER1 Overflow Interrupt Flag bitSymbol TMR1IE = PIE1.0 ' TIMER1 Overflow Interrupt Enable bitSymbol INTE = INTCON.4 ' external Interrupt enable on RB0/INT Symbol INTF = INTCON.1 ' interrupt flagSymbol INTEDG = OPTION_REG.6 'INT.EDGE bitSymbol led = PORTA.0 : Low leda var Byte'-------------------------- config timer1 -----------------------------------------GIE = 0 'disable all interruptsINTEDG = 0 'INT. EDGE on fallingINTE = 1 'Enable external interrupt on PB0/INTT1CKPS1 = 1 ' \ TIMER1 Prescaler to 1:4T1CKPS0 = 1 ' /T1OSCEN = 0 ' Disable External OscillatorTMR1CS = 0 ' Increment on the internal ClkTMR1ON = 1 ' Enable TIMER1TMR1IE = 1 ' Enable the TIMER1 overflow interruptPEIE = 1 ' Enable all peripheral interruptsGIE = 1 ' Enable all interrupts'------------------------MENIUL PRINCIPAL-------------------------------------------main:'programul principal se pune aiciGoTo mainInterrupt_routine:If TMR1IF = 1 Then GoSub Timer1_routine 'verifica timer1 flagIf INTF = 1 Then GoSub INT_routine 'verifica INT_flagContext RestoreTimer1_routine:Toggle led 'executa operatia dataTMR1IF = 0 'reseteaza Timer1_flagReturnINT_routine:Inc a 'executa o operatie dataINTF = 0 'reseteaza INT_flagReturnLa compilare nu mi-a dat nici o eroare; magandesc ca trebuie sa fie OK. E bine asa? Eu lucrez cu ProtonBasic. Cele bune. Link spre comentariu
francezu Postat Iulie 28, 2010 Partajează Postat Iulie 28, 2010 Da, este ok, atat cat pot eu sa-mi dau seama( folosesc mikroBasic). Poti incerca o simulare, de exemplu in Proteus. Daca compilatorul stie sa genereze fisiere .cof / .coff -atunci poti face chiar si rulare pas cu pas la nivel de cod sursa. O intrebare doar : macro-urile astea : '---------------------- interrupt variables --------------------------Symbol T1CKPS1 = T1CON.5 ' TIMER1 Input Clock Prescale Select bitsSymbol T1CKPS0 = T1CON.4 'Symbol T1OSCEN = T1CON.3 ' TIMER1 Oscillator Enable bitSymbol TMR1CS = T1CON.1 ' TIMER1 Clock Source Select bitSymbol TMR1ON = T1CON. 0 ' TIMER1 On bitSymbol GIE = INTCON.7 ' Global Interrupt Enable bitSymbol PEIE = INTCON.6 ' Peripheral Interrupt Enable bitSymbol TMR1IF = PIR1.0 ' TIMER1 Overflow Interrupt Flag bitSymbol TMR1IE = PIE1.0 ' TIMER1 Overflow Interrupt Enable bitSymbol INTE = INTCON.4 ' external Interrupt enable on RB0/INTSymbol INTF = INTCON.1 ' interrupt flagSymbol INTEDG = OPTION_REG.6 'INT.EDGE bitnu sunt predefinite in compilator ? asa mi s-ar parea normal. Link spre comentariu
Vizitator Xplicit Postat Iulie 29, 2010 Partajează Postat Iulie 29, 2010 Nu am facut niciodata vreo simulare cu un cod de program. Eu lucrez direct pe placa de testare. Am sa incerc sa testez codul de program afisat si sa vad daca e OK cu aceste doua intreruperi simultane in acelasi cod.Acele macrouri cred ca sunt predefinite in compilatorul ProtonBasic deoarece atunci cand scriu denumirea, de ex. TMR1IF, sau INTF, automat recunoaste denumirea si o modifica in alta culoare cu litere ingrosate. Asta inseamna ca sunt predefinite? Link spre comentariu
francezu Postat Iulie 29, 2010 Partajează Postat Iulie 29, 2010 Nu am facut niciodata vreo simulare cu un cod de program. Eu lucrez direct pe placa de testare. Cand o sa ai coduri mari/complexe si ceva n-o sa mearga , o sa fie foarte greu sa descoperi problema in circuit, doar daca folosesti un debugger( ex: ICD2) ai sanse. In simulator, sau cu debugger-ul poti vedea la orice moment de timp continutul registrilor, al variabilelor etc. Am sa incerc sa testez codul de program afisat si sa vad daca e OK cu aceste doua intreruperi simultane in acelasi cod. Led-ul ar trebui sa palpaie cam de 4 ori pe secunda. Cum verifici daca variabila a este incrementata la intreruperea data de INT ? Acele macrouri cred ca sunt predefinite in compilatorul ProtonBasic deoarece atunci cand scriu denumirea, de ex. TMR1IF, sau INTF, automat recunoaste denumirea si o modifica in alta culoare cu litere ingrosate. Asta inseamna ca sunt predefinite? Probabil, n-am folosit ProtonBasic, citeste prin help, tre' sa scrie ce si cum. Link spre comentariu
Vizitator Xplicit Postat Iulie 29, 2010 Partajează Postat Iulie 29, 2010 Francezule, tin sa-ti multumesc de la inceput pentru faptul ca vad aici ca vrei sa ma ajuti. Si asta inseamna mult pentru mine. Nu pot decat sa-ti multumesc.Simulari nu am facut niciodata deoarece am spus ca sunt la inceput in programare si inca nu m-am lansat asa de mult in toate secretele. Am incercat odata sa simulez un program in MPLAB dar nu am reusit sa inteleg nimic si am lasat-o balta.Ma intrebi cum verific variabila "a" daca este incrementata de intrerupere? Pai, nu stiu. Cum ar trebui sa o verific? Eventual la cateva incrementari sa aprinda un alt LED, e OK? E bine de stiut ca acel program este pentru explicatii nu neaparat ceea ce vreau eu sa fac. Ideea e ca am inteles cum se fac intreruperile cumulate in acelasi soft. Cele bune. Link spre comentariu
francezu Postat Iulie 29, 2010 Partajează Postat Iulie 29, 2010 Francezule, tin sa-ti multumesc de la inceput pentru faptul ca vad aici ca vrei sa ma ajuti. Si asta inseamna mult pentru mine. Nu pot decat sa-ti multumesc. Cu placere! De cate ori am ocazia incerc si eu sa-i ajut pe cei care cer ajutor, pentru ca la randul meu, am fost in aceeasi situatie si informatiile de pe forumul acesta au fost foarte utile. Simulari nu am facut niciodata deoarece am spus ca sunt la inceput in programare si inca nu m-am lansat asa de mult in toate secretele. Am incercat odata sa simulez un program in MPLAB dar nu am reusit sa inteleg nimic si am lasat-o balta. Atunci ai timp sa-nveti cum este si cu simularile si cand ceva nu merge, postezi pe forum si poate gasim solutia impreuna. Ma intrebi cum verific variabila "a" daca este incrementata de intrerupere? Pai, nu stiu. Cum ar trebui sa o verific? Eventual la cateva incrementari sa aprinda un alt LED, e OK? E bine, si mai bine ar fi daca ai vedea valoarea ei, nu ? Eu propun sa incluzi linia asta,inainte de main: TRISD=0 ' all outputsApoi dupa Inc a ' executa o operatie datamai adaugi : PORTD= aAstfel trimiti valoarea variabilei "a" la PORTD. Atasezi 8 leduri cu rezistente serie de 300-500 ohmi pe fiecare iesire a portului: anod la port-rezistenta-gnd. Led-urile o sa afiseze valoarea lui "a" in binar- sper ca stii sistemul de numeratie binara, din moment ce te joci cu PIC-uri Bafta Link spre comentariu
Vizitator Xplicit Postat Iulie 30, 2010 Partajează Postat Iulie 30, 2010 Francezule mersi mult inca odata si daca nu te superi mai am o nelamurire. Ai zis ca in codul postat de mine LEDul palpaie cam de 4 ori pe secunda. OK, cum calculezi sa palpaie odata pe secunda? Asta pentru a face un program de ceas de ex. Sa-ti spun ce stiu pana acuma ca sa ai un pct. de reper:-Timer1 e pe 16 biti deci numara de la 0 la 65535, OK?-prescalerul este 1:4 deci impart taktul de ceas cu 4, OK?-4.000.000 Hz / 4 = 1.000.000-1 / 1.000.000 = 0,000001 = 1us este ciclul de program.- 1us * 65535 = 65,535 ms este ciclul intreruperii la Timer1, adica la overflow unde TMR1IF=1,OK?Aici ma cam incurc. Cum iti da tie de 4 ori pe secunda ca mie imi da 65,535 ms?Poate ma lamuresti si pe mine. Cele bune. Link spre comentariu
MifTy Postat Iulie 30, 2010 Partajează Postat Iulie 30, 2010 scrie mare şi clar cum se face calculul ăsta în 2 pdf-uri citite de mine până acum:- în manualul LPC demo board, pentru 16f690. (vezi pe situl microchip)- în tutorialul nr 3 de pe gooligum, pentru 12f509.(vezi pe gooligum.com.au)calculele sunt absolut identice: ambele au RC intern de 4 mhz, aşa că...şi eu abia mă pun la punct cu 12f509...edit: pagina 20 a manualului LPC-ului. The GOTO Loop (in Example 3-3) backs up and does it again. This loop takes 3 instruction times; one for the decrement and two for the GOTO (see note) and the counter will force it to go around 256 times, which takes it a total of 768 instruction times (768 μs) to execute.Even that is still too fast for the eye to see. It can be slowed down even more by adding a second loop around this one.The inner loop still takes 768 μs plus 3 for the outer loop, but now it’s executed another 256 times, 771 * 256 = 197376 μs = 0.197s.Note: GOTO instructions take two instructions due to the pipelined design of the processor. The processor fetches the next instruction while executing the current instruction. When a program branch occurs, the fetched instruction is not executed.în tutorialul australianului este explicat cu mult mai amănunţit... Link spre comentariu
francezu Postat Iulie 30, 2010 Partajează Postat Iulie 30, 2010 Ai zis ca in codul postat de mine LEDul palpaie cam de 4 ori pe secunda. OK, cum calculezi sa palpaie odata pe secunda?Sa vedem: Frecventa oscilatorului este de f=4Mhz-> frecventa interna de ceas este f/4=1 Mhz - pt fiecare ciclu masina sunt necesare 4 semnale de tact- vezi arhitectura PIC-urilor. Asa cum ai zis si tu un ciclu dureaza 1us, dar nu datorita prescaler-ului asociat lui TMR1. Mai departe intra in rol si acest prescaler, si mai divide si el frecventa odata cu 4- perioada semnalului de ceas ce ajunge la contorul TMR1 va creste deci de 4 ori- 4*1us= 4us . TMR1 poate contoriza maxim 65535 impulsuri, se mai adauga unul cand face overflow. Perioada sa de overflow va fi : 65536*4us= 262.144 ms. Frecventa de overflow este deci 1/262.144ms= 3.81 Hz.Cu aceasta frecventa face toggle iesirea spre LED, deci va palpai cam de 2 ori/ sec nu cum am zis mai devreme- uitasem ca este toggle.Pentru valori precise, poti ajusta valoarea lui TMR1 in rutina de intrerupere. Daca de exemplu in ISR scrii TMR1=50000, atunci pana la urmatoarea intrerupere TIMER1 va numara doar de la 50000 in sus, si nu de la 0. Asta este un caz in care ai nevoie de simulator, sa vezi exact timpii de executie.Un calculator online pentru timere, foarte util , gasesti aici Link spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum