pic16f1826 RB1 kesmesi oluşturma

Başlatan alexsi, 11 Mayıs 2015, 17:25:34

alexsi

Arkadaşlar,
merhaba elimde bir tane pic16f1826 ile cizilmiş bir kart(PCB)var. Bu kartın RB0/ext  girişi ext_interrupt  için kullanılıyor.
RB1 portunu da baska bir amaçla harici giriş olarak kullanmam gerekiyor.( interrupt oluşturmam lazım. Hızlı tepki için mutlaka interrupt olmalı) Kısacası pic16f1826 ile ve CCS C derleyicisi ile RB1 pinine gelen sinyali/datayi harici kesme olarak nasıl oluşturabilirim? Öneri ve yardımlarınız için şimdiden teşekkürler. Donanımsal olarak değişiklik yapamam (PCB kart çizilmiş)..

Aşağıdaki gibi bişeyler olacak anladığım kadarıyla ancak  ccs c de interrupt nasıl oluşturcam . Başlangıç ayarlarını nasıl yapmalıyım biraz sıkıntı yaşıyorum. CCS C yide çat pat biliyorum. Yardım edebilir misiniz arkadaşlar ,ete hocam !
(INTCON: INTERRUPT CONTROL REGISTER 0. bit,IOCIF: Interrupt-on-Change Interrupt Flag bit)

ete


INTCON registeri GIE biti set edilecek
INTCON rgisterinin IOCIE biti set edilecek
IOCBP.1=1 yapılacak
Buraya kadar olan ayarlamalar PORTB.1 pininde yükselenkenarda kesme oluşturur. Düşen kenarda kesme yaratılmak istenirse,
IOCBN.1=1 verilecek.

Bu pine bağlı bir kesme oluştuğu zaman IOCBF.1 =1 olacaktır. Buna bakarak kesmenin bu pinden olduğunu anlayıp ona göre işlem yapmak gerek.
Bunların hepsi data sheep 132 nolu sayfada yazıyor bende oradan okudum.

Unutulmaması gereken şey Bu denetleyicide PORTB pini Analog olabiliyor. Pinleri digital kullanmak için ANSELB=0 vermek gerekiyor.

Kesmeden çıkmadan Kesme bayrağını silip (IOCBF.1=0 verilerek ) çıkılmalıdır.

Ete


rodyum

RB1 portunda  interrupt girişi yok.

Burak

Alıntı yapılan: rodyum - 11 Mayıs 2015, 23:21:26
RB1 portunda  interrupt girişi yok.

Bu kati bilgiye nereden ulaştın ? Bak sayfa 131'de ne yazıyor denetleyici kataloğunda ...

The PORTB pins can be configured to operate as
Interrupt-On-Change (IOC) pins. An interrupt can be
generated by detecting a signal that has either a rising
edge or a falling edge. Any individual PORTB pin can
be configured to generate an interrupt.


Lütfen mesnetli yargılarda bulunalım ...

Burak
Ω Gens Una Sumus Ω

rodyum

Ben External interrupt'tan bahsettim. oda sadece RB0 portunda mevcut.
eğer siz PORTB değişiklik kesmesinden bahsediyorsanız şu şekilde olabilir:

#include <16F1826.h>
#device ADC=10
#FUSES NOPUT, NOMCLR, NOPROTECT, NOCPD, NOBROWNOUT, NOCLKOUT, NOIESO, NOFCMEN, NOWRT, NOSTVREN, BORV19, NOLVP
#use delay(crystal=4000000)
#use FIXED_IO( A_outputs=PIN_A0 )
#define LED PIN_A0

#INT_RB
void  RB_isr(void) //kesme
{
      output_high(LED);
      delay_ms(1000);
      output_low(LED);
      delay_ms(1000);
}

void main()
{
   port_B_pullups(0xFF);

   enable_interrupts(INT_RB1); //RB1 değişiklik kesmesi aktif.
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
      //sonsuz döngü
   }

}t

Burak

Alıntı yapılan: rodyum - 12 Mayıs 2015, 02:33:15
Ben External interrupt'tan bahsettim. oda sadece RB0 portunda mevcut.
eğer siz PORTB değişiklik kesmesinden bahsediyorsanız şu şekilde olabilir:

