PORTB 4-7 Değişiklik Kesmesi Hakkında

Başlatan Elektronikprojem, 29 Ağustos 2022, 22:37:04

Elektronikprojem

Merhaba. İncremental bir enkoder için puls sayısı okuma ile uğraşıyorum. Encoderden okunan pulslerde tutarsızlık görünce başka bir devreyle kendi devreme puls göndermeyi denedim. Toplamda 20 adet puls yolladım fakat burada bile portb4-7 kesmesinin düzgün çalışmadığını fark ettim. Bu konu hakkında başına böyle bir durum gelen veya bilgisi olan yardımcı olabilir mi?
Sorunumu kısaca özetleyecek olursam,
Puls aralıklarım 20ms. 20 puls gönderiyorum kesme kısmında da her pulste sayı ismindeki değişkenimi 1 arttırıyorum . puls göndermeyi bitirince işlemci 40 defa kesmeye girmesi gerekirken 30,27,32,34 gibi sayılarda kesmeye girmiş oluyor. Yani kesme bayrağı arada sırada kalkmamış oluyor. işlemcim 18f25k22 .

;-------------------------------------------------------------------------------
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings
Device = 18F25K22
Config_Start
  FOSC = INTIO67	;Internal oscillator block
  PLLCFG = OFF	;Oscillator multiplied by 4
  PRICLKEN = On	;Primary clock enabled
  FCMEN = OFF	;Fail-Safe Clock Monitor disabled
  IESO = OFF	;Oscillator Switchover mode disabled
  PWRTEN = OFF	;Power up timer disabled
  BOREN = SBORDIS	;Brown-out Reset enabled in hardware only (SBOREN is disabled)
  BORV = 190	;VBOR set to 1.90 V nominal
  WDTEN = OFF	;Watch dog timer is always disabled. SWDTEN has no effect.
  WDTPS = 32768	;1:32768
  CCP2MX = PORTC1	;CCP2 input/output is multiplexed with RC1
  PBADEN = OFF	;PORTB<5:0> pins are configured as digital I/O on Reset
  CCP3MX = PORTC6	;P3A/CCP3 input/output is mulitplexed with RC6
  HFOFST = OFF	;HFINTOSC output and ready status are delayed by the oscillator stable status
  T3CMX = PORTC0	;T3CKI is on RC0
  P2BMX = PORTB5	;P2B is on RB5
  MCLRE = INTMCLR	;RE3 input pin enabled; MCLR disabled
  STVREN = OFF	;Stack full/underflow will not cause Reset
  LVP = OFF	;Single-Supply ICSP disabled
  XINST = OFF	;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
  Debug = OFF	;Disabled
  Cp0 = OFF	;Block 0 (000800-001FFFh) not code-protected
  CP1 = OFF	;Block 1 (002000-003FFFh) not code-protected
  CP2 = OFF	;Block 2 (004000-005FFFh) not code-protected
  CP3 = OFF	;Block 3 (006000-007FFFh) not code-protected
  CPB = OFF	;Boot block (000000-0007FFh) not code-protected
  CPD = OFF	;Data EEPROM not code-protected
  WRT0 = OFF	;Block 0 (000800-001FFFh) not write-protected
  WRT1 = OFF	;Block 1 (002000-003FFFh) not write-protected
  WRT2 = OFF	;Block 2 (004000-005FFFh) not write-protected
  WRT3 = OFF	;Block 3 (006000-007FFFh) not write-protected
  WRTC = OFF	;Configuration registers (300000-3000FFh) not write-protected
  WRTB = OFF	;Boot Block (000000-0007FFh) not write-protected
  WRTD = OFF	;Data EEPROM not write-protected
  EBTR0 = OFF	;Block 0 (000800-001FFFh) not protected from table reads executed in other blocks
  EBTR1 = OFF	;Block 1 (002000-003FFFh) not protected from table reads executed in other blocks
  EBTR2 = OFF	;Block 2 (004000-005FFFh) not protected from table reads executed in other blocks
  EBTR3 = OFF	;Block 3 (006000-007FFFh) not protected from table reads executed in other blocks
  EBTRB = OFF	;Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
