ccs c delay_ms(gecikme); sorunu

SALIH-46

Üye
Katılım
20 Mar 2008
Mesajlar
47
Puanları
1
Yaş
39
Merhaba
Arkadaşlar aşağıda verilen kodda gecikme zamanını 3 den büyük seçtiğimde program sonsuz döngüye giriyor ve kod çalışmıyor ama 3 ve altında sorun yok benim ise gecikmeyi 10 alma gerek yardımcı olursanız sevinirim.

#INCLUDE <16f877a.H>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#USE DELAY (CLOCK=4000000)
/////////////////////////////////////////////////////////
#define LCD_DATA_PORT getenv("SFR:pORTD")
#define LCD_ENABLE_PIN PIN_E0 ////
#define LCD_RS_PIN PIN_E2 ////
#define LCD_RW_PIN PIN_E1 ////
#define LCD_DATA0 PIN_D7 ////
#define LCD_DATA1 PIN_D6 ////
#define LCD_DATA2 PIN_D5 ////
#define LCD_DATA3 PIN_D4
#INCLUDE <LCD.c>
///////////////////////////////////////////////////////////
#use fast_io (a)
#use fast_io (b)
#use fast_io (d)
#use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7,stop=1,parity=n)
//
unsigned int8 i=0,yon=0,j=0,l=0,karar=0,gecikme=3;
unsigned int16 puls=0;
byte data[3];

#define set_point data[2]
#define Kp data[0]
#define Ki data[1]

const int tamsag[4]={0b00001001,0b00001100,0b00000110,0b00000011};
const int tamsol[4]={0b00000011,0b00000110,0b00001100,0b00001001};
//const int tablotam[]={0b00000111,0b00000011,0b00001011,0b00001001,0b00001101,0b00001100,0b00001110,0b00000110};
//const int tabloters[]={0b00000110,0b00001110,0b00001100,0b00001101,0b00001001,0b00001011,0b00000011,0b00000111};
///////////////////////////
#int_rda
rda_kesmesi()
{
disable_interrupts(int_rda);

///////////////////////////////////
for(i=0;i<3;i++)
{
data=getc();
}
///
if(input(pin_a0)==1)
{
printf(lcd_putc,"\fKp=%u Ki=%u\nset=%u",Kp,Ki,set_point);
}
//////////////////////////
///////////////////////////////////////
if(input(pin_a0)==0)
{
puls=make16(data[1],data[0]);
set_pwm1_duty(data[2]);
printf(lcd_putc,"\fhiz = %ld d/d\npwm: %u %d",puls,data[2],j);
/////////////////////////////////
yon=input_b()&0b11100000;
if(j==0b01000000)
{
j=33;
}
if(yon==0b11000000)
{
for(i=0;i<4;i++)
{
output_b(tamsol);
delay_ms(gecikme);
}
j=0;
}
//
if(yon==0b01100000)
{
for(i=0;i<4;i++)
{
output_b(tamsag);
delay_ms(gecikme);
}
j=1;
}
//
if(yon==0b00000000)
{
if(j==0)
{
for(i=0;i<4;i++)
{
output_b(tamsol);
delay_ms(gecikme);
}
}
if(j==1)
{
for(i=0;i<4;i++)
{
output_b(tamsag);
delay_ms(gecikme);
}
}
output_high(pin_a1);
output_low(pin_a1);
}
////////////////////////////////

}
//printf("%c",j);
}
/////////////////////////////////////


//////////////////////////////////
void main()
{
set_tris_a(0x01);
output_a(0x00);
set_tris_b(0xf0);
output_b(0x00);
setup_ccp1(ccp_pwm);
setup_timer_2(t2_div_by_16,255,1); //bu şekilde pwm frekansı yaklaşık 250Hz çözünürlük 255
set_pwm1_duty(0);
enable_interrupts(int_rda);
enable_interrupts(global);
lcd_init();
printf(lcd_putc,"\fPI DENETIM");
while(1)
{
enable_interrupts(int_rda);//dfghjk

}
}
 
Hata gecikme fonksiyonundan değil başka bir yerden kaynaklanmaktadır.

