Programming PIC 18 using XC8 (MPLAB X) : IO ports

When you start the project, the main.c (or newmain.c, depends on what you named your main c file). You should be able to compile the code without any error or warning.

#include <stdio.h> #include <stdlib.h> /* * */ int main(int argc, char** argv) { return (EXIT_SUCCESS); }

The code given above does nothing. Its just a way to make sure you programming environment is set properly.

Follow the following steps

1) add config.h (remember the configuration bits?)

2) add xc.h – the compiler header

3) change int main to void main (the return type int has a reason, I’ll cover about it later)

Now your code should look like this and able to compile without a problem.

#include <xc.h> #include "config.h" /* * */ void main(int argc, char** argv) { }


PIC18 IO Setup


In order to set the pin of PIC controller you need to know the registers associated with it. There are 3 registers

  1. TRIS – Set a pin as Input or Output
  2. LAT – Buffer of each pin (tells you the value you wrote into it)
  3. PORT – To make a pin high or low/on or off

Regarding LAT, you can program the PIC without using the LAT bits, but good to know about it. If you write into LAT, it is equivalent to writing directly to the pin. But if you read from LAT bits, you will be reading the buffer, not the voltage at the pin. Instead if you use PORT bits, you will directly to the pin and read from it. This whole stuff I’m doing is to make you start programming quickly. But please read the datasheet to know more.

Set TRIS bit

1 = Input (1 looks like I – input )

0 = Output ( 0 looks like o = output)


Set PORT bit

1 = Makes pin high

0 = Makes pin low


Ctrl + Space bar will activate the intelli-sense that looks like this


To set Pin RB0 as output pin do the following



Lets try flip RB0 high and low

#include <xc.h> #include "config.h" void main(int argc, char** argv) { TRISBbits.RB0 = 0; while(1) //infinite loop { PORTBbits.RB0 = 1; //Set the PIN RB0 high PORTBbits.RB0 = 0; //Set the PIN RB0 low } }


The program will run fast that you won’t even see the difference. So we need to add some delay. You got to set some delay. XC compiler gives you delay function, but you need to set a few parameters (well actually its one line).

#define _XTAL_FREQ 1000000 //set your internal(or)external oscillator speed #include <xc.h> #include "config.h" int i = 0; void Delay1Second(void); void main(int argc, char** argv) { TRISBbits.RB0 = 0; while(1) //infinite loop { PORTBbits.RB0 = 1; //Set the PIN RB0 high Delay1Second(); PORTBbits.RB0 = 0; //Set the PIN RB0 low Delay1Second(); } } void Delay1Second() { for(i=0;i<100;i++) __delay_ms(10); }

Author: singularengineer

