Sari la conținut
ELFORUM - Forumul electronistilor

Setare timer 16bit pentru intrerupere overflow


Vizitator rapo

Postări Recomandate

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
  • Răspunsuri 9
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • 10vid

    3

  • nana

    1

  • godFather89

    1

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

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

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

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

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

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

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



×
×
  • 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