728x90

Saturday, August 28, 2021

Port B Weak Pullup Resistors of PIC18F1220

 

Introduction

Port B of PIC18F1220 has an internal programmable weak pull up resistors. However it’s not individually select-able. These resistors have only one shared global switch locates in OPTION Register.

Port B Weak Pullup Resistors of PIC18F1220
Pin diagram of PIC18F1220

Additionally, this port is multiplexed with ADC input. To configure it to a solely digital I/O, the user must check the ADCON1 register.

Interfacing and Programming

Using a simulator to simulate the circuit, the overall prototyping is fast and effective. It reduces cost, time and physical hardware defect.

Hardware Interfacing

PIC18F1220 microcontroller accept digital input on lower nibble of Port B. Its higher nibble connects to LED representing the digital input on lower nibble.

Port B Weak Pullup Resistors of PIC18F1220
Schematic Diagram

Programming

At setting up section of C main program, programmer need to clear port I/O, disabling analog input function, setting up port direction, and turning on Port B weak pull up resistors.

C

PIC18F1220 configuration bits setting is very long that programmer doesn’t want to put inside C main file.

C

Click here to download this programming example.

Friday, August 27, 2021

Getting Started With PIC18F1220 in C

 

Introduction

PIC18F1220 is an 8-bit Harvard architecture microcontroller. Its instruction is 8-bit wide. Its essential features are list below.

Getting Started With PIC18F1220 in C

PIC18F1220/PIC18F1320 Summary

Only the features of PIC18F1220 we target.

Getting Started With PIC18F1220 in C

PIC18F1220 device feature


Getting Started With PIC18F1220 in C

A used PIC18F1220 in 18-pin DIP package

Memory

It has 4KBytes in program (Flash) memory. Due to its 16-bit wide instruction length, maximum number of instruction line is 2048 lines (16×2048). Its scratch pad Static RAM (SRAM) is 256 bytes. Non-volatile auxiliary storage EEPROM is 256bytes, keeping data persistent even the controller is power off.

Program counter is 21-bit in length (address up to 2Mbyte program memory). Reset vector locates at 0x0000. Unlike Mid-range PICMicro PIC18F1220 reset vectors locate at 0x0008 and 0x0018.

Digital I/O Port

This 18-pin in DIP package device has up to 16 digital I/O, regardless of other multiplexing functions.

Getting Started With PIC18F1220 in C

Pin Diagram of PIC18F1220 in DIP package

Disabling reset pin, it can be configured as a digital input pin. User can configure RA6 and RA7 as digital I/O as long as it’s driven from internal RC oscillator. Port A and Port B are 8-bit wide.

There are three external interrupt sources relate to digital I/O. Each I/O source/sink current up to 25mA/25mA.

Analog Inputs

Analog to Digital Converter (ADC) inside this device is 10-bit in resolution. It has 7 input channel that multiplexed with digital I/O pins. These analog input pins range from RA0 to RA6. ADC must be properly configured in software.

Analog Outputs

It has an analog output – Pulse Width Modulation (PWM) inside its ECCP module. Requirements for PWM usage is its timer. PWM is useful for driving analog output device – electric motor, light dimming, DC/DC converter, etc.

Timers

Timer is an essential part of microcontroller. PIC18F1220 has up to 4 timers,

  • Timer0 – 8-bit
  • Timer1 – 16-bit
  • Timer2 – 16-bit
  • Timer3 – 16-bit

They are useful in creating precise timing delay, pulse counting, pulse measurement, waveform generation, and PWM output.

Communications

Enhanced Addressable USART is commonly communicate to host PC, and other USART devices – GSM module, bluetooth, etc. In PIC18F1220 it has many configurations.

There’s a pair of Serial Peripheral Interface (SPI) and Inter-integrated Circuit (I2C) in its SSP module.

Others

It has other features that we will not list their details here. They are,

  • Reset and its programmable brown out reset
  • Low voltage detect
  • Start up delay

Device operates up to 40MHz using its High Speed Phase Lock Loop (PLL).

Programming and Development Tools

Popular programming tools are high level programming/compiler. Embedded C is a first choice for most of small microcontroller nowadays.

C Compilers

There are some well known C compilers for this device:

  • Mikroelectronika MikroC
  • Custom Computer Service (CCS) PICC
  • MPLABX XC8

MPLABX XC8 developed by Microchip Technology. It has a free version with no code optimization and technical support. However its free version is suitable for students and hobbyists at no cost.

Development Tools

This low pin counts device is easily prototype on breadboard. However it will require more times and many types of error.

Using a simulator could save prototyping time and spending on components. It’s safe without burning components even it’s wrong wiring.

I prefer Proteus VSM for a decade now. It’s a paid software but I use it b sharing with my development team.

