atmel atmega32 programlama c kodları yardım edebilecek ?

Başlatan akbey, 30 Mart 2012, 13:22:00

akbey

merhaba arkadaşlar elimde bir proje var tansiyon ölçme aleti yapmaya çalışıyorum.atmel için hazırlanmış avr ile derlenmiş c kodları var fakat ben bu kodları css c pic diline çevirmek istiyorum  programın bir bölümünü anlamadım kesmeler ile ilgili bir bölüm. bu kodlarla neyi amaçlamış onu anlatabilir misiniz yardımcı olursanız çok sevinirim.

//timer 0 compare ISR
interrupt [TIM0_COMP] void timer0_compare(void)
{
   if(~PINB & 0x01) timepress0++; // 00000001   portb  nin birinci biti 1 mi eğer 1 ise bir sonrakini icra et
   if(~PINB & 0x02) timepress1++;  //00000010   portb nin ikinci biti  eğer 1 ise bir sonrakini icra et
   if(~PINB & 0x04) timepress2++;  //00000100   portb nin üçüncü biti  eğer 1 ise bir sonrakini icra et
   timecount++;                      
   timedeflate++;
    //Decrement each time tast if they are not already zero
    
    //timing for sampling data at every 40 msec timing her 40 ms de örnekleme verileri için
 	if(timing>0) --timing; 
 	//-----------------------------------------------------
	 //run time for different tasks  farklı görevler için çalışma zamanı
 
 	//run timerate for measuring heart rate kalp hızı ölçmek için timerate çalıştırabilir
	 if(timerate<6000) ++timerate;
 
	 //run timerun_dias   timerun_dias ı çalıştır
	 if(timerun_dias<2000) ++timerun_dias;
 
   //if(countlcd) timelcd++; 
   
    //run time for the display   ekran için çalışma zamanı
    if(timedisplay<2000) ++timedisplay;   
}

//***********************************************
// ADC Interrupt
//**********************************************************

interrupt [ADC_INT] void adc_complete(void)
{ 
 data = ADCH;
 //then calculate adc_data into float; ondalıklı analog veriyi hesapla
    adc_data = (float)(((float)data)/256*Vref);
    
 
 //if signal is above threshold, go to calculate systolic pressure sinyal eşiğin üzerinde ise, sistolik basıncı hesaplamak için gidin
 if(meas_state ==Sys_Measure)
 	{   
	   
 	   if(former<=TH_sys && adc_data>TH_sys)
 	    sys_count++;        
 	    
 	   former = adc_data;            
	    
 	   
 	   
    }
 //-----------------------------------------------------------
 else if(meas_state==Sys_Cal)
 	{ 
 	
 	  if(count<4)
 	  {
 	   accum_data=accum_data+adc_data;
 	   count++;
 	  }
 	  if(count==4)
 	  {
 	  press_data=accum_data/4;
 	  systolic = (press_data/DC_gain)*9375;//calculate from adc_data
 	  meas_state = Rate_Measure; 
 	  countpulse=0;
 	  former = 2.4; //set the initial point for rate measuring
 	  count_average=0;
 	  }
 	}
 //----------------------------------------------------------
 	
 else if(meas_state==Rate_Measure)
 {
 	if(count_average<5)
 	{
 	
 	 if(former<TH_rate && adc_data>TH_rate && countpulse==0)
 	 	{
 	    timerate=0;
 	    countpulse=1;
 	    former=adc_data;
 	    }
 	    
 	 if(former<TH_rate && adc_data>TH_rate && countpulse==1)
 	    {	    
 	    total_pulse_period=total_pulse_period+timerate; 
 	    timerate=0;
 	    count_average++; //finish reading one period  
 	    }
 	  
 	 }//count_average 
 	 
 	 former=adc_data;
 	 
}// else if(meas_state=Rate_Measure)
//-------------------------------------------------------------
else if(meas_state==dias_Measure)
{
   	if(timerun_dias<2000)
   		{
    	if(adc_data>TH_dias)
    	{ timerun_dias=0; //reset time if the signal 
    	//is still greater than threshold (so it will never reach 1999)
    	//if it doesn't reset,the time will stuck at 1999
    	lcd_clear();
		lcd_gotoxy(0,0);
		lcd_putsf("Dias measure");   
		}
   		}
   	if(timerun_dias>=2000)
   		{  
   		meas_state = dias_Cal;//if done go back to Sys_Measure to be ready for next opt
   		} 
    
}
//------------------------------------------------------------- 
else if(meas_state==dias_Cal)
{     
      diastolic = (adc_data/DC_gain)*9375;//calculate from adc_data
 	  meas_state = Sys_Measure; 
 	  currentState = displayState;  
 	  //open valve
 	  PORTD=0;
 	
}

 timing = 40;//set time for another conversion
 
}

arm-beginner

