Pic18fxxx family has a lot advantages and improvements from the pic16fxxx family of microcontrollers. What is the particular feature that make them better for C programming than the pic16fxxx devices?
Electronic – Why pic18fxxx microcontrollers is better for C language
cmicrochipmicrocontrollerpic
Related Solutions
I don't know the MSP430 in any detail, but have a lot of experience with PICs. PICs don't specifically have a separate register for input and output, but many of them do in practise. The PORT register contains the immediate pin states, for input and output. The LAT resgister contains the last-written values, so I suppose you can call it a output register. If you use PORT for input and LAT for output, then you have separate input and output registers. Just ignore that PORT could be used for output too, with slightly different properties than LAT.
The low PICs from 16 on down don't have LAT registers, only the PORT register. You therefore use the same register for input and output. That's no big deal since reading and writing are separate operations.
There is one wrinkle with this that sometimes catches people, and much superstition-based programming has evolved around it. The issue is that the PORT register always reflects the actual pin states. This may sound simple and harmless, but you can get into trouble when the external circuit holds the pin in the opposite state it was written in. Note that enough capacitance on the pin will do this, at least for a little while.
This becomes a problem when you perform a read-modify-write operation on a port register shortly before having changed a output pin. Let's take the really obvious case of ORing 0 into the PORT register. OR is a read-modify-write operation. The OR instruction will read the existing register value, perform the OR, then write the result back to the register. Now imagine the previous instruction wrote a new value to a output pin, but that pin hasn't had time to get to its new state yet. The read part of the OR instruction reads the current PORT register value, which is not the most recent value written to it because the pin hasn't slewed to its new state. The OR with 0 doesn't change anything, so the old state of the PORT register is written back to it, essentially cancelling the previous write.
Now you may say that ORing 0 into a PORT register is silly. In most cases that's true, but that was just to make a obvious example. Consider that the BSF and BCF (bit set and bit clear) instructions actually perform a read-modify-write on the whole port register. Consider the instruction sequence:
banksel portb bsf portb, 1 bsf portb, 2
Let's assume all port B pins are set to outputs and are all low to start with. After the first instruction RB1 will start going high. Due to capacitive loading, RB1 is still low and PORTB therefore reads 0 when fetched as part of the second instruction. Bit 2 is now set, so the value 4 is written to PORTB. RB1 will now go low again since 0 was written to that bit. RB2 will start going high. The net result of this instruction sequence could be that only RB2 is high, not RB1 and RB2 as probably intended.
The LAT register was introduced to avoid this problem. It holds the last written value, not the actual instantaneous pins state. If this instruction sequence was performed on LATB instead of PORTB, both RB1 and RB2 would be driven high at the end regardless of how slowly they might get there.
So what do you do? On a PIC 18 and higher read from PORT and write to LAT, and there'll be no problems. On the other PICs, avoid any read-modify-write operation on PORT until you know all pin states have settled. Some people will tell you to always use a shadow copy, modify that, then write that to the PORT register. That's just silly voodoo programming, of course. You know your circuit. Most of the time a single NOP between a write and any read-modify-write is all that's needed. If the pin can't get to its new state in at least one whole instruction cycle, then the circuit should most likely be fixed anyway. In rare cases shadow register can be useful, but those are rare cases indeed. Mostly they are just a waste of cycles, RAM, and one more thing to mess up, especially for the kind of people that blindly follow rules like "always use a shadow register". A much simpler answer is that those kind of people should just stick to a PIC 18 or higher.
Aesthetically, my favorite architecture in many was is the 14-bit series. The 16-bit PIC18Fxx architecture improves some things, but I find somehow the design less aesthetically pleasing. Which architecture you'll like better probably depends upon your design aesthetic, the extent to which your find yourself wishing things were designed differently, and the extent to which such wishing detracts from your enjoyment working with them.
From a design perspective, there's no particular reason why code addresses and data addresses need to be the same. One thing I like about the 14-bit PICs is that adding a number to an instruction address advances by that many instructions. By contrast, on the PIC18X, each instruction takes two addresses. Consequently, computed jumps using an 8-bit selector are confined to a range of 128 instructions rather than 256. It's a small detail, but having a program counter whose lowest bit is non-functional seems unaesthetic.
Also, the PIC18xx parts add a single-cycle hardware multiply, but unfortunately since it requires one operand to be in W but puts the results in a fixed pair of other registers, it can't be used very effectively for multi-precision operations. If I had my druthers, there would be two types of multiply instructions:
- Simple multiply -- Store W into multiplier register, and store op*W into PRODH:W
- Multply-add --Store PRODH+op*multiplier register into PRODH:W
With such a pattern, a 16x16 operation would be rendered as:
movf OP1L,W mul OP2L movwf RESULT0 mula OP2H movff OP2L,MULTR mula OP2L movwf RESULT1 mula OP2H muvwf RESULT2 movff PRODH,RESULT3
Further, arbitrary-length multiplies could be done with an average cost of a little over two cycles per 8x8 partial product, using the repeated pattern:
mula POSTINC0,c addwfc POSTINC1,f,c
That pattern would multiply one multi-byte number times an 8-bit value and add the result to another multi-byte number.
As it is, I think the best one can do for an extended multiply is to do the multiply to a destination buffer without doing a built-in add, at a cost of six cycles per 8x8 partial product, and then spend another two-cycles per partial product adding that result to the previous 8xN partial result.
movf multiplier,w mulwf POSTINC0,c movf PRODL,w,c addwfc POSTINC1,w movff PRODH,INDF1
Four times as long as what could be achieved with a slightly different instruction set. I don't know that I've seen any processor which included a function to compute PRODH+Op1*Op2 but it would be a very simple feature to include in shifter-based multiplies, and it facilitates computing arbitrary product widths with fixed hardware cost. Actually, since the PIC takes four hardware clocks per instruction, the hardware required to allow a 16xN or 32xN multiply would be pretty modest; when computing big products, a 16xN or 32xN multiply with suitable register usage would offer a 2x or 4x speedup.
Related Topic
- Electronic – For connecting two micro which one is better, UART or RS232
- Electronic – PIC MCUs C language Compilers and IDE for PIC16F and PIC18F
- Electronic – Writing one program for different microcontrollers
- Microchip PIC Development with OTP Devices (12C672)
- Electronic – Understanding programmers for microcontrollers
Best Answer
I don't know about "ideal for". That's a marketing term that has no place in a learned discussion.
However, one big advantage of the PIC 18 architecture versus the original PIC 16 architecture, especially related to compilers, is that it is possible to implement a software data stack on a PIC 18 with single instructions for PUSH and POP. The PIC 18 also has a deeper call stack, 32 versus 8, which can help when a compiler implicitly calls subroutines. The PLUSW indirect addressing mode is probably something a compiler would make more frequent use of than a human programmer.
The PIC 18 also has other advantages that are useful both for compilers and human programmers, like 3 hardware pointers instead of one, auto inc/dec indirect addressing modes, a 8x8 into 16 hardware multiplier, add with carry, and subtract with borrow, and a few other niceties.