Sari la conținut
ELFORUM - Forumul electronistilor

Cel mai simplu cod pt PIC16F84A


XName

Postări Recomandate

Am citit si postul cu rutinele de delay

Dar tot nu merge programul

La simulare primesc in MPLAB Sim urmatoarea eroare "Stack over flow error occurred"

iar programul e simplu:

#include p16F84a.inc   LIST p=PIC16F84A   ;modelul de microcontroler   __CONFIG _XT_OSC & _WDT_OFF   cblock 0x1C delay1      ;declar variabile delay2delay3  endc BANK0 macro   bcf STATUS,RP0   endm BANK1 macro   bsf STATUS,RP0   endm ;*******************************************************  ORG 0x0000 ;Vectorul RESET   goto Main   ORG 0x0004 ;Vectorul INTRERUPERE  goto Main;************** Programul principal ******************** Main   BANK0   clrf PORTB   BANK1   movlw B'00000000'   movwf TRISB   BANK0   clrf PORTA   BANK1   movlw B'00000000'   movwf TRISA  Loop   movlw b'00000001'  movwf PORTB  call Delay  movlw b'00000010'  movwf PORTB  call Delay  movlw b'00000100'  movwf PORTB  call Delay  movlw b'00001000'  movwf PORTB  call Delay  movlw b'00010000'  movwf PORTB  call Delay  movlw b'00100000'  movwf PORTB  call Delay  movlw b'01000000'  movwf PORTB  call Delay  movlw b'10000000'  movwf PORTB  call Delay  goto Loop ;****************** Functia Delay ********************* Delay          movlw  .6    movwf  delay1    clrf   delay2   clrf   delay3    decfsz  delay3,f   goto     $-1   decfsz  delay2,f    goto     $-3    decfsz  delay1,f    goto     $-5    return ;***************************************************   end

Am modificat .24 cu .6 pt a reduce timpul la aproximativ o secunda

La incarcarea in PIC acesta nu imi aprinde nici un led din cele legate pe portul B

 

Mersi de ajutor

Link spre comentariu
  • Răspunsuri 51
  • Creat
  • Ultimul Răspuns

As mai face o observatie. Nu afecteaza programul asta ptr ca nu lucrezi cu intreruperile, dar ca principiu, nu se iese niciodata din intrerupere cu goto, ci cu retfie. Daca iesi cu salt (goto) nu descarci stiva si e normal sa dea Stack Overflow. Dar in cazul tau, in care nu autorizezi intreruperile, nu este necasar sa faci acel org 4 si goto main.Cirip

Link spre comentariu

Si acum mai departe.

 

Ca sa mai complic lumina dinamica, am decis sa folosesc 6 pini de pe portul B si 2 de pe portul A, ceilalti 2 ramasi de pe B se folosesc pt 2 butoane (RB7, RB6) care vor creste si vor scade viteza luminii dinamice

 

Am facut tot programul si merge cu MPLAB Sim, dar am dat de o porblema pe care nu stiu cum as putea so fac directin asamblare fara directive de procesare, si anume o conditie de verificare

 

eu vreau sa pun ca viteza sa fie intre valorile 200....256, ar fi ceva de genu: if(viteza==200) ... ;nu decrementa

 

Multumesc

Link spre comentariu

Presupunem ca viteza curenta o tii intr-o variabila numita chiar asa: viteza

 

#define vitezajos 200 ;definire prag jos...viteza equ 25h; definire variabila viteza...movf vitezajos,w ;pune viteza in Wsubwf viteza,w; scade vitezajos (W) din viteza si pune rezultatul in Wbtfss status,c; daca rezultatul e negativ, sari o instructiunenop ; in mod normal daca nu e voie, atunci nu faci nimic pot sa pui un goto daca vrei totusi sa faci cevadecf viteza,f ;evident trebuie decrementata viteza daca e voie...

Parca asa ceva...[/code]

Link spre comentariu

La seria 8051 este o instructiune CJNE-(compare and jump if not equal), ceea ce facea simpla ac. operatie. La 16Fxx nu exista , asa ca o comparatie se face cu SAU-EXCLUSIV, adica instructiunea XORLW k , k fiind constanta 200 de care ziceai. Rezultatul in W, in cazul in care cele 2 numere sunt egale va fi 0. Flag-ul Z este afectat de aceasta instructiune; testezi flag-ul. Altfel spus, daca operandul pe care-l testezi este = 200, flag-ul Z se face 1. nu-ti ramane decat sa-l testezi si sa iei decizia care trebuie. :yawinkle:

Link spre comentariu

Totusi daca vreau sa compar doua variabile a==b unde si a si b sunt intre 0...256 nu am o functie pt asa ceva.exista XORWF , iar pt asta trebuie sa incarc pe a in w, iar b este f, dar are o limitare: f nu poate sa fie decat 0..127Eu m-am gandit la o solutie nu stiu daca este si corecta, si cea mai practica: mai intai compar bitul MSB de la b, si astfel impart in doua categorii, daca este 0 execut cu XORWF dar daca este 1 , scad din b pe 128 si astfel raman tot cu o valoare cuprinsa intre 0...127 asupra careia pot aplica functia XORWFCe ziceti?!? Merge? Sau sunt solutii mult mai simple si eu nu le stiu?

Link spre comentariu
Totusi daca vreau sa compar doua variabile a==b unde si a si b sunt intre 0...256 nu am o functie pt asa ceva.
Nu, nu ai o functie ptr asa ceva ptr ca asamblarea nu este limbaj de nivel inalt. Nu e prea prietenos. In asamblare nu ai functii, ci instructiuni si subrutine (daca ti le scrii sau la copiezi de undeva).

 

