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

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); }

Categories: Uncategorized Tags:
  1. August 16th, 2017 at 22:59 | #1

    Amazing! Its in fact remarkable paragraph, I have got much clear idea
    on the topic of from this post.

  2. August 14th, 2017 at 15:27 | #2

    Incrediblpe points. Sound arguments. Keep up the good work.

  3. albhee
    June 30th, 2016 at 14:17 | #3

    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){

    TRISBbits_t.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

    • June 30th, 2016 at 18:09 | #4

      No you can’t.

      It is more of a C language question. If you want to do what you are trying to do, then try using switch-case.

  4. turegn
    May 6th, 2015 at 06:45 | #5

    how can i configure portbs as interrupts during coding using mplab on pic18f452

  5. turegn
    May 6th, 2015 at 06:43 | #7

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

  6. Renato Bragion
    March 19th, 2015 at 10:07 | #8


    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.


    • March 19th, 2015 at 13:43 | #9

      Where do you see it? I just tried creating a project and the main file doesn’t show it. What file are you talking about?

  7. Martin
    January 3rd, 2015 at 13:30 | #10

    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

  8. Martin
    January 1st, 2015 at 22:03 | #11


    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!!

    • January 3rd, 2015 at 03:18 | #12

      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.

  9. tony
    May 30th, 2014 at 05:59 | #13


    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


  10. March 25th, 2014 at 02:17 | #14

    Thank you for your reply. Why we can’t use huge parameters in the delay? Something like “__delay_ms(1000);”

    • March 25th, 2014 at 05:32 | #15

      That’s why using the delay for loop. _delay…. is a macro. you can define your own if you want more delay.

  11. March 24th, 2014 at 06:03 | #16

    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.

    • March 24th, 2014 at 15:48 | #17

      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. Alessandro
    February 14th, 2014 at 08:02 | #18

    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

    • February 14th, 2014 at 09:25 | #19

      Never came across a problem like that. Give it a try in Microchip forum and you’ll get help.

  13. Alessandro
    February 13th, 2014 at 19:30 | #20

    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!

  14. Alessandro
    February 13th, 2014 at 19:07 | #21

    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

  15. February 13th, 2014 at 13:36 | #22


    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).

  16. Alessandro
    February 13th, 2014 at 12:56 | #23

    god why the include between “” are not shown? by the way they are xc.h and stdio.h

  17. Alessandro
    February 13th, 2014 at 12:54 | #24

    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

  18. Alessandro
    February 13th, 2014 at 12:50 | #25

    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

  19. Sebastian
    October 18th, 2013 at 21:19 | #26

    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)???


    • October 18th, 2013 at 22:26 | #27

      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.

  20. Mehmet
    August 15th, 2013 at 07:58 | #28

    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!


  21. SJK
    June 17th, 2013 at 17:51 | #29

    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

  22. SJK
    June 17th, 2013 at 02:50 | #31

    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….

    • June 17th, 2013 at 09:08 | #32

      Here is a microchip device documentation on oscillators: http://ww1.microchip.com/downloads/en/devicedoc/31002a.pdf
      Which chip are you using? Are you sure you need an external oscillator? Any justification for it?
      To use external oscillator of 20MHz you got to set your FOSC config bit as
      #pragma config FOSC = HS
      Also please read microchip forums where you have a vast resources.


  23. younesser
    June 10th, 2013 at 07:05 | #33

    this instruction is not recognized by the compiler : #include “config.h”



  1. No trackbacks yet.