#include <16F1826.h>
#device ADC=10
#FUSES NOPUT, NOMCLR, NOPROTECT, NOCPD, NOBROWNOUT, NOCLKOUT, NOIESO, NOFCMEN, NOWRT, NOSTVREN, BORV19, NOLVP
#use delay(crystal=4000000)
#use FIXED_IO( A_outputs=PIN_A0 )
#define LED PIN_A0

#INT_RB
void  RB_isr(void) //kesme
{
      output_high(LED);
      delay_ms(1000);
      output_low(LED);
      delay_ms(1000);
}

void main()
{
   port_B_pullups(0xFF);

   enable_interrupts(INT_RB1); //RB1 değişiklik kesmesi aktif.
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
      //sonsuz döngü
   }

}t


PortB durum degisiklik kesmeleride harici kesme grubuna girerler , Dahili kayitcilardaki vektorel degisimleri bizler internal interrupts olarak adlandiririz ,ornegin on bolucu kesmeleri , timer kesmeleri veya herhangi bir taşma ( overflow ) kesmesi ... Ki arkadas zaten RB1 kesmesinin ext index'li bir kesme oldugu konusunda bir soylemde bulunmamis ..

Burak
Ω Gens Una Sumus Ω

muratguenduez

#6
Alıntı yapılan: rodyum - 12 Mayıs 2015, 02:33:15
Ben External interrupt'tan bahsettim. oda sadece RB0 portunda mevcut.
eğer siz PORTB değişiklik kesmesinden bahsediyorsanız şu şekilde olabilir:

#include <16F1826.h>
#device ADC=10
#FUSES NOPUT, NOMCLR, NOPROTECT, NOCPD, NOBROWNOUT, NOCLKOUT, NOIESO, NOFCMEN, NOWRT, NOSTVREN, BORV19, NOLVP
#use delay(crystal=4000000)
#use FIXED_IO( A_outputs=PIN_A0 )
#define LED PIN_A0

#INT_RB
void  RB_isr(void) //kesme
{
      output_high(LED);
      delay_ms(1000);
      output_low(LED);
      delay_ms(1000);
}

void main()
{
   port_B_pullups(0xFF);

   enable_interrupts(INT_RB1); //RB1 değişiklik kesmesi aktif.
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
      //sonsuz döngü
   }

}t


merhaba ben 16f88 de pwm kullanıyorum ve external int kullanamıyorum. ccs c de wizard ile yaparken tabiki. yukarda senn yazmış olduğun kodu oluşturan secenek ise "portb any change  on b4 b7". yani bu oluşturduğun kodda, enable_interrupts(INT_RB1) bundan anlayacağım şey, sadece rb1 kesme yapar mı? başka bi port yazsam oraya ayrı bir satırda iki adet kesme oluşturabilirmiyim? yoksa int girişleri sabit mi ?

birde bu kesme stream i komple pause yapıyomuş gibi çalışıyor dimi? mesela rb1 1 olduğunda kesme oluşur, 0 olduğunda kaldığı yerden devam eder. peki kesme alt programından çıkarken bişeyler yapmamıza ne bilim bi kaç biti temizlemek falan gerekiyor mu ?

teşekkür ederim

said

Alıntı yapılan: ete - 11 Mayıs 2015, 20:09:55INTCON registeri GIE biti set edilecek
INTCON rgisterinin IOCIE biti set edilecek
IOCBP.1=1 yapılacak
Buraya kadar olan ayarlamalar PORTB.1 pininde yükselenkenarda kesme oluşturur. Düşen kenarda kesme yaratılmak istenirse,
IOCBN.1=1 verilecek.

Bu pine bağlı bir kesme oluştuğu zaman IOCBF.1 =1 olacaktır. Buna bakarak kesmenin bu pinden olduğunu anlayıp ona göre işlem yapmak gerek.
Bunların hepsi data sheep 132 nolu sayfada yazıyor bende oradan okudum.