Programming with MPLABX XC8

MPLABX Integrated Development Environment (IDE) is a powerful software. Programmer can write codes and debug in software and hardware. Currently MPLABX version 5.40 is the latest version.

XC8 is a compiler that plugged into this software targeting 8-bit PIC micro-controllers. XC8 2.1 is currently the latest version.

Getting Started with Coding

Blinking LED on microcontroller port is an easiest starting up with embedded C programming. This introductory programming toggles Port B of PIC18F1220 on for 0.5 second and off for 1 second.

I don’t show project setting up in MPLABX XC8 due to repetition. To get started with this tool chain click here.

Source code files are divided into two files.

/*
 * Start coding PIC18F1220 in XC8
 */
#include <xc.h>
#include "p18f1220Config.h"
#define _XTAL_FREQ  20000000
void main(void){
    /*Clear Port B*/
    LATB=0x00;
    /*Port B output*/
    TRISB=0x00;
    while(1){
        LATB=0x00;
        __delay_ms(500);
        LATB=0xFF;
        __delay_ms(1000);
    }
}

It needs another file “p18f1220Config.h” in the same project.

// PIC18F1220 Configuration Bit Settings
// CONFIG1H
#pragma config OSC = HS         // Oscillator Selection bits (HS Oscillator)
#pragma config FSCM = ON        // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode enabled)
// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = ON         // Brown-out Reset Enable bit (Brown-out Reset enabled)
// BORV = No Setting
// CONFIG2H
#pragma config WDT = ON         // Watchdog Timer Enable bit (WDT enabled)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled, RA5 input pin disabled)
// CONFIG4L
#pragma config STVR = ON        // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Low-Voltage ICSP Enable bit (Low-Voltage ICSP enabled)
// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (00200-0007FFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (000800-000FFFh) not code-protected)
// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (00200-0007FFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (000800-000FFFh) not write-protected)
// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (00200-0007FFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (000800-000FFFh) not protected from table reads executed in other blocks)
// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from table reads executed in other blocks)

MPLABX IDE version is v1.51 while XC8 compiler in used is v2.00. I prefer these old versions because the are light weight.

Getting Started With PIC18F1220 in C

MPLABX IDE and XC8 Compiler screen shot

Schematic Diagram

Circuit diagram drawn in Proteus. It can be used for on board wiring, and also in simulation.

Getting Started With PIC18F1220 in C

Circuit Diagram


Monday, August 23, 2021

PIC16F818 Simple Clock Using Multiplexing Display

 

Introduction

An electronics digital clock usually equipped with a Real Time Clock (RTC) IC – for example DS3231 RTC. However we can build a non-complex one’s using internal timer of a microcontroller. This feature doesn’t have time keeping as RTC chip. It lost all its previous timing when it’s powered off.

PIC16F818 Simple Clock Using Multiplexing Display

PIC16F818 Simple Clock Using Multiplexing Display
A commercial sample of DS3231 RTC module from Ali Express

Digital Clock made from Timer0

Timer0 module creates a precise timing when it’s running in timer mode. Timing tick period is configurable by user. A a simple programming example we start with showing timing data on a multiplexing display.

Hardware Preparation

Main controller powered by PIC16F818 microcontroller. It’s suitable for this simple project. Display is assumed to be a dedicated digital clock display in multiplexing type. It’s common anode type as there’s no other option.

PIC16F818 Simple Clock Using Multiplexing Display
Schematic diagram

We don’t use external reset on RA5 pin. Higher nibble of Port A is reserved for digital inputs. These four inputs are minute and second adjustment. Controller clocks from its internal 8MHz oscillator.

Program Preparation

Blueprint of this digital clock project is Timer0 interrupt. Timer0 clock source is internal microcontroller clock with 1:2 prescaler. Timer0 interrupt creates timing tick of 100us. Each time the interrupt occurs Timer0 register is preloaded with 100 to get this timing interval.

Display

Multiplexing display is activated for every 5ms for each digit. A counting register schedule this task. It runs from 0 to 20ms before it rolls back to 0.

Buttons

Four input buttons are,

  • Increasing minute on RA4
  • Decreasing minute on RA5
  • Increasing second on RA6
  • Increasing second on RA7

Each button pressing will be accept by controller after 200ms. This 200ms timer tick create by buttonTime counting variable. Whenever any button is pressed time adjustment is made, and this time counting variable is reset to 0.

Timer0 Interrupt

ISR of PIC16F818 keeps track of Timer0 overflow interrupt. Each time interrupt occurs Timer0 Register (TMR0) preload with value of 100 to gain a 100us timer tick.

/*Interrupt Service Routine*/
void interrupt _myISR(void){
    /*Check Timer0 Interrupt Flag*/
    if(TMR0IE&&TMR0IF){
        TMR0=-100;   
        t0Counter+=1;
        micro_100+=1;
        
        TMR0IF=0;
    }
}

