Sari la conținut

Despre programarea microcontrolere Atmel AVR - intrebari si raspunsuri


Postări Recomandate

  • Răspunsuri 163
  • Created
  • Ultimul Răspuns

Top Posters In This Topic

Top Posters In This Topic

Posted Images

sper ca vorbim de codul postat un pic mai sus (nu stiu de unde a aparut x)

 

codul initial unde shiftezi la stanga (<<)

deci daca incepi cu b=1 si faci shift la stanga dupa ce faci shift de opt ori bitul ala de pe MSB dispare (face shift peste cei 8 biti ai byte-ului b) si b==0, - cand detectezi asta il readuci pe LSB (b=1)

 

daca vrei sa shiftezi la dreapta

cand faci shift right (>>) cand bitul ala cade din octet (b==0) il readuci pe pozitia MSB (b=0x80) ca sa ai de unde sa-l tot shiftezi la dreapta.

 

RR

Editat de roadrunner

Cred ca am inteles. Partea asta cu shift stanga si dreapta o studiez detaliat.

 

Inca o chestiune. Am vazut in datasheet-ul lui Atmega 32 pinii PD2 si PD3 unde la descriere apare INT0 si INT1. Numai la pinii astia merge sa conectez un buton care sa actioneze intreruperile sau pot sa folosesc orice pin a microcontrolerului ?

Citesc datasheet-ul dar.. (intotdeauna exista un dar).. ca sa actionez INT0 de la pinul PD2 atmega32 foloseam o instructiune de forma:

ISR(INT0_vect)
{
...................
}

Dar daca vreau ca functia lu PD2 sa fie luata de alt pin, spre exemplu PA0, cum fac ? sau cum scriu codul de mai sus?

Editat de dan_e

Nu am reusit sa schimb intreruperile pe alti pini atmega 32, dar cercetez in continuoare. Am incercat un cod asa dar nu functioneaza (am ales pinul PA2 de la atmega32):

 

ISR(PA2_vect)
{
// Codul meu
}

 

dar intre timp am gasit pe net un tutorial unde era un program care aprindea si stingea ledurile conectate la portul B. Eu l-am adaptat pentru portul C Atmega 32 dar nu se compileaza, imi afiseaza eroarea: '::main' must return 'int' si nu stiu ce inseamna asta!! Asta e programul:

 

#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER0_OVF_vect)
{static uint8_t t=0;
if(++t==3)
{t=0;
if(PORTC) PORTC=0;
else PORTC=0xFF;
}
}
void main()
{DDRC=0xFF;
TIMSK|=(1<<TOIE0); //Enable Timer0 overflow interrupt
TCCR0|=(1<<CS02)|(1<<CS00); //Timer0 prescaler =f/1024
sei();
while(1);
}

Care o fi problema?

Editat de dan_e

haha pai de unde

ISR(PA2_vect) ?

toti vectorii de intrerupere sunt declarati in : iom32.h

 

 

functia main () - are prototipul

int main(void) sau

int main (int)

 

daca o scrii

int main(void)

o sa mearga.

ce compilator folosesti?

RR

Editat de roadrunner

Referitor la problema nr.2, eroarea '::main' must return 'int' se afiseaza din cauza ca:

void main()
{DDRC=0xFF;
TIMSK|=(1<<TOIE0); //Enable Timer0 overflow interrupt
TCCR0|=(1<<CS02)|(1<<CS00); //Timer0 prescaler =f/1024
sei();
while(1);
}

ar trebui sa fie:

int main()
{DDRC=0xFF;
TIMSK|=(1<<TOIE0); //Enable Timer0 overflow interrupt
TCCR0|=(1<<CS02)|(1<<CS00); //Timer0 prescaler =f/1024
sei();
while(1);
return 0;
}

Deci, se modifica void main() in int main() si dupa while(1); se adauga return 0;

 

La problema cu intreruperile din pacate nu pot sa formulez un raspuns exact din cauza ca nu prea m-am lovit de acest aspect. Din acest motiv, la problema cu intreruperile o sa rog un alt utilizator sa te lamureasca.

 

Numai bine

mersi

 

a ramas in continuoare problema cu intreruperile. Am incercat codul propus de roadrunner dar nu-mi iese deloc! :frust: Nu stiu cum sa fac sa folosesc, spre ex. pinul PA2 in locul lui PD2 de la atmega 32 (sa se declanseze pe front high-low). :wacko:

daca folosesti atmega32 (nu 328) atunci nu are intreruperi externe pe toti pinii.

totusi daca iti doresti tu asa tare o intrupere pe PA2 poti sa faci urmatorul artificiu (tinind cont ca e PA2=ADC2)

 

selectezi mux-ul analogic pe intrarea PA2 (ADC2) - care automat ajunge intern pe intrarea negativa a comparatorului analogic.

selectezi Bandgap reference (sau aplici o tensiune de referinta de VCC/2 la pinul AIN0) - ca sa ajunga + al comparatorului analogic. (tensiune de VCC2 o faci cu un divizoe rezistiv)

faci enable la intreruperea de analog compare (si o configurezi sa faca triger la ANA2 < Vref)

 

http://www.atmel.com...doc2503.pdf la pagina 198. (cipul asta a fost facut in 2002 noi suntem in 2013 are si el limitarile lui, dar cu putina fantezie ...)

easy peasy

RR

Editat de roadrunner

poti sa faci cum fac PLC-urile, sa scanezi continuu portul A, citesti si compari cu valoarea anterioara, daca valorile sunt diferite vezi care biti sunt diferiti si iei decizie sa faci cutare lucru. Scanarea o faci bazata pe un eveniment cu intrerupere (o intrerupere periodica de timer). Metoda asta are deficienta ca mananca din resurse CPU chiar daca starea pinilor nu se schimba, dar e ok in cele mai multe cazuri, cand nu trebuie sa faci multe alte operatii pe langa asta. (iar pentru invatat e un exercitiu bun)

RR

 

 

PS - De fapt pin change interrupt face in hardware exact ce am descris eu mai sus, numai ca mult mai repede, cu viteza (CLK_IO la atmel) la fiecare tact al CLK_IO compara starea unui port cu starea memorata de la citirea anterioara (tine starea anterioara intr-un registru IO) daca e diferita face trigger la intrerupere. (in comparator se pot masca bitii care nu vrei sa-i ignore comparatorul)

Editat de roadrunner

roadrunner, am gasit pe site-ul asta:

http://blog.roderick...1/atmega32-pwm/

un cod scris asa:

TCCR1A = _BV(COM1A1)

inseamna asta:

TCCR1A  = (1<<COM20);

E acelasi lucru? :scratchchin:

 

Si tot acolo scrie asa:

TCCR1A = !_BV(COM1A1)

apare semnul exclamarii in fata lu _BV, de ce?

:ermm:

Editat de dan_e

astea sunt intrebari de limbaj C (revin la ideea mea fixa cu cartea de C)

 

TCCR1A = _BV(COM1A1) 

 

este un macro (adica un fel de pseudo instructiune definita de user) si vine de la prescurtarea "Bit Value" -

practic calculeaza un octet la care bitul din paranteza e setat ( COM1A1 sa zicem ca e egal cu 5 atunci calculeaza octetul care are bitul 5 setat pe unu)

 

TCCR1A = (1<<COM20);

 

este ce am discutat mai sus cu cateva posturi

 

calculeza numaru 1 siftat la stanga cu COM20 pozitii - ( de exemplu daca COM20=5 sifteaza 0x01 spre stanga cu 5 pozitii, care matematic vorbind e echivalent cu _BV(COM20) de la exemplul de mai sus.

 

 

- folosirea semnului excalmarii insemana negatie pentru variabile de tip bool (FALSE/TRUE) se foloseste in general la varibile bool dar nu e recomadat sa fie folosit la alte tipuri de variabile pentru ca rezultatul depinde de compilator/ tipul variabilei

daca vrei sa faci complementare bitwise, ca sa inversezi starea bitilor dintr-un octete mai bun operatorul "~" (tilda) care face complemntare bitwise

 

de exemplu la evaluarea (a==2) intr-o intructiune if daca brei sa evaluezi inegalitatea devine (a!=2) sau FALSE=! TRUE (negarea lui TRUE intoarce valoare FALSE)

 

carte de C, carte de C.....

RR

 

PS - intrebarile de mai sus sunt tipice pentru interviul de angajare, cam toti care scriu in CV ca stiu sa programeze microcontrollere primesc asemenea exercitii si intrebari despre pointeri.

Editat de roadrunner

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 cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
  • Navigare recentă   0 membri

    • Nici un utilizator înregistrat nu vede această pagină.

×
×
  • Creează nouă...

Informații Importante

Folosim cookie-uri și tehnologii asemănătoare pentru a-ți îmbunătăți experiența pe acest website, pentru a-ți oferi conținut și reclame personalizate și pentru a analiza traficul și audiența website-ului. Înainte de a continua navigarea pe www.tehnium-azi.ro te rugăm să fii de acord cu: Termeni de Utilizare.

ATENTIE !!! Functionarea Tehnium Azi depinde de afisarea de reclame.

Pentru a putea accesa in continuoare site-ul web www.tehnium-azi.ro, va rugam sa dezactivati extensia ad block din browser-ul web al vostru. Dupa ce ati dezactivat extensia ad block din browser dati clic pe butonul de mai jos.

Multumim.

Apasa acest buton dupa dezactivarea extensiei Adblock