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)
The DDmmmYYYY character font
Interpreting a numeric DATE string added by a VTI (Video Time Inserter) can be a real problem when much CCTV kit is designed in the USA. This is because the US software inevitably shows the data as Month Day Year, whilst here in Europe we use Day Month Year. Of course both are wrong (Year, Month, Day is what you need if you expect to 'sort' anything in data order) One way to eliminate the doubt is to show the Month as a 3 character string, rather than a 2 digit number The 'simplest' character shapes that are legible are defined in a 5x7 (5 pixel wide, 7 line high) character 'map'. To output the time and date as "DD mmm YYYY hh:mm:ss.ss", the character set we must define is :-
The numbers [0-9], 10 maps (70 table entries)
plus
The 3 char month names [Jan, Feb, Mar, Apr, May, Jun, Jly, Aug, Spt, Oct, Nov, Dec]
Whilst the characters could be held in any order, alphabetic makes is easier to remember :-
A a b c D e F g J l M N n O o p r S t u v y = 22 char. maps
Total 10+22 = 32 @ 7 lines ea. = 224 bytes (assuming we use 1 byte for each of the 5 pixels i.e. no packing)
The required punctuation ('space', ':', '.') can all be 'hard coded' rather than 'mapped'
Note that the bit map is output 'MSB first' (i.e. it's 'shifted up') which means the maps have to be held as 'mirror images' in b0-b4
The 16F54 has only 256 'Call' locations, so using 224 locations for the pixel map Data Table leaves only 32 into which we have to fit all the subroutine 'Call' hooks !
This means that the 3 character month will only be possible with the 16F57 or 59 (which has 2k instruction space in 54 pages, i.e. 4 sets of 256 Tables)
Loading the 3 character month pixel maps
Generating a 3 char month is a bit complex. If the month value held a decimal count (0-11 or 1-12) we could use that as an index into a pre-character Table to pre-load the string registers with the required character code offsets. However that not only requires another data table (of 12x3 = 36 entries) but also wastes time (the Call, computed Jump, Return is at least 6 clks, plus we have to copy the count to the Acc before calling and then copy the Acc to the Register after Return for at least 2 more). So, instead, we will have to 'hard code' a sequence of CALL's into the pixel map table
; Get the 3 alpha offsets into the 3 mmm Registers (mInitial, m10s, m1s).
; Current month is in MmmReg, value 1-12 (binary). slInit:
loadMonth: ;CALL here to load the 3 month regs with the char codes
DEC MmmReg,Acc ; Month 0-11, to Acc
CLR Cy ; make sure Cy clear
ROTL Acc ; double the month
ROTL Acc ; double again (now have 0,4,8, .. each load takes 8 instructions )
ADD Acc,PCL ; Jump to the correct month load code
; Here for Jan (each month requires 8 inst)
LOAD 'J',Acc
CALL getMap:
COPY Acc,mInitial ; save msb pixel map
LOAD 'a',Acc
CALL getMap:
COPY Acc,m10s ;save middle pixel map
LOAD 'n',Acc
JMP getMap: ; shape table RET will return to original calling routine
; Note: the calling routine must save the lsb pixel map (COPY Acc,m1s)
;
; Here for Feb (each month requires 8 inst)
LOAD 'F',Acc
...
; main line code
CALL loadMonth: ;load mInitial, m10s pixel maps
COPY Acc, m1s ;load m1s pixel map
...
NOTE that loading a 3 character alphabetic month consumes at least 12x8 = 96 instructions of Low address space (so, again, this is only on the 2k instruction space 16F57/9))
Adding a day post-fix
The 16F57/9 has enough space to add day post-fix '1st, 2nd, 3rd, 4th ...') at a 'cost' of only 3 more character (s d h)
The pixel bit map Data Tables
Note that, after the Table is CALL'd, the Data Table values are accessed with a calculated jump (using a 'Copy Acc to PCL' command), so the entire table must be within the first 256 locations.
Since the Month character maps depends on the device used (16F54 or 57/9), a separate Month table will be used. This means the numeric pixel map is common for all devices
The Table has to be organised in 'scan line sets' (i.e. sets of 10 scan lines, one for each numeral (0-9) together)
The 'punctuation' marks (. and :) are present in b7 of the relevant scan line pixel maps. The output code will only 'use' these bits if the number is in one of the units positions (so the bits never appear when '10's are output). To avoid a '.' turning into a ':', on return, b7 is cleared in the unit seconds except for the bottom scan-line 6
; numeric Table, Call here
getNoMap:
AND 0x0F ; remove top nibble (1)
ADD slNumb,Acc ; add the current scan line number, char top 0, to 7 char bottom line (1)
ADD Acc,PCL ; get the map (+2 CLK)
; The call (+2) has to load the Acc, so +1 and on return (+2) save the shape (+1), so total is 10 CLK's per digit
slNumb:
RET No0line0 ; bit map for '0' (and 'mark' in top bits) for top scan line, return with data (= +2 CLK)
RET No1line0 ; ... 9 more locations consisting of scan line N defn. for No. 1-9
..
RET No0line1
..
RET No0line2
..
..
RET No0line6 ;last set of 10 (7th = bottom scan line)
Since a 'computed jump' is required for each character (there is no such thing as a 'computed Call'), there is no simple** way to look up the pixel maps any faster
**A rather more complex way does exist - manipulating the Return Stack and performing Returns without a Call - however that only saves significant CLK cycles when loading a series of shapes using INDF register addressing
This note last modified: 8th Mar 2016 10:29.