Unutulmaması gereken şey Bu denetleyicide PORTB pini Analog olabiliyor. Pinleri digital kullanmak için ANSELB=0 vermek gerekiyor.

Kesmeden çıkmadan Kesme bayrağını silip (IOCBF.1=0 verilerek ) çıkılmalıdır.

Ete

 


bu işlemi ccs c de nasıl birşey yazarak gerçekleştire biliriz.

Ph.D.

#8
Aşağıdaki gibi yapılabilir. RB0-RB7 pinlerindeki IOC kesmesi, RB4-RB7 Port Change kesmesi ile aynı türde kesmedir diye düşünüyorum. Daha önce hiç kullanmadım ancak aşağıdaki gibi yazarak kullanabilirsiniz. Kesmeden çıkarken gerekli bit ayarlarını CCS halletmektedir. Tabi yinede bit ayarlarında dikkatli olmak lazım, CCS'nin versiyon farklılıklarına göre değişiklik olabiliyor. Bir de sigortaları kendinize göre ayarlayınız. Osilatör seçeneğinizi de ayarlayınız, ben dahili osilatör PLL ile 32MHz olarak ayarlardım.

Kolay gelsin.

C dosyası:
#include <16F1826.h>

#device ADC=10

#FUSES PUT                      //Power Up Timer
#FUSES MCLR                    //Master Clear pin enabled
#FUSES PROTECT                  //Code protected from reads
#FUSES CPD                      //Data EEPROM Code Protected
#FUSES BROWNOUT                //Reset when brownout detected
#FUSES IESO                    //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOWRT                    //Program memory not write protected
#FUSES STVREN                  //Stack full/underflow will cause reset
#FUSES BORV19                  //Brownout reset at 1.9V

#use delay(internal=32MHz)

#ZERO_RAM

#INT_IOC //PortB için IOC Kesme Başlangıcı
void  IOC_isr(void) 
{
   //Kesme ile ilgili kodları buraya yazabilirsiniz.
}

void main()
{

  enable_interrupts(INT_IOC);
  enable_interrupts(GLOBAL);

  while(TRUE)
  {

  }

}
...hiç...

said

sizin kodda
#INT_IOC //PortB için IOC Kesme Başlangıcı
enable_interrupts(INT_IOC);

bu iki satır hata veriyor.


birde ben aşağıdaki gibi birşey yazdım. ama bunda da kesmeye giriyor çıkamıyor.

#include <16F1826.h>
//#FUSES NOPUT, NOMCLR, NOPROTECT, NOCPD, NOBROWNOUT, NOCLKOUT, NOIESO, NOFCMEN, NOWRT, NOSTVREN, BORV25, NOLVP

#fuses HS,NOPROTECT,NOWDT,NOLVP

#use delay(clock=4000000)
//#use rs232(baud=4800 ,xmit=Pin_a1 ,rcv=pin_a0)
void  main() {

  set_tris_a(0xff);
  set_tris_b(0b00000011);
 // output_a(0x01);
  output_b(0b00000011);
  enable_interrupts(INT_RB1_L2H);
 
  //enable_interrupts(INT_RB1);
  enable_interrupts(INT_RB1); //Rb1 interrupt aktifleştir
  input_b();                  //ihtiyat 
  clear_interrupt(INT_RB);
  enable_interrupts(GLOBAL);
  while (1) {
  
  
  
  output_high(pin_b7);
  delay_ms(100);
    output_low(pin_b7);
  delay_ms(100);


  }

}

#INT_RB
void fonk()
{
output_high(pin_b3);
    output_high(pin_b7);
    output_high(pin_b4);
    delay_ms(1000);
    output_low(pin_b3);
    output_low(pin_b7);
    output_low(pin_b4);
  delay_ms(1000);
  
  
}

ete

