Jump to content
  • 0

What is the difference between PORT x and LAT x on PIC16 and PIC18 Microcontrollers and what does ANSELx actually do?



1 answer to this question

Recommended Posts

  • Member

The best way to start this is to show the pin diagram from a device datasheet. I captured this from the PIC16F18875 datasheet from the chapter on I/O Ports.


The operation is described in the datasheet as follows 


The Data Latch (LATx registers) is useful for read-modify-write operations on the value that the I/O pins are driving. A write operation to the LATx register has the same effect as a write to the corresponding PORTx register. A read of the LATx register reads of the values held in the I/O PORT latches, while a read of the PORTx register reads the actual I/O pin value.

From this diagram you will see that when you write to LATx or when you write to PORTx the value will be "latched" into the D Flip-flop, so upon writes it seems very similar. There are actually 8 of these circuits per port, and modifying port data is often done one pin at a time, which gives rise to one of the most common problems on PIC microcontrollers, the "Read-Modify-Write" problem.

This happens when you have code like this to set a single bit:

PORTA |= 0x01; // Set the lowest bit (0) on the port

The problem with this is that the PORT is read first, and then the resulting read is modified and written back to the port. Now if you look carefully at the circuit above you will see that when we read the PORT register we will be reading one of 2 values. When ANSELx for the pin has been set to a 1 the reading of the pin is disabled and the value we read from PORT will always be a 0, even if the pin is currently an output and we are driving it high! This means that code like the line above will try to set only the lowest bit on PORTA, but it may accidentally turn other outputs low by accident due to reading a 1 on those outputs when I have  ANSELx as a 1. (btw. The purpose of ANSELx is to disable reads on pins that we know will be carrying analog voltages. For input pins carrying a voltage between a 0 and a 1 can cause excessive power disappation by the pin and this should be avoided, so do use ANSEL when you know the pin will be floating!)

The other possibility is that ANSELx is set to a 0, in which case we are reading the actual voltage on the pin. The problem here is that if we are e.g. driving a high current LED the port voltage may actually sag so low that reading it back would not give us a 1, or there may just be noise on the pin, or it may be shorted to GND, either way we will be accidentally changing the outputs of other pins because we are reading the PORT.

Having a seperate LATA register allows us to completely avoid this problem! So now reading from LATA will NOT read what is on the pin and will be unaffected by the setting of ANSELA on the pin. As you can see from the diagram reading from LATA will simply read back what is in the D Flip-flop and be unaffected by what is going on at the physical pin. This means that doing the or to set a bit will be guaranteed to only affect that pin.

Here is another example of the problem (you can even run this in the MPLAB-X simulator to see what happens. If you do that you should create watches on PORTA and LATA, and you will see that no matter what you do PORTA will always be 0x00, and LATA will behave as described in the comments:

ANSELA = 0xFF; // We disable reads on all pins on PORTA

LATA = 0xFE;   // Write all the pins except for LATA0 to a 1, LATA0 = 0
LATA |= 0x01;  // Set LATA0 to a 1, now all port pins are high.

PORTA |= 0x01; // Here we attempt to force the lowest pin on PORTA to a 1, but by
               //   accident we are setting all the other pins to 0 !!

// At this point LATA = 0x01 and PORTA = 0x00 (as it always reads 0x00 due to ANSELA being all 1's)



So in summary the purpose of the LATx registers is to allow us to easily mask bits into our output ports without having to worry about read-modify-write problems. A general rule of thumb is to always read and write the LATx registers if you are trying to manipulate outputs on a PORT and always read the PORT registers only in the case where you are trying to get the digital input values of the pins on the port.

Link to comment
Share on other sites


This topic is now archived and is closed to further replies.


  • Create New...