The code presented in the MX1 tutorial to flash the single LED connected to RA0 can be represented by this code.
// advanced topics, GPIO // register addresses for MX1 may not be the same for an MX3 device constant ANSELACLR 0xBF886004 constant TRISACLR 0xBF886014 constant LATAINV 0xBF88603C constant LED 1 << 0 // LED connected to bit 0 function go() @TRISACLR = LED // set port for o/p @ANSELACLR = LED // port to digital while comkey?(2) = 0 @LATAINV = LED // toggle LED wait(1000) wend endf
It is more complex than the 'rookie' version but is more flexible and more efficient as it deals with the registers directly.
How it Works
@TRISACLR = LED
TRISACLR is an address in the processors memory. In this processor all of the peripherals are mapped to a memory address.
The name TRISACLR is defined as a constant so in fact if you were to 'print TRISACLR' you would get a large number. The constant is defined in the library and if you look at the code it has been included at the top of file. The number is the address of the TRISACLR register that will enable us to set a particular line of port a to be an output.
The ‘@’ in front of the address means the contents of that address and so the contents of the address at TRISACLR are set to LED. LED in this case simply has the value 1. so the result of the line is to clear bit 1 of register TRISA to 0. See below for an explanation of what SET, CLR and INV mean.
constant LED 1 << 0
This is trivial in this case but does serve to see how a particular pin of a port can be easily set. The ‘<<’ is shift left so if say pin 3 needed setting then we would use constant LED 1 << 3. The effect of this is to shift ‘1’ 3 positions to the left. Rather than work this out to be 0×4, it is less error prone to use the shift method.
In all PIC microcontrollers (as far as I know) there is a TRIS register that sets a digital port to be either input or output, if the bit representing the pin is 0 then its an output, if it’s a 1 then its an input. So we have set bit 1 of TRISA to 0. by using the TRISACLR variant, see the box below for an explanation.
@ANSELACLR = LED
Port A can also be set to an analogue rather than a digital port and it is analogue by default so this sets it to be digital by setting the correct bit of ANSELA to be 0.
while comkey?(2) = 0
This is very useful. ‘comkey?(2)’ will return the number of keys that are in the UART2 buffer. This is the UART (Universal Asynchronous Transmitter and Receiver) we are using to communicate with the IC it is set by default. Placed in a while loop it will stay there until RX is received from the host PC, in other words when you press any key on the keyboard.
@LATAINV = LED
LATA is a direct communication with the output pins, PORTA can also be used but for output LATA is recommended. The INV on the end of LATA (LATAINV) will toggle the output – another very useful feature of the PIC32 registers.
CLR, SET & INV
All registers in a PIC32 are 32 bits wide and so if for example you need to set bit 0 to 1 but leave all of the other bits as they are then you cant simply write @TRISA = 1 as this will set all of the other bits to 0. For smaller members of the PIC family the only way to set just one bit is to read the register first and then either AND or OR the bit required and then write the register back.
The PIC32 however has a very neat way of dealing with this problem. Taking TRISA which is the register responsible for setting whether a pin on port a is either an input or output (0 is output, 1 is input). It has three additional registers CLR, SET and INV thus: TRISACLR, TRISASET and TRISAINV. These are write only registers but will clear, set or invert a particular bit and thus a pin just by specifying that bit (pin). None of the other bits are effected. All registers have these counterparts making it very easy to manipulate them.