Config_End
;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------------------
Declare All_Digital=On
Declare Xtal = 64
;------------------------------------------------------------------------------
PORTA=0:TRISA=%00000000
PORTB=0:TRISB=%11111111
PORTC=0:TRISC=%10111000
PORTE=0:TRISE=%00001000
;------------------------------------------------------------------------------- 
OSCCON    =%01110000 ; 16Mhz
OSCTUNE.6 = 0 ; Enable 4x PLL 
ANSELA=0 :ANSELB=0 
CCP1CON=0:CCP2CON=0:CCP3CON=0 :CCP4CON=0  :CCP5CON=0
CM1CON=0 :CM2CON=0
ADCON0=0 :ADCON1=0 :ADCON2=0
INTCON    =%11001000
INTCON2   =%00000001
IOCB      =%00010000       
';---------------------------DEĞİŞKENLER----------------------------------------------------
Dim SAYI        As Dword
;-------------------------------------------------------------------------------
RCSTA = $90   ' Enable serial port & continuous receive
TXSTA = $20   ' Enable transmit, BRGH = 0
SPBRG = 25    ' 38400 Baud @ 16MHz, 0,16%
SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
Symbol GIE =INTCON.7 'genel interruptları açıyor
Symbol PEIE =INTCON.6 'peripheralinterruptları açıyor
Symbol RCIE =PIE1.5 'USART Recive interrupt enable bit
Symbol RCIF =PIR1.5 'USART Receive interrupt flag bit
RCIE=0
Dim temp As Byte
temp=PORTB
On_Hardware_Interrupt GoTo INT
';-------------------------------------------------------------------------------
Clear
DelayMS 200
GoTo BASLA
';--------------------------------------------------------------------------------
INT:
Context Save 
LATA.0=PORTB.4
If INTCON.0=1 Then
temp=PORTB
Inc SAYI
INTCON.0=0
EndIf
Context Restore 
;----------------------------------------------------------------------------------
BASLA: 
LATA.1=PORTB.4
If PORTB.1=1 Then
HSerOut["DEGER:",Dec SAYI,13,10]
SAYI=0
While PORTB.1=1
Wend
EndIf

GoTo BASLA
;---------------------------------------------------------------------------------------

End 

alisumer

#1
yazılımda kesme rutininde bir yanlışlık yok değilmi normalde  örneğin yükselen kenarda kesmeyi tek kesme kaynağı
 ayarladıysan kesme içerisinde if ile tekrar yüksekmi diye bakmazsınen zaten yüksektir ki kesmeye girmiştir.program doğru varsayarsak . mantıklı açıklamam bacağın parazite açık olması olabilir f1938 de bende kullandım kesme rutinini asm kullanarak yaptığımda hem 1 hem 0 da kesme bayrakları 100 khz ve üstünde bile  hiç kaçırma yapmadı 18 serisinde donanımsal bir sorun olacağına ihtimal vermiyorum(arızalı değilse) .pullup kullanıyorsanız direnç değerini biraz düşürün (daha kararlı olması için ben yarım köprü mosfet çıkışlı bir hall sensörle manyetik enkoder yapmıştım pull up tan daha kararlı ve hızlı ).kullanmadığınız bacakları çıkış yapın.
kodda anlamadığım yerler den biri (18 serisini bilmiyorum) kesmede iki bacaktan okuma yapılan cinsten bir artımsal okuma göremedim 18 serisinde  intcon 0 ilgili bayrak ise ki tek olmaz bence alt serilerde bile kesme bayrakları için ayrı register var gönderdiğin 20 puls karşılığında 40 sayısını görmen mantıksız bu hali ile 20 görürsün. varsayalım hem yükselen kenar hem düşern kenar kesmesi yakalayıp işlem yaptın onda da iki bacak için 20 pulsta 60 kesme yakalarsın 
artımsal enkoderim için asm kesme rutinii var bir anlamı olurmu bilmiyorum aşağıya bıraktım
Hep meraktan

alisumer

