Si quieres tener más información respecto a este compilador, ve a la web oficial de CCS haciendo clic aquí.
Para escribir un programa en C con CCS se deben tener en cuenta una serie de conceptos básicos con respecto a su estructura, estas son:

DIRECTIVAS DE PRE-PROCESADO: Indispensables para controlan la conversión del programa a código maquina por parte del compilador.
FUNCIONES: Son un conjunto de instrucciones. Puede haber una o varias funciones dentro del programa; en cualquier caso siempre se debe definir una como principal mediante la inclusión de una función llamada main().
INSTRUCCIONES: Indican como se debe comportar el PIC en todo momento.
COMENTARIOS: Permiten describir el significado de cada línea del programa.
A continuación, haremos un repaso de conceptos necesarios para programar PIC's con lenguaje C.
CCS C acepta los siguientes tipos de datos:

Las constantes se pueden clasificar en decimal, octal hexadecimal o en binario:

También se definen caracteres especiales, tales como:

Una variable es un espacio de memoria identificado por un nombre, donde se almacenan valores de un tipo determinado y que pueden variar a lo largo del programa. Para hacer uso de ellas es necesario declararlas antes, para ello se debe indicar el tipo de dato que se manejara y el nombre de la variable, ejemplo:
int alto;
alto = 5;
alto = 70;
Las variables pueden declararse como tipo LOCAL o GLOBAL dependiendo del uso que se le quiera dar.
Las variables locales son declaradas en el interior de una función y solo tienen validez dentro de esta, es decir, solo existen dentro de la función donde fueron declaradas.
Las variables globales deben ser declaradas antes de cualquier función y fuera de ellas, pero, a diferencia de las locales, se pueden utilizar y/o modificar su valor dentro de una función del programa.

Una expresión de asignación tiene la siguiente forma:
expr1 = expr1 operador expr2; por ejemplo: i = i + 7;
pero se puede representar de otra forma más corta:
expr1 operador= expr2; por ejemplo: i += 7;
A continuación se muestra una tabla que describe los operadores de asignación representados en su forma corta:

Los operadores aritméticos se usan para realizar operaciones matemáticas:

Las operaciones de incremento y decremento dependen de la posición del operador, es decir, (a) representa un pre-incremento, mientras que (a) representa un post-incremento.

Su misión es comparar dos valores y dar un resultado de tipo short: 0 o false (falso), 1 o true (verdadero).

Al igual que los operadores relacionales, estos devuelven un resultado de tipo short: 0 o false (falso), 1 o true (verdadero) tras la evaluación de sus operandos.

Estos operadores permiten actuar sobre los operandos a nivel de bits y solo pueden ser enteros (tipo int).

Los operadores de desplazamiento otorgan al C capacidad de control a bajo nivel similar al lenguaje ensamblador. Estos operadores utilizan dos operandos enteros (tipo int): el primero es el elemento a desplazar y el segundo, el número de posiciones de bits que se desplaza.

Los operadores & y * se utilizan para trabajar con punteros, pero ¿qué es un puntero? Bueno un puntero es una variable que contiene la dirección de una variable o de una función, es decir, es una variable que apunta a otra variable. El uso de punteros es muy beneficioso debido a que permiten la manipulación indirecta de datos y códigos, pero su uso es muy delicado debido a que se trabaja directamente con direcciones de memoria, por lo tanto para su uso se recomienda práctica.
Disponemos de dos operadores:

El operador de dirección & : Nos da la dirección de memoria de su operando.
El operador de indirección * : Nos da el contenido de la variable cuya dirección está apuntada por el puntero.
Por ejemplo, si queremos guardar en el puntero p la dirección de memoria de la variable entera contador, debemos hacer lo siguiente:


Son empleadas para controlar el proceso de ejecución del programa.
Las declaraciones de control admitidas por CCS son:
Empleado en situaciones donde sea necesario realizar una toma de decisiones.

Los IF-ELSE pueden anidarse, es decir, usarse unos dentro de otros permitiendo tomar decisiones múltiples.

Es una herramienta de control de decisión múltiple empleada muy seguido debido a su simplicidad y alta fiabilidad:

Se trata de un ciclo repetitivo empleado para repetir sentencias un número conocido de veces.

Es un tipo de ciclo empleado para repetir sentencias un número indefinido de veces siempre que se cumpla una condición especifica (expresión).

Parecido al ciclo while, con la diferencia de que este se ejecuta al menos una sola vez.

Si se ejecuta alguno de los siguientes segmentos de código se consigue ciclo infinito

Se emplea para devolver datos en las funciones.
Permite salir de un bucle. Se utiliza para while, do-while, for y switch.
Provoca un salto incondicional a cualquier lugar dentro del programa.
Los comentarios cumplen un papel importante dentro del programa y es que facilitan la comprensión de las distintas expresiones tanto para el programador como para quien tiene que interpretar dicho programa, además, no afecta al código ni al funcionamiento normal del PIC por lo que pueden ser tan extensos como se quiera.
Existen dos formatos de comentarios según su uso:
Comentario de una línea: Al colocar estos signos // se comienza el comentario y finaliza automáticamente al final de la línea.
Comentario multi-línea: Se logran utilizando los signos /* y */ al inicio y al final del comentario, pero no pueden repetirse dentro del mismo.

Una función se describe en pocas palabras como un bloque de sentencias agrupadas en un solo paquete que son llamadas a ejecutarse en el momento que se requiera y con solo escribir el nombre de la función. Son empleadas con frecuencia en la ejecución de tareas repetitivas como configuración de puertos, control de giro de un motor, encendido secuencial de leds, control de relés, en fin, el límite es la imaginación, y como son funciones de usuario somos nosotros quienes elegimos en que emplearlas.
La estructura de una función es:

La forma de devolver un valor es mediante la sentencia return:

Donde expresión debe manejar el mismo tipo de dato que el especificado en la definición de la función. En el caso de no devolver nada se finaliza con return, al encontrar esta sentencia el compilador vuelve a la ejecución de la sentencia de llamada. También se puede finalizar la función sin el comando return, tan solo con la llave de cierre.
Por ejemplo analicen el siguiente programa:

El programa anterior es un ejemplo simple del uso de una función. Pueden ver que en la línea_#7 se ha declarado una función llamada read_button, y como no retorna valor alguno se declara tipo void. Más adelante, en la línea_#17 se puede apreciar la definición de la función indicando cada una de las sentencias que debe ejecutar cuando sea invocada. Para ejecutar la función vean la línea_#13 dentro de la función principal main donde podrán notar que solo se requiere escribir su nombre seguido de sus parámetros encerrados entre paréntesis, pero en este caso como no presenta parámetros dichos paréntesis están vacíos. Además, se muestra una aplicación simple de la declaración de control switch.
Si tienen dudas o sugerencias ya saben, comentenlas abajo que con gusto respondo.
Me despido feliz de haber compartido este conocimiento con ustedes.