I'm interested in doing serial IO on a PIC running at 32768Hz, where I figure I should be able to do 1200bps or 2400bps if I'm lucky. I wrote a little program to help out. It figures sometimes 6 instructions between bits and sometimes 7 - does this look right? Clock frequency: 32768 Serial bit rate: 1200 Instruction period: 0.000122 Serial Bit period: 0.000833 Instructions per bit: 6.826667 (actually 6) Start with extra instruction After 1 bits, 7 instruct, error is -0.000021 (-2.539062%) After 2 bits, 13 instruct, error is 0.000080 (9.570313%) After 3 bits, 19 instruct, error is 0.000181 (21.679688%) (add instr) After 4 bits, 26 instruct, error is 0.000160 (19.140625%) (add instr) After 5 bits, 33 instruct, error is 0.000138 (16.601562%) (add instr) After 6 bits, 40 instruct, error is 0.000117 (14.062500%) (add instr) After 7 bits, 47 instruct, error is 0.000096 (11.523438%) (add instr) After 8 bits, 54 instruct, error is 0.000075 (8.984375%) After 9 bits, 60 instruct, error is 0.000176 (21.093750%) (add instr) After 10 bits, 67 instruct, error is 0.000155 (18.554687%) (add instr) Here's the results at a more familiar freq and bitrate. This seems to agree with code I see at piclist.com Clock frequency: 4e6 Serial bit rate: 9600 Instruction period: 0.000001 Serial Bit period: 0.000104 Instructions per bit: 104.166667 (actually 104) After 1 bits, 104 instruct, error is 0.000000 (0.160000%) After 2 bits, 208 instruct, error is 0.000000 (0.320000%) After 3 bits, 312 instruct, error is 0.000000 (0.480000%) After 4 bits, 416 instruct, error is 0.000001 (0.640000%) After 5 bits, 520 instruct, error is 0.000001 (0.800000%) After 6 bits, 624 instruct, error is 0.000001 (0.960000%) After 7 bits, 728 instruct, error is 0.000001 (1.120000%) After 8 bits, 832 instruct, error is 0.000001 (1.280000%) After 9 bits, 936 instruct, error is 0.000002 (1.440000%) After 10 bits, 1040 instruct, error is 0.000002 (1.600000%) And here's the code in case anyone else might find it useful... /* * SerialCalc.c Used to compute delays (in "instructions") for software * driven serial communications ('bit-banged async IO') * * Written 2003 by Bill Westfield. * Released to the public domain. * * compile me sorta like: "gcc -lm serialcalc.c -o serialcalc" * * Edit History: * * 20030514 initial publication. */ #include #include /* * How many crystal cycles in each instruction */ #define CLOCKS_PER_INST 4 /* * How much error will we tolerate before adding a "correction." * This is the error in bit times of a sample from the center of * the bit. So 50% (0.5) is too much (in the next or previous bit), * but it doesn't need to be the ~2% typical of a steady clock for a * whole received byte, either. */ #define ALLOWED_ERROR 0.1 /* 10% error is allowed */ double clockfreq, /* CPU clock frequency */ instruct_period, /* CPU instruction period */ serialrate, /* Serial bit rate (ie 9600) */ serial_period, /* time for one serial bit */ currenterror, /* accumulated error so far */ real_instr_per_bit /* fractional instructions per bit */ ; int instr_per_bit; /* truncated value */ int extra_instr; /* Correction instructions */ main() { int i; printf("\nClock frequency: "); scanf("%lf", &clockfreq); printf("Serial bit rate: "); scanf("%lf", &serialrate); instruct_period = (CLOCKS_PER_INST * 1.0) / clockfreq; serial_period = 1.0 / serialrate; extra_instr = 0; /* * Everything is based on how many instructions have to go by * between samples to hit the same part of each serial bit. */ real_instr_per_bit = serial_period / instruct_period; /* * of course, we can't execute fractions of instructions. We'll * delay slightly less, and out sample period will creep toward the * start of the bit. That'll be fine if we don't creep too far. */ instr_per_bit = floor(real_instr_per_bit); printf("\nInstruction period: %f Serial Bit period: %f", instruct_period, serial_period); printf("\nInstructions per bit: %f (actually %d)\n", real_instr_per_bit, instr_per_bit); if (real_instr_per_bit - instr_per_bit > 0.5) { printf("\nStart with extra instruction"); extra_instr++; } for (i=1; i <= 10; i++) { /* * Calculate how far off we are by comparing how many instructions * we've actually "executed" vs how many we would have needed to * execute (including fractions) to sample at exactly the right time. */ currenterror = instruct_period * (i * real_instr_per_bit - (i * instr_per_bit)); /* * adjust for any corrections we've made in the form of * "extra" instructions */ currenterror -= extra_instr * instruct_period; printf("\nAfter %-2d bits, %-6d instruct, error is %f (%f%%)", i, i*instr_per_bit + extra_instr, currenterror, (currenterror*100.0)/serial_period); if (currenterror >= (ALLOWED_ERROR * serial_period)) { /* * if our sample time is drifting backward in the bit * too far, insert an extra instruction worth of delay */ extra_instr++; printf(" (add instr)"); } } printf("\n\n"); } -- http://www.piclist.com hint: To leave the PICList mailto:piclist-unsubscribe-request@mitvma.mit.edu