Links to all my PIC tips, tricks and 'mini-project' notes
Whilst the mid-range PIC's can tackle many complex and otherwise almost impossible applications with ease, the challenge is to minimise cost by using the cheapest baseline PIC 'whenever possible'. Baseline PIC's can be had for less than 50p each = I purchased many 16F5x chips for between 40 and 50p each (mainly from CPC as 'remaindered' stock in their 'Bargain bin' section).
The even cheaper to use 12F675 (it has an internal OSC) can be found for as little as 20p (in Qty 10pcs, eBay), as can many other PIC's for less than £1 each. These PIC's are so cheap that you will soon start using them 'for everything' (especially as the PIC can often be used in place of a higher cost 'single function' digital chip - such as divider, ADC, PWM generator etc.) !
Buying the PIC in a 'TSOP' package is (sometimes) cheaper than the DIL/DIP package version = and whilst this costs you 10-20p extra for a mini-PCB TSOP-DIP 'converter', if you use a 'bigger' PCB than the PIC TSOP really needs you can mount other devices (resistors, caps, even osc. crystals) on the same board - and make use of the extra 'pin holes' to wire this up to the rest of your circuit
Below is a mix of programming tips and tricks, common circuit tricks and all the 'mini-projects' I've used the PIC for
I hope these details proves as useful to you as it does to me !
Below, click on the '+' to expand 'in place' (includes diagrams/images) or click the title URL (to view/download the text only version).
(+) 0004 Multi byte ADD - (24bit)
(+) 0005 new PIC 33 instruction set - (macros)
(+) 0006 Binary multiply methods
(+) 0007 8x8 - (multiply)
(+) 0008 8x16 - (multiply)
(+) 0011 Bi color LED driving
(+) 0012 One pin dual LED and button detect
(+) 0013 Input only multi button detect
(+) 001a One pin controls motor Fwd off Reverse
(+) 001c One pin controls 3 relays
(+) 0020 I2C bit banging
(+) 0021 I2C code
(+) 0021 Serial link - (9600 baud)
(+) 0028 RS422 RS485 drive with one PIC pin
(+) 0030 D to A conversion - (R2R DAC)
(+) 0031 Ternary DAC - (R3R)
(+) 0032 Hybrid ternary bit conversion - (code)
(+) 0035 Pulse Width Modulation - (PWM)
(+) 0040 Gearing axis sensor
(+) 005a TYC50 AC motor details
(+) 0061 16F54 2char month map - (VTI)
(+) 0062 DDmmmYYYY character map - (VTI)
(+) 1000 PIC16F684 tips and tricks
(-) 2000 18Fx tips and tricks
The 18F series has some extra instructions and a deeper stack. One huge improvement is the PUSH (and POP) instructions plus the ability to access the ToS (Top of Stack) as a Register. The only drawback is that access to the ToS is limited to the low byte of the address - and ADDing or SUBing to TOSL has no effect on the upper bits. Since all addresses are byte addresses, this limits manipulation to the current 128 instruction 'block'. However, despite these restrictions, all sorts of 'stack' tricks can be pulled, especially using the 'Return with value' (Look Up Table - although since each LUT entry is a one word 'Return with value' instruction, the max. LUT size is 128). String look-up It's not unusual to want to look-up a 'string' (sequence of codes) and 'output' the looked up values at maximum speed to one of the PORTS (for example, look up ascii character shape pixel values in a FONT LUT and output the pixels as a video feed for a VTI/OSD) The 'classical' method is to set up a loop in the 'main' code that Calls the LUT control code which in turn calculates a 'jump' into the LUT. The LUT then 'Returns with value' to the Calling code which outputs the value, and loops until 'end of string' is detected. If the 'end of string' is 'flagged' by one of the codes being 'looked up' (0x00 is typically used), then the LUT control code has all the data it needs to detect 'end of string'. Time can be saved if the control code outputs the values (and only returns to the main-line code when all have been output). To get the LUT to 'Return with value' to the start of it's own control code (rather than back to the main code) the control code must 'PUSH' to create a new entry on the stack and then over-write the ToS to 'point' back to the very start of the control code (which will be the 'output to PORT instruction). So when the LUT 'Returns with value', it returns to it's own control code. The EOL (End of Line) = 'End of String' character is 'detected' not by 'testing' for 0x00 (which wastes time) but by replacing LUT entry 0x00 with a 'POP'. When code 0x00 is 'looked up', the POP removes the control code Return address from the stack and exposes the Return address to the main-line code, so when execution 'falls through' from the 0x00 'POP' to the next LUT entry, 0x01 'Return with value', it will Return to the main-line code.
ControlStart:
Output value
MainLineCall: ;main line code Calls here
PUSH
Set ToS = ControlStart:
Calculate next LUT address
Jump to LUT address ;LUT Returns with value either to 'ControlStart:' (or the mainline Return address when you jump to 0x00=EOL)
Note that no value is output for the EOL 'end of string' code. This means that a 'null' string (one consisting of a single EOL (0x00) code) will generate no output. Loops with Interrupts Another 'cunning trick' to save time in a 'loop' is not to bother with 'counting' or 'testing' in any way for an 'end of loop'. Instead the Timer/Counter is pre-set with the N loop (CLK count) before the loop is started. The loop code is then written so it 'runs for ever', i.e. until N CLK's have elapsed and the Timer/Counter terminates the loop :-)
This note last modified: 1st May 2016 19:32.