Interrupt içinde birkaç satır yazılır; uzun süren işler için bir flag set edilir ve onun ile ilgili çalışmalar main-loop'da yapılır.
Bu gönderdiğin kodlarda birileri interrupt içinde roman yazmış; üstelik bu yetmiyormuş gibi birde float kullanmış.
Bence bu kodları hiç dikkate alma ve kendin bildiğin gibi programı yaz veya yazmaya çalış.



akbey

Alıntı YapInterrupt içinde birkaç satır yazılır; uzun süren işler için bir flag set edilir ve onun ile ilgili çalışmalar main-loop'da yapılır.
Bu gönderdiğin kodlarda birileri interrupt içinde roman yazmış; üstelik bu yetmiyormuş gibi birde float kullanmış.
Bence bu kodları hiç dikkate alma ve kendin bildiğin gibi programı yaz veya yazmaya çalış.



kendim yazıcam zaten  algoritmayı çıkarmaya çalışıyorum tüm kodlardan çözemediğim bir burası kaldı. burada ne yapmaya çalışmış onu anlayamadım hani mantığı anlasam kendim o mantıkta yazıcam kodları.

internetten de baktım yabancı kaynaklardan da baktım
//timer 0 compare ISR  
interrupt [TIM0_COMP]


böyle bir kesme var mı veya ne yapılmaya çalışılmış çözemedim veya bu kesmenin pic deki karşılığı nedir konu ile ilgili bilgisi olan arkadaşlar lütfen yardımcı olabilir mi ?

arm-beginner

Öyle bir interrupt CodeVision compiler kullanıyor.
GCC compiler bunun için ISR (TIMER0_COMPA_vect) gibi bir şey kullanıyor. Kullandığın işlemciye göre değişiyor.

ilhan_mkp

http://students.iitk.ac.in/eclub/old/lectures/MCU2.pdf
hocam bu linkteki pdfnin üçüncü sayfasına bakın belki bişiler çözersiniz ben c bilmiyorum
bu dökümanı aarken buldum datasheete timer counter bölümündede açıklamalar var

bocek

hocam burda 1. interrupt timer0 compare interruptı
timer0'ın sayacı olan 8 bitlik TCNT0 (Timer CouNTer0) değeri, OCR0 (Output Compare Register0) registerinde yazan değere eşit olduğunda bu interrupt üretilir. TCNT0 8 bit olduğundan her 255'ten sonra sıfırlayacak ve her OCR0'a eşit oluşunda bu interrupt oluşacaktır.
bu TCNT0 ve OCR0'ın programın init kısmında değerlerinin belirtiliyor olması lazım.

diğer interrupt fonksiyonu ise zaten malum ADC çevrimi bittiğinde oluşan interrupt fonksiyonu.
programın bir yerlerinde adc çevrimi başlatılıyor. bittiğinde de bu fonksiyona dallanıp, ADCH ile sadece HIGH byte'i okuyor, çünkü 8 bit çözünürlük yeterli diye düşünülüyor. 10 bit'e ihtiyacı olsaydı ADCL'yi de okuyup ikisini birleştirecekti. buna gerek duymamış.
detayları atmega32'nin datasheet 76. sayfasında bulabilirsin..

PIC'te bu işler nasıl yapılıyor burdan yola çıkarak bulabilirsin sanırım.
1 ya da 0. işte 'bit'ün mesele..

arm-beginner

".... ADCH ile sadece HIGH byte'i okuyor, çünkü 8 bit çözünürlük yeterli diye düşünülüyor. 10 bit'e ihtiyacı olsaydı ADCL'yi de okuyup ikisini birleştirecekti. buna gerek duymamış."
ADMUX register:
ADLAR - Left adjust result

bocek

armbeginner ne demek istedin anlamadım?

atmega32 datasheet 220. sayfa:
Alıntı Yap
The ADC generates a 10-bit result which is presented in the ADC Data Registers, ADCH and
ADCL. By default, the result is presented right adjusted, but can optionally be presented left
adjusted by setting the ADLAR bit in ADMUX.
If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data
Registers belongs to the same conversion...

Türkçesi:
"ADC, ADCH ve ADCL registerlerinde saklanan 10-bitlik bir sonuç üretir. ADLAR biti 1 ise sonuc (normalde sağa yaslı olan) ADC registerine sola dayalı olarak yazılır. ADLAR biti 1 iken, sonuç için 8-bit çözünürlük yeterliyse ADCH'yi okumak yeterlidir. 8-bit yeterli değilse önce ADCL okunmalı, ardından ADCH okunmalıdır ki her ikisinin de aynı çevrime sahip sonuçlar olduğundan emin olunsun..."

yalnız winavr'de şöyle bir kolaylık var:
sonuc = ADC;
dediğimiz zaman derleyici bizim yerimize ADCL ve ADCH'yi sırayla okuyup birleştirip sonucu verir.
1 ya da 0. işte 'bit'ün mesele..