bu hi tech c de kesmeler nasıl oluyor.cok araştırdım ama bir türlü işin içinden çıkamadım acaba basitçe biraz bilgi verebilecek hocalarımdan yardım bekliyorum.
bu kesmeler 877 de olmadan programlar bir sürü döngü ile oluyor ve bu da boşuna hafızaydolduyor ve ben de istediğim kadar özellik kullanamıyorum.
yardımlarınızı bekliyorum
saygılarımla
Merhaba,
Hi-Tech içinde samples klasörü var orada kesmelerle ilgili örnek kodlar var onları öncelikle bir incele. Ayrıca kesme deyince akla bir sürü kesmeler geliyor. timer0, timer1, timer2, int0, intrb, usart, pwm, ccp v.b. bir sürü kesmeler var sen hangisini kullanacaksın?
Selamlar,
Hasan ARSLAN.
sayın arslan hocam dediklerinize baktım ama pek birsey anlamadım.mesela 16f877 de dış kesme olarak buton ekliyeceğim ve buna göre programı kontrol edeceğim burada yanı 877 de 5 tane dı kesme uygulayabılıyoruz dıye duymustum .işte ben bunun nasıl olduğunu belirtmenizi isteyorum.
teşekkürler
saygılarımla.
Merhaba,
Samples klasörünün içinde ki "intr1.c" dosyasını incele. aşağıda kodu tekrar yayınlıyorum.
#include <pic.h>
/*
* Interrupt demo for PIC; wait for button press on RB0/INT,
* turn on a relay on another port bit for a period of time.
* For simplicity here, literal constants are used, usually these
* should be calculated with compile-time arithmetic.
*/
static bit RELAY @ (unsigned)&PORTB*8+7; // use this bit to drive relay
static unsigned int relay_timer; // timer value for relay driver
void
main(void)
{
/* setup stuff */
RELAY = 1; // ensure relay is off before enabling output
TRISB = 0x3F; // Port B bits 7 and 6 are output
T0CS = 0; // Timer increments on instruction clock
T0IE = 1; // Enable interrupt on TMR0 overflow
INTEDG = 0; // falling edge trigger the interrupt
INTE = 1; // enable the external interrupt
GIE = 1; // Global interrupt enable
for(;;)
CLRWDT(); // Idly kick the dog
}
static void interrupt
isr(void) // Here be interrupt function - the name is
// unimportant.
{
if(T0IF) { // timer interrupt
TMR0 -= 250; // reload the timer - 250uS per interrupt
T0IF = 0; // clear the interrupt flag
if(relay_timer != 0) // is the relay timer running?
relay_timer--; // decrement it
if(relay_timer == 0) // if it has time out
RELAY = 1; // turn the relay off
PORTB ^= 0x40; // toggle a bit to say we're alive
}
if(INTF) { // did we see a button press?
RELAY = 0; // turn the relay on
relay_timer = 4000; // start the timer - 4000 ticks = 1 second
INTF = 0; // clear the interrupt
}
}
İnterrupt alt programı
static void interrupt
isr(void)
ile başlar, o kodun içinden interupt flaglerine bakarak interruptun nereden geldiğine anlayacaksın.
Mesela "T0IF" flagı timer0 için, "INTF" ide intRB0 ait flaglerdir.
Selamlar.
sayın arslan hocam ağzımın payını aldım.artık ben bu işleri bırakacağım.yine birşeyler anladım ama
static bit RELAY @ (unsigned)&PORTB*8+7; // use this bit to drive relay
static unsigned int relay_timer; // timer value for relay driver
kısımlarından ve main den pek birşey anlamadım.
ve kesme fonk siyonunda kaç tane daha kesme ekleyebiliriz.butonsal bazda yani dış kesme olarak.bunun bir algoritma ve quick user guidesi yokmudur varsa ben bulamadım.veya bana bir kaynak önerebilirmisiniz.
belki yeni bir tartışma yaratmış olacağım ama bu pic işini öğrenmek için doğan ibrahimin tüm kitaplarını aldım fakat bir kaç basit özelliğinden ileriye gidemedim.sizlere sonsuz saygı duyuyorum.böyle sınırlı kaynaklarla bu işi çözmüşünüz.
bense hayatımda ilk kez pes edeceğim
saygılarımla.
Merhaba,
Öncelikle senin "C" bilgin ne seviyede. Cünkü sorduğun bu sorular PIC'den daha ziyade C ile alakalı sorular. Eğer C bilgin yoksa o zaman sana bu derleyici cok fazla zor gelir ve fazla birşey anlamassın. Sana tavsiyem parana kıyıb güzel C eğitimi veren bir kursa gitmek. C dili iyi öğrendiğinde işin cok daha kolaylaşacaktir.
Kısaca yapılan işlemleri anlatayım.
RB7 bacağını Role cıkışı olarak tanımlamış.
static bit RELAY @ (unsigned)&PORTB*8+7; // use this bit to drive relay
relay_timer diye int(2byte) türünden bir değişken tanımlamış.
static unsigned int relay_timer; // timer value for relay driver
Şimdi main konumuna, yani ana program kısmına gelelim.
RELAY = 1; // ensure relay is off before enabling output
Röle cıkışını kapatmış.
TRISB = 0x3F; // Port B bits 7 and 6 are output
RB6 ve RB7 bacaklarını cıkış yapmış.
T0CS = 0; // Timer increments on instruction clock
Timer0 giriş sinyalını pic kristalıne bağlamış.
T0IE = 1; // Enable interrupt on TMR0 overflow
Timer0 (interrupt) kesemesini aktif yapmış.
INTEDG = 0; // falling edge trigger the interrupt
RB0 kesmesini düşen kenarda ayarlamış.
INTE = 1; // enable the external interrupt
RB0 kesmesini aktif yapmış.
GIE = 1; // Global interrupt enable
aktif olan bütün kesmeleri devreye sokmuş.
for(;;)
CLRWDT(); // Idly kick the dog
burdada sonsuz döngü yaparak işlemi burada sonlandırmış. Sonsuz döngü içinde eğer Watchdog timeri acık ise devreye girmemesi için Watchdogu sıfırlıyor.
Yan ana program içinde hiç bir işlem olmuyor. bütün işlemler kesmede yapılıyor.
Şimdi kemse alt programını inceleyelim.
Timer 0 gelmişmi diye sorgu yapiyor.
if(T0IF) { // timer interrupt
Evet timer0 gelmiş ise bu bok içikei işlemleri yapiyor.
TMR0 -= 250; // reload the timer - 250uS per interrupt
Timer 0 registerinden 250 değerini cıkartiyor. 250 us ayarlamak için.
T0IF = 0; // clear the interrupt flag
timer 0 bayrağını sıfırlıyor.
Eğer reay_timer değişteni sıfır değil ise.
if(relay_timer != 0) // is the relay timer running?
relay_timer değişkenini bir azaltiyor.
relay_timer--; // decrement it
sonuc sıfır mı?
if(relay_timer == 0) // if it has time out
Evet sonuc sıfır
Role Cıkışını kapat.
RELAY = 1; // turn the relay off
PortB cıkışını '01000000' değeri ile özel veya işlemime tabi tutuyor.
Sonucta RB6 cıkışı nın durumu değişmiş olacak.
PORTB ^= 0x40; // toggle a bit to say we're alive
} // timer0 ait blok sonu.
// RB0 tan kesme gelmişmi? Yani butona basılmışmı?
if(INTF) { // did we see a button press?
// Evet basılmış.
Röleyi ac.
RELAY = 0; // turn the relay on
relay_timer değerini 4000 yap.
relay_timer = 4000; // start the timer - 4000 ticks = 1 second
RB0 kesem bağraını sıfırla.
INTF = 0; // clear the interrupt
}
Aslında oluşan olay kısaca söyle. RB0 bacağına bağlı bir buton var. ona bastğımızda roleyi devreye sokuyor ve 1 saniye sonra röle kendisi kapaniyor. rölenin her kapanmasında RB6 cıkışının durumu değişiyor.
Çalışmalarında başarılar.
sayın arslan hocam dediklerinizi iyice inceledim.c bilgim orta düzeylerdeyani kendim biraz c de progra yazabiliyorum.
mesela ben bu programı yazmıs olsa
#include<pic.h>
#include<delay.c>
#define tus RB0
#define cikis RB1
void bekle(unsigned int x)
{unsigned int y,i;
y=4*x;
for(i=0;i<=y;i++)
DelayMs(250);
}
void main()
{
TRISB=0b01; // rb0 giriş rb 1 çıkış
for(;;)
{
if(tus==0)
{cikis=1;
bekle(4);
cikis=0;
}
}
şeklinde yazar ve 16f84 de bir butonla okurdum ama birkaçtane
buton olunca döngü çok karmaşık oluyor ve kontrol çok fazla yer kaplıyor.bundan dolayı kesmelerı oğrenmeye calışıyorum.
peki 877 de 4 tane buton bağlasaydık
TOIE=1 gibi dört tane daha nasıl tanımlayacaktık.burada
INTF den başka kaç tane daha tanımlayacaktık.bunları oluşturamıyorum.
yanıtlarınız için çok teşekkürler.
saygılarımla.
Merhaba,
Öncelikle sen ne yapmak istediğini ayrıntılı anatırsan sana daha iyi yardımcı olunur.
Gördüğüm kadarıyla senin mikoişlemci bilginde zayıf. Öncelikle kullandığın PIC 'in datasheetini ayrıntılı bir şekilde okumanı tavsiye ederim. PIC'in donanım yapısını bilmeden sadece C bilgisiyle üstelik zayif bir C bilgisiyle birşeyler yapamassın. Mutlaka biryerde takılır ilerleyemessin.
İlk yapman gereken işlemler C bilgini biraz geliştiriyorsun. Ayrıca kullandığın PIC'in datasheetini güzelcene bir okuyub ezberliyorun, donanımın bütün çalışma prensibini öğreniyorsun. Bu işlemden sonrasında program yazmaya başlaman daha sağlıklı olacağı kanısındayım.
Cünkü burda sana vereceğim cevablar senin kafanı daha cok karıştıracak.
Selamlar.
arslan hocam dediinizi yapıp hemen iyi bir c kitabı alıp önce c yi geliştireceğim vede datasheet lere bi odaklanıyım bakalım ne çıkacak.
yardımlarınız için çok teşekkürler
saygılarımla
selamlar...
acaba hi-tech de 16f877a ile birden fazla kesmeyi nasıl kullanabiliriz tek kesmede sorun yok fakat birden fazla her türlü kesmede hatalar alıyorum ne yapmam gerekir nasıl bir yol izlemeliyim..şimdiden teşekkürler..
birden fazla kesmede kesme satırında hangi kesmenin geldiğini anlamanın bir yolu var oda şöyle;
if(T0IF)
{
// işlenecek kod
T0IF=0;
}
if(TMR1IF)
{
// işlenecek kod
TMR1IF=0;
}
if(TMR2IF)
{
// işlenecek kod
TMR2IF=0;
}
bende bunun gibi bir program akışı izledim fakat bu sefer de anlamsız gecikmeler oluşuyor ...timer1 ile timer0 ı birlikte ccs c de sorunsuz kullanabiliyordum fakat hi-tech de şu an için bunu yapamadım ..
kod paylaşın daha detaylı yardımcı olalım konuşmakla olmuyor bazı şeyler.
yazdığım kod aşağıdaki gibi..belki de sorunum hi-tech ile kesmelere öncelik verememektir umarım bu sorunu çöebiliriz
#include <pic.h>
#include "delay.h"
__CONFIG(XT & WDTDIS & BORDIS & UNPROTECT);
const unsigned char
segment[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F};
char sn,dk,sa,i;
void interrupt saat(){
TMR1H=32768/256;
TMR1L=32768%256;
if(TMR1IF==1){
sn++;
if(sn==60){
sn=0;
dk++;
}
if(dk==60){
dk=0;
sa++;
}
if(sa==24){
sa=0;
}
TMR1IF=0;
}
if(T0IF==1){
TMR0=6;
i++;
if(i==2){
PORTB=0B11111110;
PORTD=segment[dk%10];
}
if(i==4){
PORTB=0B11111101;
PORTD=segment[dk/10];
}
if(i==6){
PORTB=0B11111011;
PORTD=segment[sa%10];
}
if(i==8){
PORTB=0B11110111;
PORTD=segment[sa/10];
i=0;
}
T0IF=0;
}
}
void main(){
TRISA=0B00010000;
TRISB=0X00;
TRISC=0X01;
TRISD=0X00;
PORTA=0X00;
PORTB=0X00;
PORTC=0X00;
PORTD=0X00;
ADCON1=0X07;
TMR0=6;
T0CS=0;
PSA=0;
PS2=0;
PS1=0;
PS0=1;
T0IF=0;
T0IE=1;
TMR1H=32768/256;
TMR1L=32768%256;
T1CKPS1=0;
T1CKPS0=0;
T1SYNC=1;
T1OSCEN=1;
TMR1CS=1;
TMR1ON=1;
TMR1IF=0;
TMR1IE=1;
PEIE=1;
GIE=1;
while(1);
}
hitech de kesmeler main altına yazılır.
ayrıca
static void interrupt KESME()
{
}
şeklinde çağrılır.
dediklerinizin hepsini denedim fakat işin içinden çıkamadım bayraklara da müdahele ettim yine olmadı...kesmelere nasıl öncelik verebilirim peki
ccs c deki #priority tarzı bir olay yapabilir miyiz hi-tech de..
hitech de derleyiciye has vektörel atama mevcut değil programın akışını değiştirerek çözüm bulabilirsiniz main döngüsünü kullanmamışsınız onu kullanıp sadece zaman saatini timer1 kesmesine gerçekleştirin.
bir hata daha gördüm kodunda timer1 kesmesi gelsede gelmesede TMR1H=32768/256; TMR1L=32768%256; satırlarını işliyorsun bu satırları timer1 bayrağının içine al sorun düzelir büyük ihtimalle.
teşekkür ederim.. benim main bölümünü boş bırakma nedenim programda birden fazla kesme uygulamasına bir temel atabilmekti.. son dediğiniz kısmı deneyim sonucu yazıcam tekrar teşekkürler..
X-FI ;
çok teşekkür ederim yardımlarınız için sorunum büyük ölçüde düzeldi...
Alıntı yapılan: X-Fi - 28 Aralık 2010, 20:48:45
hitech de kesmeler main altına yazılır.
ayrıca
static void interrupt KESME()
{
}
ben hep kesmeleri main'in üstünda yazıyorum ve herhangi bir sorunlada karşılaşmadım.
birde
void interruprt kesme()
{
if(T0IF && T0IE)
{
// işlenecek kod
T0IF=0;
}
if(TMR1IF && TMR1IE)
{
// işlenecek kod
TMR1IF=0;
}
if(TMR2IF && TMR2IE)
{
// işlenecek kod
TMR2IF=0;
}
}
şeklinde flag ve enable bayraklarını beraber kontrol etmelisiniz. Örneğin programı bir yerinde timer0 interrupını kapattığınızı varsayalım. eğer IE bitini kontrol etmezseniz, timer1 kesmesi oluştuğunda timer0'ın kesme kodlarıda çalışacaktır. Çünkü timer0 sürekli çalışır ve her başa döndüğünde IF bitini 1 yapar.
hocam mainin altına yazılabilme ayrıcalığı var böylece rom hafızasında alt programlarının arasına yerleştirmez kesme opcode'larını kesme içerisinde alt program çağırıyorsanız sorun çıkabilir çıkmasa bile derleyici warning hatası verecektir.
bu IE kontrolleri programı yavaşlatmak dışında gerekli olursa kullanılabilir iyi bir hatırlatma oldu teşekkürler :)
mümkün olduğunca kesme içinde altprogram çağırmamaya çalışıyorum. Kesme main üstüne yazıldığında ve alt program çağırldığında nasıl sorunlar çıkartıyor. Şu an kadar hiç warning almadım.
program başında Interrupı bir kez açıp hiç ellenmiyorsa IE bitlerinin kontrol edilmesine gerek yok. Eğer program içinde arada interruptlar kısmi olarak kapatılıp açılıyorsa IEler mutlaka kontrol edilmeli.
retfie return farkından iç içe dallanmalarda stack taşmaları oluşuyor alt programlara doğru şekilde ulaşamıyorsunuz warning vermemesi versiyondan kaynaklanabilir hi-tech bu konuda çok karışık.
evet dediklerinizi yazdığım programa uyarladım şu an program gayet düzgün çalışıyor kesmelerdeki sorunum halledildi...yalnız kafama birşey takıldı acaba kesmelerin önceliği kesme alt programında yazdığımız sıraya göre mi oluşuyor ..mesela ilk olarak timer0 kesmesi devamında da timer1 kesmesi için alt programı yazdık burada öncelik timer0 ın mı ?