C dilinde bu işler nasıl yapılıyor ama bu gibi eksaantirk işler gerekli olduğu zaman hemen data sheet'emüracaat etmek gerekiyor.
Bölüm-13 de INTERRUPT ON CHANGE diye bir başlık var ve altında ne yapılacağı detaylı şekilde anlatılmış.
PORTB nin bütün pinleri için değişiklik kesmesi uygulanabildiği açıklanmış. Ancak kesmenin düşen kenardamı yoksa yükselen kenardamı oluşacağına karar verip bunlarla ilgili olan POzitif kenar IOCBPx veya IOCPNx registerlerinde ayarlama yapmak gerekiyor x burada hangi pini kullanacaksanız onu belirtiyor. Kesme oluştuğunda IOCBF registeri (Bayrak registeridir)nin kullandığınız pine karşılık gelenbiti set ediliyor. Dolayısıyla kesmeden çıkmadan evvel bu biti sıfırlamanız gerekir aksi halde sistem kesmeden ayrılmaz. Ayrılsada anında geri döner. Kesmeden çıkmıyor ifadeniz bunun karşılığıdır işte.
Tabiiki INTCON registeri IOCIF biti de set edilmiş olacaktır (Bit-0) bunuda çıkarken sıfırlamanız gerekiyor.

Ete

said

#11
peki nasıl sıfırlaya bilirim bu biti. datasheet de assembly olarak örnek vermiş c de nasıl yapabilirim

ete

Maalesef C bilmediğim için yardımcı olamıyorum. Ama eminim bir iki kesme örneği incelerseniz oradan yararlanarak yapabilirsiniz.

Ete

said

çok teşekkür ediyorum birşeyler buldum şuan oldu gibi

Ph.D.

@said, internetten araştırdım biraz, INT_IOC ile INT_RB her ikiside aynı kesme işlemleriymiş. Yani IOC komutları CCS içerisine sonradan eklenmiş, senin versiyon kaç bilmiyorum ama muhtemelen versiyon farkından dolayı sende hata verdi, bende herhangi bir hata yok. Yani senin yaptığın "enable_interrupts(INT_RB1)" ile "enable_interrupts(INT_IOC_B1)" aynı kesme bayraklarını ayarlıyorlar. Eğer düşen kenar yada yükselen kenar istiyorsan da "enable_interrupts(INT_RB1_L2H)" veya "enable_interrupts(INT_IOC_B1_L2H)" şeklinde belirtmen gerekiyor. Benim unuttuğum tek nokta RB1 portunu belirtmemişim. Yani "enable_interrupts(INT_IOC)" tüm B portlarını aktif ediyormuş.

Senin yazdığın kodda farkettiğim hata şu şekilde;

  enable_interrupts(INT_RB1_L2H);
 
  //enable_interrupts(INT_RB1);
  enable_interrupts(INT_RB1); //Rb1 interrupt aktifleştir

bölümünde "INT_RB1_L2H" ayarından sonra "INT_RB1" yaptığında DÜŞEN kenardan YÜKSELEN kenara geçen bölümü tekrar iptal edip her iki kenarda da kesme oluşmasını sağlıyorsun. Yani yukarıdaki "enable_interrupts" bölümlerinden sadece birisini kullanmalısın.

Alıntı yapılan: said - 20 Mayıs 2020, 08:51:16peki nasıl sıfırlaya bilirim bu biti. datasheet de assembly olarak örnek vermiş c de nasıl yapabilirim

İlgili kesme bitini sıfırlaman için yazmış olduğun kodda da kullanmış olduğun "clear_interrupt" komutu ilgili biti sıfır yapmaktadır. "clear_interrupt(INT_RB)" bu şekilde değil de "clear_interrupt(INT_RB1_L2H)" kullanmanı tavsiye ederim. Ancak daha önce de belirttiğim gibi CCS kesmelerden çıkarken ilgili biti genelde sıfırlayıp çıkar bu yüzden ekstra sıfırlamaya ihtiyaç yoktur, yine de belki versiyon farklarından kaynaklanabilir. Bunu da net bir şekilde anlamanın yolu programını derledikten sonra oluşan dosyalardan "*.lst" uzantılı dosya içerisinde kesme çıkışındaki ASM kodlarından ilgili bitin sıfırlanıp sıfırlanmadığı görülebilir. Tabi en güzel yol çalıştırmak ve/veya DEBUG yapmaktır.

Kolay gelsin.
...hiç...

Powered by EzPortal