#2
KESME:
        
 asm
        BCF     INTCON  ,7 
        BANKSEL PORTB
        BTFSS   PORTB   ,1
        GOTO    _MENU                                    ;1
        MOVLW   0X0C                                                               ;1
        ANDWF   PORTB   ,W            ;'      ;1    YON=A ^ B                            ;
        MOVWF   _YENI                 ;'     ;1     IF YON=0 THEN  GOTO EKS            ;
        SUBWF   _ESKI   ,W                  ;1                                        ;
        BTFSC   STATUS  ,Z                  ;1-2                                      ;
        GOTO    _CIK                        ;2
        RRF     _YENI   ,W                   ;1
        XORWF   _ESKI   ,W                   ;1
        MOVWF   _YON                         ;1
        BTFSS   _YON    ,2                   ;1-2
        GOTO    _EKS                         ;2          
                               
endasm                     

ART:
    ASM                              ;komut süresi   16mhz
        INCFSZ  _ONDA   ,F            ; 1-2     250 ns-500ns
        GOTO    $+2                   ; 2            500ns
        INCF    _ONDA+1  ,F             ; 1     250 ns
        INCFSZ  _SAYAC  ,F            ; 1-2     250 ns-500ns
        GOTO    $+2                   ; 2            500ns
        INCF    _SAYAC+1  ,F            ; 1       250 ns
        MOVLW   .1                    ; 1       250 ns
        SUBWF   _EKSI  ,F             ; 1       250 ns
        BTFSS   STATUS  ,C            ; 1-2     250 ns-500ns
        DECF    _EKSI+1  ,F            ; 1       250 ns
        GOTO    _CIK                  ; 2            500ns
    ENDASM    
'    ONDA   =   ONDA+1           
'    SAYAC  =   SAYAC+1 
'    EKSI   =   EKSI-1
    
;    GOTO CIK          
EKS:    
    ASM                      
Basic te yazılmış ETE hocanın çok güzel örnek kodları mevcut oradan bakarsan daha anlaşılır olur belki
Hep meraktan

ete

Kesme yaratma ve yaratılmış kesmeden yararlanma ve yeniden yaratma konusu çok önemli bir konu.
İşin mantığını iyi anlamak gerekir. Data sheet bu konuda rehber dökümandır. Bakın aşağıda INTCON.0 biti ki bu PORTB değişiklik kesme bayrağı bitidir ne diyor.

bit 0 RBIF: Port B Interrupt-On-Change (IOCx) Interrupt Flag bit(1)
1 = At least one of the IOC<3:0> (RB<7:4>) pins changed state (must be cleared by software)
0 = None of the IOC<3:0> (RB<7:4>) pins have changed state

Lisanı anlamayanlar için buradan çıkartılması gereken bilgiyi ben açıklayım. (must be cleared by software) kelimesine odaklanın. Bu kelime şunu söylüyor. Direk INTCON.0=0 şeklinde komut verilerek sıfırlanmaz yazılımla sıfırlanır. Ne demek yazılımla sıfırlanır? bununda açıklaması var yine data sheet de. Değişiklik kesmesi yaratan pinlerin durumu okunarak (yada okunup bir değişkene eşitlenerek) bu bayrak yazılımla sıfırlanmış olur diyor.

Şimdi yazılmış programa bakalım. Bayrak sıfırlaması programın başında yapılmış temp=PORTB komutu bu işi yapıyor. Ama çok önemli olan kesme içinde bu işlem yapılmamış yerine INTCON.0=0 komutu verilerek işe yaramayan bir bayrak sıfırlama komutu verilmiş. Bayrak sıfırlanmayınca  ne olur?. Program kesmeden çıkınca direk yeniden kesemeye girer ve bu esnada gelen kesmeleri yeterince görmez. Sayma işlemide biraz rastgele yapılmış olur.

Bu kadar detaylı yazdım. İyi anlaşılsın diye. Bu işi defalarca test etmiştim geçmişte. Bayrak doğru şekilde sıfırlanırsa program doğru çalışır yapılmaz ise kusurlu çalışır burası kesin.

Yeri gelmişken yazılımla sıfırlanan aklıma gelen iki kesme var birisi USART kesmesi diğeride PORTB değişiklik kesmesidir.
Sonuçta bu programda eksik olan kesme içinde çıkmadan önce TEMP=PORTB komutunun yer alması gerekir.
Bunu yapıp yeniden deneyiniz.

Ete

Elektronikprojem

