16f628A için TMR0 ve USART kesmesi birlikte kullanımı

Başlatan lewwend, 16 Ağustos 2015, 00:35:52

lewwend

Selam arkadaşlar, bir projede 628 ile hem timer0 kesmesi hem de Usart kesmesi kullanmam gerek ama bir türlü beceremedim. ETE hocanın 688 için yazdığı kodlardan yola çıkarak birşeyler yapmaya çalıştım ama olmadı. Hserin komutunu kaldırınca timer0 çalışıyor anacak devrede iken timer saymıyor. Yardımcı olursanız sevinirim. Şimdiden teşekkürler...


'-----------------------------------------------------------------
@ DEVICE pic16F628A                      'işlemci 16F628                               
@ DEVICE pic16F628A, WDT_OFF             'Watch Dog timer kapalı
@ DEVICE pic16F628A, PWRT_ON             'Power on timer açık
@ DEVICE pic16F628A, PROTECT_OFF         'Kod Koruma kapalı
@ DEVICE pic16F628A, MCLR_off            'MCLR pini kullanılıyor.
@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT  'Dahili osilatör kullanılacak
'-----------------------------------------------------------------



DEFINE OSC 4
'DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
'DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
'DEFINE HSER_SPBRG 25 ' 9600 Baud @ 0,16%
'DEFINE HSER_CLROERR 1 ' Clear overflow automatically

OPTION_REG=%10000101   'Pull up dirençleri İPTAL- Bölme oranı 1/64.
'CMCON0=7
INTCON=%10100000       'Kesmeler aktif,  TMR0 ve USART kesmesi aktif
TMR0=0
OPTION_REG.7=0         '16F628 de komparatör pinleri iptal hepsi giriş çıkış

'SYMBOL GIE  =INTCON.7   'genel interruptlary' açiyor
'SYMBOL PEIE =INTCON.6   'peripheral interruptlary' açiyor
'SYMBOL RCIE =PIE1.5     'USART Recive interrupt enable bit
'SYMBOL RCIF =PIR1.5     'USART ALICI TAMPONU DOLU 1

'SYMBOL T0IE =INTCON.5    'TMR0  interrupt enable bit
'SYMBOL T0IF =INTCON.2    'TMR0  interrupt flag bit CLEAR

'RCIE=1
'PEIE=1
'GIE=1
'T0IE=0


ON INTERRUPT GOTO SAY
'-------------------------------------------------------------------------
           
'----------------------------------------------------------------------------


PORTA=0:TRISA=%00000000
PORTB=0:TRISB=%00111111


'-----------------------------------------------------------------
PAUSE 100
'MAX7219 PINLERI
SYMBOL  DIN=PORTA.6
SYMBOL  CLK=PORTA.0
SYMBOL  LD=PORTA.7
'-----------------------------------------------------------------

SYMBOL  LED=PORTA.1
SYMBOL  ZIL=PORTA.2

RTC_RST  var  PORTA.6
RTC_DTA  var  PORTB.7
RTC_CLK  var  PORTB.6

SYMBOL COMM_PIN = PORTA.4

ADDRESS     VAR WORD
ADDRESS1    VAR WORD
DATAREG     VAR WORD
DATAREG1    VAR WORD
FDATA0      VAR WORD
FDATA1      VAR WORD
FDATA2      VAR WORD
FDATA3      VAR WORD
FDATA4      VAR WORD
FDATA5      VAR WORD
FDATA6      VAR WORD
FDATA7      VAR WORD
X           VAR BYTE
A           VAR BYTE
B           VAR BYTE
S           VAR BYTE
SN          VAR BYTE
DK          VAR BYTE
AT          VAR BYTE

VERI        VAR BYTE

DAK         VAR BYTE
SAAT        VAR BYTE
MEM         var byte
SAYI        VAR BYTE
DAY         var byte
ONLAR       VAR BYTE
BIRLER      VAR BYTE

BUSY        VAR BIT         ' Busy Status-Bit
HAM         VAR   WORD        ' Sensör HAM okuma değeri
ISI         VAR WORD        ' Hesaplanmış ISI değeri
FLOAT       VAR WORD        ' Holds remainder for + temp C display     
ISARET_BITI VAR HAM.Bit11   ' +/- sıcaklık İşaret biti,  1 = olursa eksi sıcaklık
EKSI_ISI    CON 1           ' Sıfır altında isaret biti=1  oluyor kontrol için
DERECE      CON 223         ' ° işareti
ISARET      VAR BYTE        ' ISI değeri için  +/-  işaret
TEMP        VAR BYTE        ' Div32 bit hesap için geçici değişken

