Menu

728x90

468x60

Navbar

Saturday, August 14, 2021

Programming the External Interrupt of PIC16F818 in XC8

 

Introduction

In microcontroller, interrupt is hardware or software event notification to the system. Each time interrupt occurs the system could respond or ignore to that event. Amount of interrupt capabilities of microcontroller is different. Interrupt triggered by internal or external events.

Programming the External Interrupt of PIC16F818 in XC8
Simulation Sample of this programming example


PIC16F818 has many interrupt sources that we can not list them all here. External interrupt is an interrupt source triggered by external logic change on pin RB0 of port B in PIC16F818/819. It can be an interrupt on falling or rising edge depends on user configuration in software.

External Interrupt Preparation

There are many steps of software configuration in programming. We will need to configure port data direction, interrupt edge, global interrupt control, etc.

Port Data Direction

Pin RB0 must be a digital input as it’s a logic input to the microcontroller. An optional weak pull-up resistor could save the number of external add-on components and circuit wiring. Hence the user must clear nRBPU of the OPTION register.

Programming the External Interrupt of PIC16F818 in XC8
OPTION Register

But the interrupt edge must selected to work in falling edge of input logic.

Interrupt Edge Selection

Edge of external interrupt are rising and falling edge. The user select between these two mode using Interrupt Edge Select Bit (INTEDG) of the OPTION register.

Programming the External Interrupt of PIC16F818 in XC8
Interrupt Edge Select Bit

Clearing this bit to select the interrupt on falling edge from external input device – for example a motion sensor.

Turning on External Interrupt

Interrupt Control Register (INTCON) consists of many interrupt source setting and interrupt flag, including the external interrupt. An interrupt flag in PIC microcontroller is set whenever the corresponding interrupt source occurs. The user must test and clear this flag in software at the time it occurs and ended.

Programming the External Interrupt of PIC16F818 in XC8
Interrupt Control Register (INTCON)

Bit 7 of INTCON is a Global Interrupt Enable bit (GIE) is a general interrupt switch. Setting to ‘1’ before other interrupt sources are enabled.

Bit 4 is an External Interrupt Enable bit (INTE). Setting this bit to turn on external interrupt on RB0.

Bit 1 is an External Interrupt Flag bit (INTF). This bit must be cleared first in the first program configuration for the external interrupt. In the Interrupt Service Routine (ISR), the code must test this bit to find its occurrence.

Interrupt Service Routine

An Interrupt Service Routine (ISR) is a piece of code written in the interrupt vector of PIC microcontroller. It responses to the interrupt whenever it’s enabled an occured.

In mid-range PIC microcontroller as PIC16F818 there is only one interrupt vector locates at the address 0x04 in program memory. However in a high level programming language like XC8 we don’t care about this vector. ISR in XC8 is just a C function but it’s reserved for interrupt vector.

void interrupt _ISR_NAME(void){
//Code here
}

In ISR the user must test the interrupt flag, writing codes to response to interrupt, and clear interrupt flag.

XC8 Programming for External Interrupt

This simple external interrupt programming example show a blinking LED as its normal main program routine. Whenever the external interrupt occurs, it toggles an output LED.

Schematic Diagram

External interrupt attaches to RB0 while two output LED are the main program loop blinking and another LED is interrupt response.

Programming the External Interrupt of PIC16F818 in XC8
Schematic diagram for this interrupt programming example

SW2 triggers the external interrupt at whenever it’s pressed.

XC8 Programming

Software setting configure this controller to use its internal oscillator clocks at 4MHz. Other remaining code are written to support the interrupt capabilities.

/*PIC16F818 External Interrupt Example
 * Using MPLABX XC8
 */
#include <xc.h>

// PIC16F818 Configuration Bit Settings
// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#define _XTAL_FREQ 1000000

/*Naming the Output LED*/
#define toggleLed   RB7
#define blinkLed    RB6