32 thoughts on “Programming PIC 18 using XC8 (MPLAB X) : IO ports

  1. can you give an outline of configuration of 20Mhz external crystal? I cant understand what I do in CONFIG1L resister? I dont want to enable PLL….

  2. i use pic18f4550….i have read datasheet but it cant make me clear.if you give a outline with screen short that must help me

  3. Thanks so much!!

    Thanks to you, i can understand clearly how can Programming PIC 18 using XC8 !

    I am from İstanbul/TÜRKİYE
    Excuse my bad English!


  4. Great tutorial!!

    I have a question though, Is it possible to refer to a single register bit by index? Por instance, for the TRISBbits.RB0 something like TRISB(0)???


    1. The TRISx list is actually a structure. If you right click and go to declaration of TRISx, you will be able to see the source and find a way to define the way you want. TRISBbits.RBO already addresses one bit.

  5. Hi and thank you for your great tutorials. I’m having a problem on programming a PIC18F14K22, I am using the PicKit3 with his own demoboard: I can’t use the inputs in any way. I try to explain it better: I tryed some simple programs with only outputs (RC0-4 are connected to 4 led) and they works good. But inputs don’t work! I tryed to connect directly with a cable the pin to Vdd but nothing changes, I tryed with the switch on the demoboard (connected to RA2 pin of the mcu, checked with a tester directly on that pin, when switch is not pressed, it get 4.97V and when pressed it get 0V so the logic is inverted) but nothing has changed. I tryed also to change the input (like putting it on RB0 and so on) Here is my code
    #define _XTAL_FREQ 16000000
    #include “myDelays.h”
    #include “config.h”
    #define TDELAYMS 50
    void delay50ms(void) {
    int i;
    for(i=0;i!=5;i++) {

    void main(void) {
    while(1) //infinite loop
    LATC0 = 1;
    LATC0 = 0;
    It doesn’t show any warning or problem, all build and programming went good, it seems that the input doesn’t reach the Vih voltage but that’s not true because I checked it with the tester and 4.97V reach that pin. It doesn’t seems to be the MCU, because that thing happened also with a PIC16F1829. For those tests Vdd is provided by an USB of my pc. voltage is quitely constant (checked with the oscilloscope) and high enough (like I said 4.97V). I don’t know where to bang my head anymore 🙁 thank you for your help, best regards

  6. sorry for the mistake, two #include directives are not shown in my message below but they’re present in project. they are #include and #include

  7. @Alessandro

    The pins you are trying to use as IO are used by ADC by default. If you go into the datasheet of 18F14K22 and check page 88, there is a note (in a box)saying that after reset the PORT C pins from RC0-RC3 and RC6 and RC7 will become analog input pins. Please turn off ADC on the pins you want to use as Output and it will start working. In order to set the pins as DIO, please read the chapter 8.4 and ADC section in the datasheet for 18F14k22 (the PIC you are using).

  8. Thank you for reply, I’ll try, but my problem isn’t on the output, it’s on the input, I tryed it on all “A” bank (like in the program i posted, where I was using RA2). for example if i write
    LATC0=1; the led turns on without problems and this is true for all 4 leds (on RC0-3 pins)
    but if i write
    the led doesn’t change his state! And I tryed to use all pins of A bank as input and also to connect the input directly to Vdd (or ground). That’s the problem, it seems that on input the logical state doesn’t change

  9. I’m sorry, I hadn’t the datasheet with me. I checked it and I saw that also RA2 pin has that thing. I wrote ANSEL=0b00000000 and it works! I’m sorry for my ignorance, unfortunately I haven’t got so much time as I wish to dedicate to this great world, so I couldn’t read all parts of the datasheet. Thank you so much! All tutorial is great!

  10. I would like to ask you another question but it isn’t about IO but about MPLAB. Sometimes it happens that while it’s building a project it shows something like this message in output:
    make[2]: waiting for unfinished job
    and the building process stops here until I go to the Windows task manager, in process tab, where I find 2 process named make.exe and I have to close them to go over with build. that cause also a big slow down of whole programs. Have you got any idea on why that happens? thank you

  11. Hi this tutorial really helped me. But I am having problem. when I am using “LATB=0;” it is working fine but when I use “LATBbits_t.LATB0=1;” it is showing “no identifier in declaration error”. . In the case of TRISB both “TRISB0=1;” and “TRISBbits.TRISB0=1;” are compiling without errors.I am using MPLABX 2.05 and XC8 1.30.

    1. LATBbits_t is template. You can’t use template like that. Use LATBbits.LATB0 (that’s why ‘_t’ means template – to microchip’s naming convention). Please check the declaration and source files which will answer a lot.

  12. Hello,

    I started using Pic18f4550 with xc8 compiler. In the above program you first declared the internal oscillator freq in conf file. when you declared the new freq “#define _XTAL_FREQ 1000000”, should i remove the internal oscillator declaration from config file. if no, which frequency does the compiler consider and why. I am new to uc programming, excuse me for basic doubts


  13. Hi!!!

    Thank you very much for your tutorial!!
    You are a genius!

    Now i have two problems/doubts
    (first of all, im using MPLAB X IDE v2.26 and XC8 v1.33 with a pickit3)
    Ok, my problem is that i cant use the sentence LAT to write/read a post, It just allow me to use PORT.
    Do you know why?

    And the other (I’ve tried everything), when I set a port (for example RA0 = 1;) it turns on, but then if i set another (like RA1 = 1;) this last one turns on but RA0 turns off.
    I have this problem with all ports except the port D
    (Im ussing pic16f887 and pic16f997)

    I’ve already tried setting TRIS, ANSEL and ANSELH, and even with the RBPU from the OPTION register.

    Thanks a lot!!

    1. I don’t have any of those 16F parts with me. But looking through the header file, looks like there are no definition for LAT bits. So you can only use port bits. If you go into your compiler installation folder XC8\v1.33\include\pic16f887.h you might be able to find how the ports are defined (structures and unions). Does it still do if you address it as PORTAbits.RA0 = 1 and PORTAbits.RA1 = 1 ?

      The stuff written here are for 18F series. I would suggest you to try microchip forums. They are pretty fast.

  14. Thank you very much for your reply!!
    I’m really glad to be in touch with you.

    Never mind about the LAT sentence, as you say it they are not defined for this pic. I was reading an article which says it’s almost the same if you want to write a port (it’s not if you want to read). But I will check the structure on pic16f887h.

    But I sill have the problem that I set the port RA1 and automatically the port RA2 (or another on A) turns off.
    I couldn’t solve it

  15. Hi,

    I am beginner in microcontrollers programming and I have several doubts. Could you help me?

    My first quetion is:

    I´m trying to initiate the project in XC 8, but appear different syntax like a ” #ifdef__cplusplus extern “C” { #endif “. I´m familiarised with “void main”, this is because the PIC12F675 have a different instruction set?

    Thank a lot.


  16. i am trying to program ports of pic18f452 but i am confused how to configure portbs as interrupt

  17. Hi, Thank you for this tutorial.. But i have question. can i do something like below?

    #define SS RB1

    void main(){



    void init(int pin){ = 0;

    i think you’ve understood what am i trying to say. i want to pass a PIN as argument in a function and do I/O manipulation

    Thank you

Leave a Reply

Your email address will not be published. Required fields are marked *