Difference between revisions of "CCS C"

From Mech
Jump to navigationJump to search
Line 13: Line 13:
*Ideally most of your variables will be defined like this
*Ideally most of your variables will be defined like this


int8 myvariable;
int8 myvariable; // or...

or

signed int8 myvariable;
signed int8 myvariable;


Line 33: Line 30:
*It's also useful to be able to select (mask) one or more bits from an int, using the bitwise operators & (logical and), | (logical or), and ! (invert). Make order of evaluation unambiguous with parentheses.
*It's also useful to be able to select (mask) one or more bits from an int, using the bitwise operators & (logical and), | (logical or), and ! (invert). Make order of evaluation unambiguous with parentheses.


Example: if msecs is an int32 that is incremented by a 1KHz interrupt routine, then (msecs & 255) will be 0 every 256 milliseconds.
Example: if msecs is an int32 that is incremented by a 1KHz interrupt routine, then (msecs & 255) will be 0 every 256 milliseconds.


*Because float operations are so slow it's often better to use fixed point arithmetic; e.g. a continuous value between 0 and 1 can be represented as an int16 between 0 and 1000.
*Because float operations are so slow it's often better to use fixed point arithmetic; e.g. a continuous value between 0 and 1 can be represented as an int16 between 0 and 1000.

Revision as of 21:00, 25 December 2007

Read the PIC C intro by Nigel Gardner. It's short and also makes a good refresher for C programming. CCS's PIC C is a pretty standard C with a few notable exceptions:

  • You have to be very explicit about the size and type of variables. The PIC has limited memory for variables (1536 bytes). Its instruction set natively handles operations only for 8-bit integers, and all the rest is done in software. So think carefully about which variables need which data type. Adding two floats takes 150 times longer than adding two int8s.
  • The native type is the int8 which is stored in one 8-bit byte. Its value can range 0 to 255. If you add an int8 with value 250 to one with value 13, the result will be 7, because it rolls over at 256. This will not generate an error. (There are no run-time error messages.)
  • For maximum storage efficiency you can use an int1, which can only have values of 0 or 1. This is not fast however (check this). Use int8s for speed.
  • Larger integers can be stored as int16 or int32.
  • Any of the int types (except int1) can be signed; by default they are unsigned (positive only.) Operations on signed ints are just as fast as on default (unsigned) ints. (check this)
  • Ideally most of your variables will be defined like this
int8 myvariable;    // or...
signed int8 myvariable;
  • Addition and subtraction are much faster than multiplication and division. When multiplying or dividing an int8, int16, or int32 by a power of two, use the left-shift and right shift operators:
result = bignumber>>3;			//  divide by 8; right-shift by 3 bits
  • Watch out for type conversion. When in doubt force the conversion the way you expect it to be. An expression is fully evaluated before being type converted for assignment. For instance if (int8) value = 100
bignumber = value << 3  

will be wrong; what you want is

bignumber = (int16) value << 3
  • It's also useful to be able to select (mask) one or more bits from an int, using the bitwise operators & (logical and), | (logical or), and ! (invert). Make order of evaluation unambiguous with parentheses.

Example: if msecs is an int32 that is incremented by a 1KHz interrupt routine, then (msecs & 255) will be 0 every 256 milliseconds.

  • Because float operations are so slow it's often better to use fixed point arithmetic; e.g. a continuous value between 0 and 1 can be represented as an int16 between 0 and 1000.