void main(void){
    /*Oscillator Setup 1MHz*/
    OSCCONbits.IRCF=0x04;
    /*Clear Port B*/
    PORTB=0x00;
    /*RB0 Input */
    TRISB=0x01;
    /*Turn On Pull Up Resistor*/
    nRBPU=0;
    /*Enable Global Interrupt*/
    GIE=1;
    /*Enable External Interrupt*/
    INTE=1;
    /*Select Interrupt on Falling Edge*/
    INTEDG=0;
    /*Clear Interrupt Flag*/
    INTF=0;
    while(1){
        blinkLed^=1;
        __delay_ms(250);
    }
}

void interrupt _ISR(void){
  /*Test external interrupt flag*/
    if(INTF){
      /*Clear flag*/
        INTF=0;
      /*Toggle LED*/
        toggleLed^=1;
    }
}

Click here to download this example archive.

Thursday, August 12, 2021

Programming Timer0 of PIC16F818 in XC8

 

Introduction

Timer of a microcontroller is an auto-incremental register configured by user’s program. It’s useful for creating a timing delay, measuring the duration of external event, etc.

Programming Timer0 of PIC16F818 in XC8
A software simulation sample of this programming example


Timer0 of PIC16F818

Timer0 is an 8-bit read/write register locates at the address 01h and 101h in SFR. Timer0 works in both timer and counter mode, but we mention only timer mode in this post.

Programming Timer0 of PIC16F818 in XC8
Block Diagram of Timer0/WDT Prescaler

This peripheral module contains its storage register TMR0, control registers and its interrupt flag.

Prescaler Selection

Both timer and counter mode have a programmable prescaler, as it’s configured in Option register (OPTION_REG).

Programming Timer0 of PIC16F818 in XC8
OPTION_REG of PIC16F818

Its 8-bit Prescaler must between Timer0 and Watch Dog Timer (WDT) prescaler. These two prescaler selection is set in Prescaler Assignment bit (PSA). Setting PSA assigns its prescaler to the WDT, otherwise it’s assigned to Timer0 module.

Prescaler Rate Select bits (PS2:0) of the OPTION_REG configures the prescaler between 1:1 and 1:256.

Programming Timer0 of PIC16F818 in XC8
Prescaler Rate Select bits (PS2:0)

To get a 1:1 prescaler it must switch to WDT Rate. But getting a 1:256 prescaler rate it must switch to TMR0 Rate as listed above.

Timer0 Overflow and Interrupt

Timer0 register TMR0 is an 8-bit wide register. As it’s configured to a free running register that clocks from the microcontroller instruction clock, it triggers an interrupt flag at the time it reaches 0xFF (255 in decimal) and rolls back to 0. This interrupt flag is called Timer0 Overflow Interrupt Flag (TMR0IF), locates in the INTCON.

Programming Timer0 of PIC16F818 in XC8
Timer0 Overflow Interrupt Flag (TMR0IF) of INTCON

User’s program must clear this flag in code. This flag is auto-set whenever the overflow happens regardless of Timer0 Interrupt Enable bit (TMR0IE). We will show about timer 0 interrupt programming in later post.

Timer0 Programming in XC8

We have mentioned about timer utilization in microcontroller. Now we will use this microcontroller inside’s to create a timing delay of about one second. This one second pulse blink the LED.

Circuit Design

Microcontroller system circuit is very simple. It’s just build with a +5V power supply unit and its output LED connects to RB7. We don’t need microcontroller reset circuit and crystal oscillator.

Programming Timer0 of PIC16F818 in XC8
Circuit diagram without reset and clock circuit

Calculation for Timer 0 Overflow

With its feature of internal RC oscillator, the system select its 8MHz maximum clock frequency to heart-beat the CPU. For Mid-Range PIC device its instruction rate is,

Fosc/4 = 8MHz/4 = 2MHz or 2MIPS , as its instruction executing time is mostly completed in only one instruction cycle.

The cycle time of its instruction clock is,

1/(2MHz) = 0.5us.

I choose the 1:256 prescaler. So timer 0 clock input has a rate of.

256*0.5us = 128us.

Eight-bit TMR0 register overflows and set its interrupt flag within this duration,

256*128us = 32.768ms.

To find an approximate 1 second delay,

1/(32.768ms) = 30.51 counts or 31 counts.

All setting will be set and shown in programming section next time.

XC8 Programming

XC8 program set the controller to utilize its 8MHz maximum clock frequency as it’s done with OSCCON register. Option register configure timer 0 mode of operation to work as a free running counter with a prescaler of 1:256.

The program main loop regularly test the interrupt flag (TMR0IF). As it’s set a C variable will increase by 1, until it reaches a one second count. The the time of getting its one second count, RB7 toggles its output LED.

Its C program made of between 40 and 50 lines of code.

/*
 */
#include <xc.h>
// PIC16F818 Configuration Bit Settings
// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
#define onSecondCounts  31
void main(void){
    unsigned int intCounts=0;
    /*Select 8MHz Crystal Frequency*/
    OSCCONbits.IRCF=0x07;
    /*Clear Port B*/
    PORTB=0x00;
    /*RB7 digital output*/
    TRISB&=~(1<<7);
    /*Select internal MCU clock for Timer0*/
    T0CS=0;
    /*Select Timer 0 Prescaler*/
    PSA=0;
    /*Select 1:256 Prescaler*/
    OPTION_REGbits.PS=0x07;
    /*Clear timer 0 overflow interrupt flag*/
    TMR0IF=0;
    /*Clear Timer 0*/
    TMR0=0;
    while(1){
        if(TMR0IF){
            TMR0IF=0;
            intCounts+=1;
        }
        if(intCounts>=onSecondCounts){
            intCounts=0;
            RB7^=1;
        }
    }
}

Generated hex file requires only 4.7% of the total program memory space.

Program Testing

Both software simulation and physical hardware experiment work in the same manner. However in Proteus simulator the delay time is shorter than in physical hardware experiment.

Programming Timer0 of PIC16F818 in XC8
microcontroller program experiment on breadboard

I don’t show the picture of Proteus simulation here due its duplication. Click here to download this example in zip file format.


Tuesday, August 10, 2021

PIC16F818 Timer0 Interrupt Programming in XC8

 

Introduction

As it’s discussed in previous post, Timer0 of PIC microcontroller is able to trigger an interrupt signal every time its timer register overflows and reset to its initial value of 0.

Programming for Timer0 interrupt is just like other interrupt programming for PIC microcontroller in MPLABX XC8. The programmer is required to enable its global interrupt switch, Timer0 interrupt enable bit, writing an interrupt service routine, etc.

Timer0 Interrupt Programming

We have discussed a lot in previous post about a preparation for interrupt in XC8 programming. Special function registers relate to this interrupt are already shown in these posts.

More About Related Registers

Option register (OPTION_REG) is in used for selecting clock source, timer mode and its clock prescaler.

PIC16F818 Timer0 Interrupt Programming in XC8
OPTION Register – OPTION_REG

Interrupt Control Register (INTCON) contain some fundamental interrupt control bits and flags.

PIC16F818 Timer0 Interrupt Programming in XC8
Interrupt Control Register – INTCON

Set Global Interrupt Enable (GIE) bit to enable interrupt for any interrupt source.

Timer0 Overflow Interrupt Enable (TMR0IE) bit must be set to turn on timer 0 interrupt capability.

Timer0 Overflow Interrupt Flag (TMR0IF) bit functions as a testing flag to find the present of timer 0 overflow interrupt occurrence. Initially the program must clear this flag and Timer0 register (TMR0) in software.

Circuit Diagram for Hooking Up and Simulation

The system is prepared to utilize an external crystal oscillator with its maximum frequency of 20MHz. It’s optionally have a reset circuit as usual micro-controllers have. We can ignore this reset circuit in configuration section in source code as it was done in previous post.

PIC16F818 Timer0 Interrupt Programming in XC8
Circuit diagram for both physical hardware prototyping and software simulation

XC8 Programming

Since the system clock is 20MHz we will need to find all related timing parameters to predict the interrupt interval.

Instruction executing speed is a quarter of microcontroller clock source. So the microcontroller speed is,

FOSC = (20MHz/4) = 5MHz or 5MIPS.

Instruction executing frequency is.

(1/5MHz) = 0.2us.