There are two additional timer variable to multiplex display and create a one millisecond time.

Programming

Overall XC8 program made of about 168 lines of code including white spaces and comments.

/*
 * PIC16F818 Simple 7-Segments
 * multiplexing display clock
 */
#include <xc.h>
#include "pic16f818Config.h"
#define MININC RA4
#define MINDEC RA5
#define SECINC RA6
#define SECDEC RA7
#define maxPress 200
void ioInit(void);
void timer0Init(void);
void ssdDisplay(void);
void timeAdjust(void);
unsigned long getOneSecond(void);
unsigned long t0Counter=0;
unsigned long micro_100=0;
unsigned char oneSecond=0;
unsigned char buttonTime=0;
unsigned char minute=12;
char blinker=0xFF;
void main(void){
    unsigned long oneSecond=0;
    ioInit();
    timer0Init();
    while(1){
        oneSecond=getOneSecond();
        timeAdjust();
        ssdDisplay();
    }
}
/*Digital IO and Clock Set Up*/
void ioInit(void){
    /*Clear IO*/
    PORTA=0x00;
    PORTB=0x00;
    /*Port A higher nibble is digital input*/
    TRISA=0xF0;
    /*Port B as output*/
    TRISB=0x00;
    /*Turn on Pull Up Resistors*/
    nRBPU=0;
    /*Clear Analog function on Port A*/
    ADCON1=0x06;
    /*Set up internal oscillator*/
    OSCCONbits.IRCF=0x07;
}
/*Timer 0 Set Up Section*/
void timer0Init(void){
    /*Select internal timer mode*/
    T0CS=0;
    /*Select Timer0 Prescaler*/
    PSA=0;
    /*Select 1:2 Timer0 Rate*/
    OPTION_REGbits.PS=0x00;
    /*Enable Timer0 Interrupt*/
    TMR0IE=1;
    /*Turn On Global Interrupt*/
    GIE=1;
    /*Clear Timer0 Interrupt Flag*/
    TMR0IF=0;
    /*Clear Timer0*/
    TMR0=0;
}
/*Get one second routine*/
unsigned long getOneSecond(void){
    
    if(t0Counter>=10000){
        oneSecond+=1;
        blinker^=0x80;
        blinker|=0b01111111;
        t0Counter=0;
    }
    return oneSecond;
}
/*Multiplexing Display Routine*/
void ssdDisplay(void){
    /*common anode display pattern*/
 char anodePattern[16]={192,249,164,176,153,146,130,248,128,144,136,131,198,161,134,142};
    static unsigned char oneMilli=0;
    if(micro_100>=10){
        oneMilli+=1;
        micro_100=0;
        buttonTime+=1;
    }
    if(oneMilli>20){
        oneMilli=0;
    }
    if(oneSecond>=60){
        oneSecond=0;
        minute+=1;
        if(minute>=60) minute=0;
    }
    /*Driving multiplexing display*/
    switch(oneMilli){
        case 0:
            PORTA=0x00;
            PORTB=anodePattern[oneSecond%10]&blinker;
            PORTA=0x08;
            break;
        case 5:
            PORTA=0x00;
            PORTB=anodePattern[oneSecond/10]&blinker;
            PORTA=0x04;
            break;
        case 10:
            PORTA=0x00;
            PORTB=anodePattern[minute%10]&blinker;
            PORTA=0x02;
            break;
        case 15:
            PORTA=0x00;
            PORTB=anodePattern[minute/10]&blinker;
            PORTA=0x01;
            break;
    }
}
/*Adjusting Time*/
void timeAdjust(void){
    /*Checking digital inputs*/
    if(buttonTime>=maxPress){
        if(MININC==0){
            if(minute<60) minute++;
            buttonTime=0;
        }
        if(MINDEC==0){
            if(minute>0) minute--;
            buttonTime=0;
        }
        if(SECINC==0){
            if(oneSecond<60) oneSecond++;
            buttonTime=0;
        }
        if(SECDEC==0){
            if(oneSecond>0) oneSecond--;
            buttonTime=0;
        }
    }
}
/*Interrupt Service Routine*/
void interrupt _myISR(void){
    /*Check Timer0 Interrupt Flag*/
    if(TMR0IE&&TMR0IF){
        TMR0=-100;   
        t0Counter+=1;
        micro_100+=1;
        
        TMR0IF=0;
    }
}

PIC16F818 C configuration settings store in  “pic16f818Config.h” file.

// 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 MCLR)
#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)

Click here to download source file. Its statistic shown below.

PIC16F818 Simple Clock Using Multiplexing Display
Dashboard in MPLABX



Search This Blog