7 Segment Display ve Kesmeler (Interrupts) Hafta6-7 Dr. Bülent Çobanoğlu-SAÜ 1
Çevrim Tabloları Ve 7 Segment Display Uygulaması Çevrim / Bakış tabloları ile bir kodu başka bir koda dönüştürmek için kullanılırlar. Örneğin PIC mikro denetleyiciyi portlarına bağlı 7 Segment display / gösterge üzerinde hexadecimal (onaltılık tabandaki) sayıları göstermek, sıcaklık dönüşümü(derece-fahrenayt gibi) yapma, sinus, kosinus alma gibi işlemlerde dönüşüm/çevrim tabloları kullanılır. 7 Segment display 7 adet çubuk ledin bir rakam oluşturacak şekilde bir araya gelmesi ile oluşan bir elemandır. 7 segment displayler ortak anot ve ortak katotlu olmak üzere iki farklı şekilde bulunurlar. YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Çevrim Tabloları Ve 7 Segment Display Uygulaması 7 segment displaylerin içerisinde aslında 8 adet led bulunmaktadır. Her bir segment bu ledler ile oluşturulmuştur ve göstergenin hangi segmentinin yanmasını istiyor isek o ledi yakarız. Ortak anotlu display: tüm ledlerin anotları birleştirilmiştir ve bu uca +5V uygulanır. Katota şase gelen led yanar. Yanmasını istediğimiz lede +0V (logic 0) verilir. Ortak katotlu display: tüm ledlerin katotları birleştirilmiştir ve bu uç şaseye bağlanır. Yanmasını istediğimiz lede +5V (logic 1) verilir. YRD.DOC.Dr.BÜLENT ÇOBANOĞLU. G F E D C B A 0 b 0 0 1 1 1 1 1 1' 1 b 0 0 0 0 0 1 1 0 2 b 0 1 0 1 1 0 1 1' 3 b 0 1 0 0 1 1 1 1' 4 b 0 1 1 0 0 1 1 0 5 b 0 1 1 0 1 1 0 1 6 b 0 1 1 1 1 1 0 1 7 b 0 0 0 0 0 1 1 1 8 b 0 1 1 1 1 1 1 1 9 b 0 1 1 0 1 1 1 1 A b 0 1 1 1 0 1 1 1 b b 0 1 1 1 1 1 0 0 C b 0 0 1 1 1 0 0 1 d b 0 1 0 1 1 1 1 0 E b 0 1 1 1 1 0 0 1 F b 0 1 1 1 0 0 0 1
Assembly dilinde çevrim tablosunda uygun kodu seçmek için program sayıcıyı (PCL Program Counter), seçilen kodu ana programa göndermek için de RETLW komutunu kullanırız Birden fazla display bağlantısı Çevrim tablosundaki verilere sıralı olarak erişerek PCL ye yani o anki adrese istediğimiz sayıyı ekleyerek istediğimiz adrese / elemana ulaşırız. PCL nin o anki değerine ADDWF ile istediğimiz sayıyı ekleriz. Kullanım Şekli: ADDWF PCL, F İstediğimiz değeri geri döndürecek komut ise RETLW (RETLW h 3F gibi) dir. RETLW komutu ile alt alta yazılan sayı değerleri dt komutu yanyana yazılabilir. DIZI ADDWF PCL, F dt 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D,0x7D, 0x07, 0x7F,... YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Uygulama-1: 0 dan 9 kadar olan sayıları PORTB uçlarına bağlı 7 segment display de gösteren programı 7447 entegresi ile (bakış tablosu kullanmadan) gerçekleştiriniz. Hazırlayan: Dr.Bülent ÇOBANOĞLU 5
Uygulama 2: 7 segment display de 6 sayısını gösteren programı yazınız. // C programı #include <xc.h> const unsigned char dizi[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d, 0x7D; void main(void) // Ana fonksiyon alanı { TRISB=0x00; // PORTB çıkıs PORTB=0x00; for(;;) // Sonsuz döngüye giriliyor { PORTB=dizi[6]; //7 segment değerini al YRD.DOC.Dr.BÜLENT ÇOBANOĞLU ;Assembly LIST P=16F877 #INCLUDE "P16F877.INC" ORG 0X00 goto BASLA BASLA CLRF PORTB BANKSEL TRISB CLRF TRISB BANKSEL PORTB MOVLW.6 CALL DIZI MOVWF PORTB DON GOTO DON DIZI ADDWF PCL,F RETLW b'00111111' ;W ya 0 değeri yüklendi RETLW b'00000110 ;W ya 1 değeri yüklendi RETLW b'01011011 ;W ya 2 değeri yüklendi RETLW b'01001111' ;W ya 3 değeri yüklendi RETLW b'01100110 ;W ya 4 değeri yüklendi RETLW b'01101101 ;W ya 5 değeri yüklendi RETLW b'01111101' ;W ya 6 değeri yüklendi RETLW b'00000111 ;W ya 7 değeri yüklendi RETLW b'01111111' ;W ya 8 değeri yüklendi RETLW b'01101111' ;W ya 9 değeri yüklendi END
Uygulama 3: 0 dan F ye kadar olan sayıları PORB uçlarına bağlı 7 segment display de 1 sn aralıklarla gösteren programı C dili ile gerçekleştiriniz. // 0 dan F e ileri sayıcı #include <xc.h> #define _XTAL_FREQ 4000000 const unsigned char dizi[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f, 0x6F,0x77,0x7C, 0x39, 0x5E, 0x79, 0x71; unsigned char i; void main(void) // Ana fonksiyon alanı { TRISB=0x00; // PORTB çıkıs PORTB=0x00; for(i=0;i<=16;i++) // Sonsuz döngüye giriliyor { delay_ms(1000); PORTB=dizi[i]; //7 segment değerini al YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Uygulama 3: 0 dan F ye kadar olan sayıları 1sn gecikmeli PORB uçlarına bağlı 7 segment display de gösteren programı ASSEMBLY dili ile gerçekleştiriniz. LIST P=16F877 #INCLUDE "P16F877.INC" CBLOCK 0X20 SAY1,SAY2,SAY3,SAYAC ENDC ORG 0X00 goto BASLA BASLA CLRF PORTB BANKSEL TRISB CLRF TRISB BANKSEL PORTB CLRF SAYAC DON MOVF SAYAC,W ANDLW 0X0F ; SAYI 15 I GECMESİN CALL DIZI MOVWF PORTB CALL BEKLE INCF SAYAC,F GOTO DON DIZI ADDWF PCL,F dt h'3f',h'06',h'5b',h'4f',h'66',h'6d',h'7d',h'07' dt h'7f',h'6f',h'77',h'7c', h'39',h'5e',h'79',h'71' BEKLE MOVLW d'4' ;1s bekle MOVWF SAY1 BEKLE_250MS MOVLW d'250';250ms bekle MOVWF SAY2 BEKLE_1MS MOVLW d'249' MOVWF SAY3 LOOP NOP DECFSZ SAY3, F GOTO LOOP DECFSZ SAY2,F GOTO BEKLE_1MS DECFSZ SAY1,F GOTO BEKLE_250MS RETURN END
Uygulama 4: 9 Dan 0 A Geri Sayıcı // C kodu #include <xc.h> const unsigned char dizi[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x0 7,0x7F,0x6F; void bekle(){ for (int i=0;i<10000;i++) ; void main(void) // Ana fonksiyon alanı { char j=9; // Herhangi bir değisken tanımlanıyor TRISB=0x00; // PORTB çıkıs olarak yönlendiriliyor PORTB=0x00; for(;;) // Sonsuz döngüye giriliyor { PORTB=dizi[j]; // 7 segment değerleri alınıyor j--; bekle(); if(j<0) { j=9; YRD.DOC.Dr.BÜLENT ÇOBANOĞLU BASLA DISPLAY DIZI ;Assembly Kodu LIST P=16F877 INCLUDE "P16F877.INC" SAYAC EQU h 20' CLRF PORTB CLRF SAYAC BSF STATUS,5 CLRF TRISB BCF STATUS,5 INCF SAYAC,F MOVF SAYAC,W SUBLW d'10' BTFSS STATUS,Z GOTO DISPLAY MOVLW h'00' MOVWF SAYAC GOTO DISPLAY GOTO BASLA CALL DIZI MOVWF PORTB GOTO BASLA ADDWF PCL,F RETLW b'00111111 RETLW b'00000110' RETLW b'01011011' RETLW b'01001111' RETLW b'01100110' RETLW b'01101101' RETLW b'01111101' RETLW b'00000111';7 RETLW b'01111111' RETLW b'01101111' END ;W=10-W ;0GFEDCBA
Uygulama-5: 0 dan 9 kadar olan sayıları PORB uçlarına bağlı 7 segment display de gösteren timer gecikmeli (ileri sayıcı) Assembly programını gerçekleştiriniz. TRISB PORTB BASLA DON LIST P=16F877 #INCLUDE<P16F877.INC> SAYAC EQU h'20' CLRF PORTB BSF STATUS,5 ; BANKSEL CLRF TRISB MOVLW b'11010111' MOVWF OPTION_REG BCF STATUS,5 ; BANKSEL CLRF SAYAC MOVF SAYAC,W CALL DIZI CALL GECIKME MOVWF PORTB INCF SAYAC,F CALL GECIKME GOTO DON DIZI ADDWF PCL,F RETLW b'00111111' RETLW b'00000110' RETLW b'01011011' RETLW b'01001111 RETLW b'01100110' RETLW b'01101101' RETLW b'01111101' RETLW b'00000111' RETLW b'01111111' RETLW b'01101111 GECIKME CLRF TMR0 DON1 BTFSS INTCON, T0IF GOTO DON1 BCF INTCON, T0IF RETURN END YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Uygulama 6: 00-99 arası sayıcı C Kodu: #define _XTAL_FREQ 8000000 #include <xc.h> int A[]={0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0X7D,0x07,0x7F,0x6F; void goster(char i) { PORTA=0x02; // RA1 aktif PORTB=A[i/10]; // Onlar basamağı delay_ms(100); // Bekle PORTA=0x01; // RA0 aktif PORTB=A[i%10]; // Birler basamağı delay_ms(100); void main() { unsigned char i=0; TRISB=0; TRISA=0; ADCON1=0x07; PORTA=0; PORTB=0; for (;;) { i++; if (i>99) i=0; goster(i); YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Uygulama 7: Timer gecikmeli 0-99 arası void main() { TRISB=0; TRISA=0; ADCON1=0x07; PORTA=0; PORTB=0; T0CS=0; //TMR0 kaynağı PSA=0; // ön bölücü PS0=1; PS1=1; PS2=1; TMR0=0; T0IE=1; T0IF=0; GIE=1; // Genel kesme izni veriliyor for (;;) { goster(); YRD.DOC.Dr.BÜLENT ÇOBANOĞLU #define _XTAL_FREQ 4000000 #include <xc.h> unsigned char sayac=0; const unsigned int A[]={0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0X7D,0x07,0x7F,0x6F; static void interrupt olay(void){ if (sayac==100) { sayac=0; T0IF=0;//TMR0 bayrağını temizle TMR0=0; void goster() { sayac++; PORTA=0x02; // RA1 aktif PORTB=A[sayac/10]; // Onlar basamağı delay_ms(50); // Bekle PORTA=0x01; // RA0 aktif PORTB=A[sayac%10]; // Birler basamağı delay_ms(50);
Uygulama 8: 00-99 a İleri-Geri Sayıcı (Tarama Yöntemi ile) YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Uygulama 8: 00-99 a İleri-Geri Sayıcı (Tarama Yöntemi ile) [1/2] YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Uygulama 8: 00-99 a İleri-Geri Sayıcı (Tarama Yöntemi ile) [2/2] YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Uygulama 8: Trafik Işığı Program Parçası BASLA CLRW DON SINYAL MOVWF DURUM CALL SINYAL ; DURUMU DEĞİŞTİR. MOVWF PORTB ; SINYAL DEĞERINI PORTB DE GOSTER INCF ANDLW 0X03 DURUM,W ; DURUMU BİR ARTIR, SONUCU W YA YAZ. MOVWF DURUM CALL GECIKME ; BEKLE :-) GOTO DON MOVF DURUM,W ; DURUMU W YA TAŞI. ADDWF PCL,F RETLW 0X41 RETLW 0X23 RETLW 0X14 RETLW 0X32 ; MAKSIMUM 3 E KADAR ARTIR. B7 B6 B5 B4 B3 B2 B1 B0 ; W İÇERİĞİNİ DURUM DEĞİŞKENİNE AKTAR ; DURUM==0 İSE YEŞİL VE KIRMIZI(RB6,RB0) ; DURUM==1 İSE SARI VE KIRMIZI/SARI (RB5, RB0/RB1) ; DURUM==2 İSE KIRMIZI VE YEŞİL (RB4,RB2) 0 Y S K 0 Y S K 41 1 1 23 1 1 1 14 1 1 32 1 1 1 ; DURUM==3 İSE KIRMIZI/SARI VE SARI (RB4/RB5, RB1 K S Y K S Y YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Örnek Uygulama 8: Trafik Işığı Programı Tamamı K S Y K S Y B7 B6 B5 B4 B3 B2 B1 B0 0 Y S K 0 Y S K 41 1 1 23 1 1 1 14 1 1 32 1 1 1 #include <xc.h> void main() { unsigned char A[]={0X41, 0X23, 0X14, 0X32 ; TRISB=0; PORTB=0; while(1) { for (int i=0; i<4;i++) { YRD.DOC.Dr.BÜLENT PORTB=A[i]; ÇOBANOĞLU
Kesmeler Kesme, mikrodenetleyicinin gerçekleştirdiği işleme bakmaksızın belirli durumların veya olayların oluşması halinde isteklere/olaylara cevap verilmesini sağlayan mekanizmadır. Oluşan her kesme olayı ile programın normal işlenme süreci değiştirilerek program durdurulur ve kesme alt programı işletildikten sonra ana programın işlenmesi kalınan noktadan devam eder. Kesme kaynakları;
PIC16F877 Kesme Kaynakları ve Kaydedicileri YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
RB0/INT KESME OLAYI RB0/INT girişinden harici olarak kesme oluşturulur. Bu girişe uygulanan interrupt sinyalinin hangi kenarda olacağı OPTION_REG 6. biti (INTEDG) ile belirlenir. INTCON 7.biti GIE ile kesmelerine izin verilir. INTCON 4. biti INTE ile kesmeye izin verilir. INTCON 1. biti INTF bitinin 1 olması kesme oluştuğunu 0 olursa harici kesme oluşmadığının bildirir. Programda kesme alt programı içerisind e INTF=0 yapılmalıdır. OPTION_REG INTCON
Uygulama:PORTB nin RB0/INT ucundan gelen bir kesme gerçekleşince kesme alt pr ogramında PORTD ye bağlı 7 segment displayde L karakterini gösteren programı Assembly ve C ile yazalım Program Algoritması: RB0/INT ucunu giriş olarak seç, OPTION_REG kaydedicisinin INTEDG biti ile düşen veya yükselen kenar tetiklemesini seç, INTCON kaydedicisinin GIE ve INTE bitleri 1 yapılarak kesmeye izin verilir, Kesme oluşup, program kesme alt programına dallandığında INTF bitini 0 yap. Yrd.Doç.Dr. Bülent ÇOBANOĞLU
Örnek: RB0 girişine bağlı butonun harici kesme mekanizması kullanılarak RD0 a bağlı olan LED Toggle olarak çalıştırması istenmektedir. #include <htc.h> #define LED RD0 interrupt kesme(){ if(intf){ main(){ TRISD0=0; LED=1; INTF=0; INTE=1; INTEDG=0; GIE=1; while(1); // RB0 kesme bayrağı 1 ise INTF=0; // Bayrağı sıfırla ve LED=!LED; // Çıkış Led'ini tersle // Led için RD0'ın çıkış yapılması // Led yansın // RB0 kesme bayrağı // RB0 kesme yetkisi // Harici tetikleme girişi 1 -> Yükselen, 0->Düşen kenar // Global kesme yetkisi // Sonsuz döngüde kesme bekle
Çalışma Sorusu: 1. RB0 pinine bağlı olan bir tuşa her basıldığında kesme üreten ve PD4-PD7 pinlerine bağlı olan 4 adet led ile 0-9 arasında binary sayan program kodlarını yazın. 2. Şekilde çalışma devresi verilen Çamaşır makinesinin programını yazınız.
PORTB Değişim Kesme Olayı PORTB nin 4,5,6,7. pinlerinden en az birinde durum değişikliği olması durumunda RB Port değişimi kesme olayı meydana gelir. INTCON 7.biti GIE ile kesmelerine izin verilir. INTCON 3. biti RBIE biti ile kesmeye izin verilir. INTCON 0. biti RBIF kesme bayrağı biti PORTB nin 4,5,6,7 pinlerindeki değişikliği bildirir. INTCON
Örnek: PORTB nin 4,5,6,7 pinlerindeki butonlardan herhangi birisine basılması ile kesme alt programı çalışarak kesme olayı hangi pin de olduğunu PORTD nin 0,1,2,3 pinlerindeki LED lerde görülmesi.
Örnek: PORTB nin 4,5,6,7 pinlerindeki butonlardan herhangi birisine basılması ile kesme alt programı çalışarak kesme olayı hangi pin de olduğunu PORTD nin 0,1,2,3 pinlerindeki LED lerde gösteren Assembly programı. LIST P=16F877 INCLUDE "P16F877.INC" ORG 0X00 GOTO BASLA ORG 0X04 KESME GOTO KESME BASLA D1 BSF STATUS,5 MOVLW 0XF0 MOVWF TRISB D2 CLRF TRISD BCF STATUS,5 CLRF PORTD D3 CLRF PORTB BSF INTCON,RBIE BSF INTCON,GIE D4 GOTO BASLA BCF INTCON,RBIF BTFSS PORTB,4 GOTO D1 BSF PORTD,0 BTFSS PORTB,5 GOTO D2 BSF PORTD,1 BTFSS PORTB,6 GOTO D3 BSF PORTD,2 BTFSS PORTB,7 GOTO D4 BSF PORTD,3 RETFIE END
TMR0 Kesmesi TMR0 taştığında kesme oluşur. INTCON 7.biti GIE ile kesmelerine izin verilir. INTCON 5. biti T0IE biti ile kesmeye izin verilir. INTCON 2. biti T0IF kesme bayrağı ile kesme belirlenir. INTCON
Örnek: TMR0 kesme mekanizmasını kullanarak RD0 çıkışında 10 hz lik bir kare dalga sinyal elde ediniz. #include <htc.h> #define LED RD0 /*TMR0 taştığında çağırılır*/ interrupt KesmeTMR0(){ if(t0if){ TMR0=-200; main(){ LED=!LED; T0IF=0; // Kesme oldu ise // TMR0'a başlangıç değerini yeniden ata. // LED'ini değille. // Kesme bayrağını sıfırla. TRISD0=0; // RD0 çıkış T0CS=0; // TMR0, Timer olarak çalışsın T0SE=1; // Yükselen kenar tetikleme PSA=0; // WDT pasif T/C aktif PS0=1; // Ön yükleyici 111 => 256'e bölünecek PS1=1; // OSC=4 MHz, Timer => 1Mhz / 256 PS2=1; // Timer bir sayması 256 usn TMR0=-200; // TMR0=-200 => 256 usn x 200 =51.200 usn T0IF=0; // TMR0 kesme bayrağını resetle T0IE=1; // TMR0 kesmesi aktif GIE=1; // Global kesme aktif while(1); // Kesme bekle
TMR1 Kesmesi TMR1 taştığında kesme oluşur. INTCON 7.biti GIE ile global olarak kesmeye izin verilir. INTCON 6.biti PEIE ile çevre birim kesmelerine izin verilir. PIE1 0.biti TMR1IE ile kesmelerine izin verilir. PIR1 0.biti TMR1IF ile kesme kontrol edilir.
Örnek.TMR1 kesme mekanizmasını kullanarak RD0 çıkışında 0,5 sn aralıklarla değişen bir kare dalga sinyal oluşturunuz. #include <xc.h> #define LED RD0 /* TMR1 kesme hizmet fonksiyonu (4 Mhz'lik kristalde 0,5sn aralıklarla bu fonksiyona girilir)*/ void main(){ LED=0; TRISD0=0; TMR1ON=1; TMR1CS=0; // RD0 portu çıkış // TMR1 aktif // Dahili clock (timer) T1CKPS0=1; // Ön Bölücü 11 T1CKPS1=1; // 1:8 (8 usn) TMR1H=3036/256; // 65536-62500=3036 say TMR1L=3036%256; // 62500 sayma x 8 usn = 0.5 sn TMR1IF=0; resetle TMR1IE=1; PEIE=1; kesmeleri aktif GIE=1; while(1); // TMR1 kesme bayrağını // TMR1 kesmesi aktif // Çevre birim // Global kesme aktif // Kesme bekle void interrupt kesmetmr1() { if(tmr1if){ // Kesme geldi mi? TMR1H=3036/256; //0'lanan TMR1 a yeniden 3036 değeri yükle TMR1L=3036%256; // 62500 sayma x 8 usn = 0.5 sn LED=~LED; // Çıkış LED'ini tersle TMR1IF = 0; // TMR1 kesme bayrağını sıfırla. Açıklama: 4MHz, 1µSn dir ve 500.000 sayım için Timer 1 i 62.500 e kadar saydıracak olursak; Prescaler oranını 1:8 seçdiğimizde 62500*8=500000 yani 0,5 sn lik gecikme demektir. O zaman bu örnekte TMR1 e başlangıç değeri olarak; 65536-62500=3036 değeri yüklenmelidir. Not: 3036 sayısının hex karşılığı:0x 0BDC de yüklenebilir.
Birden fazla kesmenin bir arada kullanılması interrupt Kesme(){ if(t0if){ // Timer kesmesi var mı?. if(intf){ // RB0 kesmesi var mı?.. if(tmr1if) { // TMR! Kesmesi var mı?.... if(rcif) { // Seri port alım kesmesi var mı?....
Örnek: 2 haneli çoğullamalı displayde 0-99 arası sayıların sayılması istenmektedir. Sayma işlemi RB0 a bağlı olan bir buton yardımıyla ve RB0 kesmesi ile yapılmalıdır. Display lere segment değerlerinin sıra ile gönderimi ise 1msn aralıklar la ve TMR0 kesmesi ile yapılmalıdır. 13 14 2 3 4 5 6 7 8 9 10 1 U1 OSC1/CLKIN RB0/INT OSC2/CLKOUT RB1 RB2 RA0/AN0 RB3/PGM RA1/AN1 RB4 RA2/AN2/VREF-/CVREF RB5 RA3/AN3/VREF+ RB6/PGC RA4/T0CKI/C1OUT RB7/PGD RA5/AN4/SS/C2OUT RC0/T1OSO/T1CKI RE0/AN5/RD RC1/T1OSI/CCP2 RE1/AN6/WR RC2/CCP1 RE2/AN7/CS RC3/SCK/SCL RC4/SDI/SDA MCLR/Vpp/THV RC5/SDO RC6/TX/CK RC7/RX/DT RD0/PSP0 RD1/PSP1 RD2/PSP2 RD3/PSP3 RD4/PSP4 RD5/PSP5 RD6/PSP6 RD7/PSP7 PIC16F877A 33 34 35 36 37 38 39 40 15 16 17 18 23 24 25 26 19 20 21 22 27 28 29 30 7 1 2 6 4 5 3 U2 A B C D BI/RBO RBI LT 7447 R1 10k QA QB QC QD QE QF QG 13 12 11 10 9 15 14
Örnek: Birden fazla kesmenin kullanılması (Çoğullamalı Display) #include <htc.h> #define segment PORTD #define OU1 RC6 #define OU2 RC7 main(){ TRISD=0xF0; // Segmentlerin bağlı olduğu PORTD'nin 4 biti çıkış yap TRISC6=0; // Display'in 1.Ortak ucu için PORTC'nin 6 bitini çıkış yap TRISC7=0; // Display'in 2.Ortak ucu için PORTC'nin 7 bitini çıkış yap T0CS=0; // TMR0, Timer olarak çalışsın T0SE=1; // Yükselen kenar tetikleme PSA=0; // WDT pasif T/C aktif PS0=0; // Ön yükleyici 001 => 4'e bölünecek PS1=0; // OSC=4 MHz, Timer => 1Mhz / 4 PS2=1; // Timer'ın bir sayması 4 usn TMR0=-250; // TMR0=-250 => 250 sayıp taşacak yani 4 usn x 250 =1 msn T0IF=0; // TMR0 kesme bayrağını resetle T0IE=1 // TMR0 kesmesi aktif INTF=0 // RB0 kesme bayrağını resetle INTE=1 // RB0 kesme yetkisi INTEDG=0; // Harici kesme tetikleme giriş 0 -> Yükselen, 1->Düşen kenar GIE=1; // Global kesme aktif while(1); // Kesme bekle
Örnek: Birden fazla kesmenin kullanılması (Çoğullamalı Display) /*TMR0 taştığında veya RB0 kesmesi geldiğinde çağırılır*/ interrupt KesmeTMR0(){ static unsigned char sayac=0; //Butona her badıldığında oluşacak sayıyı tutan değişken static bit durum=0; // Timer taşınca farklı segmente değer gönderimini sağlayacak değişken. if(t0if){ // Timer taştı mı? (1 msn oldu mu?) durum=!durum; // durum değişkeni tersle if(durum){ // Eğer durum=1 ise display'e sayac'ın birler basamağını gönder OU1=0; // Soldaki Display' pasif et segment=sayac%10; // Sayının birler basamağını segmentlere gönder OU2=1; // Sağdaki displayi aktif et else{ // Eğer durum=1 ise display'e sayac'ın birler basamağını gönder OU2=0; // Sağdaki Display'i pasif et segment=sayac/10; // Sayının onlar basamağını segmentlere gönder OU1=1; // Soldaki displayi aktif et TMR0=-250; // TMR0'a başlangıç değerini yeniden ata. T0IF=0; // Timer Kesme bayrağını sıfırla. if(intf){ // RB0 kesmesi oldu mu? (Butona basıldımı) sayac=(++sayac)%99; // Sayma sayısını maksimum 99'a kadar bir arttır. INTF=0; // RB0 kesme bayrağını sıfırla
Seriport Kesmeleri Seriport tan bir karakter gönderimi bittiğinde veya karakter alımı bittiğinde seriport kesmesi oluşur. INTCON 7.biti GIE ile global olarak kesmeye izin verilir. INTCON 6.biti PEIE ile çevre birim kesmelerine izin verilir. PIE1 4. ve 5.bitleri olan RCIE ve TXIE ile kesmelere izin verilir. PIR1 4. ve 5. bitleri olan TXIF ve RCIF ile kesmeler kontrol edilir.
Seri port kesme işleyişi YRD.DOC.Dr.BÜLENT ÇOBANOĞLU
Örnek: 2 haneli çoğullamalı displayde 0-99 arası sayıların sayılması istenmektedir. Sayma işlemi RB0 a bağlı olan bir buton yardımıyla ve RB0 kesmesi ile yapılmalıdır. Display lere segment değerlerinin sıra ile gönderimi ise 1msn aralıklar la ve TMR0 kesmesi ile yapılmalıdır. Seriport kesmesi kullanılarak herhangi bir anda seriportttan s karakterine basılarak sayıcının sıfırlanması sağlanmalıdır. R1 10k 13 14 2 3 4 5 6 7 8 9 10 1 U1 OSC1/CLKIN RB0/INT OSC2/CLKOUT RB1 RB2 RA0/AN0 RB3/PGM RA1/AN1 RB4 RA2/AN2/VREF-/CVREF RB5 RA3/AN3/VREF+ RB6/PGC RA4/T0CKI/C1OUT RB7/PGD RA5/AN4/SS/C2OUT RC0/T1OSO/T1CKI RE0/AN5/RD RC1/T1OSI/CCP2 RE1/AN6/WR RC2/CCP1 RE2/AN7/CS RC3/SCK/SCL RC4/SDI/SDA MCLR/Vpp/THV RC5/SDO RC6/TX/CK RC7/RX/DT RD0/PSP0 RD1/PSP1 RD2/PSP2 RD3/PSP3 RD4/PSP4 RD5/PSP5 RD6/PSP6 RD7/PSP7 33 34 35 36 37 38 39 40 15 16 17 18 23 24 25 26 19 20 21 22 27 28 29 30 7 1 2 6 4 5 3 U2 A B C D BI/RBO RBI LT 7447 QA QB QC QD QE QF QG 13 12 11 10 9 15 14 RXD TXD RTS CTS
Örnek: Birden fazla kesmenin kullanılması (Çoğullamalı Display+ Seriport) #include <htc.h> #define segment PORTD #define OU1 RC0 #define OU2 RC1 main(){ TRISD=0xF0; // Segmentlerin bağlı olduğu PORTD'nin 4 biti çıkış yap TRISC0=0; // Display'in 1.Ortak ucu için PORTC'nin 0 bitini çıkış yap TRISC1=0; // Display'in 2.Ortak ucu için PORTC'nin 1 bitini çıkış yap T0CS=0; // TMR0, Timer olarak çalışsın T0SE=1; // Yükselen kenar tetikleme PSA=0; // WDT pasif T/C aktif PS0=0; // Ön yükleyici 001 => 4'e bölünecek PS1=0; // OSC=4 MHz, Timer => 1Mhz / 4 PS2=1; // Timer'ın bir sayması 4 usn TMR0=-250; // TMR0=-250 => 250 sayıp taşacak yani 4 usn x 250 =1 msn T0IE=1; // TMR0 kesmesi aktif INTE=1; // RB0 kesme yetkisi INTEDG=0; // Harici kesme tetikleme giriş 0 -> Yükselen, 1->Düşen kenar RCIE=1; // Seriport alım kesmesi aktif TXIE=1; // Seriport gönderim kesmesi aktif PEIE=1; // Çevre birim kesmeleri aktif GIE=1; // Global kesme aktif UARTBaslat(); printf("\r Sayiciyi sifirlamak icin <s> tusuna basiniz..\n"); while(1); // Kesme bekle
Örnek: Birden fazla kesmenin kullanılması (Çoğullamalı Display+ Seriport) # /*TMR0 taştığında,rb0 kesmesi geldiğinde veya seriporttan karakter geldiğinde çağırılır*/ interrupt KesmeTMR0(){ static unsigned char sayac=0; //Butona her badıldığında oluşacak sayıyı tutan değişken static bit durum=0; // Her 1 msn'de farklı segmente değer gönderimini sağlayacak değişken. if(t0if){ // Timer taştı mı? (1 msn oldu mu?) durum=!durum; // durum değişkeni tersle if(durum){ // Eğer durum=1 ise display'e sayac'ın birler basamağını gönder OU1=0; // Soldaki Display' pasif et segment=sayac%10; // Sayının birler basamağını segmentlere gönder OU2=1; // Sağdaki displayi aktif et else{ // Eğer durum=1 ise display'e sayac'ın birler basamağını gönder OU2=0; // Sağdaki Display'i pasif et segment=sayac/10; // Sayının onlar basamağını segmentlere gönder OU1=1; // Soldaki displayi aktif et TMR0=-250; // TMR0'a başlangıç değerini yeniden ata. T0IF=0; // Timer Kesme bayrağını sıfırla. if(intf){ // RB0 kesmesi oldu mu? (Butona basıldımı) sayac=(++sayac)%99; // Sayma sayısını maksimum 99'a kadar bir arttır. INTF=0; // RB0 kesme bayrağını sıfırla if(rcif){ // seriporttan veri geldi mi? TXREG=RCREG; // Gelen verinin gözükmesi için yeniden gönder if(rcreg=='s' RCREG=='S') // Gelen karakter s(s) ise sayac=0; // Sayacı sıfırla RCIF=0; // Seriport alma bayrağını sıfırla