@ete hocam portb bin durumunu kesme içerisinde de okuyorum. Attığım kodda da temp=portb var kesme içerisinde.

@alisumer hocam değişiklik kesmesi o pinin her durumunda kesme oluşması demektir. Ben şu anda denemelerde sadece portb.4 pininde değişiklik kesmesi uyguluyorum. Bakacak olursak 20 pulsin hem Hugh hem low konumunda kesmeye girecek demektir. Yani bu da 40 puls eder.

Anlamlandiramadigim nokta bunu aralıklı olarak yapması. Bu arada pic i de değiştirdim. Şu anda devre kısmında da parazit alacak bir yer görünmüyor.

ete

Haklısın, bakar kör oldum herhalde. Kesme içinde kesme bayrağını sıfırlayan komut varmış.
Bu kısımda sorun olmayınca programın diğer kısımlarına baktım görebildiğim kusur şu;
Programa 64 Mhz de çalışacak diye osilatör komutu verilmiş. Burada sorun yok verilebilir.
OSCCON registerinede 16Mhz de çalışacak şekilde değer verilmiş. Buda doğru. Bu durumda PLL nin aktif edilerek sistemin 4xosc şeklinde yani 64 Mhzde çalıştırılması gerekir ama PLL config de OFF yapılmış bu yanlış. OSCTUNE.6 biti sıfır verilerek PLL orada da pasif yaılmış buda yanlış. SOnuçta yine yalış görmüyor isem program PLL ile çalışacak şekilde ayarlamış ama PLL pasif yapılmış.
Programın yeride olsam şaşırırdım. Bu gibi durumlarda default değer devreye girer diye biliyorum ama default değer nedir onu bilmiyorum. Bence OSC konfigürasyonlarına yeniden odaklanmalısın.

Ben olsam sistemi önce 4-8-16 MHZ lik frekansların birinde çalıştırır sorun yok ise sonra PLL yi devreye alırdım. Tabiiki alacak isen. Programa 64 Mhz de çalışacaksın deyip sonra 16Mhzde çalıştırmak sorun çıkartabilir.


Ete

Elektronikprojem

@ete hocam aslında ben pll aktif edip 64 MHz de çalışıyordum. Acaba orasiyla alakalı bir sorun mu var deyip sigorta ayarından ve osctune registerinden kapattım. Ama defin osc kısmını 16 yapmayı atlamışım. Bir de 16 yapıp deneyeyim bakalım

ete

#7
Belki okumamışsın diye aşağıdaki linki vermek isterim.

https://etepic.com/index.php/topic,1967.0.html
incelemende fayda var.

Incremental encoderde aslında iki çıkış var bunlar bir birlerine göre faz farkı ile çıkış verirler. Bir yönde dönerken alınan çıkış değerlerine bakılırsa %00 - %01 - %10 - %11 şeklinde çıkışlar olduğunu görebilirsin. Tek çıkışa (B) bakarsan 4 hareket de 0-0 sonra 1-1 oluyor. A çıkışı ise 0 - 1 - 0 - 1  şeklinde 2 puls üretmiş oluyor. Senin bağlantı şeklini göremiyoruz.
Sorunun sebebi bu bağlantı bile olabilir.

Ete

alisumer

#8
Alıntı yapılan: elektronarge - 30 Ağustos 2022, 10:06:46@ete hocam portb bin durumunu kesme içerisinde de okuyorum. Attığım kodda da temp=portb var kesme içerisinde.

@alisumer hocam değişiklik kesmesi o pinin her durumunda kesme oluşması demektir. Ben şu anda denemelerde sadece portb.4 pininde değişiklik kesmesi uyguluyorum. Bakacak olursak 20 pulsin hem Hugh hem low konumunda kesmeye girecek demektir. Yani bu da 40 puls eder.

