PIC16F1508 – GPIO İşlemleri

Mikrodenetleyiciler, içerisine program yazarak hayatımızı kolaylaştırmaya yarayan mini bilgisayarlardır. Bu eğitimde PIC16F1508 mikrodenetleyicisi kullanılarak MPLAB ortamında XC8 dili ile Genel Amaçlı Giriş-Çıkış İşlemlerinin uygulamaları yapılacak. Öncelikle devrenin tasarımını KiCAD üzerinde yapılacak daha sonra ise bu devreye özgü uygulamalar geliştirilecek. Bu uygulamalar ile MPLAB ortamında nasıl kod yazıp derlenileceği öğrenilecek ve PIC mikrodenetleyicisi ile bir pini nasıl giriş-çıkış olarak kullanılabileceği gösterilecek.

Neden PIC?

Arduino gibi platformların ilgisinin daha fazla olduğu bu dönemde neden PIC öğrenmeliyiz? Sözünü ettiğimiz platformlar daha çok prototipleme işlemleri için kullanılmaktadır. PIC ise projelerin prototiplemeden çıkıp ürüne dönüştüğü yerlerde kullanılabileceği bir yongadır. Arduino’nun kullandığı Atmel veya ST mikrodenetleyicilerini de kullanabiliriz fakat kaynak bakımından PIC mikrodenetleyicileri daha zengin olduğu için Atmel (veya ST) mikrodenetleyicilerden öncelikli olarak öğrenilebilir.

PIC16F1508’in Özellikleri

Mikrodenetleyicinin çoğu özellikleri altta listelenmiştir.

  • Dahili 16MHz kristale sahip. Böylelikle harici bir kristal kullanma zorunlulluğumuz bulunmamaktadır.
  • 4 x PWM modülü. Bu modül ile kare dalga sinyali üretebiliriz ve bunu kullanarak motor sürebiliriz.
  • 4 x Yapılandırılabilir Mantık Hücresi (CGC). Bu hücreler ile Flip Flop ve bazı kapılar ile mantık işlemlerini gerçekleyebiliriz.
  • Entegre Sıcaklık Göstergesi Modülü. Bu modül ile -40°C ile +85°C arasındaki sıcaklıkları ölçebiliriz.
  • 12 kanal 10-bit ADC Modülü. Bu modül ile analog bir veriyi okuyup dijitale dönüştürebiliriz. Örneğin ayarlı direnç ile oluşan analog veri.
  • 5-bit DAC Modülü. Bu modül ile dijital bir veriyi analog bir veriye dönüştürebiliriz.
  • 2 x Karşılaştırıcı Modülü
  • EUSART, I2C ve SPI Modülü. Haberleşme için kullanırız.
  • 2 x 8-bit Timer (TMR0/TMR2)
  • 1 x 16-bit Timer (TMR1)
  • Genişletilmiş WDT

KiCAD Şematik Tasarımı

Genel Amaçlı Giriş-Çıkış İşlemleri (GPIO) Uygulaması için 4 adet LED (Çıkış) ve 2 adet Buton (Giriş) kullanarak devremizi tasarladık. Bunlara ek olarak devre için 5V çıkışlı regülator (açma-kapama için bir anahtar ve ters gerilim koruması için diyot eklendi.), PICkit ile program yüklemek için ICSP pinleri ve Reset butonu ekledik.

PIC16F1508 GPIO İşlemleri – Şematik

KiCAD PCB Tasarımı

PIC16F1508 GPIO İşlemleri – PCB

KiCAD 3D Görünümü

PIC16F1508 GPIO İşlemleri – 3D

Uygulama 1 – LED Yakıp Söndürme

Bu uygulamada RB4 pinine bağl LED1’i 1 saniye aralıklarla yakıp söndürmeyi göstereceğiz.

Öncelikle MPLAB X IDE uygulamasını çalışırıp File > New Project… yoluna tıklayarak aşağıdaki işlemleri uygulayalım.

Projemizi oluşturduktan sonra main.c dosyasını oluşturalım.

Main.c dosyasını oluşturduktan sonra yapmamız gereken iş konfigürasyon bitlerini ayarlamaktır. Bunun için üst menüten Production > Set Configuration Bits ‘e tıklayarak Configuration Bits penceresini açıyoruz ve aşağıdaki gibi ayarlıyoruz. Daha sonra Generate Source Code to Output butonuna tıklayarak kaynak kodun oluşmasını sağlıyoruz ve pencerede çıkan kodu kopyalayarak main.c dosyası içerisine ekliyoruz.

Osilatör Ayarları

Konfigürasyon bitlerinde belirttiğimiz gibi biz osilatör olarak mikrodenetleyici içerisinde bulunan osilatörü kullanacağımızı belirttik. Şimdi ise bunu yazılımda belirtmemiz ve osilatörün kaç MHz olacağını ayarlamamız gerekiyor. Bunun için OSCCON Yazmacını ayarlıyoruz.

OSCCON Register

OSCCON Yazmacının 2. ve 7. bitleri bir fonksiyona sahip değil. 0. ve 1. bit ile System Clock Select bits (Sistem Zaman Seçim bitleri)’ni ayarlıyoruz. 3-6. bitler ile eğer dahili osilatör kullanılacaksa bunun hangi frekasta olacağını ayarlıyoruz. Daha fazla bilgi için alttaki butona tıklayın.

Şuan için OSCCON Yazmacını 16MHz dahili kristal olarak ayarlıyoruz.

_XTAL_FREQ Tanımı

Kodlarımızı yazarken bazı fonksiyonlar için _XTAL_FREQ tanımına ihtiyaç vardır. Örneğin __delay_ms() fonksiyonu için zamanı hesaplamada bu tanıma ihtiyaç vardır. Sonuç olarak bizim kullanacağımız temel kod aşağıdaki gibi olacaktır.

/*
* File: main.c
* Author: elektroneo
*
* Created on July 5, 2019, 10:31 PM
*/
// PIC16F1508 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#define _XTAL_FREQ 16000000
#include <xc.h>
void main(void) {
OSCCONbits.SCS = 0b10; // Internal oscillator.
OSCCONbits.IRCF = 0b1111; // 16 MHz internal crystal.
while(1) {
// Loop…
}
}

While döngüsü içerisine yazacağımız kodlar sürekli çalışmasını istediğimiz kodlar olacaktır. Onun üstüne yazacağımız kodlar ise bir kerelik çalıştırılacak başlangıç kodlarını yazıyoruz.

LED1’i bağşadığımız RB4 pinini çıkış yapmak için TRISB yazmacının 4. bitini 0 yapıyoruz. Daha sonra while döngüsü içerisinde PORTB bitinin 4. bitini sırasıyla arasına __delay_ms(500) ile 500 milisaniyelik bekleme koyarak 1 ve 0 yaparak ledin yanıp sönmesini sağlıyoruz.

Not: ANSELB Yazmacını 0 (sıfır) yaparak analog çıkışı pasif etmemiz gerekiyor.

/*
* File: main.c
* Author: elektroneo
*
* Created on July 5, 2019, 10:31 PM
*/
// PIC16F1508 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#define _XTAL_FREQ 16000000
#include <xc.h>
void main(void) {
OSCCONbits.SCS = 0b10; // Internal oscillator.
OSCCONbits.IRCF = 0b1111; // 16 MHz internal crystal.
// For digital i/o operations
ANSELB = 0;
TRISBbits.TRISB4 = 0;
while(1) {
PORTBbits.RB4 = 0;
__delay_ms(500);
PORTBbits.RB4 = 1;
__delay_ms(500);
}
}

Toggle (Tersini Alma) işlemi ile bir pinin durumunu kolayca değiştirebiliriz. Aşağıda verilen örnekte gösterildiği gibi üstteki ve alttaki kod parçası aynı işlemi yapmaktadır.

// Toggle RB4 pin.
PORTBbits.RB4 = 0;
__delay_ms(500);
PORTBbits.RB4 = 1;
__delay_ms(500);
//================
// Toggle RB4 pin.
PORTBbits.RB4 ^= 1;
__delay_ms(500);
view raw Toggle-Trick.c hosted with ❤ by GitHub

Kodumuzu yazdıktan sonra F11 tuşu ile derleme işlemini yapyoruz. Derleme işlemi başarıyla bittikten sonra MPLAB X Projesini klasörde açıp dist/default/production/*.hex dosyasını Proteus için mikrodenetleyiciye ekleyerek PICkit kullanıyorsak MPLAB IPE ile mikrodenetleyiciye yükleyebiliriz.

Uygulama 2 – Sıralı LED Yakma

4 LED’in hepsini kullanarak sırasıyla yanmasını sağlayan bir uygulama yapacağız. Bunun için for döngüsünü kullanarak yapabiliriz. Aşağıdaki kod ile sırasıyla 1, 2, 3 ve 4. LED’leri yakacak daha sonra 4, 3, 2 ve 1. LED’leri yaparak sonsuz döngüde sürdürecek.

// PIC16F1508 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#define _XTAL_FREQ 16000000
#include <xc.h>
void main(void) {
// Internal oscillator.
OSCCONbits.SCS = 0b10;
// 16 MHz internal crystal.
OSCCONbits.IRCF = 0b1111;
// For digital i/o operations
ANSELB = 0;
// PORTB as Output
TRISB = 0;
PORTB = 0b00010000;
while(1) {
for(short i = 0; i < 3; i++) {
PORTB <<= 1;
__delay_ms(500);
}
for(short i = 0; i < 3; i++) {
PORTB >>= 1;
__delay_ms(500);
}
}
}

Yukarıdaki kodda bulunan PORTB <<= 1 ve PORTB >>= 1 işlemleri ile PORTB Yazmacı içerisinde bulunduğu değeri alıp 1 sola veya sağa kaydırarak tekrar PORTB’ye atıyoruz.

Örneğin, PORTB’nin değeri ikili sayı sisteminde 00010000 olsun. PORTB <<= 1 işlemi uyguladığımızda PORTB’nin yeni değeri 00100000 olacaktır

Uygulama 3 – Buton İle LED Yakıp Söndürme

BTN1 ve BTN2 butonlarına basıldığında aşağıdaki işlemleri yapan bir uygulama yapacağız. Butonlar için 0 > basılı değil, 1 > basılı anlamı verecektir. LED’ler için ise 0 > yanık, 1 > sönük olacaktır.

BTN2BTN1LED1LED2LED3LED4
001000
010100
100010
110001
short btn1 = PORTAbits.RA0;
short btn2 = PORTAbits.RA1;
view raw Button-Input.cpp hosted with ❤ by GitHub

PORTA’nın 0. ve 1. bitlerinde bulunan veriyi almak için (buton durumunu kontrol etmek için) aşağıdaki kod parçası kullanılır.

short btn1 = PORTAbits.RA0;
short btn2 = PORTAbits.RA1;
view raw Button-Input.c hosted with ❤ by GitHub

Yaptığımız bu 3 uygulama ile GPIO (Genel Amaçlı Giriş Çıkış İşlemleri)’ni anlamış olduk.

Yorum Gönderin

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir