Vizitator rapo Postat Septembrie 20, 2010 Partajează Postat Septembrie 20, 2010 Buna ziua, Am o placa care teoretic trebuie sa preia date prin ADC de la cativa senzori de temperatura. Am facut o interfata in C# care comunica serial cu placa, in momentul in care dau Open Port(din PC), trimit numarul de senzori si perioada de esantionare din PC la placa, pe portul serial, perioada fiind perioada de timp in care placa trebuie sa faca achizitia si sa-mi trimita inapoi valorile senzorilor,senzori care pot avea nr variabil (de la 1 la 5, in functie de cati selectez eu, din PC). Pentru a realiza perioada de esantionare am folosit timer-ul de 16bit de la Atmega16, care functioneaza la 16 Mhz. Teoretic perioadele de esantionare ar fi multipli de un minut(60 sec,300 sec,600 sec, 1800 sec,3600 sec), am facut o initializare a timerului dar nu functioneaza corect. Daca poate cineva sa arunce un ochi peste cod si sa-mi dea cateva sfaturi.... ISR(TIMER1_OVF_vect) //Intrerupere odata la 5 secunde{ static uint16_t tick; TCNT1 = 0xffff - 0xC350;//overflow la 5 sec la 16 Mhz tick++; if( (tick % 12 == 0) && (per_esant == 0) ) ///per_esant = perioada de esantionare codata de la (0 la la 4; 0->60 secunde, 1->300,etc) { flag_interr = 1; tick = 0; } if( (tick % 60 == 0) && (per_esant == 1) ) //per esant stabilita la 300 de secunde { flag_interr = 1; tick = 0; } if( (tick % 120 == 0) && (per_esant == 2) ) { flag_interr = 1; tick = 0; } if( (tick % 360 == 0) && (per_esant == 3) ) { flag_interr = 1; tick = 0; } if( (tick % 720 == 0) && (per_esant == 4) ) { flag_interr = 1; tick = 0; }}ISR(USART_RXC_vect) { // USART RX interrupt char_recv = UDR; if(char_recv<5) {per_esant=char_recv;} else {nr_senzori = char_recv;} flag_recv=1;}void initializare_timer(){ TCCR1B = (1<<CS11)|(1<<CS10);//prescale 64 TIMSK = (1<<TOIE1);//enable ovf1 interrupt TCNT1 = 0xffff - 0xC350;//seteaza valoarea pt intrerupere la 5 secunde pt 16 Mhz}while(1) { if(flag_recv) //aici verific daca am primit numarul de senzori si per de esantionare de la PC { //daca da, dezactivez intreruperea pe uart pt receive si pun flag-ul de continuare a programului pe 1(flag_ok) flag_recv=0; flag_ok=1; UCSRB |= (0 << RXCIE); } if(flag_ok) { //pornesc timerul initializare_timer(); if(flag_interr) {//numarul de senzori este cuprins intre 5 si 9( 5 -> un senzori, 6-> 2 senzori,etc) for(cont=5;cont<=nr_senzori;cont++) { preluare_date(cont); _delay_ms(200); send_UART(preluare_senzor); } flag_interr =0 } } ADC_off(); return 0;} Problema e ca nu pot verifica foarte corect ce se intampla ca nu am un programator JTAG sa folosesc debugger si pe PC nu prea pot detecta corect ce se intampla. Precizez ca folosesc Atmega16 @ 16Mhz, de la PC trimit la initializare 2 date; perioada de esantionare(0 si 4) si nr de senzori(5 si 9), trimiterea de date de la PC la placa facandu-se doar cand deschid portul pt comunicare dupa aceea nu ma mai intereseaza sa primesc nimic de pe PC doar sa transmit valorile senzorilor la perioada stabilita. Link spre comentariu
10vid Postat Septembrie 24, 2010 Partajează Postat Septembrie 24, 2010 TCNT1 = 0xffff - 0xC350;//overflow la 5 sec la 16 Mhz Cred ca ar trebui sa folosesti o combinatie de prescaler si o valoare de inceput a timerului astfel incat sa-ti dea macar 1s, iar apoi din soft sa repete numaratoarea de 5 ori pentru 5s. TCNT1 numara pana la 16,000,000 in 1s fara prescaler. Ce ai dat tu e overflow dupa 0.003s. Link spre comentariu
Vizitator rapo Postat Septembrie 27, 2010 Partajează Postat Septembrie 27, 2010 Am rezolvat problema, am modificat codul initializarii timer-ului void initializare_timer(){ TCCR1B |= (1<<CS12) |(1<<CS10); //prescale 1024 TIMSK |= (1<<OCIE1A); //enable ovf1 interrupt TCNT1 = 0x0000; OCR1A = 0x7A12; //intrerupere la 2 secunde sei();}dar am intampinat o alta problema: ISR(TIMER1_COMPA_vect){ tick++; switch(temp_sens) { case 0: { if(tick == 60) { flag_interr = 1; tick = 0; } break; } case 1: { if(tick == 300) { flag_interr = 1; tick = 0; } break; } case 2: { if(tick == 600) { flag_interr = 1; tick = 0; } break; } case 3: { if(tick == 1800) { flag_interr = 1; tick = 0; } break; } case 4: { if(tick == 3600) { flag_interr = 1; tick = 0; } break; } }}main(){.... if(flag_interr) { send_UART('a'); flag_interr =0; }} Variabila flag_interr este declarata: volatile uint8_t flag_interr=0; Nu-mi dau seama,de ce nu imi valideaza if-ul respectiv,cand flagul va fi setat pe 1 din intrerupere. Timer-ul functioneaza, l-am testat separat. Link spre comentariu
10vid Postat Septembrie 27, 2010 Partajează Postat Septembrie 27, 2010 Doar incarcand OCR1A cu o valoare nu inseamna ca uC va face ceva cu ea. Timer-ul are enshpe moduri de functionare vezi tabelul de la pagina 112 in datasheet. Va trebui sa alegi modul CTC (Clear Timer on Compare match) avand ca valoare de top OCR1A. Astfel, bitul WGM12 din TCCR1B va trebui sa fie setat. Link spre comentariu
Vizitator rapo Postat Septembrie 28, 2010 Partajează Postat Septembrie 28, 2010 Da,am copiat prost functia de init, il am setat si nu merge... Link spre comentariu
godFather89 Postat Septembrie 28, 2010 Partajează Postat Septembrie 28, 2010 flag_interr e setat ca volatile?LE: nu am observat ca ai mentionat asta. Cum ai verificat timerul separat? Link spre comentariu
Vizitator rapo Postat Septembrie 28, 2010 Partajează Postat Septembrie 28, 2010 Da, e volatile. Am verificat timer-ul intr-un alt proiect, l-am pus sa-mi numere din secunda in secunda si sa-mi afiseze pe ecran. Chestia e ca nu stiu de ce o chestie de genul acesta: if(tick == 60) {...} nu funtioneaza in intrerupere, niciodata if-ul acesta nu e adevarat, ce functie sa mai incerc sa fac o comparatie intre 2 int-uri? Link spre comentariu
10vid Postat Septembrie 29, 2010 Partajează Postat Septembrie 29, 2010 Poate ai vrut asa: ISR(TIMER1_COMPA_vect){ tick++; switch(tick) { case 30: { tick = 0; flag_interr = 1; } break; } case 150: { tick = 0; flag_interr = 1; } break; } ...............s.a.m.d......................... Link spre comentariu
nana Postat Septembrie 29, 2010 Partajează Postat Septembrie 29, 2010 Poate ai vrut asa: ISR(TIMER1_COMPA_vect){ tick++; switch(tick) { case 30: { tick = 0; flag_interr = 1; } break; } case 150: { tick = 0; flag_interr = 1; } break; } ...............s.a.m.d......................... Eu nu cred ca a vrut asa pentru ca se executa doar primul case 30: ... pentru ca defiecare data restarteaza valoarea counter-ului tick=0; si reia incrementarea. Link spre comentariu
Vizitator 3Nigma Postat Septembrie 29, 2010 Partajează Postat Septembrie 29, 2010 Este întradevăr curios.Poți să postezi întregul proiect curent ca să ne dăm seama mai bine unde clachează? Dacă nu este prea mare . 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