Timer0 prescaler is 1:256 then Timer0 input clock rate is,

(256*0.2us)= 51.2us.

Timer0 overflow interrupt occurs for every,

(256*51.2us) = 13.1ms.

Finally for every 13.1ms, RB0 of PIC16F818 changes its output logic state.

/*
 * PIC16F818 Timer0 Interrupt
 * Programming Example
 */
#include <xc.h>
// PIC16F818 Configuration Bit Settings
// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON         // Low-Voltage Programming Enable bit (RB3/PGM pin has PGM function, Low-Voltage Programming enabled)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

void main(void){
    /*Clear Port B*/
    PORTB=0x00;
    /*Port B As Digital Output*/
    TRISB=0x00;
    /*Select Timer0 Prescaler*/
    PSA=0;
    /*Select timer mode*/
    T0CS=0;
    /*Select 1:256 Prescaler*/
    OPTION_REGbits.PS=0x07;
    /*Enable Global Interrupt*/
    GIE=1;
    /*Enable Timer0 Overflow Interrupt*/
    TMR0IE=1;
    /*Clear Timer0 register*/
    TMR0=0;
    /*Clear Timer0 Overflow Interrupt Flag*/
    TMR0IF=0;
    /*Main program loop contain void of codes*/
    while(1);
}
void interrupt timer0ISR(void){
    /*Check for Timer0 overflow*/
    if(TMR0IF){
        /*Clear overflow flag*/
        TMR0IF=0;
        RB0^=1;
    }
}

Simulation in Proteus

There is no essence to prototype this programming example on a real bared board. However it will require an oscilloscope to keep track of output signal on RB0 pin. I just see the result of this programming in simulator. Click here to download this example in zip file format.


336x280

Search This Blog

Labels

23K256 (1) 24C16B (2) 25AA010A (2) 8051 (7) 93AA46B (1) ADC (34) Analog Comparator (1) Arduino (16) ARM (13) AT89C52 (7) ATMega32 (58) ATMega644P (27) AVR (87) AVR PCB (2) Bootloader (1) CCS PICC (31) Change Notify Interrupt (CNI) (2) DAC (2) DHT11 (4) Display (133) Distance Sensor (3) ds1307 (10) DS18B20 (5) ds3231 (1) ds3232 (2) dsPIC (5) dsPIC30F1010 (3) dsPIC30F2010 (5) EEPROM (5) Environment Sensor (5) ESP32 (1) esp8266 (1) Graphical LCD (2) I2C (38) ILI9341 (1) Input/Output (76) Interrupt (22) IoT PCB (1) Keil (5) Keypad (16) KS0108 (2) LCD (75) LM35 (3) Master/Slave (2) MAX7221 (1) MCP23017 (8) MCP23S17 (7) MCP4921 (1) MCP4922 (2) Meter (3) MikroC (2) Module PCB (1) Motor (15) MPLABX (73) Nokia 5110 LCD (4) OLED (2) One-Wire (7) Oscillator (8) PCB (10) PCD8544 (3) PCF8574 (10) PIC (108) PIC12F (3) PIC16 (105) PIC16F628A (3) PIC16F630 (2) PIC16F716 (4) PIC16F818 (11) PIC16F818/819 (3) PIC16F84A (16) PIC16F876A (2) PIC16F877A (9) PIC16F88 (2) PIC16F887 (60) PIC18 (19) PIC18F1220 (5) PIC18F2550 (5) PIC18F4550 (12) PICKit2 (1) PICMicro PCB (4) Pin Change Interrupt (1) PWM (12) RTC (12) SBN0064G (1) Sensor (13) SH1106 (3) Shift Register (13) Shift Registers (10) Software TWI (2) SPI (39) ST7735 (1) STM32 (11) STM32 Black Pill (1) STM32 Blue Pill (12) STM32 HAL (5) STM32CubeIDE (13) STM32F103C8T6 (9) STM32F401CCU6 (1) SysTick (4) temperature sensor (13) TFT (1) TG12864A (1) Thermometer (22) Timer/Counter (32) TM1637 (2) twi (10) UART (8) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (96)