'-----------------------------------------------------------------
'MAX7219 AYAR
ADDRESS = $0C : DATAREG = $01   : GOSUB MAXYAZ 'On/Off Register.
ADDRESS = $09 : DATAREG = $00   : GOSUB MAXYAZ 'Decode register
ADDRESS = $0A : DATAREG = $0F   : GOSUB MAXYAZ 'Intensity register.
ADDRESS = $0B : DATAREG = $07   : GOSUB MAXYAZ 'Scan-limit register.
ADDRESS = $0F : DATAREG = $00   : GOSUB MAXYAZ 'Test mode register (all digits on, 100% bright)

ADDRESS1 = $0C : DATAREG1 = $01   : GOSUB MAXYAZ 'On/Off Register.
ADDRESS1 = $09 : DATAREG1 = $00   : GOSUB MAXYAZ 'Decode register
ADDRESS1 = $0A : DATAREG1 = $0F   : GOSUB MAXYAZ 'Intensity register.
ADDRESS1 = $0B : DATAREG1 = $07   : GOSUB MAXYAZ 'Scan-limit register.
ADDRESS1 = $0F : DATAREG1 = $00   : GOSUB MAXYAZ 'Test mode register (all digits on, 100% bright)


'-----------------------------------------------------------------

                                               
'-----------------------------------------------------------------
BASLA:
FDATA0=A
FDATA1=B
FDATA2=SN
FDATA3=DK
FDATA4=SAAT
FDATA5=DAK
FDATA6=ISI
FDATA7=FLOAT


      'SERIN2 PORTA.3,396,[WAIT("TUNA"),VERI]

      IF PORTB.4=0 THEN
      GOSUB T
      ENDIF

      IF PORTB.0=0 THEN
      GOSUB AY
      ENDIF
     
      IF PORTB.1=0 THEN
      GOSUB AA
      ENDIF     
     
      IF PORTB.2=0 THEN
      GOSUB BY
      ENDIF
     
      IF PORTB.3=0 THEN
      GOSUB BA
      ENDIF
     
      IF PORTB.5=0 THEN
      DK=DK+5
      WHILE PORTB.5=0
      WEND
      ENDIF
     
      IF PORTA.5=0 THEN
      DK=DK-1
      WHILE PORTA.5=0
      WEND
      IF DK=255 THEN DK=0
      ENDIF
     
      IF PORTA.3=1 AND DK=0 AND SN=0 THEN
      GOSUB UYARI
      ENDIF
     
     
     
     
     
     
         

      GOSUB SA
GOTO BASLA

'-----------------------------------------------------------------
SA:
ADDRESS=8 : X = FDATA3 DIG 1     : GOSUB AL : GOSUB MAXYAZ
ADDRESS=7 : X = FDATA3 DIG 0     : GOSUB AL : GOSUB MAXYAZ
ADDRESS=6 : X = FDATA2 DIG 1     : GOSUB AL : GOSUB MAXYAZ
ADDRESS=5 : X = FDATA2 DIG 0     : GOSUB AL : GOSUB MAXYAZ
ADDRESS=4 : X = FDATA0 DIG 1     : GOSUB AL : GOSUB MAXYAZ
ADDRESS=3 : X = FDATA0 DIG 0     : GOSUB AL : GOSUB MAXYAZ
ADDRESS=2 : X = FDATA1 DIG 1     : GOSUB AL : GOSUB MAXYAZ
ADDRESS=1 : X = FDATA1 DIG 0     : GOSUB AL : GOSUB MAXYAZ
RETURN
'-----------------------------------------------------------------

'-----------------------------------------------------------------
AL:    LOOKUP X,[126,48,109,121,51,91,95,112,127,123,99,78,128],datareg :RETURN
'-----------------------------------------------------------------

'-----------------------------------------------------------------
MAXYAZ:
shiftout DIN,CLK,1,[ADDRESS,DATAREG]
PULSOUT LD,2
return
'-----------------------------------------------------------------

'----------------ISI SENSÖR OKUMA BÖLÜMÜ --------------------------------
SENSOROKU:
           ham=$FE6F:Gosub hesapla:RETURN  'NORMAL ÇALIŞMADA BU SATIR SİLİNECEK
           OWOUT   Comm_Pin, 1, [$CC, $44]' ISI değerini oku
Bekle:
           OWIN    Comm_Pin, 4, [Busy]    ' Busy değerini oku
           IF      Busy = 0 THEN Bekle    ' hala meşgulmü? , evet ise goto Bekle..!
           OWOUT   Comm_Pin, 1, [$CC, $BE]' scratchpad memory oku
           OWIN    Comm_Pin, 2, [HAM.Lowbyte, HAM.Highbyte]' İki byte oku ve okumayı bitir.
           GOSUB   Hesapla
           RETURN
   
Hesapla:                 ' Ham değerden Santigrat derece hesabı
    ISARET  = "+"
    IF ISARET_BITI = EKSI_ISI THEN
       ISARET   = "-" 
       temp=($ffff-ham+1)*625
       ISI  = DIV32 10
       GOTO GEC   
    endif
    TEMP = 625 * HAM        '
    ISI = DIV32 10          ' Div32 hassas derece hesabı için 32 bit bölme yapıyoruz.
GEC:
    FLOAT = (ISI //1000)/100
    ISI=ISI/1000
    RETURN
'-----------------------------------------------------------------
AY: A=A+1
    WHILE PORTB.0=0
    WEND
    IF A=100 THEN A=0
    RETURN   
'-----------------------------------------------------------------

'-----------------------------------------------------------------
AA: A=A-1
    WHILE PORTB.1=0
    WEND
    IF A=255 THEN A=0
    RETURN   
'-----------------------------------------------------------------

'-----------------------------------------------------------------
BY: B=B+1
    WHILE PORTB.2=0
    WEND
    IF B=100 THEN B=0
    RETURN   
'-----------------------------------------------------------------

'-----------------------------------------------------------------
BA: B=B-1
    WHILE PORTB.3=0
    WEND
    IF B=255 THEN B=0
    RETURN   
'-----------------------------------------------------------------

'-----------------------------------------------------------------
T:  TOGGLE PORTA.3
    WHILE PORTB.4=0
    WEND
    RETURN   
'-----------------------------------------------------------------

'-----------------------------------------------------------------
UYARI: 
    HIGH ZIL  :PAUSE 1500
    LOW ZIL
    LOW PORTA.3
    RETURN   
'-----------------------------------------------------------------


DISABLE
'-----------------------------------------------------------------
SAY:

GIE=0          'tüm interruptlari kapat  INTCON.7=0
                 
IF T0IF=1 THEN SAY1
HSERIN 5,CIK,[WAIT("RED"),VERI ]
TEMP=RCREG
US=1
RCIF=0
GOTO CIK


SAY1:

       IF PORTA.3=1 THEN
       S=S+1         'kesme sayacı  1 sn= 61(sayac) x 256 (Tmr0) x 64 (bölme)
       IF S=61 then  '61 adet kesme olunca 1 sn. süre geçiyor.(999424 us)
          S=0        'sayaç sıfırlanıyor
          SN=SN-1
       ENDIF
       
       IF SN=255 THEN
          SN=59 
          DK=DK-1
       ENDIF
       
       IF DK=0 THEN DK=0
       IF S<30 THEN
       LED=1
       ELSE
       LED=0
       ENDIF

       
       ENDIF

T0IF=0

CIK:                   
GIE=1                  ' INTCON.7=1 kesmeleri açtik.
RESUME                                                                                                                                                                                                                                                                                                                                                                                                                   
ENABLE
END

ete

Programın içinde her şey var gözüküyor ama ne yazıkki hemen hepsi kapatılmış durumda. Program asıl olması gereken şekilde olsa idi hata ayıklamak elbette daha kolay olurdu. Bu durumda neyi açıp neyi kapadığını bilemediğim için muhtemel hataları sıralamaktan başka yapabileceğim bir şey yok. Programa en baştan bakarsak sırası ile;
1. TRIS ayarlamalarını bütün tanımlamalardan sonra yapmak bir kusur olabilir. Programın en başında bu tanımlamayı yapman gerekirdi.
2. TRISB ayarlarına bakınca normalde giriş olması gereken PORTB.1 (Default USART_RX pini) çıkış olarak ayarlanmış gözüküyor. Muhtemelen asıl sebep budur.
3.Sensör okumada       ( ham=$FE6F:Gosub hesapla:RETURN )UYARI  satırını çıkarman gerekir. Çok eskiden simulasyon amaçlı koyduğum bir satır idi. Çıkarmazsan sensörün çalışmaz.
4. UYARI isimli etiket altında PAUSE 1500 gibi bir gecime verilmiş. Bu komut 2 adet kesme kaynağı ile çalışan programın aksamasına sebep olur. Bu gecikmeyi daha akıllıca bir şekilde yaratmanda yarar var. Mesela döngü kurup her biri 1 ms lik gecikme diimleri yaratarak aynı gecikmeyi sağlayabilirsin. Böylece program aksamaz.
5.Kesme etiketi altında fazla komut gecikmesi yaratmayacak daha akıllıca bir tasarım yapabilirsin. En fazla kesme oluşturacak eleman TMR0 olacağına göre onu kesme etiketinde öne almak daha akıllıca olur. Mesela aşağıdaki gibi
DISABLE
SAY:

GIE=0          'tüm interruptlari kapat  INTCON.7=0
                 
IF T0IF=1 THEN
   IF PORTA.3=1 THEN
      S=S+1         'kesme sayacı  1 sn= 61(sayac) x 256 (Tmr0) x 64 (bölme)
      IF S=61 then  '61 adet kesme olunca 1 sn. süre geçiyor.(999424 us)
         S=0        'sayaç sıfırlanıyor
         SN=SN-1       
         IF SN=255 THEN
           SN=59 
           DK=DK-1
           IF DK=0 THEN DK=0       
         ENDIF
       endIF       
       IF S<30 THEN
         LED=1
       ELSE
         LED=0
       ENDIF       
   ENDIF 
   T0IF=0
   GOTO CIK
ENDIF

HSERIN 10,CIK,[WAIT("RED"),VERI ]
TEMP=RCREG
US=1
CIK:                   
GIE=1                  ' INTCON.7=1 kesmeleri açtik.
RESUME                     
ENABLE
END

6. Hserin komutu içinde verilen 5 ms lik zaman aşımı süresi her zaman yeterli olmayabiliyor. Genellikle bu süreyi önce 10ms kullanmak ve her şey normal çalışıyor ise sonra 5ms yi denemek gerekir. Bu nedenle ben 10 ms yazdım oraya.
7. TMR0 kesmesinin çalışması ayrıca PORTA.3 pinine bağlanmış. Bu pin HIGH olursa ancak zaman sayacı çalışıyor. İşin bu kısmını anlamadım. Umarım bu pini HIGH yapmayı unutmuyorsundur.
8. SOn olarak tabiiki he riki kesmeninde çalışabilmesi için aşağıdaki satırların açılması gerektiğini unutmamalısın.
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_SPBRG 25 ' 9600 Baud @ 0,16%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
CMCON0=7

SYMBOL GIE  =INTCON.7   'genel interruptlary' açiyor
SYMBOL PEIE =INTCON.6   'peripheral interruptlary' açiyor
SYMBOL RCIE =PIE1.5     'USART Recive interrupt enable bit
SYMBOL RCIF =PIR1.5     'USART ALICI TAMPONU DOLU 1

SYMBOL T0IE =INTCON.5    'TMR0  interrupt enable bit
SYMBOL T0IF =INTCON.2    'TMR0  interrupt flag bit CLEAR

RCIE=1
PEIE=1
GIE=1
T0IE=0


Hepsi bu kadar
Ete

lewwend

ETE hocam çok çoook teşekkür ederim ilginiz sabrınız ve hızlı cevabınız için. Dediklerinizi yaptım ve çalıştı Allah razı olsun, iyiki varsınız ve bilgilerinizi bizlerle paylaşıyorsunuz. Tekrar teşekkür ederim, iyi çalışmalar...

lewwend

Hocam merhabalar. TMR0 çalıştı ancak USART ı çalıştıramadım bir türlü. Sizi belki basit birşeyden dolayı rahatsız ediyorum ama sizin sayenizde tanıştığım pic programlama ile hayalini kurduğum elektronik birçok projemi hayata gerçirdim.
Ancak burada tıkandım. Yardım edebilirseniz sevinirim. Şimdiden teşekkürler. Proje dosyaları ekte bulunmakta...

ete

Bir program içinde aynı işi yapan birden fazla komut olmamalıdır.
GIE=1  'global kesemeleri aktif ediyor.
PEIE=1 'çevre birimleri (USART) kesmeleri aktive ediyor
RCIE=1 'USART kesmesini aktive ediyor
T0IE=1 'tmr0 kesmesini aktive ediyor.

komut satırları her birisi bir KESME fonksiyonunu aktive etmektedir. yanlarına yazdım ne yaptıklarını.
Bu komutları verdikten bir kaç satır sonra şu komutuda verirsen ,
INTCON=%10100000 
işler bozuluyor işte. Zira aktive ettiğin çevre birimlerini bu komutla pasif hale getirmiş oluyorsun. Bu bir yerde USART kesmesini iptal etmek anlamına geliyor.
Sonradan verilen INTCON komutunu silmen gerekiyor. Çünki onun işini yapan komutları önceden verdin.

16F628A da A portu default olarak komparatör olarak açılır. Programa CMCON=7 komutunu eklemen gerekir. Böylece komparatör özelliği iptal edilerek ilgili pinler normal giriş çıkış pini olarak kullanılabilir. Hem alıcıda hemde vericide bu komut olmalıdır.
Devrede ise işlemcinin birisinin çalışma frekansı 1Mhz olarak gözüküyor. Onuda 4Mhz yaparsan sistem çalışacaktır.

Başkada bir kusur göremedim. Zaten bu değişiklikleri yaptığımda USART'ın çalışmaya başladığını görebildim.

Ete

Powered by EzPortal