dar are o limitare: f nu poate sa fie decat 0..127
Cred ca este o neintelegere. f are 8 biti. Pe 8 biti se pot reprezenta numere intregi fara semn de la 0 la 255. Deci de unde limita 0...127?

 

Eu m-am gandit la o solutie [...]
Operatia cu care se face comparatia este scaderea. XOR este prea restrictiva; poate detecta numai egalitatea. Nu folosesti rezultatul scaderii, ci numai starea indicatorilor C si Z dupa scadere. Daca Z=1 atunci variabilele sunt egale. Daca Z=0, atunci C iti da relatia de ordine intre variabile. Te las pe tine sa experimentezi. :)

Cirip

Link spre comentariu

Pai in datasheets asa scrie pt PIC16F84A sunt doua instructiuni XORLW si XORWF , prima se face cu o constanta 0XORWF Exclusive OR W with f

Syntax: [label] XORWF f,d

Operands: 0 <= f <= 127

d - [0,1]

Operation: (W) .XOR. (f) --> (destination)

Status Affected: Z

Description: ..."

 

Intradevar solutia zisa de tine e mult mai utila, poate prezenta si egalitatea si care este mai mic sau mai mare :d

Trebuie sa-mi fac niste rutine in prinvinta ei

 

Mersi

Link spre comentariu

Hehe... Studiaza putin modurile de adresare. Prima, xorlw, este adresare imediata, adica ii dai la nas data de 8 biti cu care sa faca xor.A doua este adresare indirecta, adica ii spui sa-si ia data de la adresa pe care i-o dai tu in instructiune. 0...127 este domeniul adreselor la care se pot gasi datele, adica locatiile file register-elor. Prin urmare, XORWF f, d inseamna "fa sau exclusiv intre continutul registrului de lucru W si data aflata la locatia cu adresa din f si depune rezultatul in w sau inapoi in (f)". Aici (f) inseamna adresare indirecta, adica data aflata la adresa indicata de valoarea lui f din codul instructiunii. Dar locatia e tot de 8 biti, deci poate reprezenta de la 0 la 255.Cirip

Link spre comentariu

Cirip: Mersi, am inteles acuma. Deabia azi am reusit cat de cat sa-mi raspund in mare la intrebarea de ce au pus memoria pe bankuri si nu toata intrun singura zona. Am citit destul de multe documentatii inainte sa incep efectiv cu microcontrolere, dar nu am remarcat in niciuna sa prezinte de ce pe bankuri :)Tech_Fun: Mersi de link, cu adevart utile. Raspunsurile la multe dintr intrebarile mele Pe parcursul ultimelor zile, am aprofundat Simulatorual si MPLAB, este ft util pt a vedea ce se intampla in interirorul PICului.Din pacate nu am reusit sa lucrez cu TMR0 in simulator, in help scrie ca este suportat, dar nu se incrementeaza deloc. Singura solutie a fost sa-i dau stimuli externi pt GIE si flag-ul de TMR0, insa nu prea e buna solutia, nu pot face calcule de timpiSi mai am o intrebare legata de intreruperi: Am RB7, RB6 doi pini care pot produce intrerupere, in momentul in care acestia se schimba se produce intreruperea, programul executa rutina de intrerupere, in acest timp poate sa apara intrerupere si pe celalalt pin, rutina mea pt prima intrerupere sa zicem ca dureaza undeva la 200 de cicluri, timp in care poate sa dispara intreruperea de pe al doilea pin, stiu ca ramane flagul pt intreruperi activat, dar rutina de la prima interupere se va termina nu voi mai putea sti care din cei doi pini a dat a doua intrerupere ?!

Link spre comentariu

Din pacate nu am reusit sa lucrez cu TMR0 in simulator

Merge brici. Nu e configurat. Reseteaza-i T0CS din OPTION_REG. Timpii de executie ii masori cu Stopwatch.

Am RB7, RB6 doi pini care pot produce intrerupere,[...] nu voi mai putea sti care din cei doi pini a dat a doua intrerupere ?

Foloseste un registru in care tii o variabila temporara, ca sa stii ce a fost acolo cand ai intrat in intrerupere. Daca ai din nou cerere imediat dupa ce ai iesit, compara ce e in RB cu ce ai in variabila temporara si detectezi de la ce port vine intr. E cam scarpinata cu piciorul stang la urechea dreapta, dar merge. Atentie, nu citi RB-ul in intr, ca-ti sterge conditia de port change. Stii ce zic, da?Cirip
Link spre comentariu

Atentie, nu citi RB-ul in intr, ca-ti sterge conditia de port change.

Nici eu nu prea am inteles la ce te referi, dar eu zic ca la intrarea in intrerupere trebuie sa incarc portul b intro variabila, deci trebuie neaparat sa fac o citire de port b Am ajuns la concluzia ca totusi nu se pot gestiona prea bine intreruperile pe port, daca eu gestionez intreruperea de la primul pin, intre timp apare intreruperea pe pinul 2 dar si dispare ft repede, inainte ca eu sa fi terminat cu prima intrerupereO solutie ar fi fost daca picul ar fi avut flag pt fiecare pin al portului, sau ar mai fi o solutie ca la fiecare cateva cicluri sa testezi portul si daca este si pe al pin sa memorezi undeva, :rolleyes: Se poate sa existe intrerupere in intrerupere, cred ca nu :d, ca GIE e dezactiva, dar daca eu il activez imediat la prima intrerupere?!Si se poate ca sa imi maresc stiva de mai mult de 8 biti pt ca am facut doar programele simple si am ajuns sa incarc stiva la 6 nivele :DPt proiectele care le am in cap imi trebuie o stiva imensa :)
Link spre comentariu

Arhivat

Acest subiect este acum arhivat și este închis pentru alte răspunsuri.




×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări