This shows you the differences between two versions of the page.
pm:lab:lab1 [2020/02/27 13:50] ana.constantinescu [4. Exerciții] |
pm:lab:lab1 [2020/03/03 14:31] (current) daniel.berbece [5. Resurse] |
||
---|---|---|---|
Line 26: | Line 26: | ||
Transmisia asincronă de date se face la nivel de **cadre**(frames), fiecare cadru fiind format din mai mulți biți, având formatul descris în figură. | Transmisia asincronă de date se face la nivel de **cadre**(frames), fiecare cadru fiind format din mai mulți biți, având formatul descris în figură. | ||
- | {{ .:lab1:seriala.png | Transmisia serială }} | + | {{ .:lab1:uart_ctranca.png | Transmisia serială }} |
Line 101: | Line 101: | ||
''UBRRn'' este registrul care selectează **baud rate**-ul. Are 12 biți. Primii 4 se află în ''UBRRnH'', ceilalți 8 în ''UBRRnL''. Valoarea pe care o scriem în ''UBRRn'' depinde de frecvența procesorului și de baud rate-ul dorit. În tabelul următor găsiți valorile pentru frecvența de 16 Mhz. | ''UBRRn'' este registrul care selectează **baud rate**-ul. Are 12 biți. Primii 4 se află în ''UBRRnH'', ceilalți 8 în ''UBRRnL''. Valoarea pe care o scriem în ''UBRRn'' depinde de frecvența procesorului și de baud rate-ul dorit. În tabelul următor găsiți valorile pentru frecvența de 16 Mhz. | ||
- | {{ .:lab1:baud_rate.png?nolink |}} | + | <note tip> |
+ | Pentru valorile UBRR pentru 12MHz cautati valorile in acest {{https://cache.amobbs.com/bbs_upload782111/files_22/ourdev_508497.html | link}} | ||
+ | </note> | ||
+ | {{ pm:lab:lab1:pm-lab01-baudrate.png?nolink |}} | ||
==== 2.2 Exemplu de utilizare ==== | ==== 2.2 Exemplu de utilizare ==== | ||
Line 107: | Line 110: | ||
void USART0_init(unsigned int baud) { | void USART0_init(unsigned int baud) { | ||
/* setează baud rate */ | /* setează baud rate */ | ||
- | UBRR0H = (unsigned char)(baud>>8); | + | UBRR0 = baud; |
- | UBRR0L = (unsigned char)baud; | + | /* UBRR0 este un registru pe 16 biți, la nivel de compilator se vor face doua scrieri de 8 biti */ |
- | /* UBRR0 este un registru pe 16 biți | + | |
- | Alternativ se poate scrie UBRR0 = baud, pentru că la nivel de compilator | + | |
- | se vor face două scrieri de 8 biți */ | + | |
/* pornește transmițătorul */ | /* pornește transmițătorul */ | ||
Line 342: | Line 342: | ||
* secțiunea 19.11 este referința pentru registrele I/O | * secțiunea 19.11 este referința pentru registrele I/O | ||
- | ==== USART ==== | + | ** Task 0 **(1p) |
- | ** Task 0 **(xp) | + | |
Rulați exemplul pentru USART. Pentru configurările serialei, vedeți fisierul usart.c din schelet. | Rulați exemplul pentru USART. Pentru configurările serialei, vedeți fisierul usart.c din schelet. | ||
- | **Task 1 **(xp) | + | **Task 1 **(3p) |
- | Configurați USART0 cu următorii parametri: baud rate 19200, 8 biți de date, 1 bit de stop, paritate pară. Transmiteți către PC câte un mesaj pentru fiecare eveniment de apăsare/lăsare a unui buton (ex: se apasă PD6, se transmite “PD6 apăsat”, se lasă PD6, se transmite “PD6 lăsat”, câte o singură dată pe apăsare). | + | Configurați USART0 cu următorii parametri: baud rate 19200, 8 biți de date, 2 bit de stop, fara paritate. Transmiteți către PC câte un mesaj pentru fiecare eveniment de apăsare/lăsare a unui buton (ex: se apasă PD6, se transmite “PD6 apăsat”, se lasă PD6, se transmite “PD6 lăsat”, câte o singură dată pe apăsare). |
- | **Task 2 **(xp) | + | **Task 2 **(2p) |
Comandați prin serială generarea in cod Morse a numelui vostru, folosind buzzer-ul. | Comandați prin serială generarea in cod Morse a numelui vostru, folosind buzzer-ul. | ||
<note> | <note> | ||
Line 355: | Line 354: | ||
</note> | </note> | ||
- | **Task 3: **Bonus USART (xp) | + | **Task 3 **(1p) |
- | Configurați printf astfel încât să printeze direct pe USART0. Refaceți exercițiul 1 folosind printf. | + | Rulați exemplul pentru LCD. |
- | ** Tips pentru printf (click to show)** | + | **Task 4** (3p) |
- | <spoiler> | + | Implementați funcțiile din bibliotecă: |
- | <note tip> | + | * LCD_putCharAt |
- | După cum știți de la programare, printf este echivalent cu fprintf(stdout,... ), cu alte cuvinte, folosește stdout ca fișier în care să scrie. Pentru a putea utiliza printf corect pe AVR, trebuie ca stdout trebuie să pointeze către o **structură validă FILE**. | + | * LCD_printAt |
- | + | Puteți folosi funcțiile LCD_writeInstr și LCD_writeData. | |
- | <code> | + | - Utilizați funcțiile implementate pentru a afișa un mesaj pe prima linie a LCD-ului. |
- | struct __file { | + | - Folositi implementarea anterioara pentru a afisa un mesaj trimis pe USART. |
- | char *buf; /* buffer pointer */ | + | <note > |
- | unsigned char unget; /* ungetc() buffer */ | + | Mesajul trebuie să poată fi deplasat la stânga cu butonul PB2 și la dreapta cu butonul PD6. Limitați deplasarea mesajului astfel încât acesta să nu iasă de pe ecran. |
- | uint8_t flags; /* flags, see below */ | + | |
- | #define __SRD 0x0001 /* OK to read */ | + | |
- | #define __SWR 0x0002 /* OK to write */ | + | |
- | #define __SSTR 0x0004 /* this is an sprintf/snprintf string */ | + | |
- | #define __SPGM 0x0008 /* fmt string is in progmem */ | + | |
- | #define __SERR 0x0010 /* found error */ | + | |
- | #define __SEOF 0x0020 /* found EOF */ | + | |
- | #define __SUNGET 0x040 /* ungetc() happened */ | + | |
- | #define __SMALLOC 0x80 /* handle is malloc()ed */ | + | |
- | int size; /* size of buffer */ | + | |
- | int len; /* characters read or written so far */ | + | |
- | int (*put)(char, struct __file *); /* function to write one char to device */ | + | |
- | int (*get)(struct __file *); /* function to read one char from device */ | + | |
- | void *udata; /* User defined and accessible data. */ | + | |
- | }; | + | |
- | + | ||
- | #typedef struct __file FILE | + | |
- | + | ||
- | </code> | + | |
- | + | ||
- | Pentru un fișier în care trebuie doar să scriem, nu ne trebuie decât câmpul ''flags'' și câmpul ''put''. ''put'' este un pointer către o funcție care scrie un caracter, iar ''flags'' este un câmp cu flag-uri, printre care există și un flag care spune că putem scrie în fișier, ''__SWR''. Este suficient să faceți o structură cu ''put'' și flags corecte și să pointeze stdout către ea ca să vă meargă ''printf''. | + | |
</note> | </note> | ||
- | </spoiler> | ||
- | |||
- | |||
- | |||
- | |||
- | ==== LCD ==== | ||
- | |||
- | **Task 0 **(xp) | ||
- | Rulați exemplul pentru LCD. | ||
- | |||
- | **Task 1** (xp) | ||
- | Implementați funcțiile LCD_putCharAt și LCD_printAt din bibliotecă. Puteți folosi funcțiile LCD_writeInstr și LCD_writeData. Utilizați funcțiile implementate pentru a afișa un mesaj pe prima linie a LCD-ului. Mesajul trebuie să poată fi deplasat la stânga cu butonul PB2 și la dreapta cu butonul PD6. Limitați deplasarea mesajului astfel încât acesta să nu iasă de pe ecran. | ||
<note tip> | <note tip> | ||
Trebuie să folosiți o instrucțiune a LCD-ului (apelată cu ''LCD_writeInstr'') pentru a poziționa cursorul la poziția dorită, apoi să scrieți datele către LCD (cu ''LCD_writeData''). Codul instrucțiunilor LCD le puteți vedea fie în <tabref instructiuni_lcd>, fie în fișierul ''lcd.h'' prezent în scheletul de laborator. | Trebuie să folosiți o instrucțiune a LCD-ului (apelată cu ''LCD_writeInstr'') pentru a poziționa cursorul la poziția dorită, apoi să scrieți datele către LCD (cu ''LCD_writeData''). Codul instrucțiunilor LCD le puteți vedea fie în <tabref instructiuni_lcd>, fie în fișierul ''lcd.h'' prezent în scheletul de laborator. | ||
</note> | </note> | ||
- | ==== USART ==== | ||
- | <hidden> | ||
- | ------------Exercitii vechi | ||
- | <spoiler>Pentru partea de UART: recomand sa lasam exercitile 0 (relevant pentru ca pe orice placa te vei conecta mai intai cu UART pana sa ai ssh sau mai stiu eu ce), 1 si 2 (faciliteaza ENORM debuggingul). Totusi, la exercitiul 1 haideti sa schimbam formatul cadrelor uart (si baud rate-ul), ca sa nu serveasca din anii trecuti. | ||
+ | **Task 5: **Bonus USART (1p) | ||
+ | Configurați printf astfel încât să printeze direct pe USART0. Refaceți exercițiul 1 folosind printf. | ||
- | 3 ar trebui sa fie scos. | + | ** Tips pentru printf (click to show)** |
- | </spoiler> | + | |
- | + | ||
- | ** Task 0** (1p). Rulați exemplul pentru USART. Pentru configurările serialei, vedeți fisierul ''usart.c'' din schelet. | + | |
- | + | ||
- | ** Task 1** (3p). Configurați //USART0// cu următorii parametri: baud rate 19200, 8 biți de date, 1 bit de stop, paritate pară. Transmiteți către PC câte un mesaj pentru fiecare eveniment de apăsare/lăsare a unui buton (ex: se apasă PB2, se transmite "PB2 apăsat", se lasă PB2, se transmite "PB2 lăsat", **câte o singură dată pe apăsare**). | + | |
- | + | ||
- | <note tip> | + | |
- | + | ||
- | Switch-urile mecanice suferă de un efect numit "bounce". Linia nu va avea o tranziție clară de la 1 la 0 sau invers, ci va oscila un pic (este un efect pur mecanic). Pentru a nu afișa de multiple ori o secvență de apăsat -> lăsat -> apăsat etc. pentru o singură apăsare, trebuie să aplicăm o tehnică de **debouncing**: | + | |
- | * Fie ignorăm orice tranziție după prima pentru o perioadă mică de timp, de ex 10-20ms (varianta simplă) | + | |
- | * Fie măsurăm cât de lung este un puls continuu și luăm o apăsare doar dacă apare pentru mai mult de câteva ms (de exemplu, cu o buclă cu delay de 10ms, dacă am măsurat 0 de 4 ori consecutiv consider că este cu adevărat o apăsare) | + | |
- | + | ||
- | {{ .:lab1:bounce.jpg?400 |}} | + | |
- | </note> | + | |
- | + | ||
- | ** Task 2** (3p). Comandați prin serială generarea de cod Morse folosind buzzer-ul. În scheletul de laborator găsiți variabila morse_alphabet ce conține literele alfabetului în cod Morse. Pe serială veți trimite caractere ASCII litere mici (ex: 'a', 'b', 'c', etc.). Placa va citi caractere de pe serială și va reda semnalul Morse corespunzător de fiecare dată când citește un caracter valid. | + | |
- | + | ||
- | <spoiler>** Task 3 (Bonus)** (1p). Configurați //printf// astfel încât să printeze direct pe //USART0//. Refaceți exercițiul 1 folosind //printf//.</spoiler> | + | |
<spoiler> | <spoiler> | ||
- | ** Tips pentru printf (click to show)** | ||
<note tip> | <note tip> | ||
După cum știți de la programare, printf este echivalent cu fprintf(stdout,... ), cu alte cuvinte, folosește stdout ca fișier în care să scrie. Pentru a putea utiliza printf corect pe AVR, trebuie ca stdout trebuie să pointeze către o **structură validă FILE**. | După cum știți de la programare, printf este echivalent cu fprintf(stdout,... ), cu alte cuvinte, folosește stdout ca fișier în care să scrie. Pentru a putea utiliza printf corect pe AVR, trebuie ca stdout trebuie să pointeze către o **structură validă FILE**. | ||
Line 464: | Line 408: | ||
</note> | </note> | ||
</spoiler> | </spoiler> | ||
- | </hidden> | ||
- | ==== LCD ==== | ||
- | |||
- | <hidden> | ||
- | ----Exercitii vechi | ||
- | <spoiler> | ||
- | Pentru partea de LCD: cred ca 0 si 1 sunt relevante (sa vada cum folosesc un API + ca laburile viitoare vor necesita sa stie sa lucreze cu LCD-ul), deci 0 si 1 ar trebui sa ramana. | ||
- | |||
- | 2 este masturbare intelectuala, nu aduce plus valoare: cum sa transmita pe UART se face in prima parte a laboratorului, cum sa afiseze la exercitile 0 si 1. In conlzie, 2 ar trebui sa fie scos. | ||
- | |||
- | Pe 3 oricum nu il face nimeni si nici nu ii prea vad sensul (daca ne gandim la scopul laboratorului). Si 3 ar trebui sa fie scos. | ||
- | </spoiler> | ||
- | |||
- | **Task 0** (0p). Rulați exemplul pentru LCD. | ||
- | |||
- | **Task 1** (3p). Implementați funcțiile //LCD_putCharAt// și //LCD_printAt// din bibliotecă. Puteți folosi funcțiile //LCD_writeInstr// și //LCD_writeData//. Utilizați funcțiile implementate pentru a afișa un mesaj pe prima linie a LCD-ului. Mesajul trebuie să poată fi deplasat la stânga cu butonul PB2 și la dreapta cu butonul PD6. Limitați deplasarea mesajului astfel încât acesta să nu iasă de pe ecran. | ||
- | |||
- | <note tip> Trebuie să folosiți o instrucțiune a LCD-ului (apelată cu ''LCD_writeInstr'') pentru a poziționa cursorul la poziția dorită, apoi să scrieți datele către LCD (cu ''LCD_writeData''). Codul instrucțiunilor LCD le puteți vedea fie în <tabref instructiuni_lcd>, fie în fișierul ''lcd.h'' prezent în scheletul de laborator. | ||
- | </note> | ||
- | |||
- | |||
- | <spoiler>**Task 2** (2p). Afișați pe ecranul LCD-ului caracterele primite pe interfața seriala USART0. Utilizați ambele linii ale ecranului astfel: afișați caracterele secvențial, pe prima linie, apoi pe linia a doua, și reveniți la prima linie suprascriind vechile caractere în momentul umplerii ecranului. | ||
- | |||
- | **Task 3 (Bonus)** (2p + bragging rights). Implementați și afișati caracterul custom din <imgref lcd_chuck>. Inițial Chuck se află pe linia de jos a LCD-ului. El trebuie să poată fi mutat cu o poziție la stânga/dreapta pentru fiecare apasare a butoanelor PB2/PD6. Cât timp ambele butoane sunt apăsate, Chuck își va folosi puterea specială și se va muta pe aceeași coloană a liniei de sus. | ||
- | |||
- | <imgcaption lcd_chuck center | Courageous Chuck>{{.:lab1:lcd_chuck.png|}}</imgcaption> | ||
- | </spoiler> | ||
- | </hidden> | ||
===== 5. Resurse ===== | ===== 5. Resurse ===== | ||
- | * {{.:lab1:lab1_skel.zip | Schelet laborator}} | + | * {{:pm:lab:lab1_skel2020.zip | Schelet laborator}} |
<hidden> * {{.:lab1:lcd_schema.zip| Schemă simulare}} ({{.:lab1:lcd_schema_2012.zip| varianta 2012}}, cu ATmega16, pentru versiunile de Proteus vechi)</hidden> | <hidden> * {{.:lab1:lcd_schema.zip| Schemă simulare}} ({{.:lab1:lcd_schema_2012.zip| varianta 2012}}, cu ATmega16, pentru versiunile de Proteus vechi)</hidden> | ||
* {{.:lab1:hd44780_datasheet.pdf| Datasheet Hitachi 44780}} | * {{.:lab1:hd44780_datasheet.pdf| Datasheet Hitachi 44780}} | ||
* {{:pm:doc8272.pdf | Datasheet ATmega324}} | * {{:pm:doc8272.pdf | Datasheet ATmega324}} | ||
+ | * {{https://cache.amobbs.com/bbs_upload782111/files_22/ourdev_508497.html | AVR Baud Rate Tables}} | ||
<hidden> * <html><a class="media mediafile mf_pdf" href="/wiki/pm/lab/lab1?do=export_pdf">PDF laborator</a></html></hidden> | <hidden> * <html><a class="media mediafile mf_pdf" href="/wiki/pm/lab/lab1?do=export_pdf">PDF laborator</a></html></hidden> | ||
* Responsabili: [[dorin_marian.ionita@cs.pub.ro | Dorin Ionita]] [[ Ana Dragan ]] | * Responsabili: [[dorin_marian.ionita@cs.pub.ro | Dorin Ionita]] [[ Ana Dragan ]] | ||