PIC Compiler
PIC Compiler
PIC Compiler
máxima optimización del compilador con estos dispositivos. Dispone de una amplia librería de
funciones predefinidas, comandos de preprocesado y ejemplos. Además suministra los
controladores (drivers) para diversos dispositivos como LCD, convertidores AD, relojes en tiempo
real, etc.
El PIC C COMPILER es c estándar y, además de las directicas estándar (#include, etc.), suministra
unas directivas específicas para PIC (#device, etc); además incluye funciones específicas (bit_set(),
etc.). Se suministra con un editor que permite controlar la sintaxis del programa.
Estructura de un programa
Para escribir un programa en C con el PIC C COMPILER se debe tener en cuenta una serie de
elementos básicos de su estructura tales como:
Entorno de trabajo
Elementos básicos del entorno de trabajo de PIC C COMPILER; existen dos formas de iniciar una
sección: abriendo un fichero de código fuente o creando un proyecto.
Tipos de datos
123 Decimal
0123 Octal
0x123 Hexadecimal
0b010010 Binario
¨ x¨ Carácter
¨/010¨ Carácter octal
¨/xA5¨ Carácter hexadecimal
Int8 127U
Long 80UL
Signed INT16 80L
Float 3.14F
Char Con comillas simples
\n Cambio de línea
\r Retorno de carro
\t Tabulación
\b Backspace
Variables
Las variables se utilizan para nombrar posiciones de memoria RAM ; se deben declarar,
obligatoriamente, antes de utilizarlas; para ello se debe indicar el nombre el nombre y el tipo de
dato que se manejará. Se definen de la siguiente forma:
Ejemplo:
Float temp_limi=500.0;
Las variables definidas en un programa pueden ser de tipo local o global. Las variables locales solo
se utilizan en la función donde se encuentran declaradas; las variables globales se pueden utilizar
en todas las funciones del programa. Ambas deben declararse antes de ser utilizadas y las globales
deben declararse antes de cualquier función y fuera de ellas. Las variables globales son puestas a
cero cuando se inicia la función principal main ().
Ejemplo:
Void main ( )
AUTO: (usada por defecto, no hace falta que se indique) donde la variable existe mientras
la función esta activa. Estas variables no se inicializan a cero. Su valor se pierde cuando se
sale de la función.
STATIC: Una variable local se activa como global, se inicializa a cero y mantiene su valor al
entrar y salir de la función.
Operadores de asignación:
+= Asignación de suma
-= Asignación de resta
*= Asignación de multiplicación
/= Asignación de división
%= Asignación del resto de la división
<<= Asignación de desplazamiento ala izquierda
>>= Asignación de desplazamiento ala derecha
&= Asignación AND de bits
|= Asignación OR de bits
^= Asignación OR EXCLUSIVA de bits
Operadores aritméticos:
+ Suma
- Resta
* Multiplicación
/ División
% Modulo
-- Incremento
++ Decremento
sizeof Termina el tamaño, en bytes, de un operando
Operadores relacionales
Operadores lógicos:
! NOT
&& AND
|| OR
Operadores de bits
~ Complemento a 1
& AND
^ OR EXCLUSIVA
| OR
>> Desplazamiento a derechas
<< Desplazamiento a izquierdas
Punteros
& Dirección
* Indireccion
-> Puntero a estructura
Estas función son de uso común, son utilizadas para el manejo de datos y configuraciones básicas
del entrada y salida de información.
Los parámetros
Función que se encarga de configurar las
set_tris_x(binario: corresponde a indicar las
entradas y salidas del microcontrolador,
0b00000) entradas o salidas del
configura el registro TRIS. El carácter "x"
set_tris_x(hexadecimal: microcontrolador donde
corresponde al valor de los puesto; a,b,c,d...
0x00) "1" es igual entrada y "0"
Según sea el microcontrolador.
es igual a salida.
Los parámetros
corresponde a los
Esta función se utiliza para darle valores
output_x(binario: valores iniciales del
iniciales al puesto. El carácter "x"
0b00000) puesto, donde "1"
corresponde al valor de los puesto; a,b,c,d...
output_x(hexadecimal: significa un nivel alto
Según sea el microcontrolador.
0x00) lógico y "0" nivel bajo
lógico.
El parámetro configura
Pone a "1" el pin indicado. El método de
output_high(pin) un PIN específico para
acceso debe ser salida.
cambiar estado alto.
El parámetro configura
Pone a "0" el pin indicado. El método de
output_low(pin) un PIN específico para
acceso debe ser salida.
cambiar estado bajo.
El parámetro configura
Pone a "0" o "1" el pin indicado. El método de
output_toggle(pin) un PIN específico para
acceso debe ser salida.
intercambiar el estado.
Parámetro tiempo en ms
que equivale a
delay_ms(int:time), Función que realiza una pausa ya sea en MS
microsegundos o us que
delay_us(int:time) (micro-segundos) ó US(nano-segundos).
equivale a
nanosegundos.
c = GETC ()
c = GETCH ()
c = GETCHAR ()
Estas funciones esperan un carácter por la patilla RCV del dispositivo RS232 y retorna el carácter
recibido.
Es preciso utilizar la directiva #USE RS232 antes de la llamada a esta función para que el
compilador pueda determinar la velocidad de transmisión y la patilla utilizada. La directiva #USE
RS232 permanece efectiva hasta que se encuentre otra que anule la anterior.
Los procedimientos de I/O serie exigen incluir #USE DELAY para ayudar a sincronizar de forma
correcta la velocidad de transmisión. Recordad que es necesario adaptar los niveles de voltaje
antes de conectar el PIC a un dispositivo RS-232.
Ejemplo:
printf("Continuar (s,n)?");
do
{ respuesta=getch();
} while(respuesta!='s'&& respuesta!='n');
GETS(char *string)
Esta función lee caracteres (usando GETC ()) de la cadena (string) hasta que encuentra un retorno
de carro (valor ASCII 13). La cadena se termina con un 0.
PUTC () PUTCHAR ()
Estas funciones envían un carácter a la patilla XMIT del dispositivo RS232. Es preciso utilizar la
directiva #USE RS232 antes de la llamada a esta función para que el compilador pueda determinar
la velocidad de transmisión y la patilla utilizada. La directiva #USE RS232 permanece efectiva hasta
que se encuentre otra que anule la anterior.
Ejemplo:
if (checksum==0)
putchar(ACK);
PUTS (string)
Esta función envía cada carácter de string a la patilla XMIT del dispositivo RS232. Una vez
concluido el envío de todos los caracteres la función envía un retorno de carro CR o RETURN (ASCII
13) y un avance de línea LF o LINE-FEED (ASCII 10).
Ejemplo:
La función de impresión formateada PRINTF saca una cadena de caracteres a la estándar serie RS-
232 o a una función especificada. El formato está relacionado con el argumento que ponemos
dentro de la cadena (string).
Cuando se usan variables, string debe ser una constante. El carácter % se pone dentro de string
para indicar un valor variable, seguido de uno o más caracteres que dan formato al tipo de
información a representar.
Si ponemos %% obtenemos a la salida un solo %. El formato tiene la forma genérica %wt, donde w
es optativo y puede ser 1,2,...,9. Esto es para especificar cuántos carácteres son representados; si
elegimos el formato 01,...,09 indicamos ceros a la izquierda, o también 1.1 a 9.9 para
representación en punto flotante.
KBHIT ()
Esta función devuelve TRUE si el bit que se está enviando al pin RCV de un dispositivo RS232, es el
bit de inicio de un carácter. Es preciso utilizar la directiva #USE RS232 antes de la llamada a esta
función para que el compilador pueda determinar la velocidad en baudios y la patilla utilizada. La
directiva #USE RS232 permanece efectiva hasta que se encuentre otra que anule la anterior.
Ejemplo:
keypress=' ';
if ( kbhit () )
output_high(PIN_B3);
else output_low(PIN_B3)
DIRECTIVAS
# device PIC16F84
LP, XT, HS, RC, NOWDT, WDT, NOPUT, PUT, PROTECT, NOPROTECT.
# device PIC16F84
#include <16F84.h>
#USE DELAY( CLOCK=SPEED), permite definir las frecuencias del oscilador del PIC, el
compilador lo utiliza para realizar cálculos de tiempo. Se puede utilizar M, MHZ, K y KHZ
para definir la frecuencia.
#include <16F877.h>
Estructuras de control
Las declaraciones de control son usadas para controlar el proceso de ejecución del programa, las
que admite PIC C COMPILER son:
If – else
While
Do – while
For
Switch –case.
Return
Break, continue y goto.
IF – ELSE
If (expresion)
Sentencia_1;
else
Sentencia_2;
Pueden anidarse los if – else dando lugar al else– if; esto permite tomar decisiones múltiples.
If (expresion)
Sentencia_1;
Else if (expresion_2)
Sentencia_2;
Else
Sentencia_3;
En este caso las expresiones se evalúan en orden, si algunas de ellas es cierta la sentencia asociada
a ella se ejecutara y se termina la función. En caso contrario se ejecuta la sentencia del else. En
ambos casos si existen varias sentencias para ejecutar se deben utilizar las llaves {}.
SWITCH
Switch (expresion)
Case constante 1:
Sentencias;
Break;
Case constante 2:
Sentencias;
Break;
default:
Sentencias;
Evalúa la expresión y en orden a la constante adecuada realiza las sentencias asociadas. Si ninguno
de los cases corresponde a la constante se ejecuta el default.
El caso break provoca la salida del switch, de lo contrario se ejecuta el siguiente case.
FOR
Sentencias;
En las expresiones del for la inicialización es una variable a la cual se le asigna un valor inicial con
el que con el que controlar el bucle. La condición de finalización sirve para evaluar antes de
ejecutar las sentencias si es cierto o no, en el caso de ser cierto se ejecutan las sentencias en caso
contrario se sale del for. Por último, la expresión de incremento o decremento modifica la variable
de control después de ejecutar el bucle.
WHILE
While (expresión)
Sentencias;
DO WHILE
Se diferencia del while y del for en la condición de finalización, la cual se evalúa al final del bucle,
por lo que las sentencias se ejecutan al menos una vez.
Do
Sentencias;
While (expresión);
Otros:
RETURN
BREAK
GOTO
Las funciones son bloques de sentencias; todas las sentencias se deben enmarcar dentro de las
funciones. Al igual que la variable, las funciones deben definirse antes de utilizarse.
Una función puede ser invocada desde una sentencia de otra función. Una función puede devolver
un valor a la sentencia que le ha llamado. El tipo de dato se indica en la definición de la función; en
el caso de no indicarse nada se entiende que es un int8 y en el caso de no devolver un valor se
debe especificar el valor VOID. La función, además de devolver un valor, puede recibir parámetros
o argumentos.
Una característica importante de las funciones, es que pueden recibir parámetros y que pueden
devolver un valor. La misma función nos puede servir para varios casos, con tan solo variar el valor
de los parámetros. El compilador de CCS incluye muchas funciones "built-in" (listas para usarse) en
sus librerías para el control directo de muchos de los recursos del PIC, para utilizarlas sólo
necesitamos saber los parámetros que reciben y los valores que devuelven.
La llamada a la función.
El hecho de que nuestro programa defina una función, no quiere decir que esa función sea
ejecutada. A menos que se produzca una llamada a la función, la función no será ejecutada, sino
tan solo definida.
Por ejemplo, cuando nosotros incluimos la directiva #USE RS232 que es una directiva asociada a
las bibliotecas pre compiladas, incluimos los prototipos de muchas funciones, pero sólo se
ejecutan aquellas funciones a las que llamamos, como printf. Vamos a ver con más detalle cada
una de estas partes.
(Sentencias);
El prototipo aparece antes del bloque main, o normalmente en los archivos de cabecera (.h)
tipo nombre_función(parámetros);
De donde
tipo-> es el tipo de dato que va a devolver la función. Si no se indica ningún tipo de dato, por
defecto se asume el tipo int. Si la función no va a devolver ningún dato hay que poner void.
tipo nombre_función(parámetros)
{
declaración de datos de la función.
cuerpo de la función
}
La función va encabezada por el prototipo, pero esta vez sin finalizar en punto y coma. Después,
se
incluye el bloque de sentencias de la función.
La lista de parámetros puede ser vacía, sin parámetros, si bien los paréntesis de la función deben
colocarse de igual forma.
Para ejecutar una función hay que llamarla. La llamada a una función consta del nombre de la
misma
y de una lista de argumentos o valores a pasar denominados parámetros actuales, separados por
comas y encerrados entre paréntesis.
Cuando el programa llama a una función, la ejecución del programa se transfiere a dicha función.
El
programa retorna a la sentencia posterior a la llamada cuando acaba esa función. La sintaxis de
una
llamada a una función es:
nombre (parámetros);
De dónde
RETURN
return (expresión);
return expresión ;
Donde expresión debe manejar el mismo tipo de dato que el indicado 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 RETURN, tan solo con la llave de cierre “}”.
Las funciones pueden agruparse en ficheros de librerías <fichero.h>, que se pueden utilizar
mediante la directiva #include <fichero.h>.
1 #INCLUDE <16f887.h>
2 #USE DELAY(CLOCK=4000000)
3 #FUSES XT,PROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
4 #DEFINE SW PORTA,1
6 #BYTE PORTA= 5
7 #BYTE PORTB= 6
8 MAIN()
9 {
10 SET_TRIS_A(0B10); //Configura el puerto A
11 SET_TRIS_B(0B11111110); //Configura el puerto B
13 {
15 {
17 }
19 {
21 }
22 }
23 }
En el siguiente ejemplo, vamos a encender y a apagar un LED conectado a RB0 cada medio
segundo.
1 #INCLUDE <16f887.h>
2 #USE DELAY(CLOCK=4000000)
3 #FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP
5 #BYTE PORTB= 6
6
7 MAIN()
8 {
9 SET_TRIS_B(0B11111110); //Configura el puerto B
10 WHILE(TRUE) // Haga por siempre
11 {
16 }
17 }
#include < 16F84A . h >
2: #use delay ( clock = 4000000 )
3: #fuses XT , NOWDT
4: #use standard_io ( B )
5:
6: void main ( void )
7:
8:
9: {
10: Do {
11:
12: OUTPUT_HIGH ( PIN_B0 );
13: delay_ms ( 200 );
14:
15: OUTPUT_HIGH ( PIN_B1 );
16: delay_ms ( 200 );
17:
18: OUTPUT_HIGH ( PIN_B2 );
19: delay_ms ( 200 );
20:
21: OUTPUT_HIGH ( PIN_B3 );
22: delay_ms ( 200 );
23:
24: OUTPUT_HIGH ( PIN_B4 );
25: delay_ms ( 200 );
26:
27: OUTPUT_LOW ( PIN_B0 );
28: delay_ms ( 200 );
29:
30: OUTPUT_LOW ( PIN_B1 );
31: delay_ms ( 200 );
32:
33: OUTPUT_LOW ( PIN_B2 );
34: delay_ms ( 200 );
35:
36: OUTPUT_LOW ( PIN_B3 );
37: delay_ms ( 200 );
38:
39: OUTPUT_LOW ( PIN_B4 );
40: delay_ms ( 200 );
41:
42: }
43:
44: WHILE ( TRUE );
45:
46: }
5
7
8
9 {
13
16 }
17
19
20 }