Anlamlandiramadigim nokta bunu aralıklı olarak yapması. Bu arada pic i de değiştirdim. Şu anda devre kısmında da parazit alacak bir yer görünmüyor.
hocam dediğim gibi 18 serisine hakim değilim ama datasına baktım düşen kenar ve yükselen kenar kesmeleri intcon2.0 ile yapılıyor sen onu 1 yapıp bırakmışsın program içerisinde de değiştirmiyorsun görebildiğim kadarıyla düşen kenarda kesmeyi nasıl yakalıyorsun başka bir reg ayarı mevcutmu ayrıntılı bakmadım.normalde yükselen kenarda kesmeye gidince kesme içerisinde düşen kenarda kesme olsun diye reg ayarı yapılır öyle çıkılır ki birdahaki kesme düşen kenarda olacağı kesin olduğu için kaçırmasın .belki ben okuyamadım programında .birde başka kesme kaynağı kullanıyorsanız kesme kaçırmanız normal
Hep meraktan

Elektronikprojem

@ete hocam enkoder bağlantılarında a ve b uçlarını portb.4 ve portb.5 olarak bağlamıştım o şekilde ölçüm yaptığımda gelen pulsleri yanlış saydığını fark edince dışardan puls vererek kesmeye giriş çıkışına baktım. Kesmeye 40 defa girmesi gerekirken 32 defa girince fark ettim ki kesmede bir sorun var.  Programın içerisinde kesme biriminde portb.4 un duruma göre bir çıkış atadim portb.4 ne oluyorsa o da aynısı olsun diye. Bir de başla dongusune başka bir çıkışı portb.4 e esitledim. Çıkışa da 2 adet LED bağladım. Başla satırında kullandığım LED sürekli sinyal gelip gittikçe yanıp sönüyor. Ama kesme satırında kesmeye girince portb.4 e eşit olan LED arada yanık kalıyor. Veya yanık olması gerekirken sönük kalıyor. Sonrasında anladım ki kesme bayrağı demekki kalkmıyor.


@alisumer hocam portb değişiklik kesmesi intcon.3 ile açılıyor. Kesme öncelik durumu yüksek öncelikli yapmak istersek intcon2.0 bitini 1 yapıyoruz. Ayrıca IOCB registeriyle de hangi pinlerin kesme için kullanılacağı ayarlanıyor.

alisumer

Düşen kenar yükselen kenar nasıl ayarlanıyor anlamadım hala ama .kesme içerisinde if satırını kaldırın zaten kesme oluşmuş girmiş farklı bir kesme de kullanmıyorsunuz şu an için herhalde sorgulamadan bir deneyin belki kesmeye girene kadar durum değişiyordur anında giremiyor malesef çoğu zaman
	INT:
Context Save 
LATA.0=PORTB.4

temp=PORTB
Inc SAYI
INTCON.0=0

Context Restore
Hep meraktan

Elektronikprojem

@alisumer hocam portb değişiklik kesmesinde düşen veya yükselen kenar ayarlanmaz. Kesme için ayarlanan portta değişiklik olursa kesme oluşur.  Normalde bir de usart kesmesi vardı programda o yüzden if ile sorguluyordum. İf olmayan halini de denedim 18f45k22 ve 18f25k22 olarak iki ayrı picte de denedim durum aynı. İlginç bir durum anlamlandıramadım.

alisumer

şöyle bir uyarı buldum :
If a change on the I/O pin should occur when the read operation is being executed (start of the Q2 cycle), then the RBIF interrupt flag may not get set. Furthermore, since a read or write on a port affects all bits of that port, care must be taken when using multiple pins in Interrupt-on-change mode. Changes on one pin may not be seen while servicing changes on another pin.
18 srisinden nefret ediyordum katlandı sayenizde :o  portb nin tüm diğer bacaklarını çıkış yapıp sadece kullandığınız bacağı giriş yapmayı deneyin  belki diğerlerinden parazit ile kesme oluyordur yazıdaki bir bağlantı noktasındaki okuma diğerlerini engeller dediğinin neyin okuması olduğunu anlamadım ama sanırım aynı portta başka bacakların etkileyebileceği gibi bir kanı oluştu.bu da olmazsa benden bu kadar benim kafaya 18 serisi ağır gelir kaldıramaz daha fazla
Hep meraktan

Elektronikprojem

@alisumer hocam teşekkür ederim bunu bir deneyeyim aslında çok güzel bir işlemci ama bazı teferruatları oluyor. Uzun süredir bu işlemci ile çalışıyorum ilk kez böyle bir olaya denk geldim açıkcasıç  :)

Powered by EzPortal