STANDARD STRING FUNCTIONS -->

ATOF()
ATOI()
ATOL()
ATOI32()

CALLOC()
REALLOC()
MALLOC()
FREE()
MALLOC()
MEMCPY()
MEMMOVE()
MEMSET()

FGETC()
GETC()
GETCH()
CH() 
GETCHAR()
GETS()
FGETS()
GETENV()

PUTC()
PUTCHAR()
PUTS()
FPUTS()
FPUTC()

PRINTF()
FPRINTF()
SPRINTF()

Goto

ISALNUM(char)
ISALPHA(char)
ISDIGIT(char)
ISLOWER(char)
ISSPACE(char)
ISUPPER(char)
ISXDIGIT(char)
ISCNTRL(x)
ISGRAPH(x)
ISPRINT(x)
ISPUNCT(x)
TOLOWER()
TOUPPER()






STATEMENT
 EXAMPLE
 
if (expr) stmt; [else stmt;]
 if (x==25)

    x=1;

else

    x=x+1;
 
while (expr) stmt;
 while (get_rtcc()!=0)

   putc(‘n’);
 
do stmt while (expr);
 do {

   putc(c=getc());

} while (c!=0);
 
for (expr1;expr2;expr3) stmt;
 for (i=1;i<=10;++i)

   printf(“%u\r\n”,i);
 
switch (expr)  { 

case cexpr: stmt; //one or more case [default:stmt]

... }
 switch (cmd) {

   case 0:  printf(“cmd 0”);

      break;

   case 1: printf(“cmd 1”);

      break;

   default: printf(“bad cmd”);

      break; }
 
return [expr];
 return (5);
 
goto label;
 goto loop;
 
label: stmt;
 loop: I++;
 
break;
 break;
 
continue;
 continue;
 
expr;
 i=1;
 
;
 ;
 
{[stmt]}

Zero or more
 {a=1;
  b=1;}
 
How can a constant data table be placed in ROM?
-----------------------------------------------

The compiler has support for placing any data structure into the device ROM as a constant read-only element.  Since the ROM and RAM data paths are separate in the PIC®, there are restrictions on how the data is accessed.  For example, to place a 10 element BYTE array in ROM use:

BYTE CONST TABLE [10]= {9,8,7,6,5,4,3,2,1,0};

and to access the table use:

x = TABLE [i];

OR

x = TABLE [5];

BUT NOT

ptr = &TABLE [i];

In this case, a pointer to the table cannot be constructed.

Similar constructs using CONST may be used with any data type including structures, longs and floats.

Note that in the implementation of the above table, a function call is made when a table is accessed with a subscript that cannot be evaluated at compile time.

=-=----=--=-=-=-
How are type conversions handled?

The compiler provides automatic type conversions when an assignment is performed.  Some information may be lost if the destination can not properly represent the source.  For example: int8var = int16var;  Causes the top byte of int16var to be lost.

Assigning a smaller signed expression to a larger signed variable will result in the sign being maintained.  For example, a signed 8 bit int that is -1 when assigned to a 16 bit signed variable is still -1.

Signed numbers that are negative when assigned to a unsigned number will cause the 2's complement value to be assigned.  For example, assigning -1 to a int8 will result in the int8 being 255.  In this case the sign bit is not extended (conversion to unsigned is done before conversion to more bits).  This means the -1 assigned to a 16 bit unsigned is still 255.

Likewise assigning a large unsigned number to a signed variable of the same size or smaller will result in the value being distorted. For example, assigning 255 to a signed int8 will result in -1.

The above assignment rules also apply to parameters passed to functions.

When a binary operator has operands of differing types then the lower order operand is converted (using the above rules) to the higher.  The order is as follows:

Float

Signed 32 bit

Unsigned 32 bit

Signed 16 bit

Unsigned 16 bit

Signed 8 bit

Unsigned 8 bit

1 bit

The result is then the same as the operands.  Each operator in an expression is evaluated independently.  For example:

i32 = i16 - (i8 + i8)

The + operator is 8 bit, the result is converted to 16 bit after the addition and the - is 16 bit, that result is converted to 32 bit and the assignment is done.  Note that if i8 is 200 and i16 is 400 then the result in i32 is 256.  (200 plus 200 is 144 with a 8 bit +)

Explicit conversion may be done at any point with (type) inserted before the expression to be converted.  For example in the above the perhaps desired effect may be achieved by doing:

i32 = i16 - ((long)i8 + i8)

In this case the first i8 is converted to 16 bit, then the add is a 16 bit add and the second i8 is forced to 16 bit.

A common C programming error is to do something like:

i16 = i8 * 100;

When the intent was:

i16 = (long) i8 * 100;

Remember that with unsigned ints (the default for this compiler) the values are never negative.  For example 2-4 is 254 (in 8 bit).  This means the following is an endless loop since i is never less than 0:

int i;

for( i=100; i>=0; i--)

=--=-=-- monitor =-=-=-
Debugger - Monitor

The monitor window shows data from the target and allows entry of data to be sent to the target.  This is done on the target like this:

#use RS232(DEBUGGER)

...

printf(“Test to run? “);

test=getc();

 

For the PIC16 ICD the B3 pin is used on the target to implement this capability.  The normal ICD cable is already set up correctly for this.

-=-=-=-= rs232-=-=-=-
How can I use two or more RS-232 ports on one PIC®?

The #USE RS232 (and I2C for that matter) is in effect for GETC, PUTC, PRINTF and KBHIT functions encountered until another #USE RS232 is found.

The #USE RS232 is not an executable line.  It works much like a #DEFINE.

The following is an example program to read from one RS-232 port (A) and echo the data to both the first RS-232 port (A) and a second RS-232 port (B).

#USE  RS232(BAUD=9600, XMIT=PIN_B0, RCV=PIN_B1)
void  put_to_a( char c ) {
   put(c);
}

char  get_from_a( ) {
    return(getc()); }

#USE RS232(BAUD=9600, XMIT=PIN_B2,RCV=PIN_B3)
void put_to_b( char b ) {
   putc(c);
}

main() {
   char c;  
   put_to_a("Online\n\r");
   put_to_b("Online\n\r");
   while(TRUE) {
     c=get_from_a();
     put_to_b(c);
     put_to_a(c);
   }
}

The following will do the same thing but is less readable:

#USE RS232(BAUD=9600, XMIT=PIN_B0, RCV=PIN_B1, STREAM=COM_A)
#USE RS232(BAUD=9600, XMIT=PIN_B2, RCV=PIN_B3, STREAM=COM_B)

   main() {
      char c;
      fprintf(COM_A,"Online\n\r");
      fprintf(COM_B,"Online\n\r");
      while(TRUE) {
        c = fgetc(COM_A);
        fputc(c, COM_A);
        fputc(c, COM_B);
      }
    }
-=-=--=-ICD-=-=-=
How do I put a NOP at location 0 for the ICD?

The CCS compilers are fully compatible with Microchips ICD debugger using MPLAB.  In order to prepare a program for ICD debugging (NOP at location 0 and so on) you need to add a #DEVICE ICD=TRUE after your normal #DEVICE.

For example:

#INCLUDE <16F877.h>
#DEVICE  ICD=TRUE