Kural olarak kesme rutini içerisinde fonksiyon kullanmak beklenmedik hatalara neden olabilir. En basit örneği: ana programında lcd ekrana birşeyler yazdırıyorsun. 4 stack alanı kullanır bu yazdırma işlemi. Tam 4. stack kullanılırken seri porttan bilgi geldi ve kesmeye gittin. 5. stağı kullanmış oldun. ISR içerisinde tekrar lcd ekrana yazdırma işlemi yapıyorsun. 4 stack ta o götürdüğünden toplam 9 alan kullanıyorsun. 877 de 8 tane alan vardı. 9. stack olmadığı için döner ilk başa yazar. Bu da bir daha ana programa dönmeyeceğin anlamına gelir. ana programa dönmek istediğinde gideceğin yer lcd rutininde son stackı kullanan fonksiyon olur.


#int_rda
rda_kesmesi()
{
disable_interrupts(int_rda);

kesme içerisinde tekrar kesmeyi disable etmenin anlamı yok zaten kesmeye gider gitmez gie disable edilir. Portu okuduğunda flagi otomatik olarak sıırlanır. ana programa döndüğünde de kesmeyi enable etmene gerek yok çünkü kesmeden dönüş her zaman retie komutuyladır ve bu otomatik olarak gie yi enable eder.

Programında kesmeyi kullanmana gerek yok. Kesmeye gidişinde senin görmediğin bir çok işlem yapıldığı için gereksiz yere zaman kaybı olur. Onun yerine kemse içerisindeki algoritmayı ana programda ana döngü içerisinde
if(kbhit()) { buraya ekleyebilirsin.}
 
Hocam cevabınız için teşekkür ederim
Hocam yığın bellekten kaynaklanıyor demişsiniz ama o ana menüde olan lcd'ye yazma işleminden olacağını zannetmiyorum çünkü 3sn bekledikten sonra diğer 877a dan seri bilgiler gönderilmeye başlıyor ve kesme alt programına gelince yığın bellekten bir tane kullansa geriye 7 tane kalıyor ve eğer lcd'ye yazma içinde 4 tane kullanılsa bile ve diğer fonksiyonlar olan getc() komutu filan hepsi bir alt programa gidip işlem yapıp dönüyorlarsa vede ilk giren son çıkacaksa her alt programın bitişinde yığın bellekte ne kadar yer kaplandıysa o kadarda boşalma olacaktır ama şunu bilmiyorum acaba bir lcd ye yazma işleminde, seri porttan bir okuma yapma işleminde veya 10ms lik bir gecikme işleminde yığın bellekte bu işlemler ne kadar yer kaplıyor bunu bilmediğim için yani arka tarafta ne olup bittiğini bilmediğim için bir şey diyemiyorum kafamı karıştıran konu ise niye 1,2 ve 3ms de kod düzgün bir şekilde çalışırken 4,5,..10ms gibi değerlerde düzgün çalışmıyor bunun nedeni gecikme alt programlarının yığın bellekte kapladıkları alanların farklılığından olabilirmi acaba
 
9600 bps ile bir bilgi yaklaşık 1 ms de gelir.

Senin portuna gönderilen sayıların gönderimi arasında ne kadar zaman farkı var bilmiyorum. Eğer 4 ms. de bir gönderiyorsan, kesme rutininden çıkmadan diğer bilgi gelir, eğer üstüste iki bilgi gelmiş ve bufferdan okutamamış isen overrun hatası ile karşılaşırsın.

Kesme rutininden ayır o algoritmayı ve kbhit() fonksiyonu ile seri bilgi gelip gelmediğini kontrol et (ana programdaki sonsuz döngü içerisinde).

Ayrıca yazdığın yazılımı Proteus ISIS üzerinde debug edebilirsin. Seri porta başka bir mcu dan bilgi gönderiliyorsa onu da aynı anda debug edebilirsin ISIS'te. Her iki mikrokontrolör için ayrı watch windowlar açabilirsin. Hangi mcu nerede takılıyor rahatlıkla görebilirsin.

Son bir not, algoritma açısından değil ama yazım ve kullanılan fonksiyonlar ve teknik açısından programa orta-ileri arası seviyede bir profesyonel eli değmiş. İleri düzey diyemiyorum çünkü bariz 2 hata yapmış, onları da yukarıda yazdım. Profesyonel yazılımcı arada bir program listingine, derleme sonucu raporuna bakmalı, donanım hakkında da bilgi sahibi olmalıdır. Örneğin, kesmeye gidip ilk program adımını işletinceye kadar yapılan ara işlemleri ve bunlar için geçen zamanı görmeli, bunlara değer mi diyebilmelidir.

Programı tamamen siz yazmışsanız sizi tebrik ederim.
 
Son düzenleme:
Hocam ilginiz için teşekkür ederim
Hocam size tam olarak ne yapmak istediğimi anlatayım ilk önce
Hocam pi denetimini kullanarak hız deneteimli bir çizgi izleyen robot yapmaya çalışıyorum ve bunu isisde de simülasyonunu yapıyorum ve sizin tavsiyeniz üzerine interrupt işlemini iptal ederek kbhit()' kullanıyorum ama yine bir yerde delay_ms(gecikme); burdaki gecikme değeri 50'yi geçersen yine proram biryerde takılıyor...
hocam iki ayrı kod bloğu aşağıda ve bir tane de ortak anahtar var bu anahtar 1 konumundayken pi için kp, ki ve set değerleri alınıyor seri olarak diğer 877a ya gönderiliyor ve lcd de görüntüleniyor anahtar 0 konumundayken ise budefa kp, ki ve set değerleri için pi işlemi yapılıyor ve yine burdada hız bilgisi ve pwm sayısı seri olarak diğer 877a ya gönderiliyor ve işlem bu şekilde devam ederken step motoru için "delay_ms(gecikme)" işlemi içinde bu defa 10 ms olsada sorun yok kod çalışıyor ama 50ms geçerse yine kod çalışmıyor neyse hocam forma resim yüklemesini bilmediğim için isisdeki şemayı yükleyemiyorum ama ko blogları aşagıda
ve birde hocam bu "int_rda" kesmesi için Serdar ÇİÇEK'in kitabında bu kesme için böyle işlem yapılması gerektiği yazıyor o nedenle eklemiştim o kodu

pi ilem kodu
************************************************
#INCLUDE <16F877A.H>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#device adc=10
#INCLUDE <math.h>
#USE DELAY (CLOCK=4000000)
#use rs232(baud=600,xmit=pin_c6,rcv=pin_c7,stop=1,parity=n)
#use fast_io (a)
#use fast_io (d)
float pre_out=0,out=0,error=0,pre_error=0,set_point=0,integral=0;
unsigned int8 i,Kp,Ki;
char j;
signed int16 dout=0;
byte deger[4]; //set=deger[0], Kp=deger[1], Ki=deger[2]
//#define set_point deger[2]
//#define Kp deger[0]
//#define Ki deger[1]
#byte tmr1l= 0x0e
#byte tmr1h =0x0f

/////////////////////////////////////////
#int_timer0
void timer_kesme0()
{
error=set_point-get_timer1(); //hata bulunuyor
//out=pre_out+Kp*(error-pre_error)+Ki*((error+pre_error)/2);
integral=integral+((error+pre_error)/2)*0.051; //integral işlemi
out=Kp*error+Ki*integral; //çıkış
//
if(out>255)
{
dout=255;
}
if (out<0)
{
dout=0;
}
else
{
dout=floor(out);
}
//pre_out=out;
printf("%c",tmr1l);
printf("%c",tmr1h);
printf("%c",dout);
pre_error=error;
j=getc();
set_timer0(60);
set_timer1(0);
}
//
/////////////////////////////////////
void main()
{
set_tris_a(0xff);
set_tris_d(0x80);
output_d(0x00);
setup_adc(adc_clock_div_32);
setup_adc_ports( AN0_AN1_AN2_AN3_AN4 );// BU AYARLAR İÇİN C/PİCC/DEVİCES/877A KLASÖRÜNÜN İÇİNE BAK
setup_timer_1(t1_div_by_1|t1_external); //encoder pulsleri sayılıyor
DELAY_MS(2000);
while(1)
{
while(input(pin_d7)==1)
{
disable_interrupts(int_timer0);
for(i=0;i<3;i++)
{
set_adc_channel(i);
delay_us(100);
deger=read_adc();// 2>>set_point, 0>>Kp, 1>>Ki
printf("%c",deger);
delay_ms(10);
}
delay_ms(100);
Kp=deger[0];
Ki=deger[1];
set_point=deger[2];
}
while(input(pin_d7)==0)
{
setup_timer_0(rtcc_internal|rtcc_div_256);//timer0 kuruldu
enable_interrupts(int_timer0);
enable_interrupts(global);
set_timer1(0);
set_timer0(60);//kesme süresi 50ms
while(input(pin_d7)==0);

}}}

step motor_pwm ve lcd************************************
#INCLUDE <16f877a.H>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#USE DELAY (CLOCK=4000000)
/////////////////////////////////////////////////////////
#define LCD_DATA_PORT getenv("SFR:pORTD")
#define LCD_ENABLE_PIN PIN_E0 ////
#define LCD_RS_PIN PIN_E2 ////
#define LCD_RW_PIN PIN_E1 ////
#define LCD_DATA0 PIN_D7 ////
#define LCD_DATA1 PIN_D6 ////
#define LCD_DATA2 PIN_D5 ////
#define LCD_DATA3 PIN_D4
#INCLUDE <LCD.c>
///////////////////////////////////////////////////////////
#use fast_io (a)
#use fast_io (b)
#use rs232(baud=600,xmit=pin_c6,rcv=pin_c7,stop=1,parity=n)
//
unsigned int8 i=0,yon=0,j=0,l=0,karar=0,gecikme=10;
unsigned int16 puls=0;
byte data[3];

#define set_point data[2]
#define Kp data[0]
#define Ki data[1]

const int tamsag[]={0b00001001,0b00001100,0b00000110,0b00000011};
const int tamsol[]={0b00000011,0b00000110,0b00001100,0b00001001};
//const int tablotam[]={0b00000111,0b00000011,0b00001011,0b00001001,0b00001101,0b00001100,0b00001110,0b00000110};
//const int tabloters[]={0b00000110,0b00001110,0b00001100,0b00001101,0b00001001,0b00001011,0b00000011,0b00000111};
//////////////////////////////////
void main()
{
set_tris_a(0x01);
output_a(0x00);
set_tris_b(0xf0);
output_b(0x00);
setup_ccp1(ccp_pwm);
setup_timer_2(t2_div_by_16,255,1); //bu şekilde pwm frekansı yaklaşık 250Hz çözünürlük 255
set_pwm1_duty(0);
lcd_init();
printf(lcd_putc,"\fPI DENETIM");
while(1)
{
///////////////////////////////////////////////////
while(input(pin_a0)==1)
{
if(kbhit())
{
for(i=0;i<3;i++)
{
data=getc();
}
printf(lcd_putc,"\fKp=%u Ki=%u\nset=%u",Kp,Ki,set_point);
}
}
//////////////////////////////////////////////////
///////////////////////////////////////
while(input(pin_a0)==0)
{
if(kbhit())
{
for(i=0;i<3;i++)
{
data=getc();
}
puls=make16(data[1],data[0]);
set_pwm1_duty(data[2]);
printf(lcd_putc,"\fhiz=%ldd/d\npwm:%u",puls,data[2]);
/////////////////////////////////
yon=input_b()&0b11100000;
switch (yon)
{
case 0b01000000:break;
//
case 0b11000000:
for(i=0;i<4;i++)
{
output_b(tamsag);
delay_ms(gecikme);
}
break;
//
case 0b01100000:
for(i=0;i<4;i++)
{
output_b(tamsol);
delay_ms(gecikme);
}
}
////////////////////////////////
printf("%c",j);
}
}
}
}

**************************************************
 
Size özel mesaj attım.

programınızda exp, log, sin, cos vs gibi, tablolarla çözülemeyecek hesaplar içermedikçe programlarınızda floating point aritmetikten kaçının. Aynı veya yakın hassasiyette integer aritmetiği ile işlem yapabilirsiniz ve işleminiz daha hızlı yapılır.
 

Forum istatistikleri

Konular
128,198
Mesajlar
915,767
Kullanıcılar
449,979
Son üye
schule48

Yeni konular

Geri
Üst