Rev: 1.0
MPLAB C18: C Bรกsico
Omar Gurrola http://www.proprojects.wordpress.com 5/22/2012
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
CONTENIDO LICENCIA ............................................................................................................................................1 AGRADECIMIENTOS ...........................................................................................................................2 INTRODUCCIÓN .................................................................................................................................2 OBJETIVO DE ESTE TUTORIAL..............................................................................................................2 1.
SOFTWARE Y HARDWARE UTILIZADO ..........................................................................................2
2.
VARIABLES Y DATOS ...................................................................................................................3
3.
4.
2.1.
TIPOS DE VARIABLES Y TAMAÑOS ................................................................................................ 3
2.2.
CONSTANTES NUMÉRICAS ............................................................................................................ 4
2.3.
CONVERSIÓN DE TIPO (TYPECASTING) ......................................................................................... 5
2.4.
ÁMBITO DE VALIDEZ (SCOPE) ....................................................................................................... 5
2.5.
REDEFINICIÓN DE VARIABLES (TYPEDEF) ...................................................................................... 6
2.6.
ENUMERACIONES ......................................................................................................................... 7
2.7.
ESTRUCTURAS ............................................................................................................................... 8
2.8.
UNIONES ....................................................................................................................................... 9
2.9.
ARREGLOS ................................................................................................................................... 11
2.10.
CADENAS DE CARACTERES ...................................................................................................... 12
2.11.
PUNTEROS ............................................................................................................................... 13
2.12.
TAMAÑO (SIZEOF()) ................................................................................................................ 14
MODIFICADORES DE VARIABLES ............................................................................................... 15 3.1.
AUTO ........................................................................................................................................... 15
3.2.
STATIC ......................................................................................................................................... 15
3.3.
EXTERN ........................................................................................................................................ 16
3.4.
VOLATILE ..................................................................................................................................... 17
3.5.
REGISTER ..................................................................................................................................... 17
3.6.
CONST ......................................................................................................................................... 17
3.7.
OVERLAY (C18) ............................................................................................................................ 18
3.8.
RAM (C18) ................................................................................................................................... 18
3.9.
ROM (C18) ................................................................................................................................... 19
OPERADORES ........................................................................................................................... 20 4.1.
OPERADORES ARITMÉTICOS ....................................................................................................... 20
Revisión: 1.0 [05/2012]
MPLAB C18: C Básico
5.
6.
7.
8.
9.
Omar Gurrola http://www.proprojects.wordpress.com
4.2.
OPERADORES DE COMPARACIÓN ............................................................................................... 20
4.3.
OPERADORES LÓGICOS ............................................................................................................... 21
4.4.
OPERADORES DE BITS ................................................................................................................. 22
4.5.
PROCEDENCIA Y ORDEN DE EVALUACIÓN .................................................................................. 23
ESTRUCTURAS DE CONTROL ...................................................................................................... 23 5.1.
IF-ELSE ......................................................................................................................................... 23
5.2.
ELSE-IF ......................................................................................................................................... 24
5.3.
SWITCH........................................................................................................................................ 24
5.4.
WHILE .......................................................................................................................................... 24
5.5.
DO-WHILE.................................................................................................................................... 25
5.6.
FOR .............................................................................................................................................. 25
5.7.
CONTINUE ................................................................................................................................... 25
5.8.
BREAK .......................................................................................................................................... 26
5.9.
GOTO ........................................................................................................................................... 26
FUNCIONES .............................................................................................................................. 26 6.1.
DECLARACIÓN Y DEFINICIÓN ...................................................................................................... 26
6.2.
PARÁMETROS .............................................................................................................................. 27
DIRECTIVAS DEL PREPROCESADOR ............................................................................................ 28 7.1.
#INCLUDE .................................................................................................................................... 28
7.2.
#DEFINE, #IFDEF, #IFNDEF, #UNDEF, #IF, #ELIF, #ELSE, #ENDIF, #ERROR .................................. 28
7.3.
#PRAGMA (C18) .......................................................................................................................... 29
7.4.
SECCIONES DE MEMORIA (C18) .................................................................................................. 31
7.5.
ENSAMBLADOR EN LÍNEA ........................................................................................................... 33
LIBRERÍAS ................................................................................................................................. 34 8.1.
QUE ES UNA LIBRERÍA Y COMO USARLA..................................................................................... 34
8.2.
COMO CREAR TU LIBRERÍA DE DEMORAS .................................................................................. 35
8.3.
COMO CREAR TU LIBRERÍA DE TIPOS DE VARIABLES .................................................................. 37
REFERENCIAS ............................................................................................................................ 39
Revisión: 1.0 [05/2012]
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
LICENCIA
MPLAB C18: C Básico por Omar Gurrola – http://www.proprojects.wordpress.com se encuentra bajo una Licencia Creative Commons Atribución-NoComercial-CompartirIgual 3.0 Unported.
Revisión: 1.0 [05/2012]
1
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
AGRADECIMIENTOS Gracias a mi esposa Tomiko, por ser mí apoyo y darme fortaleza. También quiero agradecer a Alejandro Casanova “infopic.comlu.com” por su excelente tutorial de MPLAB C18. A todas las personas que han dedicado tiempo y esfuerzo a realizar tutoriales y/o guías para que personas como yo aprendan de forma fácil y rápida.
INTRODUCCIÓN El lenguaje C a pesar de tener mucho tiempo que se inventó (1972), sigue siendo muy utilizado en varios ámbitos, principalmente en los que se requiere programación de más bajo nivel como es el caso de microcontroladores, drivers, etc. Por lo que si te quieres especializar a desarrollar firmware para microcontroladores como yo, es indispensable que domines este lenguaje. Algunos microcontroladores ya se pueden programar en C++ lo que facilita mucho estructurar programas más grandes y complejos, pero por el momento los microcontroladores que estaré utilizando se programan en C.
OBJETIVO DE ESTE TUTORIAL Este tutorial tiene el objetivo de poner en práctica varios aspectos básicos del lenguaje C enfocado a microcontroladores, utilizando el compilador de Microchip llamado C18.
1. SOFTWARE Y HARDWARE UTILIZADO Todas las prácticas fueron desarrolladas y probadas con: Software:
Windows 7 SP1 x64 Microchip MPLAB IDE v8.84 Microchip C18 3.4
Hardware:
AMD Phenom II 9600B Quad-Core 2.3 GHz 4GB DDR2
Revisión: 1.0 [05/2012]
2
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico 2. VARIABLES Y DATOS 2.1. TIPOS DE VARIABLES Y TAMAÑOS
En C existen diferentes tipos de variables que se utilizan para almacenar datos e información durante la ejecución del programa. Son los siguientes para C18: Tipo: char unsigned char int unsigned int short unsigned short short long unsigned short long long unsigned long float double
Tamaño (bits): 8 8 16 16 16 16 24 24 32 32 32 32
Mínimo: -128 0 -32768 0 -32768 0 -8388608 0 -2174483648 0 exp(-126) exp(-126)
Máximo: 127 255 32767 65535 32767 65535 8388607 16777215 2147486647 4294967295 exp(128) exp(128)
2.1.1. Ejemplo. main.c void main(void) { // Variables locales char c_variable; char c_variable2; unsigned char uc_variable; int i_variable; int i_variable2; unsigned int ui_variable; short s_variable; short s_variable2; unsigned short us_variable; short long sl_variable; short long sl_variable2; unsigned short long usl_variable; long l_variable; long l_variable2; unsigned long ul_variable; float f_variable; double d_variable;
// 8b -128 -> 127 // 8b 0 -> 255 // 16b -32,768 -> 32,767 // 16b 0 -> 65,535 // 16b -32,768 -> 32,767 // 16b 0 -> 65,535 // 24b -8,388,608 -> 8,388,607 // 24b 0 -> 16,777,215 // 32b -2,147,483,648 -> 2,147,483,647 // 32b 0 -> 4,294,967,295 // 32b exp(-126) -> exp(128) // 32b exp(-126) -> exp(128)
c_variable = -128; c_variable2 = 127; uc_variable = 255; i_variable=-32768; i_variable2=32767; ui_variable=65535; s_variable = -32768; s_variable2 = 32767; us_variable = 65535; sl_variable=-8388608; sl_variable2=8388607;
Revisión: 1.0 [05/2012]
3
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico usl_variable=16777215; l_variable=-2141483648; l_variable2=2141483647; ul_variable=4294967295; f_variable=-5.321; d_variable=6.999; }
2.2. CONSTANTES NUMÉRICAS Nos ayuda a definir valores en diferentes bases numéricas directamente. Base: Decimal Hexadecimal Binario Octal
Prefijo: Ninguno 0x 0b 0
Ejemplo: 250 0xAA 0b11110000 077
2.2.1. Ejemplo. main.c void main(void) { unsigned char a,b,c,d; a b c d
= = = =
250; 0xAA; 077; 0b11110000;
// // // //
Decimal Hexadecimal Octal Binario
}
Revisión: 1.0 [05/2012]
4
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
2.3. CONVERSIÓN DE TIPO (TYPECASTING) Permite que una variable actué como de otro tipo, pero la variable original nunca es modificada. Este tipo de conversión nos ayuda a realizar operaciones y que el resultado no se vea afectado por el tipo de variable en ciertos casos. Se utiliza poniendo el tipo al que queremos convertirlo entre paréntesis antes de la variable a convertir. 2.3.1. Ejemplo. main.c void main(void) { unsigned char uc_a,uc_b,uc_c; unsigned int ui_x,ui_y; uc_a uc_b uc_c ui_x ui_y
= = = = =
100; 200; uc_a + uc_b; // ERROR: El resultado no estará correcto por que el resultado requiere mas de 8 bits uc_a + uc_b; // ERROR: El resultado tampoco estará correcto por que la operación se realizó con 8 bits (unsigned int)uc_a + (unsigned int)uc_b; // OK y = 300
}
2.4. ÁMBITO DE VALIDEZ (SCOPE) El ámbito de validez de un identificador (función, variable, etc.) es la parte del código donde el identificador puede ser utilizado. Existen cuatro ámbitos:
Ámbito de aplicación (Global) Este ámbito permite que el identificador sea visto por todo el programa. Ámbito de archivo Este ámbito solo se limita para archivos adicionales a main.c, como archivo1.c, etc. Ámbito de función (Local) Los identificadores solo son reconocidos dentro de la función donde se definieron. Ámbito de bloque (En C18 no funcionan) Los identificadores solo son reconocidos dentro del bloque, ejemplo bloque for, while, etc.
2.4.1. Ejemplo. main.c // Ámbito de aplicación unsigned char uc_global = 25; void funcion(unsigned char); void main(void) { // Ámbito de función (Local) unsigned char uc_localmain = 50; unsigned char r;
Revisión: 1.0 [05/2012]
5
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
r = uc_global; // Accedemos a la variable global r = uc_localmain; // Accedemos a la variable local de main funcion(r); } void funcion(unsigned char uc_localparam){ // Ámbito de funcion (Local) unsigned char uc_localfuncion = 100; unsigned char s; s = uc_localfuncion; // Accedemos a la variable local de función s = uc_localparam; // Accedemos al parámetro local de función s = uc_global; // Accedemos a la variable global } archivo1.c // Ámbito de archivo unsigned char x=23; unsigned char getx(){ return x; }
2.5. REDEFINICIÓN DE VARIABLES (TYPEDEF) Se utiliza para redefinir tipos de variables y otros tipos de datos que se verán más delante. Ayudan a que los nombres sean más significativos y cortos. typedef unsigned char BYTE; typedef unsigned int UINT;
2.5.1. Ejemplo. main.c // 8b signed [-128 -> 127] typedef char // 8b unsigned [0 -> 255] typedef unsigned char
INT8, s8; UCHAR, UINT8, u8, BYTE;
// 16b signed [-32,768 -> 32,767] typedef int INT16, s16; // 16b unsigned [0 -> 65,535] typedef unsigned int UINT, UINT16, u16, WORD; // 24b signed [-8,388,608 -> 8,388,607] typedef short long INT24, s24; // 24b unsigned [0 -> 16,777,215] typedef unsigned short long UINT24, u24; // 32b signed [-2,147,483,648 -> 2,147,483,647] typedef long INT32, s32; // 32b unsigned [0 -> 4,294,967,295] typedef unsigned long ULONG, UINT32, u32, DWORD; // 32b decimal point [exp(-126) -> exp(128)] typedef float FLOAT; typedef double DOUBLE; void main(void) { INT8 var1 = -128; INT16 var2 = -32768; INT24 var3 = -8388608; INT32 var4 = -2147483648; UINT8 var5 = 255; UINT16 var6 = 65535; UINT24 var7 = 16777215; UINT32 var8 = 4294967295;
Revisión: 1.0 [05/2012]
6
MPLAB C18: C B谩sico
Omar Gurrola http://www.proprojects.wordpress.com
BYTE var9 = 255; WORD var10 = 65535; DWORD var11 = 4294967295; FLOAT var12 = 5.7; DOUBLE var13 = 8.99; }
2.6. ENUMERACIONES Permite realizar una lista de constantes con nombres que pueden ser f谩cilmente utilizados en el programa. enum {cero,uno,dos,tres}; enum nombres {omar=5,carlos,juan}; typedef enum nombres {omar=5,carlos=7,juan} NOM;
2.6.1. Ejemplo. main.c enum {cero,uno,dos,tres}; // 0,1,2,3 typedef enum nombres {omar=5,carlos=7,juan} NOM; // 5,6,7 void main(void) { unsigned char n0,n1,n2; enum nombres minombre; // Creamos una variable para alojar nombre NOM minombre2, minombre3; // Creamos otra variable para alojar nombre usando la redefinici贸n n0 = cero; // n0 = 0 n1 = uno; // n1 = 1 n2 = dos; // n2 = 2 minombre = omar; // minombre = 5 minombre2 = carlos; // minombre2 = 7 minombre3 = juan; // minombre3 = 8 }
Revisi贸n: 1.0 [05/2012]
7
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
2.7. ESTRUCTURAS Es una colección de variables que pueden contener diferentes tipos de datos que ayudan a organizar y manejar los datos de forma agrupada y fácil. Comúnmente diferentes variables sin agrupar se definían así: unsigned char Hora, Minutos, Segundos, Actualizar, Alarma1, Alarma2, Alarma3;
Con una estructura se definen así: Struct Reloj{ unsigned char Hora; unsigned char Minuto; unsigned char Segundos; unsigned Actualizar:1; unsigned Alarma1:1; unsigned Alarma2:1; unsigned Alarma3:1; } Reloj1; Se utiliza de la siguiente manera: Reloj1.Minutos=15; if(Reloj1.Actualizar==1){ }
2.7.1. Ejemplo. main.c struct Reloj{ unsigned unsigned unsigned unsigned unsigned unsigned unsigned };
char Hora; char Minuto; char Segundos; Actualizar : 1; Alarma1 : 1; Alarma2 : 1; Alarma3 : 1;
typedef struct Calendario{ unsigned int Anio; unsigned char Mes; unsigned char Dia; } CAL; void main(void) { struct Reloj RelojTest; struct Calendario Calendario1; CAL Calendario2; RelojTest.Hora = 10; RelojTest.Minuto = 40; RelojTest.Segundos = 0; RelojTest.Actualizar = 1; Calendario1.Anio = 2011; Calendario1.Mes = 5; Calendario1.Dia = 9; Calendario2.Anio = 2012; Calendario2.Mes = 5; Calendario2.Dia = 9; }
Revisión: 1.0 [05/2012]
8
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
2.8. UNIONES Son similares a las estructuras, la única diferencia es que los campos se sobreponen y se utilizan para llamar de distintas formas a la misma área de memoria. En este ejemplo se reservan 16 bits para un unsigned int que también puede ser accedido por dos unsigned char: union{ unsigned int Valor; struct{ unsigned LSB:8; unsigned MSB:8; }; } Variable;
Y se utiliza de la siguiente manera: Variable.Valor = 0xAB; Variable.LSB = 0xD; Variable.MSB = 0xC;
2.8.1. Ejemplo. main.c typedef union UUINT16{ unsigned int Valor; struct{ unsigned LB:8; unsigned HB:8; }; struct{ unsigned b0:1; unsigned b1:1; unsigned b2:1; unsigned b3:1; unsigned b4:1; unsigned b5:1; unsigned b6:1; unsigned b7:1; unsigned b8:1; unsigned b9:1; unsigned b10:1; unsigned b11:1; unsigned b12:1; unsigned b13:1;
Revisión: 1.0 [05/2012]
9
MPLAB C18: C B谩sico
Omar Gurrola http://www.proprojects.wordpress.com
unsigned b14:1; unsigned b15:1; }; } UINT16_VAL; void main(void) { union UUINT16 Variable1; UINT16_VAL Variable2; Variable1.HB = 0xAB; Variable1.LB = 0xCD; Variable2.Valor = 0; Variable2.b0 = 1; Variable2.b1 = 1; Variable2.b2 = 1; Variable2.b3 = 1; }
Revisi贸n: 1.0 [05/2012]
10
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico 2.9. ARREGLOS
Permiten trabajar con un conjunto de variables del mismo tipo y acceder a cada elemento utilizando un índice que va de 0 hasta N-1, donde N es el número de elementos del arreglo. Para declarar un arreglo se hace de la siguiente forma: unsigned unsigned unsigned unsigned
char char char char
Arreglo[N]; Arreglo2[N][M]; Arreglo3[]={1,2,3,4,5} Arreglo4[2][3]={1,2,3,4,5,6};
2.9.1. Ejemplo. main.c
void main(void) { unsigned char Variable; // Arreglo sin inicializar unsigned char Numeros[3]; unsigned char Numeros2[2][2]; // Arreglo inicializados unsigned char Numeros3[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; unsigned char Numeros4[2][2] = {0, 1, 2, 3}; Numeros[0] = 0; Numeros[1] = 1; Numeros[2] = 2; Numeros2[0][0] Numeros2[0][1] Numeros2[1][0] Numeros2[1][1]
= = = =
0; 1; 2; 3;
Variable = Numeros3[0]; // Variable = 0 Variable = Numeros3[5]; // Variable = 5 Variable = Numeros3[9]; // Variable = 9 Variable Variable Variable Variable
= = = =
Numeros4[0][0]; Numeros4[0][1]; Numeros4[1][0]; Numeros4[1][1];
// // // //
Variable Variable Variable Variable
= = = =
0 1 2 3
}
Revisión: 1.0 [05/2012]
11
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico
2.10. CADENAS DE CARACTERES Es un arreglo de caracteres, donde el último carácter es nulo para definir el fin de la cadena. 2.10.1. Ejemplo. main.c
void main(void) { char caracter1 = 'H'; char caracter2 = 0x48; char mensaje1[] = "Hola mundo!"; char mensaje2[] = "\"Hola\""; }
Revisión: 1.0 [05/2012]
// // // //
Carácter H Carácter H en hexadecimal Cadena de caracteres Cadena de caracteres con comillas
12
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Bรกsico 2.11. PUNTEROS
Un puntero es una variable de 16 bits o 24 bits (Puntero a FAR ROM) que contiene una direcciรณn de memoria. Para declarar un puntero se realiza de la siguiente manera: unsigned char *ptr;
Para asignar la direcciรณn se realiza de la siguiente manera: ptr = &variable; ptr = &Arreglo[0];
Para cambiar o leer el valor de la direcciรณn a la que apunta es de la siguiente manera: *ptr = 0x78; var2 = *ptr;
2.11.1. Ejemplo. main.c void main(void) { unsigned char aVarRAM[3] = {0xAA,0xBB,0xCC}; unsigned char VarRAM = 20; static near rom unsigned char ConROMNear = 30; static far rom unsigned char ConROMFar = 40; unsigned char *pVarRAM; // Puntero a ram de 16b near rom unsigned char *pConROMNear; // Puntero a rom de 16b far rom unsigned char *pConROMFar; // Puntero a rom de 24b unsigned char a,b,c,d,e,f; pVarRAM = &VarRAM; pConROMNear = &ConROMNear; pConROMFar = &ConROMFar;
// pVarRAM apunta a VarRAM; // pConROMNear apunta a pConROMNear // pConROMFar apunta a pConROMFar
a = *pVarRAM; b = *pConROMNear; c = *pConROMFar;
// 20 // 30 // 40
pVarRAM = &aVarRAM[0]; d = *pVarRAM; e = *(pVarRAM+1); f = *(pVarRAM+2);
// // // //
pVarRAM apunta a aVarRAM[0] 0xAA 0xBB 0xCC
}
Revisiรณn: 1.0 [05/2012]
13
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico
2.12. TAMAÑO (SIZEOF()) Nos da el tamaño de una variable (normal, arreglo, puntero, estructura, unión o tipo) en bytes. 2.12.1. Ejemplo. main.c void main(void) { unsigned char r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16,r17,r18,r19; unsigned char *pVarRAM; // Puntero a ram de 16b static near rom unsigned char *pConROMNear; // Puntero a rom de 16b static far rom unsigned char *pConROMFar; // Puntero a rom de 24b unsigned int Arreglo[2][2] = {1,2,3,4}; // Arreglo 2x2 char ArregloCaracteres[] = "Hola mundo!"; // Arreglo de caracteres struct { // Estructura unsigned int Anio; unsigned char Mes; unsigned char Dia; } Estructura1; union{ // Union unsigned int Valor; struct{ unsigned LSB:8; unsigned MSB:8; }; } Union1; r1 = sizeof(char); r2 = sizeof(unsigned char); r3 = sizeof(int); r4 = sizeof(unsigned int); r5 = sizeof(short); r6 = sizeof(unsigned short); r7 = sizeof(short long); r8 = sizeof(unsigned short long); r9 = sizeof(long); r10 = sizeof(unsigned long); r11 = sizeof(float); r12 = sizeof(double);
// // // // // // // // // // // //
1 1 2 2 2 2 3 3 4 4 4 4
(8b) (8b) (16b) (16b) (16b) (16b) (24b) (24b) (32b) (32b) (32b) (32b)
r13 = sizeof(pVarRAM); r14 = sizeof(pConROMNear); r15 = sizeof(pConROMFar);
// 2 (16b) // 2 (16b) // 3 (24b)
r16 = sizeof(Arreglo); r17 = sizeof(ArregloCaracteres);
// 8 (64b) // 12 (96b)
r18 = sizeof(Estructura1); r19 = sizeof(Union1);
// 4 (32b) // 2 (16b)
}
Revisión: 1.0 [05/2012]
14
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico
3. MODIFICADORES DE VARIABLES 3.1. AUTO Es el modificador por default de una variable y no es necesario ponerlo explícitamente. 3.1.1. Ejemplo.s main.c void main(void) { unsigned char Variable; auto unsigned char Variable2;
// Variable auto // Variable auto explícitamente (no es necesario poner auto)
Variable = 100; Variable2 = 200; }
3.2. STATIC Se define dentro de una función y no son destruidas al terminar, manteniendo su valor en cada llamada a la función. Si diferentes funciones tiene la misma variable static cada una tiene una copia con su propio valor. 3.2.1. Ejemplo. main.c unsigned char funcion1(unsigned char, unsigned char); unsigned char funcion2(unsigned char, unsigned char); void main(void) { unsigned char a,b,c,d,e,f,g,h; a = funcion1(0,1); b = funcion1(20,0); c = funcion1(30,0);
// static x = 0, a = 0 // b = x + 20 = 20 // c = x + 30 = 50
d = funcion2(0,1);
// static x = 0, d = 0
Revisión: 1.0 [05/2012]
15
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C B谩sico e = funcion2(40,0); f = funcion2(40,0);
// e = x + 20 = 40 // f = x + 30 = 80
g = funcion1(0,0); h = funcion2(0,0);
// g = 50 // h = 80
} unsigned char funcion1(unsigned char w, unsigned char s){ static unsigned char x; if(s) x = 0; x = x + w; return x; } unsigned char funcion2(unsigned char w, unsigned char s){ static unsigned char x; if(s) x = 0; x = x + w; return x; }
3.3. EXTERN Se utiliza cuando la variable o funci贸n se encuentra definida en otro modulo y no se requiere reservar memoria nuevamente. 3.3.1. Ejemplo. main.c extern unsigned char Suma(unsigned char, unsigned char); // funci贸n declarada suma.c void main(void) { extern unsigned char Variable; unsigned char r, r2;
// Declarada en suma.c
r = Suma(50,30); r2 = Variable; } suma.c unsigned char Variable = 100; unsigned char Suma(unsigned char a, unsigned char b){ return (a + b); }
Revisi贸n: 1.0 [05/2012]
16
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
3.4. VOLATILE El contenido de la variable puede cambiar sin previo aviso, se utiliza para puertos I/O, memoria mapeada, variables modificadas en interrupciones, etc. Básicamente le dice al optimizador que no modifique el código donde se utilicen este tipo de variables. Si no se utiliza volatile donde se requiere puede que el programa no funcione bien cuando se utilice el optimizador o interrupciones. 3.4.1. Ejemplo. main.c void main(void) { volatile unsigned char vol = 0; // Si se utiliza el optimizador y vol no se declarada como volatile // esta línea podría ser cambiada por while (TRUE) y nunca terminaría while (vol != 255) { ; // continue; } }
3.5. REGISTER Son variables que se guardan en el registro del CPU, son mucho más rápidas que las variables de memoria pero son muy limitadas. 3.5.1. Ejemplo. main.c void main(void) { register unsigned char reg = 0; reg = reg + 10; }
3.6. CONST El contenido es constante y no se puede modificar. 3.6.1. Ejemplo. main.c void main(void) { unsigned char r; const unsigned char const_var = 20; r = const_var; //const_var = 20; // No se puede cambiar el valor por ser const }
Revisión: 1.0 [05/2012]
17
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico 3.7. OVERLAY (C18)
Solo se puede utilizar para variables tipo local (no globales ni parámetros). Las variables de este tipo ocupan el mismo lugar de memoria con lo que se puede reducir el uso de la misma y también se reducen la cantidad de instrucciones necesarias para accederlas. Se utilizan para variables en funciones que no pueden activarse al mismo tiempo. 3.7.1. Ejemplo. main.c void Inicializa(unsigned char ); unsigned char Suma(unsigned char); void main(void) { unsigned char r, r2; Inicializa(0); r = Suma(5); Inicializa(10); r2 = Suma(90);
// // // //
var var var var
= = = =
0 5 10 100
} void Inicializa(unsigned char i) { overlay unsigned char var; // variable overlay var = i; } unsigned char Suma(unsigned char a) { overlay unsigned char var; // variable overlay var = var + a; return var; }
3.8. RAM (C18) Variables de este tipo residen en la memoria de datos, pueden ser near o far.
Near (16b, <= 64KB): Se alojan en las primeras posiciones de memoria, generando menos código y accediendo más rápido. Far (24b, <= 2MB): Pueden alojarse en cualquier posición de memoria dentro de los 2MB.
3.8.1. Ejemplo. main.c void main(void) { near ram unsigned char varnear; far ram unsigned char varfar;
// variable near ram <= 64KB // variable far ram <= 2MB
varnear = 0x55; varfar = 0x77; }
Revisión: 1.0 [05/2012]
18
MPLAB C18: C BĂĄsico
Omar Gurrola http://www.proprojects.wordpress.com
3.9. ROM (C18) Constantes de este tipo residen en la memoria de programa y se utilizan normalmente para almacenar cadenas de caracteres. Pueden ser near y far tambiĂŠn. 3.9.1. Ejemplo. main.c void main(void) { static near rom const unsigned char nrc_var = 0xAA; static far rom const unsigned char frc_var = 0xBB; static rom const unsigned char rc_var = 0xCC; unsigned char a,b,c; a = nrc_var; b = frc_var; c = rc_var; }
RevisiĂłn: 1.0 [05/2012]
19
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico 4. OPERADORES 4.1. OPERADORES ARITMÉTICOS Sirven para realizar cálculos matemáticos básicos. Operador: + * / ++ --
Función: Suma Resta Multiplicación División Incremento Decremento
4.1.1. Ejemplo. main.c void main(void) { unsigned char a, b, c; unsigned int d, e, f; a b c c c c c c c c
= = = = = = = = = =
10; 2; a + b; a - b; a*b; a / b; ++a; a++; --a; a--;
// // // // // // // //
c=12 c=8 c=20 c=5 c=11,a=11 c=11,a=12 c=11,a=11 c=11,a=10
// Con enteros e = 200; f = 100; d = e + f; d = e - f; d = e*f; d = e / f; d = ++e; d = e++; d = --e; d = e--;
// // // // // // // //
d=300 d=100 d=20,000 d=2 d=201,e=201 d=201,e=202 d=201,e=201 d=201,e=200
}
4.2. OPERADORES DE COMPARACIÓN Son utilizados para comparar dos condiciones de una expresión, siendo el resultado verdadero (true 1) o falso (false 0). Operador: == != < > <= >=
Revisión: 1.0 [05/2012]
Función: Igual Diferente Menor que Mayor que Menor igual que Mayor igual que
20
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Bรกsico 4.2.1. Ejemplo. main.c void main(void) { unsigned char r; // == Igual r = 1 == 0; // false 0 r = 1 == 1; // true 1 // != Diferente r = 2 != 3; // true 1 r = 2 != 2; // false 0 // < Menor que r = 3 < 5; // true 1 r = 5 < 3; // false 0 // < Mayor que r = 3 > 5; // false 0 r = 5 > 3; // true 1 // < Menor que r = 3 < 5; // true 1 r = 5 < 3; // false 0 // <= r = 5 r = 3 r = 5
Menor igual que <= 3; // false 0 <= 5; // true 1 <= 5; // true 1
// >= r = 3 r = 5 r = 5
Mayor igual que >= 5; // false 0 >= 3; // true 1 >= 5; // true 1
}
4.3. OPERADORES Lร GICOS Son utilizados para realizar operaciones lรณgicas, siendo el resultado verdadero (true 1) o falso (false 0). Operador: && || !
Funciรณn: AND OR NOT
4.3.1. Ejemplo. main.c void main(void) { unsigned char r; // && AND r = (5<3) && (3>1); // False 0 r = (5>3) && (3>1); // True 1 // || OR r = (5<3) || (3<1); // False 0 r = (5>3) || (3>1); // True 1 // ! NOT r = !(5<3); // False 0 r = !(5>3); // True 1 }
Revisiรณn: 1.0 [05/2012]
21
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico 4.4. OPERADORES DE BITS
Son utilizados para realizar operaciones lógicas con los bits de las variables. Comúnmente se utilizan para realizar mascaras poniendo a uno o cero ciertos bits. Operador: & | ^ ~ << >>
Función: And Or Xor Not Rotar izquierda Rotar derecha
4.4.1. Ejemplo. main.c void main(void) { unsigned char r; // & And (C=1 cuando A y B son uno) r = 0xA0 & 0x0B; // r=0x00 r = 0xCA & 0x0F; // r=0x0A // | Or (C=1 cuando A o B son uno) r = 0x0C | 0xC0; // r=0xCC r = 0xAB | 0x0F; // r=0xAF // ^ Xor (C=1 cuando A y B son diferentes) r = 0x0F ^ 0x00; // r=0x0F r = 0xAA ^ 0x55; // r=0xFF // ~ Complemento (C=1 cuando A=0 y viceversa) r = ~0x0F; // r=0xF0 r = ~0xAA; // r=0x55 // << Corrimiento r = 0x01 << 1; // r = 0x01 << 7; // r = 0x0F << 4; //
izquierda r=0x02 r=0x80 r=0xF0
// >> Corrimiento r = 0x08 >> 1; // r = 0x80 >> 7; // r = 0xF0 >> 4; //
derecha r=0x04 r=0x01 r=0x0F
// Mascaras con And (Pone a ceros los bits específicos) r = 0xCD & 0x0F; // r=0x0D r = 0xCD & 0xF0; // r=0xC0 // Mascaras con Or (Pone a unos los bits específicos) r = 0xCD | 0x0F; // r=0xCF r = 0xCD | 0xF0; // r=0xFD // Mascaras con Xor (Invierte los bits específicos) r = 0xAA ^ 0x0F; // r=0xA5 r = 0xAA ^ 0xF0; // r=0x5A }
Revisión: 1.0 [05/2012]
22
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico 4.5. PROCEDENCIA Y ORDEN DE EVALUACIÓN
Todas las operaciones se realizan de arriba hacia abajo en el siguiente orden: Operador: () [] -> . ! ~ ++ -- + - * (type) sizeof */ % + << >> < <= > >= == != & ^ | && || ?: = += -= *= /= %= &= ^= |= <<= >>= ,
Orden: Izquierda a derecha Derecha a izquierda Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Derecha a izquierda Derecha a izquierda Izquierda a derecha
5. ESTRUCTURAS DE CONTROL 5.1. IF-ELSE Se utiliza para ejecutar cierto código si la condición es verdadera o falsa según sea el caso. 5.1.1. Ejemplo. main.c void main(void) { unsigned char a, b, c; a = 5; b = 3; // if if (a > b) { c = 1; } // if-else if (a < b) { c = 1; } else { c = 2; }
// 5 > 3 = Verdadero
// 5 < 3 = FALSO // Se ejecuta el else
}
Revisión: 1.0 [05/2012]
23
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
5.2. ELSE-IF Se utiliza para evaluar una condición adicional si la primera resulto verdadero o falso según sea el caso. 5.2.1. Ejemplo. main.c void main(void) { unsigned char a,b,c; a = 5; b = 3; // if-else if (a < b) { // 5 < 3 = FALSO c = 1; } else if(a == b) { // Se ejecuta el else y se evalua el nuevo if c = 2; } else { c = 3; // Se ejecuta el else } }
5.3. SWITCH Este tipo de estructuras permiten ejecutar un bloque de código dependiendo el valor de la variable. 5.3.1. Ejemplo. main.c void main(void) { unsigned char a,c; // switch a = 5; switch(a){ // Ejecuta el bloque correspondiente al case case 1: c = 1; break; case 2: c = 2; break; case 5: c = 5; break; default: c = 255; break; } }
5.4. WHILE Ejecuta un grupo de instrucciones mientras la condición sea verdadera. Si la condición es falsa desde el principio el bloque no se ejecuta. 5.4.1. Ejemplo. main.c void main(void) { unsigned char a; // while a = 0;
Revisión: 1.0 [05/2012]
24
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico
while (a < 10) { // Se ejecutara mientras se cumpla la condición, puede no ejecutarse ni una vez a++; // a=1,2,3,4,5,6,7,8,9,10 } }
5.5. DO-WHILE Esta estructura es similar a la anterior, con la diferencia de que se ejecutara al menos una vez el código aunque la condición sea falsa. 5.5.1. Ejemplo. main.c void main(void) { unsigned char a; // do-while a = 0; do { a++; // a=1,2,3,4,5,6,7,8,9,10 } while (a < 10); // Se ejecutara mientras se cumpla la condición, se ejecuta por lo menos una vez }
5.6. FOR Se utiliza para un número definido de ciclos, se le da el valor inicial, la condición y el incremento. 5.6.1. Ejemplo. main.c void main(void) { unsigned char a,c; // for for (a = 0; a < 10; a++) { // Se ejecutara diez veces c = 1; } }
5.7. CONTINUE Sirve para pasar el control al final de la estructura y evitar que se ejecute el código siguiente, haciendo que se revalúe la condición. 5.7.1. Ejemplo. main.c void main(void) { unsigned char a,b; b = 0; for(a = 0 ; a < 10 ; a++){ if(a == 5 || a == 8) continue; b++; }
// Se brinca el resto del código si a = 5 o 8
}
Revisión: 1.0 [05/2012]
25
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico 5.8. BREAK
Sirve para pasar el control fuera de la estructura, literalmente es para salirse de la estructura. 5.8.1. Ejemplo. main.c void main(void) { unsigned char a,b; b = 0; for(a = 0 ; a < 10 ; a++){ if(a == 5) break; b++; }
// Se sale del for si a = 5 // b = 5
}
5.9. GOTO Se utiliza para transferir el control a una etiqueta especificada. 5.9.1. Ejemplo. main.c void main(void) { unsigned char a,b; b = 0; for(a = 0 ; a < 10 ; a++){ if(a == 5) goto SAL; b++; }
// Brinca a SAL si a = 5 // b = 5
SAL: b = 0; }
6. FUNCIONES 6.1. DECLARACIÓN Y DEFINICIÓN Las funciones son subprogramas encargas de realizar ciertas tareas. Antes de definir una función se debe declarar para que el compilador la conozca y se pueda utilizar. Esto puede estar definido antes de main() o en otro archivo, a esto también se le conoce como prototipo. La definición de una función se define normalmente al final del programa. 6.1.1. Ejemplo. main.c // Declaración de funciones (Prototipos de funciones) void Mostrar(void); unsigned int Suma(unsigned char, unsigned char); int Resta(unsigned char, unsigned char);
Revisión: 1.0 [05/2012]
26
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico unsigned int Multiplicacion(unsigned char a, unsigned char b) { unsigned int r = (unsigned int) a * (unsigned int) b; return r; } void main(void) { unsigned int a,b; int c; Mostrar(); a = Suma(100,200); b = Resta(210,110); c = Resta(150,250);
// // // //
Llamamos a Mostrar 300 100 -100
}
// Definición de la función Mostrar void Mostrar(void) { ; // Muestra algo... } // Definición de la función Suma unsigned int Suma(unsigned char a, unsigned char b) { unsigned int r = (unsigned int) a + (unsigned int) b; return r; } // Definición de la función Resta int Resta(unsigned char a, unsigned char b) { int r = (int) a - (int) b; return r; }
6.2. PARÁMETROS Las funciones reciben y regresan variables que pueden ser de cualquier tipo: básicos, estructuras, uniones, enumeraciones, punteros y arreglos. Cuando no reciben o regresan valor se pone “void”. Las funciones pueden regresar un solo valor si así se requiere, pero se puede recibir más de uno regresando un puntero o un arreglo. 6.2.1. Ejemplo. main.c // Declaración de funciones (Prototipos de funciones) void Mostrar(void); unsigned int Suma(unsigned char, unsigned char); void Swap(unsigned char *, unsigned char *); void Reemplazar(char *, char, char);
// // // //
No recibe parámetros ni regresa valor. Recibe dos parámetros unsigned char y regresa un unsigned int Recibe dos punteros para modificarlos Recibe un puntero y dos unsigned char
void main(void) { unsigned int a,b; char Mensaje[] = "Hola!!!!"; Mostrar(); a = Suma(100,200);
// Llamamos a Mostrar // 300
a = 100; b = 200; Swap(&a,&b);
// Intercambiamos a y b dando sus direcciones
Reemplazar(&Mensaje[0],'!','?'); // Remplaza !!!! por ???? }
// Definición de la función Mostrar void Mostrar(void) { ; // Muestra algo... }
Revisión: 1.0 [05/2012]
27
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico // Definición de la función Suma unsigned int Suma(unsigned char a, unsigned char b) { unsigned int r = (unsigned int) a + (unsigned int) b; return r; } void Swap(unsigned char *a, unsigned char *b){ unsigned char t; t = *a; *a= *b; *b = t; } void Reemplazar(char * Texto, char Token, char Remplazo){ while(*Texto != '\0'){ if(*Texto == Token) *Texto = Remplazo; Texto++; } }
7. DIRECTIVAS DEL PREPROCESADOR 7.1. #INCLUDE Se utiliza para añadir archivos de cabeceras. #include <cabecera.h>
La cabecera se encuentra en el directorio de librerías.
#include “cabecera2.h”
La cabecera se encuentra en la misma carpeta que el proyecto.
7.1.1. Ejemplo. main.c #include<p18f14k50.h> void main(void) { PORTA = 0x00; }
// Declarada en la cabecera.
7.2. #DEFINE, #IFDEF, #IFNDEF, #UNDEF, #IF, #ELIF, #ELSE, #ENDIF, #ERROR Son utilizadas para realizar compilaciones condicionadas, permitiendo compilar cierto código para varias arquitecturas, compiladores, etc. 7.2.1. Ejemplo. main.c #define MAX 100 // Definimos MAX = 100 #define P18F14K50 // Definimos P18F14K50 #ifdef P18F14K50 #include <p18f14k50.h> #elif P18C #include <p18cxxx.h> #endif
// Si se definió P18F14K50 incluimos esta cabecera // En otro caso si se definió P18C incluimos esta cabecera // Cerramos el if
void main(void) { unsigned char a,b,c; a = 100;
Revisión: 1.0 [05/2012]
28
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico b = 2; #ifndef RESTA c = a + b; #else c = a - b; #endif #if MAX == 200 c = a * b; #else #undef MAX #endif
// Si no esta definido RESTA, sumamos // En otro caso restamos // Cerramos el if // FALSO // Si MAX == 200 -> multiplicamos // Indefinimos MAX
#ifndef MAX #error No se definió MAX #endif
// MAX no esta definido muestra este mensaje de error
}
7.3. #PRAGMA (C18) Se utiliza para definir directivas y su utilización depende del compilador. Para C18 se utiliza para definir los fusibles del microcontrolador y para definir la sección de memoria donde se almacenaran ciertos datos, los cuales de ven en la siguiente sección. Para configurar los fusibles se define de la siguiente manera, la información se puede consultar en el archivo “hlpPIC18ConfigSet.chm”: #pragma config Fusible=estado 7.3.1. Ejemplo. main.c #include <p18F14k50.h> #pragma config CPUDIV=NOCLKDIV
#pragma config USBDIV=OFF
#pragma config FOSC=HS
#pragma config PLLEN=ON
#pragma config PCLKEN=ON
#pragma config FCMEN=OFF #pragma config IESO=OFF
#pragma config PWRTEN=OFF #pragma config BOREN=ON
Revisión: 1.0 [05/2012]
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
CPU System Clock Selection bit: NOCLKDIV No CPU System Clock divide CLKDIV2 CPU System Clock divided by 2 CLKDIV3 CPU System Clock divided by 3 CLKDIV4 CPU System Clock divided by 4 USB Clock Selection bit: OFF USB Clock comes directly from the OSC1/OSC2 oscillator block; no divide ON USB clock comes from the OSC1/OSC2 divided by 2 Oscillator Selection bits: LP LP oscillator XT XT oscillator HS HS oscillator ERCCLKOUT External RC oscillator, CLKOUT function on OSC2 ECCLKOUTH EC, CLKOUT function on OSC2 (high) ECH EC (high) ERC External RC oscillator IRC Internal RC oscillator IRCCLKOUT Internal RC oscillator, CLKOUT function on OSC2 ECCLKOUTM EC, CLKOUT function on OSC2 (medium) ECM EC (medium) ECCLKOUTL EC, CLKOUT function on OSC2 (low) ECL EC (low) 4 X PLL Enable bit: OFF PLL is under software control ON Oscillator multiplied by 4 Primary Clock Enable Bit: OFF Primary clock is under software control ON Primary clock enabled Fail-Safe Clock Monitor Enable bit: OFF Fail-Safe Clock Monitor disabled ON Fail-Safe Clock Monitor enabled Internal/External Oscillator Switchover bit: OFF Oscillator Switchover mode disabled ON Oscillator Switchover mode enabled Power-up Timer Enable bit: ON PWRT enabled OFF PWRT disabled Brown-out Reset Enable bits: OFF Brown-out Reset disabled in hardware and software
29
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C B谩sico
#pragma config BORV=30
#pragma config WDTEN=OFF
#pragma config WDTPS = 1
#pragma config MCLRE=OFF
#pragma config HFOFST=OFF #pragma config STVREN=ON
#pragma config LVP=ON
#pragma config BBSIZ=OFF #pragma config XINST=OFF
#pragma config CP0=OFF
#pragma config CP1=OFF #pragma config CPB=OFF
#pragma config CPD=OFF #pragma config WRT0=OFF
#pragma config WRT1=OFF #pragma config WRTB=OFF
#pragma config WRTC=OFF
#pragma config WRTD=OFF
#pragma config EBTR0=OFF
#pragma config EBTR1=OFF
#pragma config EBTRB=OFF
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
ON Brown-out Reset enabled and controlled by software (SBOREN is enabled) NOSLP Brown-out Reset enabled in hardware only and disabled in Sleep mode (SBOREN is disabled) SBORDIS Brown-out Reset enabled in hardware only (SBOREN is disabled) Brown Out Voltage: 30 VBOR set to 3.0 V nominal 27 VBOR set to 2.7 V nominal 22 VBOR set to 2.2 V nominal 19 VBOR set to 1.9 V nominal Watchdog Timer Enable bit: OFF WDT is controlled by SWDTEN bit of the WDTCON register ON WDT is always enabled. SWDTEN bit has no effect. Watchdog Timer Postscale Select bits: 1 1:1 2 1:2 4 1:4 8 1:8 16 1:16 32 1:32 64 1:64 128 1:128 256 1:256 512 1:512 1024 1:1024 2048 1:2048 4096 1:4096 8192 1:8192 16384 1:16384 32768 1:32768 MCLR Pin Enable bit: OFF RE3 input pin enabled; MCLR disabled ON MCLR pin enabled, RE3 input pin disabled HFINTOSC Fast Start-up bit: OFF The system clock is held off until the HFINTOSC is stable. ON HFINTOSC starts clocking the CPU without waiting for the oscillator to stabilize. Stack Full/Underflow Reset Enable bit: OFF Stack full/underflow will not cause Reset ON Stack full/underflow will cause Reset Single-Supply ICSP Enable bit: OFF Single-Supply ICSP disabled ON Single-Supply ICSP enabled Boot Block Size Select Bit: OFF 1kW boot block size ON 2kW boot block size Extended Instruction Set Enable bit: OFF Instruction set extension and Indexed Addressing mode disabled (Legacy mode) ON Instruction set extension and Indexed Addressing mode enabled Code Protection bit: ON Block 0 code-protected OFF Block 0 not code-protected Code Protection bit: ON Block 1 code-protected OFF Block 1 not code-protected Boot Block Code Protection bit: ON Boot block code-protected OFF Boot block not code-protected Data EEPROM Code Protection bit: ON Data EEPROM code-protected OFF Data EEPROM not code-protected Write Protection bit: ON Block 0 write-protected OFF Block 0 not write-protected Write Protection bit: ON Block 1 write-protected OFF Block 1 not write-protected Boot Block Write Protection bit: ON Boot block write-protected OFF Boot block not write-protected Configuration Register Write Protection bit: ON Configuration registers write-protected OFF Configuration registers not write-protected Data EEPROM Write Protection bit: ON Data EEPROM write-protected OFF Data EEPROM not write-protected Table Read Protection bit: ON Block 0 protected from table reads executed in other blocks OFF Block 0 not protected from table reads executed in other blocks Table Read Protection bit: ON Block 1 protected from table reads executed in other blocks OFF Block 1 not protected from table reads executed in other blocks Boot Block Table Read Protection bit: ON Boot block protected from table reads executed in other blocks OFF Boot block not protected from table reads executed in other blocks
void main(void) { ; }
Revisi贸n: 1.0 [05/2012]
30
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
7.4. SECCIONES DE MEMORIA (C18) Las secciones son diversas áreas de memoria del PIC18:
Memoria de programa (ROM) Memoria de datos (RAM) Memoria de datos de USB (USB-RAM) Memoria EEPROM Etc.
En el archivo *.lnk del PIC18 en específico se pueden observar las diferentes áreas y rangos de las memorias, donde:
page: Memoria de programa (code y romdata) gprX: Memoria de datos en grupos de 256B (idata y udata) usbX: Memoria de datos para USB en grupos de 256B (Solo algunos uC) PROTECTED: Áreas donde el compilador no colocara instrucciones o datos automáticamente, a menos que se lo indiquemos con #pragma.
La sintaxis para definir cada área es la siguiente:
Contiene variables no inicializadas estáticas. #pragma udata [attribute-list] [section-name [=address]]
Contiene variables inicializadas estáticas. #pragma idata [attribute-list] [section-name [=address]]
Contiene constantes estáticas. #pragma romdata [overlay] [section-name [=address]]
Contiene instrucciones. #pragma code [overlay] [section-name [=address]]
El [attribute-list] pueden ser [access] y le indica al compilador que debe incluir la sección por el modo acceso a datos access bank sin necesidad de modificar el banco actual de la RAM. El modo [overlay] permite que otras secciones se sitúen en las mismas posiciones físicas, permitiendo conservar memoria siempre que no se activen simultáneamente. Para que el modo [overlay] sea válido se deben cumplir las dos siguientes condiciones: 1. 2.
Las dos secciones deben pertenecer a fichero distintos. Deben tener el mismo nombre y dirección.
Revisión: 1.0 [05/2012]
31
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico 7.4.1. Ejemplo. main.c // Prototipos void funcion1(unsigned char); void funcion2(unsigned char); void funcion3(unsigned char); extern void funcion10(void); // pertenecen a otro modulo extern void funcion14(void); extern void funcion12(void); extern void funcion16(void);
// Variables globales #pragma udata seccion_uvar=0x200 unsigned char var1; char varchar; #pragma udata #pragma udata access seccion_uvar_access // Con modo access no se especifica la dirección near unsigned char var2; #pragma udata #pragma idata unsigned char #pragma idata #pragma idata near unsigned #pragma idata
seccion_ivar=0x210 var3 = 25; access seccion_ivar_access // Con modo access no se especifica la dirección char var4 = 30;
#pragma romdata const_table=0x3000 // constante a partir de la dirección de programa 0x3000 const rom unsigned char a_num[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; const rom char a_hola[] = "Hola"; #pragma romdata void main(void) var1 = 100; var2 = 200; var3 = 150; var4 = 180;
{ // // // //
Dirección Dirección Dirección Dirección
0x200 0x2 definida por el compilador sin utilizar bancos (access ram <= 0x5F) 0x210 0x3 definida por el compilador sin utilizar bancos (access ram <= 0x5F)
var1 = a_num[0]; // var1=0 leída de la memoria de programa var1 = a_num[3]; // var1=3 leída de la memoria de programa var1 = a_num[10]; // var1=10 leída de la memoria de programa varchar varchar varchar varchar
= = = =
a_hola[0]; a_hola[1]; a_hola[2]; a_hola[3];
// // // //
varchar='H' varchar='o' varchar='l' varchar='a'
leída leída leída leída
de de de de
la la la la
memoria memoria memoria memoria
de de de de
programa programa programa programa
funcion1(1); funcion2(2); // Llamada a la funcion2 que empieza en la dirección 0x100 específicamente funcion3(3); // Llamada a la funcion3 que continua de la dirección de la funcion2 funcion10(); funcion14(); funcion12(); funcion16();
// // // //
var10=0x10 dir=0x250, var11=0x11 var14=0x14 dir=0x260, var15=x015 var12=0x1212 dir=0x250 por estar var16=0x1616 dir=0x260 por estar
dir=0x251 dir=0x261 en overlay sobrescribe var10 y var11 en overlay sobrescribe var14 y var15
} // La dirección de este codigo la definirá el compilador void funcion1(unsigned char x) { x++; } // Este código se pondrá en la posición 0x100 específicamente #pragma code mi_codigo=0x100 void funcion2(unsigned char x) { x = 150; } // Este código continuara de la funcion2 void funcion3(unsigned char x) { x = 180; } #pragma code
Revisión: 1.0 [05/2012]
32
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Bรกsico
archivo1.c #pragma udata overlay overlay_udat=0x250 unsigned char var10, var11; #pragma udata #pragma idata overlay overlay_idat=0x260 unsigned char var14=100, var15=200; #pragma idata void funcion10(void){ var10=0x10; var11=0x11; } void funcion14(void){ var14=0x14; var15=0x15; }
archivo2.c #pragma udata overlay overlay_udat=0x250 unsigned int var12; #pragma udata #pragma idata overlay overlay_idat=0x260 unsigned int var16=0xFFFF; #pragma idata void funcion12(void){ var12=0x1212; } void funcion16(void){ var16=0x1616; }
7.5. ENSAMBLADOR EN Lร NEA Nos ayuda a escribir cรณdigo ensamblador directamente sobre C. El cรณdigo se escribe entre _asm
_endasm.
7.5.1. Ejemplo. main.c #pragma udata access seccion_uvar_access unsigned char count; #pragma udata void main(void) {
_asm MOVLW 10 MOVWF count,0
// W = 10 // count = W = 10
DECFSZ count,1,0 BRA start GOTO done
// count--, brinca si es igual a cero // goto start:
start:
done: _endasm }
Revisiรณn: 1.0 [05/2012]
33
Omar Gurrola http://www.proprojects.wordpress.com
MPLAB C18: C Básico 8. LIBRERÍAS 8.1. QUE ES UNA LIBRERÍA Y COMO USARLA
Una librería es un conjunto de cabeceras, variables, funciones y definiciones agrupadas en un archivo para que puedan ser utilizadas, normalmente este grupo se encarga de realizar ciertas tareas específicas para un dispositivo o para cierto proceso. Las librerías se diseñan con el objetivo de reutilizar el código y reducir el tiempo de programación. Para usar una librería solamente utilizamos la directiva #define <cabecera.h> o #define “cabecera.h” al principio de nuestro programa en main.c. Para este ejemplo utilizaremos la librería <delays.h> que se encarga de generar retardos en el microcontrolador utilizando las siguientes funciones:
Delay1TCY(); Delay10TCYx(0-255); Delay100TCYx(0-255); Delay10KTCYx(0-255);
Nop(); = 1xTCY Múltiplos de 10xTCY, 0 = 2,560 ciclos Múltiplos de 100xTCY, 0 = 256,000 ciclos Múltiplos de 10KxTCY, 0 = 2,560,000 ciclos
Donde un: Para convertir el tiempo a ciclos se utiliza la siguiente formula: Dónde:
TCY: FrecOsc: CR: Tiempo:
Tiempo de un ciclo del microcontrolador (s). Frecuencia oscilador (MHz). Ciclos requeridos (TCY). Tiempo (s)
Para el ejemplo la frecuencia del microcontrolador se establece a 48 MHz, por lo tanto TCY = 83.33 ns Se busca generar retardos de 100ms, 250ms, 500ms y 1s. Por lo tanto utilizando la formula anterior calculamos los TCY para cada tiempo. 100ms = 1.2M TCY 250ms = 3M TCY 300ms = 3.6M TCY 500ms = 6M TCY 1s
= 12M TCY
Revisión: 1.0 [05/2012]
34
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
8.1.1. Ejemplo. main.c // Añadimos la librería de demoras #include <delays.h> void main(void) { // Estos ejemplos están calculados con un reloj de 48MHz // Usando la librería <delays.h> Delay1TCY(); // 1xTC = 83.33nS Delay10TCYx(0); Delay10TCYx(128); Delay10TCYx(255);
// 2559xTC = 213.25uS // 1280xTC = 106.666uS // 2549xTC = 212.416uS
Delay100TCYx(0); Delay100TCYx(128); Delay100TCYx(255);
// 25599xTC = 2.133mS // 12800xTC = 1.066mS // 25499xTC = 2.124mS
Delay10KTCYx(0); Delay10KTCYx(128); Delay10KTCYx(255);
// 2559999xTC = 213.333mS // 1280000xTC = 106.666mS // 2550009xTC = 212.500mS
Delay10KTCYx(120); // Para 100ms Delay10KTCYx(255); Delay10KTCYx(45);
// Para 250ms
Delay10KTCYx(255); Delay10KTCYx(105);
// Para 300ms
Delay10KTCYx(255); Delay10KTCYx(255); Delay10KTCYx(90);
// Para 500ms
Delay10KTCYx(255); Delay10KTCYx(255); Delay10KTCYx(255); Delay10KTCYx(255); Delay10KTCYx(180);
// Para 1s
}
8.2. COMO CREAR TU LIBRERÍA DE DEMORAS Para crear nuestra propia librería de demoras predefinidas o funciones para generarlas hay que crear dos archivos:
El archivo de cabecera nombrelibreria.h con el siguiente formato: nombrelibreria.h #ifndef __NOMBRELIBRERIA_H #define __NOMBRELIBRERIA_H /** INCLUDES *******************************************************/ /** MACROS & TYPEDEF ***********************************************/ /** PROTOTYPES *****************************************************/ #endif // __NOMBRELIBRERIA_H
El archivo de definiciones nombrelibreria.c con el siguiente formato: nombrelibreria.c /** INCLUDES *******************************************************/ #include "nombrelibreria.h" /** DEFINITIONS ****************************************************/ void FuncionX(void){ ; }
Revisión: 1.0 [05/2012]
35
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
8.2.1. Ejemplo. wait.h #ifndef __WAIT_H #define __WAIT_H /** INCLUDES *******************************************************/ #include <delays.h> // Delays in instructions /** MACROS & TYPEDEF ***********************************************/ #define Wait1us() Delay10TCYx(1); Delay1TCY(); Delay1TCY() // INST: 12 * 83 = 0.996us #define Wait5us() Delay10TCYx(6) // INST: 60 * 83 = 4.999us #define Wait10us() Delay10TCYx(12) // INST: 122 * 83 = 10.126us #define Wait20us() Delay10TCYx(24) // INST: 242 * 83 = 20.086us #define Wait25us() Delay10TCYx(30) // INST: 303 * 83 = 25.149us #define Wait50us() Delay10TCYx(60) // INST: 602 * 83 = 49.966us #define Wait100us() Delay10TCYx(120) // INST: 1202 * 83 = 99.766us #define Wait200us() Delay10TCYx(240) // INST: 2402 * 83 = 199.366us #define Wait250us() Delay100TCYx(30) // INST: 3002 * 83 = 249.166us #define Wait500us() Delay100TCYx(60) // INST: 6002 * 83 = 498.166us /** PROTOTYPES *****************************************************/ /******************************************************************* * Function: void Waitmsx(unsigned int) * Input: 1-65535 ms (16b) * Output: None * Description: Wait 1 to 65535 ms *******************************************************************/ void Waitmsx(unsigned int); #endif // __WAIT_H wait.c /** INCLUDES *******************************************************/ #include "wait.h" /** FUNCTIONS ******************************************************/ /******************************************************************* * Function: void WaitXms(unsigned int) * Input: 1-65535 ms (16b) * Output: None * Description: Wait 1 to 65535 ms * INST: 1 = 12062 * 83 = 1.001ms *******************************************************************/ void Waitmsx(unsigned int ms){ unsigned int c; for(c=0; c < ms; c++) Delay1KTCYx(12); } main.c #include "wait.h" void main(void) { // Estos ejemplos están calculados con un reloj de 48MHz // Usando la librería “wait.h” Wait1us(); // 12 = 1us Wait5us(); // 60 = 5us Wait10us(); // 120 = 10us Wait20us(); // 240 = 20us Wait25us(); // 300 = 25us Wait50us(); // 600 = 50us Wait100us(); // 1200 = 100us Wait200us(); // 2400 = 200us Wait250us(); // 3000 = 250us Wait500us(); // 6000 = 500us Waitmsx(0); Waitmsx(1); Waitmsx(5); Waitmsx(100); Waitmsx(500); Waitmsx(1000); Waitmsx(5000);
// // // // // // //
41 = 3.416us 12060 = 1.005ms 60136 = 5.011ms 1201941 = 100.161ms 6009544 = 500.795ms 12019048 = 1.001s 60095090 = 5.007s
}
Revisión: 1.0 [05/2012]
36
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
8.3. COMO CREAR TU LIBRERÍA DE TIPOS DE VARIABLES Para facilitar la declaración de variables vamos a crear una librería con varios typedef más significativos, por ejemplo el unsigned char también es conocido como BYTE o u8 y es más corto, también declararemos un tipo bool como true y false, entre otros más. Esto también ayuda a que si portamos el código a otro compilador y la cantidad de bits se mueve o el tipo básico no existe podemos solamente ajustarlo en esta cabecera y no en el código del programa. 8.3.1. Ejemplo. variables.h #ifndef __VARIABLES_H #define __VARIABLES_H /** MACROS & TYPEDEF ***********************************************/ // 8b signed [-128 -> 127] typedef char INT8, s8; // 8b unsigned [0 -> 255] typedef unsigned char UCHAR, UINT8, u8, BYTE; // 16b signed [-32,768 -> 32,767] typedef int INT16, s16; //typedef short SSHORT; // 16b unsigned [0 -> 65,535] typedef unsigned int UINT, UINT16, u16, WORD; //typedef unsigned short USHORT; // 24b signed [-8,388,608 -> 8,388,607] typedef short long INT24, s24; // 24b unsigned [0 -> 16,777,215] typedef unsigned short long UINT24, u24; // 32b signed [-2,147,483,648 -> 2,147,483,647] typedef long INT32, s32; // 32b unsigned [0 -> 4,294,967,295] typedef unsigned long ULONG, UINT32, u32, DWORD; // 32b decimal point [exp(-126) -> exp(128)] typedef float FLOAT; typedef double DOUBLE; // 8b Boolean typedef enum {false,true} boolean, bool; #endif // __VARIABLES_H
main.c // Añadimos la libreria #include "variables.h" void main(void) { // 8b signed [-128 -> 127] INT8 a = -128; s8 b = 127; // 8b unsigned [0 -> 255] UCHAR c = 0; UINT8 d = 255; u8 e = 0; BYTE f = 255; // 16b signed [-32,768 -> 32,767] INT16 g = -32768; s16 h = 32767; // 16b unsigned [0 -> 65,535] UINT i = 0;
Revisión: 1.0 [05/2012]
37
MPLAB C18: C B谩sico UINT16 u16 WORD
Omar Gurrola http://www.proprojects.wordpress.com
j = 65535; k = 0; l = 65535;
// 24b signed [-8,388,608 -> 8,388,607] INT24 m = -8388608; s24 n = 8388607; // 24b unsigned [0 -> 16,777,215] UINT24 o = 0; u24 p = 16777215; // 32b signed [-2,147,483,648 -> 2,147,483,647] INT32 q = -2147483648; s32 r = 2147483647; // 32b unsigned [0 -> 4,294,967,295] ULONG s = 0; UINT32 t = 4294967295; u32 u = 0; DWORD v = 4294967295; // 32b decimal point [exp(-126) -> exp(128)] FLOAT x = -2.69; DOUBLE y = 2.69; // 8b Boolean boolean z1 = true; bool z2 = false; }
Revisi贸n: 1.0 [05/2012]
38
MPLAB C18: C Básico
Omar Gurrola http://www.proprojects.wordpress.com
9. REFERENCIAS
Casanova Alejandro, “Tutorial MPLAB C18”, 2010 http://issuu.com/suky_pdfs/docs/tutorial_c18_v2
Huss Eric, “The C Library Reference Guide”, 1997 http://www.acm.uiuc.edu/webmonkeys/book/c_guide/
Microchip, “MPLAB C18 C COMPILER GETTING STARTED”, 2005 http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en0100 14
Revisión: 1.0 [05/2012]
39
http://www.proprojects.wordpress.com