4
\$\begingroup\$

I'm programming a PIC18F4680 using mikroElektronika's mikroC PRO compiler and I've set the LCD library to use following ports to communicate with LCD:

// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

and the LCD is sometimes displaying garbage. I was told to LATB instead of PORTB registers and after reading the I/O Ports section of the datasheet, it's still not clear to me when I should use PORT and when LAT registers.

\$\endgroup\$
8
\$\begingroup\$

Use PORT to read from a pin, and LAT to write to a pin (and TRIS to change the direction).

Some PICs do not have a LAT register, in those case you are forced to use the PORT register to write to a pin, which exposes you to the dreaded Read-Modify-Write (it's not a bug, it's a feature!). Check my explanation in Interfacing a keypad with a microcontroller

\$\endgroup\$
2
\$\begingroup\$

LAT is used for writing an output, PORT is for reading an input. TRIS is used to configure the direction; an output (=0) or an input (=1). I remember the tris settings on PIC platforms easily because Output is 0 (O) and Input is 1 (I).

\$\endgroup\$
2
\$\begingroup\$

The simplest rule, applicable 99% of the tine on devices which have LATx addresses, is to use LATx (or LATxn) whenever you are writing a port, or reading a value which will be used in computing a value to be written back to a port. Use PORTx (or Rxn) only when you want to determine what outside circuitry is or is not doing to state of the pins.

As a further rule, I would suggest avoiding reading LATx outside its role in the iorwf, andwf, or xorwf instructions (or the |=, &=, and ^= operators in C). If, for example, you want to set the bottom four bits of an IO port match the contents of a register which is known to be blank outside those four bits, the pattern

  LATB &= ~0x0F;  // Clear bottom four bits
  LATB |= new_data; // Set appropriate bits

is often safer than the pattern:

  LATB = (LATB & 0xF0) | new_data;

It will cause pins whose old and new value were both "1" to transition momentarily to "0", but it will work correctly even if an interrupt service routine would affect the contents of LATB. If one needs the semantics of the latter statement and interrupts could modify LATB, one must either disable interrupts during the read-modify-write sequence or use some really nasty code to enure that the update happens correctly even if an interrupt strikes during it.

BTW, an alternative formulation with semantics between those of the former and the latter is:

  LATB |= new_data;
  LATB &= (0xF0 | new_data);

This version will turn on any "new" bits a few cycles before it turns off any bits which should no longer be high, but it is interrupt-safe provided the interrupt only writes to the upper four bits.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.