Jump to content
ELFORUM - Forumul electronistilor

Setare timer 16bit pentru intrerupere overflow


Guest rapo

Recommended Posts

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 to comment
Share on other sites

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 to comment
Share on other sites

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 to comment
Share on other sites

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 to comment
Share on other sites

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 to comment
Share on other sites

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 to comment
Share on other sites

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 to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines