Está en la página 1de 57

2009

Alejandro
Autor: Suky
Web:www.infopic.comlu.com
05/11/2009
Tutorial MPLab C18
Autor: Suky Web:www.infopic.comlu.com

Contenido
Entorno de programacin. ................................................................................................................................. 4
Compilador. ........................................................................................................................................................ 4
Instalacin .......................................................................................................................................................... 4
Creacin de un nuevo proyecto. ........................................................................................................................ 8
Introduccin al C18: ......................................................................................................................................... 11
Primer ejemplo, control de leds con un pulsador. ........................................................................................... 11
Operadores aritmticos:........................................................................................................................... 11
Operadores lgicos: .................................................................................................................................. 12
Operadores bitwise: ................................................................................................................................. 12
Estructuras: .................................................................................................................................................. 12
Estructura if-else ...................................................................................................................................... 13
Estructura while ....................................................................................................................................... 13
Estructura do-while .................................................................................................................................. 13
Estructura For: .......................................................................................................................................... 13
Objetivo: ....................................................................................................................................................... 14
Cdigo: ......................................................................................................................................................... 14
Variables........................................................................................................................................................... 15
Modificadores de las variables: .................................................................................................................... 15
Segundo ejemplo: ............................................................................................................................................ 16
Codigo: ......................................................................................................................................................... 16
Tercer Ejemplo: ................................................................................................................................................ 17
Hardware: .................................................................................................................................................... 17
Cdigo: ......................................................................................................................................................... 17
Arreglos de Variables ....................................................................................................................................... 18
Cuarto Ejemplo:................................................................................................................................................ 18
Cdigo: ......................................................................................................................................................... 19
Declaracin y definicin de funciones. ............................................................................................................. 20
Dos formas de incluir una funcin en nuestro cdigo: ................................................................................. 20
Ejemplo: ....................................................................................................................................................... 21
Cdigo: ......................................................................................................................................................... 22
Control de un LCD. ........................................................................................................................................... 23
Codigo: ......................................................................................................................................................... 24
Conversin analgica digital. ............................................................................................................................ 25
Autor: Suky Web:www.infopic.comlu.com

Codigo: ......................................................................................................................................................... 26
Interrupciones: ................................................................................................................................................. 28
Mdulo USART. ................................................................................................................................................ 29
Otra manera de enviar los datos, usando printf: .......................................................................................... 33
Ejemplo de formatos: ............................................................................................................................... 33
Modificar las libreras. ...................................................................................................................................... 34
Interrupcin por cambio de estado RB4-RB7. Control de Teclado Matricial. ................................................... 36
Como crear una librera. ................................................................................................................................... 39
Uso de timers 0 ................................................................................................................................................ 43
Objetivo: ....................................................................................................................................................... 43
Configuracin de los Timers ......................................................................................................................... 43
Comunicacin I2C. ............................................................................................................................................ 48
Operacin de lectura .................................................................................................................................... 48
Hardware: .................................................................................................................................................... 49
Segundo ejemplo de comunicacin con memoria 24LC512 mediante I2C. ...................................................... 52
Lectura secuencial ........................................................................................................................................ 52
Punteros ........................................................................................................................................................... 55
Operadores unitarios: .............................................................................................................................. 55
Punteros y arreglos: ..................................................................................................................................... 55
Punteros y funciones. ................................................................................................................................... 56










Autor: Suky Web:www.infopic.comlu.com

Entorno de programacin.
MPLAB IDE.
Ensamblador, enlazador, gestin de proyectos, depurador y simulador
Gratuito, se puede descargar de www.microchip.com

Compilador.
MPLAB C18
Compilador cruzado de lenguaje C para microcontroladores PIC18
Sigue la norma ANSI C, salvo en particularidades de los microcontroladores
Libreras para comunicaciones SPI, I2C, UART, USART, generacin PWM, cadena de caracteres y
funciones matemticas de coma flotante
Maneja nmeros reales de 32 bits (float y double)
Versin demo de 60 das, descargable de www.microchip.com
Instalacin

Se debe bajar directamente desde Microchip, hay disponible una versin gratuita para estudiantes que es un
demo de 60 das. Tambin para poder descargarlo es necesario registrarse.
Una vez descargado ejecutar el instalador MPLAB-C18-Evaluation-v3_30 versin actualmente disponible.
Para a instalacin seguimos los siguientes pasos:

Autor: Suky Web:www.infopic.comlu.com




Autor: Suky Web:www.infopic.comlu.com





Autor: Suky Web:www.infopic.comlu.com




Autor: Suky Web:www.infopic.comlu.com

Creacin de un nuevo proyecto.

Project ->New
Nos aparecer una pantalla donde le indicamos el nombre de nuestro proyecto y la carpeta donde
ser guardado.


Pasamos a configurar el dispositivo con el cual trabajaremos: Configure->Select Device


Seleccionamos el compilador: Project->Select Lenguaje Toolsuite y nos aseguramos que todas las
direcciones son correctas.
Autor: Suky Web:www.infopic.comlu.com



Configuramos los subdirectorios de trabajo: Project->Build options ->Project
Seleccionamos ubicacin de ficheros de declaraciones, bibliotecas y script de enlazado.
Show directories for:
Include Search Path
Library Search Path
Linker-Script Search Path





Autor: Suky Web:www.infopic.comlu.com


Nota: Segn la versin tambin se debe agregar al proyecto el archivo (PIC18F utilizado).lkr
ubicado en MCC18/lkr, sino produce error de compilacin.



Luego vamos a New File y lo guardamos en nuestra carpeta eligiendo extensin .c agregndolo a
nuestro proyecto.


Con todo esto configurado ya podemos empezar a desarrollar nuestro cdigo.






Autor: Suky Web:www.infopic.comlu.com

Introduccin al C18:

La idea es ir adquiriendo conceptos a medida que los utilizaremos en el desarrollo de los ejemplos, de esta
manera lo que se presenta tericamente lo asociamos inmediatamente con la practica. Aunque claro esta que el
lenguaje es muy amplio y no se puede hacer ejemplos de cada concepto.

Para cualquier desarrollo es importante leer el datasheet del PIC a utilizar. En mi caso voy a utilizar el
PIC18F2550 y aqu pueden encontrar una descripcin en espaol del mismo.

Creando el cdigo:

Primer que nada debemos incluir las libreras que se van a utilizar en el proyecto, la librera que siempre
incluiremos ser la del PIC a usar, la cual tiene las direcciones de los registros del mismo.
#include <PIC18F2550.h>

Luego viene la configuracin de los fuses del microcontrolador. sea configuracin de oscilador, watch-dog,
Brown-out reset, power-on reset, proteccin del cdigo, etc. Esto depende del microcontrolador que se utilice:
La sintaxis seria: #pragma config Nombre del fuse=estado.
Para esto es muy til la ayuda que trae C18, recomiendo mirarla:
C:\MCC18\doc\ hlpPIC18ConfigSet

Definicin de variables globales, son las que se utilizaran en el programa principal y funciones del proyecto.
int variableA, variableB

Ahora viene el cdigo de nuestro programa:
main{

}
Primer ejemplo, control de leds con un pulsador.
Para este sencillo ejemplo vamos a necesitar definir operadores y estructuras de control:

Operadores:
Aqu definiremos todos los operadores utilizados por C18.-
Operadores de Comparacin:
Estos operadores se encargan de comparar dos condiciones de una expresin:

Operadores aritmticos:
Se utilizan para realizar clculos matemticos:
Autor: Suky Web:www.infopic.comlu.com



Operadores lgicos:
Son los encargados de producir resultados lgicos del tipo TRUE o FALSE


Operadores bitwise:
Son para modificar los bits de una variable:


Estructuras:

Estructura if:
Esta estructura se utiliza para ejecutar instrucciones en forma condicional, de acuerdo con la evaluacin de la
expresin. Seria si una condicin es dada entonces accin.
if(condicion){
//Accion
}





Autor: Suky Web:www.infopic.comlu.com


Estructura if-else
En este caso se agrega la instruccin else. Ahora se evala una condicin original, si es verdadera, se ejecuta y
sino no lo es, se ejecuta el bloque debajo de else.
if(condicion){
//Accin
else{
//Accion
}
}

Estructura while
Ejecuta un conjunto de instrucciones mientras una condicin sea verdadera. La principal caracterstica de esta
estructura es que, antes de comenzar el bucle, verifica la condicin, por lo que es posible que el bucle no
llegue a ejecutarse.
while(condicion){
// Sentencias
}

Estructura do-while
Es parecida a un while solo que la condicin se evala al final, por lo que el bucle se ejecutara por lo menos
una vez.
do {
// Sentencias
} while (condicion);

Estructura For:
Esta estructura se usa para ejecutar un bloque de cdigo cierto nmero de veces. Posee un valor de inicio, un
valor final y un valor de incremento.

for(valor inicial; valor final; valor de incremento ){
//Sentencias
}

Mas adelante explicaremos la estructura switch.


Accediendo a los bits de un registro:

Para acceder individualmente a los bits de un registro se escribe la siguiente sentencia:
Registrobits.bit
Ejemplo:
PORTBbits.RB0
SSP1CON2bits.ACKDT
LATBbits.LATB0

Autor: Suky Web:www.infopic.comlu.com

Objetivo: Encender 4 leds del puerto B mientras se mantenga accionado el pulsador.

Hardware

Cdigo:
1. #include <p18f2550.h>
2.
3. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
4. #pragma config PWRT = ON,BOR = OFF,BORV = 0
5. #pragma config WDT = OFF,WDTPS = 32768
6. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
7. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
8. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
9. #pragma config CPB = ON,CPD = ON
10. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
11. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
12. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
13. #pragma config EBTRB = ON
14.
15.
16. void main(void){
17. ADCON1=0x0F;//Todos entrada/salida digitales.-
18. TRISA=0xFF; //Todos como entrada.-
19. TRISB=0X00; //Todos como salida.-
20.
21. PORTB=0x00; //Leds apagados.-
22. while(1){
23. if(PORTAbits.RA0==1){ // testeamos RB0.
24. PORTB=0x00; // Si esta en 1 Apagamos leds
25. }
Autor: Suky Web:www.infopic.comlu.com

26. else{
27. PORTB=0x0F; // Si esta en 0 Encendemos leds.
28. }
29. }
30. }

Variables

Modificadores de las variables:
Mplab C18 utiliza los modificadores establecidos por ANSI:

Auto: las variables declaradas fuera de las funciones son globales y las declaradas en la funcin son locales. Si
no se inicializan toman un valor indefinido.
Static: variables locales a una funcin, y sirven para retener el valor de la variable en llamadas sucesivas a
dicha funcin.
Extern: La variable declarada pertenece a otro mdulo, por lo que no es necesario reservar memoria para ella.
Const: El contenido de la variable es fijo.
Volatile: el contenido de la variable puede cambiar.
Register: La variable declarada debe guardarse en un registro del microcontrolador.
Overlay: Se aplica a variables locales, hace un almacenamiento esttico y las inicializa en cada llamada.
Ram: La variable se sita en la memoria de datos.
Rom: la variable se sita en la memoria del programa. Por lo general se usa para cadena de caracteres
contantes.

Especificacin de banco de memoria de datos:
Far: La variable puede ir en cualquier banco.
Near: la variable tiene que estar en el banco de acceso.


Demoras:

Para utilizar demoras en nuestro cdigo debemos incluir la librera delays.h. En ella tenemos 4 funciones:
Delay10TCYx(i) -> 10.Tcy.i
Delay100TCYx(i) -> 100.Tcy.i
Delay1KTCYx(i) -> 1000.Tcy.i
Delay10KTCYx(i) -> 10000.Tcy.i
Autor: Suky Web:www.infopic.comlu.com


Donde i puede tomar valores entre 0 y 255.


Segundo ejemplo: Leds titilando.

Objetivo: Hacer titilar 10 veces los leds del puerto B al accionar el pulsador.

Hardware: Idem anterior.
Codigo:
1. #include <p18f2550.h>
2. #include <delays.h>
3.
4. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
5. #pragma config PWRT = ON,BOR = OFF,BORV = 0
6. #pragma config WDT = OFF,WDTPS = 32768
7. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
8. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
9. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
10. #pragma config CPB = ON,CPD = ON
11. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
12. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
13. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
14. #pragma config EBTRB = ON
15.
16. unsigned char i; //Para contar 0 titilaciones.-
17.
18. void main(void){
19. ADCON1=0x0F;//Todos entrada/salida digitales.-
20. TRISA=0xFF; //Todos como entrada.-
21. TRISB=0X00; //Todos como salida.-
22.
23. PORTB=0x00; //Leds apagados.-
24. while(1){
25. if(PORTAbits.RA0==1){
26. PORTB=0x00;
27. }
28. else{
29. for(i=1;i<=10;++i){//Titila 10 veces
30. PORTB=0x0F;
31. Delay10KTCYx(30);//Demora 300ms
32. PORTB=0x00;
33. Delay10KTCYx(30);//Demora 300ms
34. }
35. }
36. }
37. }

Autor: Suky Web:www.infopic.comlu.com

Tercer Ejemplo: Leds secuenciales:

Objetivo: Al accionar el pulsador se realiza una secuencia de leds como se muestra en la figura:


Hardware: Idem anterior.
Cdigo:
1. #include <p18f2550.h>
2. #include <delays.h>
3.
4. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
5. #pragma config PWRT = ON,BOR = OFF,BORV = 0
6. #pragma config WDT = OFF,WDTPS = 32768
7. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
8. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
9. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
10. #pragma config CPB = ON,CPD = ON
11. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
12. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
13. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
14. #pragma config EBTRB = ON
15.
16. unsigned char i; //Para contar 4 secuencias.-
17.
18. void main(void){
19. ADCON1=0x0F;//Todos entrada/salida digitales.-
20. TRISA=0xFF; //Todos como entrada.-
21. TRISB=0X00; //Todos como salida.-
22.
23. PORTB=0x00; //Leds apagados.-
24. while(1){
25. if(PORTAbits.RA0==1){
26. PORTB=0x00;
27. }
28. else{
29. PORTB=0x01;
30. for(i=1;i<=4;++i){
31. Delay10KTCYx(30);
32. PORTB<<=1;
33. }
34. }
35. }
36. }

Autor: Suky Web:www.infopic.comlu.com

Arreglos de Variables

Nos permite trabajar con un conjunto de variables y acceder a cada una mediante un ndice nico que lo
identifica. Todos los valores que contienen deben ser del mismo tipo.
1. unsigned char Vector[5];
2. unsigned char Matriz[3][3];
3. .
4. .
5. .
6. //Cargamos vector y matriz:
7. Vector[0]=156;
8. Matriz[1][1]=85;
9. //Leemos vector y matriz:
10. PORTB=Vector[4];
11. PORTB=Matriz[0][0];
En la declaracin se pueden pre cargar los valores de la siguiente forma:
1. unsigned char Vector[3]={1,0x10,0b000101}
2. unsigned char Matriz[3][3]={1,2,3,4,5,6,7,8,9,10};

Cuarto Ejemplo: Control de display 7 segmentos

Objetivo: utilizaremos dos pulsadores para incrementar, decrementar o resetear un conteo de 0 a 9 que
mostraremos en un display de 7 segmentos de ctodo comn. El reseteo ser el caso en el que se presiona los
dos pulsadores a la vez.

Hardware:

Autor: Suky Web:www.infopic.comlu.com

Cdigo:
1. #include <p18f2550.h>
2. #include <delays.h>
3.
4. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
5. #pragma config PWRT = ON,BOR = OFF,BORV = 0
6. #pragma config WDT = OFF,WDTPS = 32768
7. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
8. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
9. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
10. #pragma config CPB = ON,CPD = ON
11. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
12. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
13. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
14. #pragma config EBTRB = ON
15.
16. unsigned char i; //Para controlar vizualizacion del Display.-.-
17. unsigned char Display7Seg[10]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D,
0x07, 0xFF, 0x6F};
18.
19. void main(void){
20. ADCON1=0x0F;//Todos entrada/salida digitales.-
21. TRISA=0xFF; //Todos como entrada.-
22. TRISB=0X00; //Todos como salida.-
23.
24. PORTB=0x3F; //Comienza en cero.-
25. i=0;
26. while(1){
27. if(PORTAbits.RA0==0 & PORTAbits.RA1==0){// Si se presionan los 2
a la vez se resetea.-
28. i=0;
29. PORTB=Display7Seg[i];
30. Delay10KTCYx(30);
31. }else if(PORTAbits.RA0==0){// Se incrementa cuenta.-
32. ++i;
33. if(i==10){i=0;} //Volvemos a 0.-
34. PORTB=Display7Seg[i];
35. Delay10KTCYx(30);
36. }else if(PORTAbits.RA1==0){// Se decrementa cuenta.-
37. --i;
38. if(i==255){i=9;} //Volvemos a 9.-
39. PORTB=Display7Seg[i];
40. Delay10KTCYx(30);
41. }
42. }
43. }





Autor: Suky Web:www.infopic.comlu.com

Declaracin y definicin de funciones.

La declaracin da a conocer la funcin al compilador, a partir de su declaracin ya se pueden realizar
invocaciones a las mismas. La declaracin de una funcin se conoce tambin como prototipo de la funcin. En
el prototipo de una funcin se tienen que especificar los parmetros de la funcin, as como el tipo de dato que
devuelve.

La definicin estar en algn otro punto del programa, aqu se especifican las instrucciones que forman parte
de la misma y que se utilizan para llevar a cabo la tarea especfica de la funcin.


Tipo de retorno Nombre(Lista de parmetros)

Tipo de retorno : Representa el tipo del valor que devuelve la funcin. Si no devuelve ninguno de debe
colocar void.
Nombre: indica el nombre que se le da a la funcin, se recomienda que este relacionado con la tarea que
llevar a cabo.
Lista de parmetros : se enlista el tipo de dato y el nombre de cada parmetro. En caso de utilizar parmetros
se deja el parntesis vacio o se incluye la palabra void.
1. unsigned int Suma(unsigned char A, unsigned char B){
2. unsigned int C;
3. C=A+B;
4. return(C);
5. }
1. void Envio_Data(unsigned char A){
2. //Sentencia.-
3. }
1. void Muestras(void){
2. //Sentencias.-
3. }
Dos formas de incluir una funcin en nuestro cdigo:
Realizando la declaracin en el encabezado y despus la definicin en cualquier sector del programa.
1. // Declaracion de la funcion
2. void Funcion(void);
3. .
4. .
5. .
6. void main(void){
7. .
8. .
9. .
10. // Llamo a la funci&#243;n.
11. Funcion();
12. }
13.
14. //Defincion de la funcion. (Puede estar en cualquier lugar del programa)
15. void Funcion(void){
16. // Sentencias
17. }
Autor: Suky Web:www.infopic.comlu.com

Otra forma es no realizar la declaracin de la funcin y realizar directamente la definicin, pero esta tiene que
estar si o si antes de su invocacin.
1. .
2. .
3. .
4. //Defincion de la funcion
5. void Funcion(void){
6. // Sentencias
7. }
8. void main(void){
9. .
10. .
11. .
12. // Llamo a la funci&#243;n.
13. Funcion();
14. }

Ejemplo: Control de varios display, multiplexin de la seal.

Objetivo: Controlar 3 display de 7 segmentos visualizando el conteo automtico de 0 a 999.
Hardware:



Autor: Suky Web:www.infopic.comlu.com

Cdigo:
1. #include <p18f2550.h>
2. #include <delays.h>
3.
4. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
5. #pragma config PWRT = ON,BOR = OFF,BORV = 0
6. #pragma config WDT = OFF,WDTPS = 32768
7. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
8. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
9. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
10. #pragma config CPB = ON,CPD = ON
11. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
12. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
13. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
14. #pragma config EBTRB = ON
15.
16. #define UnidadBit PORTAbits.RA0
17. #define DecenaBit PORTAbits.RA1
18. #define CentenaBit PORTAbits.RA2
19.
20. unsigned char i, Unidad, Decena, Centena;
21. unsigned char Display7Seg[10]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D,
0x07, 0xFF, 0x6F};
22. void Visualizacion (void);
23.
24. void main(void){
25. ADCON1=0x0F;//Todos entrada/salida digitales.-
26. TRISA=0xF0; //Todos como entrada.-
27. TRISB=0X00; //Todos como salida.-
28.
29. PORTA=0x00;
30. Unidad=0;
31. Decena=0;
32. Centena=0;
33.
34. while(1){
35. Visualizacion();
36. ++Unidad;
37. if(Unidad==10){
38. Unidad=0;
39. ++Decena;
40. if(Decena==10){
41. Decena=0;
42. ++Centena;
43. }
44. }
45. }
46. }
47. void Visualizacion (void){
48. for(i=1;i<=20;++i){
49. PORTB=Display7Seg[Unidad];
50. UnidadBit=1; //Enciendo Display Unidad.-
51. Delay1KTCYx(5); //Demora de 5 ms (XT=4MHz)
52. UnidadBit=0;
53. PORTB=Display7Seg[Decena];
54. DecenaBit=1;
55. Delay1KTCYx(5);
56. DecenaBit=0;
57. PORTB=Display7Seg[Centena];
Autor: Suky Web:www.infopic.comlu.com

58. CentenaBit=1;
59. Delay1KTCYx(5);
60. CentenaBit=0; //Apago Display Centena.-
61. }
62. }

Control de un LCD.

Para realizar el control de un LCD necesitamos usar la librera xlcd.h ubicada en C:\MCC18\h\. Esta librera
es para un LCD con controlador Hitachi HD44780 o compatible, de 8 o 4 bits. El usuario debe proveer 3 delay
para el correcto funcionamiento, DelayPORXLCD() de 15ms, DelayXLCD() de 5ms y DelayFor18TCY() de
18 Tcy.

En este caso no vamos a modificar la librera, pues lo vamos a controlar con el puerto B, pero en el caso de
que se modifique sugiero siempre respaldarla con una copia de seguridad.

Ejemplo: Control de un LCD.

Objetivo: Vamos a escribir un simple mensaje en un LCD. Se crearon 2 funciones adicionales para un
mejor el control, la primeria seria el envo de comandos, con una previa espera de disponibilidad del LCD y la
segunda es para controlar la posicin del cursor en el LCD.

Hardware:


Autor: Suky Web:www.infopic.comlu.com

Codigo:
1. #include <p18f2550.h>
2. #include <delays.h>
3. #include <xlcd.h>
4.
5. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
6. #pragma config PWRT = ON,BOR = OFF,BORV = 0
7. #pragma config WDT = OFF,WDTPS = 32768
8. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
9. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
10. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
11. #pragma config CPB = ON,CPD = ON
12. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
13. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
14. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
15. #pragma config EBTRB = ON
16.
17.
18. void DelayFor18TCY(void){
19. Delay10TCYx(2);
20. }
21. void DelayPORXLCD(void){
22. Delay1KTCYx(15);
23. }
24. void DelayXLCD(void){
25. Delay1KTCYx(2);
26. }
27.
28. // Envia comando al LCD
29. void comandXLCD(unsigned char a){
30. BusyXLCD();
31. WriteCmdXLCD(a);
32. }
33. // Ubica cursor en (x = Posicion en linea, y = n&#186; de linea)
34. void gotoxyXLCD(unsigned char x, unsigned char y){
35. unsigned char direccion;
36.
37. if(y != 1)
38. direccion = 0x40;
39. else
40. direccion=0;
41.
42. direccion += x-1;
43. comandXLCD(0x80 | direccion);
44. }
45.
46. void main(void){
47. OpenXLCD(FOUR_BIT & LINES_5X7); // Iniciamos LCD.-
48. comandXLCD(0x06); // Nos aseguramos incremento de direccion,
display fijo
49. comandXLCD(0x0C); // Encendemos LCD.-
50. putrsXLCD("Probando LCD");
51. gotoxyXLCD(1,2); //Pasamos al oriden del
Linea 2.-
52. putrsXLCD("Por Suky");
53. while(1){ // Bucle infinito.
54. }
55. }
Autor: Suky Web:www.infopic.comlu.com



Conversin analgica digital.

Para realizar una conversin analgica digital usaremos la librera adc.h, esta tiene las funciones necesarias
para las configuraciones y lectura de dicho mdulo. En el caso de las configuraciones, este posee varias y
depende del microcontrolador que se use. Para saber en que grupo cae nuestro microcontrolador abrimos
pconfig.h, y por ejemplo para el PIC18F2550 es ADC_V5.

NOTA: Para ms informacin respecto al mdulo y sus configuraciones ver tema, Mdulo de conversin
ADC

Funciones (para ADC_V5) :
OpenADC (PARAM_SCLASS unsigned char , PARAM_SCLASS unsigned char , PARAM_SCLASS unsigned
char );

Con ella se configure el reloj, el formato, tensin de referencia, puerto y canal de la conversin. Para saber
que colocar en cada parmetro abrir AD Converter ubicado en C:\MCC18\doc\periph-lib.
Ejemplos:
OpenADC(ADC_FOSC_32 & ADC_8_TAD & ADC_RIGHT_JUST, ADC_REF_VDD_VSS & ADC_INT_OFF,
ADC_5ANA);

#define USE_OR_MASKS
OpenADC(ADC_FOSC_RC | ADC_20_TAD| ADC_LEFT_JUST, ADC_REF_VREFPLUS_VREFMINUS |
ADC_INT_OFF, ADC_15ANA);

CloseADC(); Desactiva el conversor y la interrupcin.

SetChanADC(Unsigned char); Selecciona el canal que se va a utilizar.

ConvertADC(); Comienza la conversin.

SelChanConvADC(Unsigned char); Selecciona canal y comienza conversin.

BusyADC(); Comprueba si la conversin a finalizado.

Int ReadADC(); devuelve la lectura del canal analgico seleccionado.

Ejemplo: Uso del mdulo de conversin analgico/digital.

Objetivo: Tomar lectura de 2 valores analgicos y mostrarlo en un LCD. Al accionar un pulsador, leeremos
Autor: Suky Web:www.infopic.comlu.com

los 2 canales analgicos y los mostraremos en el LCD durante 1 segundo.
Hardware:

Codigo:
1. #include <p18f2550.h>
2. #include <delays.h>
3. #include <xlcd.h>
4. #include <stdlib.h> //Libreria para conversiones.
5. #include <adc.h>
6.
7. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
8. #pragma config PWRT = ON,BOR = OFF,BORV = 0
9. #pragma config WDT = OFF,WDTPS = 32768
10. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
11. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
12. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
13. #pragma config CPB = ON,CPD = ON
14. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
15. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
16. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
17. #pragma config EBTRB = ON
18.
19.
20. void DelayFor18TCY(void){
21. Delay10TCYx(2);
22. }
Autor: Suky Web:www.infopic.comlu.com

23. void DelayPORXLCD(void){
24. Delay1KTCYx(15);
25. }
26. void DelayXLCD(void){
27. Delay1KTCYx(2);
28. }
29.
30. // Envia comando al LCD
31. void comandXLCD(unsigned char a){
32. BusyXLCD();
33. WriteCmdXLCD(a);
34. }
35. // Ubica cursor en (x = Posicion en linea, y = n&#186; de linea)
36. void gotoxyXLCD(unsigned char x, unsigned char y){
37. unsigned char direccion;
38.
39. if(y != 1)
40. direccion = 0x40;
41. else
42. direccion=0;
43.
44. direccion += x-1;
45. comandXLCD(0x80 | direccion);
46. }
47.
48.
49.
50. void main(void){
51. unsigned int Canal0, Canal1;
52. char String[4];
53. OpenXLCD(FOUR_BIT & LINES_5X7); // Iniciamos LCD.-
54. comandXLCD(0x06); // Nos aseguramos incremento de direccion,
display fijo
55. OpenADC(ADC_FOSC_RC & ADC_2_TAD & ADC_RIGHT_JUST, ADC_REF_VDD_VSS
& ADC_INT_OFF, ADC_2ANA);
56. comandXLCD(0x0C); // Encendemos LCD.-
57.
58. while(1){
59. comandXLCD(0x01); // Borra pantalla y
vuelve al origen.-
60. putrsXLCD("Presionar boton");
61. while(PORTAbits.RA2==1){} // Espero a que se accione
el pulsador.-
62. SetChanADC(0); // Selecciono canal a convertir.-
63. //Delay10TCYx(1); // 10us para que se cargue el
capacitor sample&hold (Solo cuando se selecciona ADC_0_TAD).-
64. ConvertADC(); // Comienza conversi&#243;n.-
65. While(BusyADC()==1){} // Hasta que se finalice
conversi&#243;n.-
66. Canal0= ReadADC(); // Realizo lectura.-
67.
68. SetChanADC(1); // Selecciono canal a convertir.-
69. //Delay10TCYx(1); // 10us para que se cargue el
capacitor sample&hold (Solo cuando se selecciona ADC_0_TAD).-
70. ConvertADC(); // Comienza conversi&#243;n.-
71. While(BusyADC()==1){} // Hasta que se finalice
conversi&#243;n.-
72. Canal1= ReadADC(); // Realizo lectura.-
73.
74. comandXLCD(0x01); // Borra pantalla y
vuelve al origen.-
Autor: Suky Web:www.infopic.comlu.com

75. putrsXLCD("Canal 0 = ");
76. itoa(Canal0, String); // Convertimos entero a
string.-
77. putsXLCD(String);
78. gotoxyXLCD(1,2);
79. putrsXLCD("Canal 1 = ");
80. itoa(Canal1, String); // Convertimos entero a
string.-
81. putsXLCD(String);
82. Delay10KTCYx(100);
83. }
84. }


Interrupciones:

Los dispositivos PIC18 tienen mltiples fuentes de interrupcin y una caracterstica de prioridad de
interrupcin, que permite a cada fuente de interrupcin asignarle un nivel de prioridad bajo o alto. Cuando
ocurre un evento de alta prioridad interrumpir cualquier interrupcin de baja prioridad que pueda estar en
progreso. El vector de alta prioridad esta en 0x08 y el vector de baja prioridad en 0x18.

Cada fuente de interrupcin tiene tres bits para controlar su operacin. Las funciones de estos bits son:
Bit bandera, que indica si un evento de interrupcin ha ocurrido
Bit Enable, que admiten la ejecucin de la interrupcin, permitiendo la bifurcacin del programa a la
direccin del vector de interrupcin
Bit de prioridad, para seleccionar prioridad baja o alta

La caracterstica de prioridad de interrupciones de activa seteando el bit IPEN. Si este no esta seteado, no
existen prioridades y las interrupciones se comportan como en los dispositivos de gama media (PIC16) y todas
las interrupciones se bifurcan al vector 0x08.

Rutinas de atencin a interrupciones:

La directiva #pragma interruplow nombre define rutina de servicio de interrupcin (ISR) de baja prioridad y
#pragma interrup nombre se alta prioridad.
Las ISR son funciones como cualquier otra, pero con las restricciones de que:
No devuelven ni aceptan parmetros
No se puede invocar desde otros puntos del programa
Las variables globales que utilice se den declarar como volatile
Autor: Suky Web:www.infopic.comlu.com


El C18 no sita automticamente las ISR en las posiciones de los vectores de interrupcin, por lo que el
usuario debe ubicarlas. Ejemplos:
1. #pragma interruplow ISRBajaPrioridad
2. Void ISRBajaPrioridad(void){
3. // Tratamiento de interrupci&#243;n.-
4. }
5.
6. // Creamos una nueva secci&#243;n de c&#243;digo a partir de la
direcci&#243;n 0x18.-
7. #pragma code PrioridadBaja = 0x18
8. Void VectorBajaPrioridad(void){
9. // Instruccion insertada en la direcci&#243;n 0x18.-
10. _asm goto ISRBajaPrioridad _endasm
11. }
12. #pragma code // Cerramos secci&#243;n.-

1. #pragma interruplow ISRAltaPrioridad
2. Void ISRAltaPrioridad(void){
3. // Tratamiento de interrupci&#243;n.-
4. }
5.
6. // Creamos una nueva secci&#243;n de c&#243;digo a partir de la
direcci&#243;n 0x08.-
7. #pragma code PrioridadAlta = 0x08
8. Void VectorAltaPrioridad(void){
9. // Instruccion insertada en la direcci&#243;n 0x08.-
10. _asm goto ISRAltaPrioridad _endasm
11. }
12. #pragma code // Cerramos secci&#243;n.-

Mdulo USART.

Para la comunicacin serial es necesario agregar la librera usart.h. Con esta librera se configura el modo de
transmisin y recepcin serie de nuestro microcontrolador.

Funciones:
OpenUSART( unsigned char config, unsigned int spbrg);
Esta funcin corresponde a la configuracin del mdulo USART, asincrnica o sincrnica, 8 bits o 9 bits,
velocidad de comunicacin, etc.
Para saber que colocar en cada parmetro abrir USART ubicado en C:\MCC18\doc\periph-lib.

CloseUSART(); Deshabilita mdulo USART.

putcUSART(char data); Enva un byte.

putsUSART(char *buffer); Envia un string desde la memoria de datos.

Autor: Suky Web:www.infopic.comlu.com

putrsUSART(const rom char *data); Envia un string desde la memoria de programa.

BusyUSART(); Determina si se ha transmitido el dato.

DataRdyUSART(); Indica si ha llegado un dato para ser ledo.

getcUSART(); Lee un byte.

getsUSART(char *buffer, Unsigned char len); Lee un string.

Estructura switch.
Esta estructura permite ejecutar un bloque de cdigo de acuerdo con el valor de una variable o expresin:
1. switch(Variable){
2. Case 0x01:
3. //Sentencias.-
4. Break;
5. Case 0x02:
6. //Sentencias.-
7. Break;
8. Default:
9. //Sentencias.-
10. Break;
11. }

Default: ejecuta esa sentencia si no es ninguna de las anteriores.

Ejemplo: Comunicacin Serial RS232.

Objetivo: La PC enviara comando de lectura de los canales analgicos. Si se recibe un 0x61 ('a'), enviar
canal 0, si se recibe un 0x62 ('b') enviar canal 1 y si se recibe un 0x63 ('c') enviar los 2 canales analgicos.

Hardware:

Autor: Suky Web:www.infopic.comlu.com


La adaptacin de tensiones se puede hacer con el MAX232 o con transistores, como se desee.-
1. #include <p18f2550.h>
2. #include <delays.h>
3. #include <stdlib.h> //Libreria para conversiones.
4. #include <adc.h>
5. #include <usart.h>
6.
7. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
8. #pragma config PWRT = ON,BOR = OFF,BORV = 0
9. #pragma config WDT = OFF,WDTPS = 32768
10. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
11. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
12. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
13. #pragma config CPB = ON,CPD = ON
14. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
15. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
16. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
17. #pragma config EBTRB = ON
18.
19. void ISRRecepcion(void);
20. volatile char Data, Kbhit;
21.
22. // Creamos una nueva seccion de codigo a partir de la direccion 0x08.-
23. #pragma code Interrupcion = 0X0008
24. void VectorInterrupcion(void){
25. _asm goto ISRRecepcion _endasm
26. }
27. #pragma code // Cerramos seccion.-
28.
29. // Rutina de Interrupcion.-
30. #pragma interrupt ISRRecepcion
31. void ISRRecepcion(void){
32. if(PIR1bits.RCIF==1){
33. Data=getcUSART(); // Leemos Dato recibido
34. Kbhit=1; // Indicamos que se ha
recibido un dato.-
35. PIR1bits.RCIF=0; // Borramos bandera.-
36. }
37. }
38.
39.
40. void main(void){
41. unsigned int Canal0, Canal1;
42. char String[4];
43.
44. OpenUSART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE
& USART_EIGHT_BIT &
45. USART_CONT_RX & USART_BRGH_HIGH,25); // 9600,8,n,1
46. OpenADC(ADC_FOSC_RC & ADC_2_TAD & ADC_RIGHT_JUST, ADC_REF_VDD_VSS
& ADC_INT_OFF, ADC_2ANA);
47. Kbhit=0;
48. RCONbits.IPEN=0; // Deshabilitamos Prioridades
49. INTCONbits.PEIE=1; // Habilitamos interrupcion de
perifericos.-
50. INTCONbits.GIE=1; // Habilitamos interrupcion Global.
51.
52. putrsUSART("Prueba Comunicacion Serial \r");
53. while(1){
Autor: Suky Web:www.infopic.comlu.com

54. while(Kbhit==0){}; // esperamos a recibir dato.-
55. Kbhit=0;
56. switch(Data){
57. case 0x61: // letra a
58. SetChanADC(0); // Selecciono canal a
convertir.-
59. //Delay10TCYx(1); // 10us para que se
cargue el capacitor sample&hold (Solo cuando se selecciona ADC_0_TAD).-
60. ConvertADC(); // Comienza
conversi&#243;n.-
61. While(BusyADC()==1){} // Hasta que se
finalice conversi&#243;n.-
62. Canal0= ReadADC(); // Realizo lectura.-
63. putrsUSART("Canal 0 = ");
64. itoa(Canal0, String); //
Convertimos entero a string.-
65. putsUSART(String);
66. putrsUSART("\r");
67. break;
68. case 0x62: // letra b
69. SetChanADC(1); // Selecciono canal a
convertir.-
70. //Delay10TCYx(1); // 10us para que se
cargue el capacitor sample&hold (Solo cuando se selecciona ADC_0_TAD).-
71. ConvertADC(); // Comienza
conversi&#243;n.-
72. While(BusyADC()==1){} // Hasta que se
finalice conversi&#243;n.-
73. Canal1= ReadADC(); // Realizo lectura.-
74. putrsUSART("Canal 1 = ");
75. itoa(Canal1, String); //
Convertimos entero a string.-
76. putsUSART(String);
77. putrsUSART("\r");
78. break;
79. case 0x63: // letra c
80. SetChanADC(0); // Selecciono canal a
convertir.-
81. //Delay10TCYx(1); // 10us para que se
cargue el capacitor sample&hold (Solo cuando se selecciona ADC_0_TAD).-
82. ConvertADC(); // Comienza
conversi&#243;n.-
83. While(BusyADC()==1){} // Hasta que se
finalice conversi&#243;n.-
84. Canal0= ReadADC(); // Realizo lectura.-
85.
86. SetChanADC(1); // Selecciono canal a
convertir.-
87. //Delay10TCYx(1); // 10us para que se
cargue el capacitor sample&hold (Solo cuando se selecciona ADC_0_TAD).-
88. ConvertADC(); // Comienza
conversi&#243;n.-
89. While(BusyADC()==1){} // Hasta que se
finalice conversi&#243;n.-
90. Canal1= ReadADC(); // Realizo lectura.-
91.
92. putrsUSART("Canal 0 = ");
93. itoa(Canal0, String); //
Convertimos entero a string.-
94. putsUSART(String);
95. putrsUSART("\r");
Autor: Suky Web:www.infopic.comlu.com

96. putrsUSART("Canal 1 = ");
97. itoa(Canal1, String); //
Convertimos entero a string.-
98. putsUSART(String);
99. putrsUSART("\r");
100. break;
101. }
102. }
103. }

Otra manera de enviar los datos, usando printf:

Para utilizar esta funcin debemos agregar la librera stdio.h.
printf (const rom char *fmt, ...);
Nos permite especificar el formato en que queremos mostrar datos por pantalla
Parmetros: Cadena de formato (cmo se visualizan los datos) y Lista de valores (datos que se
visualizan)
Formatos:
%d Entero con signo.
%u Entero sin signo.
%x Hexadecimal minscula.
%X Hexadecimal mayscula.

Ejemplo:
printf(Hola);
Data=10;
printf(El valor es : %u,Data);
Ejemplo de formatos:
Especificacin Valor=0x12 Valor=0xFE
%03u 018 254
%u 18 254
%2u 18 *
%d 18 -2
%x 12 fe
%X 12 FE

Entonces se puede reemplazar:
Canal0=ReadADC();
putrsUSART("Canal 0 = ");
itoa(Canal0, String);
putsUSART(String);
putrsUSART("\r");

Por:
#include <stdio.h>
.
.
.
Canal0=ReadADC();
printf("Canal 0 = %u \r", Canal0);

Autor: Suky Web:www.infopic.comlu.com

Modificar las libreras.
Se explicar como realizar cambios en las libreras de C18, para que estas se hagan efectivas a la hora de
compilar. En este caso cambiaremos el Puerto para el control del LCD.
Primero que nada se debe realizar una copia de seguridad, en este caso de xlcd.h. Luego en nuestro programa
debemos incluir a xlcd.h (MCC18\h) en Header Files, y los archivos fuentes de esta librera
(MCC18\src\pmc_common\XLCD), excepto putrxlcd, quedando de la siguiente manera:

De esta manera se recompilan los archivos, creando sus respectivos archivos objetos (*.o) necesarios para el
linkeo (MPLink) y as efectivizar los cambios realizados en las rutinas.

Vamos a modificar xlcd.h para que utilizar el Puerto C para controlar el LCD y los 4 bits ms significativos
del mismo (UPPER) para enviar los datos al LCD de la siguiente manera:
1. #define UPPER
2. /* DATA_PORT defines the port to which the LCD data lines are connected */
3. #define DATA_PORT PORTC
4. #define TRIS_DATA_PORT TRISC
5. /* CTRL_PORT defines the port where the control lines are connected.
6. * These are just samples, change to match your application.
7. */
8. #define RW_PIN LATCbits.LATC1 /* PORT for RW */
9. #define TRIS_RW TRISCbits.TRISC1 /* TRIS for RW */
10. #define RS_PIN LATCbits.LATC0 /* PORT for RS */
11. #define TRIS_RS TRISCbits.TRISC0 /* TRIS for RS */
12. #define E_PIN LATCbits.LATC2 /* PORT for D */
13. #define TRIS_E TRISCbits.TRISC2 /* TRIS for E */



Autor: Suky Web:www.infopic.comlu.com

Cualquier cambio, por mnimo que sea se debe hacer de esta manera para que se efectivicen los
cambios.
1. #include <p18f2550.h>
2. #include <delays.h>
3. #include <xlcd.h>
4.
5.
6. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
7. #pragma config PWRT = ON,BOR = OFF,BORV = 0
8. #pragma config WDT = OFF,WDTPS = 32768
9. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
10. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
11. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
12. #pragma config CPB = ON,CPD = ON
13. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
14. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
15. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
16. #pragma config EBTRB = ON
17.
18.
19. void DelayFor18TCY(void){
20. Delay10TCYx(2);
21. }
22. void DelayPORXLCD(void){
23. Delay1KTCYx(15);
24. }
25. void DelayXLCD(void){
26. Delay1KTCYx(2);
27. }
28.
29. // Envia comando al LCD
30. void comandXLCD(unsigned char a){
31. BusyXLCD();
32. WriteCmdXLCD(a);
33. }
34. // Ubica cursor en (x = Posicion en linea, y = n&#186; de linea)
35. void gotoxyXLCD(unsigned char x, unsigned char y){
36. unsigned char direccion;
37.
38. if(y != 1)
39. direccion = 0x40;
40. else
41. direccion=0;
42.
43. direccion += x-1;
44. comandXLCD(0x80 | direccion);
45. }
46.
47. void main(void){
48. OpenXLCD(FOUR_BIT & LINES_5X7); // Iniciamos LCD.-
49. comandXLCD(0x06); // Nos aseguramos incremento de direccion,
display fijo
50. comandXLCD(0x0C); // Encendemos LCD.-
51. putrsXLCD("LCD en Puerto C");
52. gotoxyXLCD(1,2); //Pasamos al oriden del
Linea 2.-
53. putrsXLCD("Por Suky");
54. while(1){ // Bucle infinito.
55. }
56. }
Autor: Suky Web:www.infopic.comlu.com


Interrupcin por cambio de estado RB4-RB7. Control de Teclado Matricial.

Objetivo: Al accionar una tecla del Teclado Matricial, esta se mostrar en la pantalla LCD.
Aprovecharemos la interrupcin por cambio de estado RB4-RB7 para detectar que se ha presionado
una tecla. Dentro de la interrupcin se realiza el rastreo fino para determinar cual ha sido.

Hardware:

Autor: Suky Web:www.infopic.comlu.com


Nota: En Proteus se deben agregar las resistencias pull-up a RB4-RB7 para simular correctamente.
Adems se usa el puerto C para el control del LCD, y para que la compilacin sea correcta se deben
seguir los pasos del mensaje anterior.
1. #include <p18f2550.h>
2. #include <delays.h>
3. #include <xlcd.h>
4.
5. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
6. #pragma config PWRT = ON,BOR = OFF,BORV = 0
7. #pragma config WDT = OFF,WDTPS = 32768
8. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
9. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
10. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
11. #pragma config CPB = ON,CPD = ON
12. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
13. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
14. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
15. #pragma config EBTRB = ON
16.
17. unsigned char Tecla;
18. unsigned char Teclas[17]={'7','8','9','/',
19. '4','5','6','x',
20. '1','2','3','-',
21. '.','0','=','+',''};
22.
23. void ISRRB4_RB7(void);
24. void DelayFor18TCY(void);
25. void DelayPORXLCD(void);
26. void DelayXLCD(void);
27. void comandXLCD(unsigned char a);
28. void gotoxyXLCD(unsigned char x, unsigned char y);
29. char TestTeclado(void);
30.
31. // Creamos una nueva seccion de codigo a partir de la direccion 0x08.-
32. #pragma code Interrupcion = 0X0008
33. void VectorInterrupcion(void){
34. _asm goto ISRRB4_RB7 _endasm
35. }
36. #pragma code // Cerramos seccion.-
37.
38. //***********************************************************************
**
39. void main(void){
40. OpenXLCD(FOUR_BIT & LINES_5X7); // Iniciamos LCD.-
41. comandXLCD(0x06); // Nos aseguramos incremento de direccion,
display fijo
42.
43. TRISB=0xF0; //eeeessss.-
44. PORTB=0x00;
45. INTCON2 = 0X80; // Habilitamos resistencias pull up.
46. INTCON = 0X88; //Configuraci&#243;n de interrupci&#243;n por
cambio de estado RB4-RB7
47.
48. comandXLCD(0x0C); // Encendemos LCD.-
49. putrsXLCD("TeclaPulsada \" \"");
50. gotoxyXLCD(2,2); //Pasamos al oriden del
Linea 2.-
Autor: Suky Web:www.infopic.comlu.com

51. putrsXLCD("<<Autor Suky>>");
52. while(1){ // Bucle infinito.
53. }
54. }
55.
56. //***********************************************************************
**
57. void DelayFor18TCY(void){
58. Delay10TCYx(2);
59. }
60. void DelayPORXLCD(void){
61. Delay1KTCYx(15);
62. }
63. void DelayXLCD(void){
64. Delay1KTCYx(2);
65. }
66.
67. // Envia comando al LCD
68. void comandXLCD(unsigned char a){
69. BusyXLCD();
70. WriteCmdXLCD(a);
71. }
72. // Ubica cursor en (x = Posicion en linea, y = n&#186; de linea)
73. void gotoxyXLCD(unsigned char x, unsigned char y){
74. unsigned char direccion;
75.
76. if(y != 1)
77. direccion = 0x40;
78. else
79. direccion=0;
80.
81. direccion += x-1;
82. comandXLCD(0x80 | direccion);
83. }
84.
85.
86. /* Rastrea Tecla presionada, para ello, se va colocando a 0 l&#243;gico
las filas de a una por vez,
87. * y se testea si alguna columna tambien lo esta. Se utiliza la variable i
para indicar que tecla
88. * esta siendo testeada, y de esta manera al detectar la pulsacion usar
esta variable para
89. * seleccionar el caracter en el Buffer Teclas.*/
90. char TestTeclado(void){
91. unsigned char i,j;
92. PORTB=0x0E; //xxxx1110.
93. i=0;
94. for(j=0;j<4;j++){
95. if(PORTBbits.RB4==0){break;}
96. i++;
97. if(PORTBbits.RB5==0){break;}
98. i++;
99. if(PORTBbits.RB6==0){break;}
100. i++;
101. if(PORTBbits.RB7==0){break;}
102. i++;
103. PORTB<<=1; //Trasladamos el 0 a siguiente Pin.
104. }
105. return(Teclas[i]);
106. }
107.
Autor: Suky Web:www.infopic.comlu.com

108. //****************************************************************
109. // Rutina de Interrupcion.-
110. #pragma interrupt ISRRB4_RB7
111. void ISRRB4_RB7(void){
112. if(INTCONbits.RBIF==1){
113. Tecla=TestTeclado(); //Realizamos test del Teclado, y
nos devuelve tecla pulsada
114. gotoxyXLCD(15,1);
115. putcXLCD(Tecla); // Visualizamos tecla pulsada.
116. while(PORTBbits.RB4==0 |PORTBbits.RB5==0 |PORTBbits.RB6==0
|PORTBbits.RB7==0){} //Esperamos a que se suelte.-
117. PORTB=0x00;
118. INTCONbits.RBIF = 0; //Borramos bandera
119. }
120. }

Como crear una librera.

Vamos a crear una librera para el control del CI ds1302, para ello necesitamos leer el datasheet del mismo
(DS1302).Necesitamos crear el archivo .h que contendr todas las definiciones de los pines y funciones a
utilizar, y el/los archivo/s fuente/s con el cdigo de nuestra librera.

Se debe definir la librera, esto se realiza colocando las lneas, por ejemplo para nuestro caso:
1. #ifndef __ds1302_H
2. #define __ds1302_H
3. //Sentencias
4. #endif
Quedando:
1. /** \file ds1302.h
2. * \brief Este fichero contiene las declaraciones de los pines y funciones
utilizadas para el control del DS1302.
3. */
4. #ifndef __ds1302_H
5. #define __ds1302_H
6.
7. #include <p18cxxx.h>
8.
9. //Definicion de los pines a utilizar.
10. #define SCLK PORTBbits.RB0 /**< Pin de Clock del DS1302*/
11. #define IO PORTBbits.RB1 /**< Pin de Data del DS1302*/
12. #define RST PORTBbits.RB2 /**< Pin de Enable del DS1302*/
13. // Definicion de los bits del Tris para configurar en modo escritura o
lectura.
14. #define TrisSCLK TRISBbits.TRISB0 /**< Tris del pin Clock*/
15. #define TrisIO TRISBbits.TRISB1 /**< Tris del pin Data*/
16. #define TrisRST TRISBbits.TRISB2 /**< Tris del pin Enable*/
17.
18. /** \brief Funci&#243;n que env&#237;a el byte por el Pin seleccionado.
19. *
20. * \param Byte Valor a enviar al DS1302.
21. */
22. void write_byte( unsigned char Byte);
Autor: Suky Web:www.infopic.comlu.com

23. /** \brief Env&#237;a los Datos al DS1302 seg&#250;n el protocolo, un
primer Byte de comando y el segundo de Data.
24. *
25. * \param Byte Byte de comando.
26. * \param Data Byte de Dato.
27. */
28. void write_ds1302( unsigned char Byte, unsigned char Data);
29. /** \brief Funci&#243;n que realiza lectura de 1 byte del DS1302, enviado
un Byte de comando y luego realizando la lectura.
30. *
31. * \param Byte Valor de Comando.
32. * \return Byte le&#237;do del DS1302.
33. */
34. unsigned char read_ds1302( unsigned char Byte);
35. /** \brief Inicializaci&#243;n del DS1302
36. */
37. void ds1302_init(void);
38. /** \brief Conversi&#243;n del valor decimal a enviar al DS1302.
39. *
40. * Por ejemplo, deseo enviar 36=0x24. Entonces, get_bcd(36) retorna 0x36.-
41. *
42. * \param Data Valor a convertir.
43. *\return Byte obtenido de la conversi&#243;n.
44. */
45. unsigned char get_bcd( unsigned char Data);
46. /** \brief Conversi&#243;n del valor le&#237;do del DS1302 al decimal.
47. *
48. * Por ejemplo, se lee 0x36, entonces al realizar rm_bcd(0x36) retorna
0x24=36.-
49. *
50. * \param Data Valor obtenido de la lectura.
51. * \retun Byte obtenido de la conversi&#243;n.
52. */
53. unsigned char rm_bcd( unsigned char Data);
54. /** \brief Funci&#243;n que carga al DS1302 valores de Hora y Fecha
seleccionados por el usuario.
55. *
56. * \param day D&#237;a de la semana, valor entre 1 y 7.
57. * \param mth Mes, valor entre 1 y 12.
58. * \param year A&#241;o, valor entre 00 y 99.
59. * \param dow Fecha, valor entre 1 y 31
60. * \param hr Hora, Seg&#250;n como se env&#237;e el dato puede ser entre 1
y 12 o 0 y 23. El &#250;ltimo nuestro caso.
61. * \param min Minutos, valor entre 0 y 59.
62. * \param sec Segundos, directamente se env&#237;a 0.
63. */
64. void set_datetime( unsigned char day, unsigned char mth,
65. unsigned char year, unsigned char
dow,
66. unsigned char hr, unsigned min);
67.
68. /** \brief Funciones que realizan la lectura del DS1302 seg&#250;n el
dato pedido.
69. */
70. unsigned char get_day();
71. unsigned char get_mth();
72. unsigned char get_year();
73. unsigned char get_dow();
74. unsigned char get_hr();
75. unsigned char get_min();
76. unsigned char get_sec();
Autor: Suky Web:www.infopic.comlu.com

77.
78. /** \brief Demora que se necesita realizar en nuestro main, que
depender&#225; del oscilador que se este usando.
79. */
80. extern void Delay_2us(void);
81. #endif

Luego queda crear el cdigo de nuestra librera, esto se puede hacer creando un archivo para cada funcin
como lo realiza Microchip o uno solo que contenga todas las funciones. En nuestro caso hacemos este ultimo
caso, donde al principio se debe invocar el archivo .h que contiene las definiciones:
1. #include <ds1302.h>
2.
3. void write_byte(unsigned char Byte){
4. unsigned char i;
5. TrisIO=0;
6. for(i=0;i<=7;++i){
7. IO=Byte&0x01;
8. Byte>>=1;
9. SCLK=1;
10. SCLK=0;
11. }
12. }
13.
14. void write_ds1302(unsigned char Byte, unsigned char Data){
15.
16. RST=1;
17. write_byte(Byte);
18. write_byte(Data);
19. RST=0;
20. }
21.
22. unsigned char read_ds1302(unsigned char Byte){
23. unsigned char i,Data;
24.
25. TrisSCLK=0;
26. TrisRST=0;
27. RST=1;
28. write_byte(Byte);
29. TrisIO=1;
30. Nop();
31. Data=0;
32. for(i=0;i<=6;i++){
33. if(IO==1){Data+=0x80;}
34. Data>>=1;
35. SCLK=1;
36. Delay_2us(); //2us
37. SCLK=0;
38. Delay_2us(); //2us
39. }
40. RST=0;
41. return(Data);
42. }
43.
44. void ds1302_init(void){
45. unsigned char j;
46.
Autor: Suky Web:www.infopic.comlu.com

47. TrisSCLK=0;
48. TrisIO=0;
49. TrisRST=0;
50.
51. RST=0;
52. Delay_2us(); //2us
53. SCLK=0;
54. write_ds1302(0x8E,0);
55. write_ds1302(0x90,0xA4);
56. j=read_ds1302(0x81);
57. if((j & 0x80)!=0){
58. write_ds1302(0x80,0);
59. }
60. }
61.
62. unsigned char get_bcd(unsigned char Data){
63. unsigned char NibleH,NibleL;
64. NibleH=Data/10;
65. NibleL=Data-(NibleH*10);
66. NibleH<<=4;
67. return(NibleH|NibleL);
68. }
69.
70. unsigned char rm_bcd(unsigned char Data){
71. unsigned char i;
72. i=Data;
73. Data=(i>>4)*10;
74. Data=Data+(i<<4>>4);
75. return(Data);
76. }
77.
78. void set_datetime(unsigned char day, unsigned char mth,
79. unsigned char year, unsigned char
dow,
80. unsigned char hr, unsigned min){
81. TrisSCLK=0;
82. TrisRST=0;
83.
84. write_ds1302(0x86,get_bcd(day));
85. write_ds1302(0x88,get_bcd(mth));
86. write_ds1302(0x8C,get_bcd(year));
87. write_ds1302(0x8A,get_bcd(dow));
88. write_ds1302(0x84,get_bcd(hr));
89. write_ds1302(0x82,get_bcd(min));
90. write_ds1302(0x80,get_bcd(0));
91. }
92.
93. unsigned char get_day() {
94. return(rm_bcd(read_ds1302(0x87)));
95. }
96. unsigned char get_mth(){
97. return(rm_bcd(read_ds1302(0x89)));
98. }
99. unsigned char get_year(){
100. return(rm_bcd(read_ds1302(0x8D)));
101. }
102. unsigned char get_dow(){
103. return(rm_bcd(read_ds1302(0x8B)));
104. }
105. unsigned char get_hr(){
106. return(rm_bcd(read_ds1302(0x85)));
Autor: Suky Web:www.infopic.comlu.com

107. }
108. unsigned char get_min(){
109. return(rm_bcd(read_ds1302(0x83)));
110. }
111. unsigned char get_sec(){
112. return(rm_bcd(read_ds1302(0x81)));
113. }
Estos 2 archivos los podemos colocar en el directorio de nuestro proyecto, o crear una carpeta especial para
ir almacenando nuestras libreras, lo nico que se debe hacer es en Project -> Build Options -> Project, en la
solapa Directories-> Include Search Path indicar la direccin de donde esta ubicada, y agregar ambos (*.h y
*.c) a nuestro proyecto para que realice la compilacin correspondiente.
Uso de timers 0
Objetivo: Crear un Reloj/Calendario usando el DS1302 y LCD, para ello utilizaremos la librera creada, y
para la actualizacin de los datos la interrupcin por desbordamiento del Timer0 cada 1 segundo.

Hardware:

Configuracin de los Timers

Para determinar las funciones y parmetros que necesitamos para configurar el Timer seleccionado vamos a
C:\MCC18\doc\periph-lib y abrimos Timer.
All debemos fijarnos, como venimos haciendo, en que grupo de funciones entra nuestro PIC en la primer
tabla del documento, para el PIC18F2550 es TMR_V2.

Las funciones que disponemos son:
Open_TimerX: Configura y habilita el Timer.
Close_TimerX: Deshabilita el Timer.
Write_TimerX: Escribe un valor en el TimerX.
Autor: Suky Web:www.infopic.comlu.com

Read_TimerX: Realiza una lectura del TimerX.
SetTmrCCPSrc: Configura el Timer para ser utilizado por algn Mdulo CCP.

Ejemplo:
Open_Timer0(unsigned char config)
Configuracin de Interrupcin:
TIMER_INT_ON Interrupcin habilitada
TIMER_INT_OFF Interrupcin deshabilitada
Seleccin entre modo de 8 o 16 bits:
T0_8BIT Modo 8 bits
T0_16BIT Modo 16 bits
Fuente del Clock:
T0_SOURCE_EXT Clock externo (I/O pin)
T0_SOURCE_INT Clock interno (Tosc)
Para Clock externo, Seleccin de flanco:
T0_EDGE_FALL Flanco descendente
T0_EDGE_RISE Flanco ascendente
Valor de Preescaler:
T0_PS_1_1 1:1 prescale
T0_PS_1_2 1:2 prescale
T0_PS_1_4 1:4 prescale
T0_PS_1_8 1:8 prescale
T0_PS_1_16 1:16 prescale
T0_PS_1_32 1:32 prescale
T0_PS_1_64 1:64 prescale
T0_PS_1_128 1:128 prescale
T0_PS_1_256 1:256 prescale

En nuestro caso necesitamos realizar una interrupcin cada 1 segundo para el refresco de los datos en el LCD,
para ello configuramos el Timer0 en Modo 16 bits, Clock interno, Preescaler 1:16 y habilitacin de la
interrupcin:
OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_16);

Y para lograr una interrupcin cada 1 segundo se debe setear el timer en 3036, calculado para oscilador de
4MHz:
WriteTimer0(3036);

Nota: Se puede ver claramente que el cdigo de actualizacin de datos en pantalla puede hacerse mucho mas
eficiente, actualizando solo parte segn sean los datos recibidos, pero solo es un ejemplo de forma de uso.



Autor: Suky Web:www.infopic.comlu.com

1. #include <p18f2550.h>
2. #include <delays.h>
3. #include <xlcd.h>
4. #include <ds1302.h>
5. #include <stdlib.h> //Libreria para conversiones.
6. #include <timers.h>
7.
8. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
9. #pragma config PWRT = ON,BOR = OFF,BORV = 0
10. #pragma config WDT = OFF,WDTPS = 32768
11. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
12. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
13. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
14. #pragma config CPB = ON,CPD = ON
15. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
16. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
17. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
18. #pragma config EBTRB = ON
19.
20. unsigned char day,mth,year,dow,hour,min,sec; //variabes para ds1302
21.
22. //
23. void DelayFor18TCY(void);
24. void DelayPORXLCD(void);
25. void DelayXLCD(void);
26. void comandXLCD(unsigned char a);
27. void gotoxyXLCD(unsigned char x, unsigned char y);
28. void printDate(unsigned char day, unsigned char mth, unsigned char year);
29. void printTime(unsigned char hour, unsigned char min, unsigned char sec);
30. void get_date(void);
31. void get_time(void);
32. void Delay_2us(void);
33. void ISRTimer0(void);
34.
35.
36. // Creamos una nueva seccion de codigo a partir de la direccion 0x08.-
37. #pragma code Interrupcion = 0X0008
38. void VectorInterrupcion(void){
39. _asm goto ISRTimer0 _endasm
40. }
41. #pragma code // Cerramos seccion.-
42.
43. // Rutina de Interrupcion.-
44. // Esta interrupci&#243;n se ejecuta cada 1s.
45. #pragma interrupt ISRTimer0
46. void ISRTimer0(void){
47. if(INTCONbits.TMR0IF==1){
48. WriteTimer0(3036); // Cargamos nuevamente Timer0
para interrupci&#243;n cada 1seg.
49. get_date(); //Lee dia,mes,a&#241;o
50. get_time(); //lee hora,minuto,segundo
51. gotoxyXLCD(1,1);
52. printDate(dow,mth,year); //lcd
53. gotoxyXLCD(1,2);
54. printTime(hour,min,sec);
55. INTCONbits.TMR0IF=0; // Borramos bandera.-
56. }
57. }
58.
59.
Autor: Suky Web:www.infopic.comlu.com

60. //***********************************************************************
**
61. void main(void){
62.
63. ds1302_init(); //inicializa
ds1302.-
64. OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_16);
//Configuracion del Timer1
65. OpenXLCD(FOUR_BIT & LINES_5X7); // Iniciamos LCD.-
66. comandXLCD(0x06); // Nos aseguramos incremento de direccion,
display fijo
67.
68. comandXLCD(0x0C); // Encendemos LCD.-
69. putrsXLCD("Usando el ds1302");
70. gotoxyXLCD(1,2);
71. putrsXLCD("by Suky");
72. day=7; mth=8; year=9;dow=18;
73. hour=22; min=59;
74. set_datetime(day,mth,year,dow,hour,min);
75. Delay10KTCYx(100);
76. comandXLCD(1); // Borramos display
77.
78. WriteTimer0(3036); // Iniciando el Timer en 3036 logramos un
interrupci&#243;n cada 1s con 4MHz.
79. RCONbits.IPEN=0; // Deshabilitamos Prioridades
80. INTCONbits.PEIE=1; // Habilitamos interrupcion de
perifericos.-
81. INTCONbits.GIE=1; // Habilitamos interrupcion Global.
82.
83. while(1){
84. }
85. }
86.
87. //***********************************************************************
**
88. void DelayFor18TCY(void){
89. Delay10TCYx(2);
90. }
91. void DelayPORXLCD(void){
92. Delay1KTCYx(15);
93. }
94. void DelayXLCD(void){
95. Delay1KTCYx(2);
96. }
97.
98. // Envia comando al LCD
99. void comandXLCD(unsigned char a){
100. BusyXLCD();
101. WriteCmdXLCD(a);
102. }
103. // Ubica cursor en (x = Posicion en linea, y = n&#186; de linea)
104. void gotoxyXLCD(unsigned char x, unsigned char y){
105. unsigned char direccion;
106.
107. if(y != 1)
108. direccion = 0x40;
109. else
110. direccion=0;
111.
112. direccion += x-1;
113. comandXLCD(0x80 | direccion);
Autor: Suky Web:www.infopic.comlu.com

114. }
115. // Demora de 2us para DS1302.
116. void Delay_2us(void){
117. Nop();
118. Nop();
119. }
120. // Funcion que imprime la Fecha en el LCD. Toma los valores ingresados,
los convierte
121. // a string y los imprime. En el caso que sea menor a 10, se imprime un
"0" antes del valor.
122. void printDate(unsigned char dow, unsigned char mth, unsigned char year){
123. char String[4];
124.
125. putrsXLCD("Fecha:");
126. itoa(dow, String); // Convertimos entero a string.-
127. if(dow<10){putrsXLCD("0");}
128. putsXLCD(String);putrsXLCD("/");
129. itoa(mth, String); // Convertimos entero a string.-
130. if(mth<10){putrsXLCD("0");}
131. putsXLCD(String);putrsXLCD("/");
132. itoa(year, String); // Convertimos entero a string.-
133. if(year<10){putrsXLCD("0");}
134. putsXLCD(String);
135. }
136. // Funcion que imprime la Hora en el LCD. Toma los valores ingresados,
los convierte
137. // a string y los imprime. En el caso que sea menor a 10, se imprime un
"0" antes del valor.
138. void printTime(unsigned char hour, unsigned char min, unsigned char sec){
139. char String[4];
140.
141. putrsXLCD("Hora:");
142. itoa(hour, String); // Convertimos entero a string.-
143. if(hour<10){putrsXLCD("0");}
144. putsXLCD(String);putrsXLCD(":");
145. itoa(min, String); // Convertimos entero a string.-
146. if(min<10){putrsXLCD("0");}
147. putsXLCD(String);putrsXLCD(":");
148. itoa(sec, String); // Convertimos entero a string.-
149. if(sec<10){putrsXLCD("0");}
150. putsXLCD(String);
151. }
152. // Funcion que realiza la lectura del todos los datos de la Fecha.
153. void get_date(void){ //Lee dia,mes,a&#241;o
154. dow=get_dow();
155. mth=get_mth();
156. year=get_year();
157. dow=get_dow();
158. }
159. // Funcion que realiza la lectura del todos los datos de la Hora.
160. void get_time(void){ //lee hora,minuto,segundo
161. hour=get_hr();
162. min=get_min();
163. sec=get_sec();
164. }


Autor: Suky Web:www.infopic.comlu.com

Comunicacin I2C.

Para saber en que grupo de funciones cae nuestro PIC se debe ver la tabla en el documento I2C que
se encuentra en \MCC18\doc\periph-lib, en nuestro caso el PIC18F2550 es I2C_V1. Sabiendo esto,
podemos ver los parmetros de cada una de las funciones que utilizaremos:

OpenI2C( unsigned char sync_mode, unsigned char slew );

sync_mode

SLAVE_7 I2C Modo Esclavo, 7-bit de direccin
SLAVE_10 I2C Modo Esclavo, 10-bit de direccin
MASTER I2C Modo Maestro

slew
SLEW_OFF Slew rate deshabilitado para modo 100 kHz
SLEW_ON Slew rate habilitado para modo 400 kHz

Para configurar la velocidad, adems debemos cargar el registro SSPADD , que depender de la
velocidad del oscilador. Clock=Fosc/(4.(SSPADD + 1))

Objetivos: Lograr comunicarnos con una memoria serial 24LC512 mediante el protocolo I2C. En
este primer ejemplo vamos a recibir un dato desde PC, lo guardaremos en la memoria y luego de un
tiempito realizaremos la lectura de la memoria reenvindolo a la PC.

Escritura de byte.
Luego de la condicin de inicio del Master, el cdigo de control (cuatro bits), los bits de seleccin de
chip (tres bits) y el bit de R / W (que es un 0) son registrados en el bus por el transmisor. Esto
indica al esclavo direccionado que el byte de direccin superior seguir despus de que se haya
generado un bit de reconocimiento durante el noveno ciclo de reloj. Por lo tanto, el prximo byte
transmitido por el Master es el byte alto de la direccin de la palabra. El prximo es el byte de
direccin menos significativo. Despus de recibir otra seal de reconocimiento del 24XX512, el
Master transmitir el dato a ser escrito en la ubicacin de memoria direccionada. El 24XX512
reconoce otra vez y el Master genera un condicin de alto. Esto inicia el ciclo de escritura interno y
durante esta vez, el 24XX512 no generar seales de reconocimiento (Figura). Despus de un byte de
comando de escritura, el contador de direccin interno apuntar a la ubicacin de direccin
siguiente.


Operacin de lectura
Las operaciones de lectura son iniciadas del mismo modo como las operaciones de escritura, con la
excepcin de que la parte de R / W del byte de control es puesta a "1". Hay tres tipos bsicos de las
operaciones de lectura: la lectura de direccin en curso, lectura aleatoria y lectura secuencial.
Autor: Suky Web:www.infopic.comlu.com


Lectura aleatoria
Las operaciones de lectura aleatorias permiten que el Master acceda a cualquier ubicacin de la
memoria en una manera aleatoria. Para llevar a cabo este tipo de operacin de lectura, la direccin
del dato a leer debe ser enviada primero. Esto se hace enviando la direccin del dato como una
operacin de escritura (R/ W a "0"). En cuanto la direccin del dato es enviada, el Master genera una
de condicin de inicio seguida al reconocimiento. El Master enva el byte de control otra vez, pero
con el bit de R / W en 1.


Hardware:


1. #include <p18f2550.h>
2. #include <delays.h>
3. #include <usart.h>
4. #include <i2c.h>
5.
6. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
7. #pragma config PWRT = ON,BOR = OFF,BORV = 0
8. #pragma config WDT = OFF,WDTPS = 32768
9. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
10. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
11. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
12. #pragma config CPB = ON,CPD = ON
13. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
14. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
Autor: Suky Web:www.infopic.comlu.com

15. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
16. #pragma config EBTRB = ON
17.
18. //**************************************************************
19. volatile char Data, Kbhit;
20.
21.
22. void ISRRecepcion(void);
23. void ByteWriteI2C( unsigned char ByteControl, unsigned char
HighDireccion,
24. unsigned char LowDireccion,
unsigned char DataI2C );
25. unsigned char ByteReadI2C( unsigned char ByteControl, unsigned char
HighDireccion,
26. unsigned char
LowDireccion );
27.
28.
29. // Creamos una nueva seccion de codigo a partir de la direccion 0x08.-
30. #pragma code Interrupcion = 0X0008
31. void VectorInterrupcion(void){
32. _asm goto ISRRecepcion _endasm
33. }
34. #pragma code // Cerramos seccion.-
35.
36. // Rutina de Interrupcion.-
37. #pragma interrupt ISRRecepcion
38. void ISRRecepcion(void){
39. if(PIR1bits.RCIF==1){
40. Data=getcUSART(); // Leemos Dato recibido
41. Kbhit=1; // Indicamos que se ha
recibido un dato.-
42. PIR1bits.RCIF=0; // Borramos bandera.-
43. }
44. }
45.
46.
47. void main(void){
48.
49. OpenUSART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE
& USART_EIGHT_BIT &
50. USART_CONT_RX & USART_BRGH_HIGH,25); // 9600,8,n,1
51. OpenI2C(MASTER,SLEW_OFF); //Master, 100KHz
52. SSPADD = 9;//100KHz para 4MHz
53.
54. Kbhit=0;
55. RCONbits.IPEN=0; // Deshabilitamos Prioridades
56. INTCONbits.PEIE=1; // Habilitamos interrupcion de
perifericos.-
57. INTCONbits.GIE=1; // Habilitamos interrupcion Global.
58.
59. putrsUSART("Prueba Comunicacion I2C con memoria 24LC512 \r\r");
60. while(1){
61. while(Kbhit==0){}; // esperamos a recibir dato.-
62. Kbhit=0;
63. ByteWriteI2C(0xA0,0x00,0x00,Data);
64. Delay1KTCYx(5);
65. putrsUSART("Lectura de Eeprom: \r");
66. putcUSART(ByteReadI2C(0xA0,0x00,0x00));
67. putrsUSART("\r");
68. }
Autor: Suky Web:www.infopic.comlu.com

69. }
70.
71. //***********************************************************************
***********
72.
73. void ByteWriteI2C( unsigned char ByteControl, unsigned char
HighDireccion,
74. unsigned char LowDireccion,
unsigned char DataI2C )
75. {
76. IdleI2C(); // El modulo esta activo?
77. StartI2C(); // Condicion de START
78. while ( SSPCON2bits.SEN );
79. WriteI2C( ByteControl ); // Envia Byte de control
80. WriteI2C( HighDireccion );
81. WriteI2C( LowDireccion );
82. WriteI2C ( DataI2C ); // Guarda Data en Eeprom en la
direcci&#243;n establecida.
83. StopI2C(); // Condicion de STOP
84. while ( SSPCON2bits.PEN );
85. while (EEAckPolling(ByteControl)); //Espera que se complete
escritura.
86. }
87.
88. unsigned char ByteReadI2C( unsigned char ByteControl, unsigned char
HighDireccion,
89. unsigned char
LowDireccion )
90. {
91. unsigned char Valor;
92.
93. IdleI2C(); // El modulo esta activo?
94. StartI2C(); // Condicion de START
95. while ( SSPCON2bits.SEN );
96. WriteI2C( ByteControl );
97. WriteI2C( HighDireccion );
98. WriteI2C( LowDireccion );
99. RestartI2C(); // Envia ReStart
100. while ( SSPCON2bits.RSEN );
101. WriteI2C( ByteControl | 0x01 ); // Cambia bit0 de ByteControl a 1
para realizar lectura.
102. Valor=ReadI2C(); // Realiza lectura.
103. NotAckI2C(); // Envia NACK
104. while ( SSPCON2bits.ACKEN );
105. StopI2C(); // Condicion de STOP
106. while ( SSPCON2bits.PEN );
107. return ( Valor ); // Retorna Lectura
108. }

Ejemplo, escribiendo y leyendo la letra v en la direccin 0x0000.



Autor: Suky Web:www.infopic.comlu.com

Segundo ejemplo de comunicacin con memoria 24LC512 mediante I2C.

En este caso vamos a recibir desde la PC un string, que guardaremos en la memoria y luego leeremos
para reenviar a la PC. Utilizaremos escritura secuencial y lectura secuencial:

Proceso de escritura. En este caso vamos a enviar un buffer directamente a la memoria, para
ello enviaremos la direccin del primer Byte a enviar como se ha realizado en el caso anterior, y
luego el buffer completo aprovechando que al realizar una escritura, el contador de direccin interno
apuntar a la ubicacin de direccin siguiente. La cantidad mxima de datos que podemos enviar de
esta manera depender de la memoria utilizada, en nuestro caso la 24LC512 tiene pginas de 128
bytes.


Lectura secuencial
Las lecturas secunciales son iniciadas del mismo modo como una lectura aleatoria excepto que
despus de que la 24LC512 transmite el primer byte de datos, el Master enva un reconocimiento.
Este ack ordena a la memoria transmitir la prxima palabra de 8 bits secuencialmente direccionada
(Figura). Cuando se recibe el ltimo dato, el Master no generar un ack, pero generar una condicin
de alto. Para proveer las lecturas secunciales, la memoria contiene un puntero de direccin interno
que es incrementado en uno en la terminacin de cada operacin.


1. #include <p18f2550.h>
2. #include <delays.h>
3. #include <usart.h>
4. #include <i2c.h>
5.
6. #pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
7. #pragma config PWRT = ON,BOR = OFF,BORV = 0
8. #pragma config WDT = OFF,WDTPS = 32768
9. #pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
10. #pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
11. #pragma config CP0 = ON,CP1 = ON,CP2 = ON
12. #pragma config CPB = ON,CPD = ON
13. #pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
14. #pragma config WRTB = ON,WRTC = ON,WRTD = ON
15. #pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
16. #pragma config EBTRB = ON
Autor: Suky Web:www.infopic.comlu.com

17.
18. //****************************************************************
19. volatile unsigned char Kbhit;
20. volatile unsigned char BufferE[19];
21. unsigned char BufferL[19];
22.
23. void ISRRecepcion(void);
24. void BufferWriteI2C( unsigned char ByteControl, unsigned char
HighDireccion,
25. unsigned char LowDireccion,
unsigned char *DataI2C );
26. void BufferReadI2C( unsigned char ByteControl, unsigned char
HighDireccion,
27. unsigned char LowDireccion,
unsigned char *Valor, unsigned char Lengh );
28.
29.
30. // Creamos una nueva seccion de codigo a partir de la direccion 0x08.-
31. #pragma code Interrupcion = 0X0008
32. void VectorInterrupcion(void){
33. _asm goto ISRRecepcion _endasm
34. }
35. #pragma code // Cerramos seccion.-
36.
37. // Rutina de Interrupcion.-
38. #pragma interrupt ISRRecepcion
39. void ISRRecepcion(void){
40. if(PIR1bits.RCIF==1){
41. getsUSART(BufferE,19); // recibimos 19 caracteres.-
42. Kbhit=1; // Indicamos que se ha
recibido un dato.-
43. PIR1bits.RCIF=0; // Borramos bandera.-
44. }
45. }
46.
47.
48. void main(void){
49. unsigned char i;
50.
51. OpenUSART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE
& USART_EIGHT_BIT &
52. USART_CONT_RX & USART_BRGH_HIGH,25); // 9600,8,n,1
53. OpenI2C(MASTER,SLEW_OFF); //Master
54. SSPADD = 9;//100KHz para 4MHz
55.
56. Kbhit=0;
57. RCONbits.IPEN=0; // Deshabilitamos Prioridades
58. INTCONbits.PEIE=1; // Habilitamos interrupcion de
perifericos.-
59. INTCONbits.GIE=1; // Habilitamos interrupcion Global.
60.
61. putrsUSART("Prueba Comunicacion I2C con memoria 24LC512 \r\r");
62. while(1){
63. while(Kbhit==0){}; // esperamos a recibir dato.-
64. Kbhit=0;
65. BufferWriteI2C(0xA0,0x00,0x00,BufferE); //Se guarda en
memoria los datos recibidos.
66. Delay1KTCYx(5);
67. BufferReadI2C(0xA0,0x00,0x00,BufferL,19);// Leemos de la
memoria los datos guardados.-
68. putrsUSART("Lectura de Eeprom: \r");
Autor: Suky Web:www.infopic.comlu.com

69. putsUSART(BufferL); putrsUSART("\r");
70. }
71. }
72. //***********************************************************************
***********************
73. void BufferWriteI2C( unsigned char ByteControl, unsigned char
HighDireccion, unsigned char LowDireccion,
74. unsigned char *BufferData)
75. {
76. IdleI2C(); // El modulo esta activo?
77. StartI2C(); // Condicion de START
78. while ( SSPCON2bits.SEN );
79. WriteI2C( ByteControl ); // Envia Byte de control
80. WriteI2C( HighDireccion );
81. WriteI2C( LowDireccion );
82. putsI2C(BufferData); // Enviamos buffer a
memoria.
83. StopI2C(); // Condicion de STOP
84. while ( SSPCON2bits.PEN );
85. while (EEAckPolling(ByteControl)); //Espera que se complete
escritura.
86. }
87.
88. void BufferReadI2C( unsigned char ByteControl, unsigned char
HighDireccion, unsigned char LowDireccion,
89. unsigned char *Valor, unsigned
char Lengh )
90. {
91. IdleI2C(); // El modulo esta activo?
92. StartI2C(); // Condicion de START
93. while ( SSPCON2bits.SEN );
94. WriteI2C( ByteControl );
95. WriteI2C( HighDireccion );
96. WriteI2C( LowDireccion );
97. RestartI2C(); // Envia ReStart
98. while ( SSPCON2bits.RSEN );
99. WriteI2C( ByteControl | 0x01 ); // Cambia bit0 de ByteControl a 1
para realizar lectura.
100. getsI2C(Valor,Lengh); // Realiza lectura de
cantidad=Lengh Datos.
101. NotAckI2C(); // Envia NACK
102. while ( SSPCON2bits.ACKEN );
103. StopI2C(); // Condicion de STOP
104. while ( SSPCON2bits.PEN );
105. }

Ejemplo de grabacin:




Autor: Suky Web:www.infopic.comlu.com

Punteros

Un apuntador o puntero es una variable de 16 bits que contiene una direccin. As si Data en un char
y ptr es un puntero que apunta a l tendremos lo siguiente:


Definicin:
1. char *ptr; // Declaraci&#243;n de una variable puntero a una variable char.
2. int *ptr; // Declaraci&#243;n de una variable puntero a una variable int.
3. unsigned char *ptr; //Declaraci&#243;n de una variable puntero a una
variable unsigned char.

Operadores unitarios:
&: Operador de direccin.
Da la direccin de una variable, por lo que la expresin ptr=&Data asigna la direccin de Data a ptr,
dicindose entonces que ptr apunta a Data.
*: Operador de indireccin.
Da acceso a la variable que apunta el apuntador. Por ejemplo la expresin *ptr=0xAA asigna a la
variable que apunta prt el valor 0xAA, sea Data=0xAA.-
Algunos ejemplos:
1. Data1= *ptr + 10; // A lo que apunta ptr se le suma 10 y se le asigna a
Data1.-
2. (*ptr)++; // Se incrementa en 1 lo que apunta ptr.-
3. *ptr++; // Se incrementa el puntero a la siguiente direcci&#243;n de
variable(Depender&#225; que tipo de variable se apunta)
4. ++*ptr; // Se incrementa en 1 lo que apunta ptr.-
5. ptr2=ptr; // se asigna al segundo puntero lo que apunta ptr. &#211;sea los
2 punteros apuntan a la misma variable.-


Punteros y arreglos:
Si declaramos un arreglo como:
char Datos[10];

Declaramos un ptr:
char *ptr;

Podemos asignar al puntero la primer posicin del arreglo:
ptr=& Datos[0];

Y podemos cargar a Datos[0] y Datos[5] de la siguiente manera:
*ptr=0xAA;
*(ptr+5)=0x48;

Cargar un buffer dentro de otro:
Autor: Suky Web:www.infopic.comlu.com

unsigned int *ptr,*ptr2;
unsigned int Datos01[20], Datos02[5]={0xFFAA,0xCC45,0x7895,0x3568,0xCC21};

ptr=&Datos01[8]; // Vamos a cargar en el arreglo 1 a partir de la posicin 8.-
for(ptr2=Datos02;ptr2<Datos02+5;ptr2++,ptr++){
*ptr=*ptr2;
}


Punteros y funciones.

En C los argumentos de las funciones se pasan por valor, as que no debera de ser posible en una
funcin modificar variables de la funcin que la llama. Digo debera porque pruebas hechas en C18
si lo permite Grin pero vamos a tratar C convencional para que sirva para otras compiladores.-

Usemos el ejemplo convencional para mostrar esto, por ejemplo si queremos reorganizar variables:

Forma incorrecta:
1. void funcion(void){
2. char a,b;
3. a=10;
4. b=15;
5. swap(a,b);
6. }
7. void swap(char q,char p){
8. char temp;
9. temp=q;
10. q=p;
11. p=temp;
12. }

Como vemos estamos modificando variables de la funcin que llama a swap. La forma correcta es
hacerlo por pasaje de referencia, sea le entregamos a la funcin swap la direccin de las variables:
1. void funcion(void){
2. char a,b;
3. a=10;
4. b=15;
5. swap(&a,&b);
6. }
7. void swap(char *q,char *p){
8. char temp;
9. temp=*q;
10. *q=*p;
11. *p=temp;
12. }

Tambin el uso de punteros en argumentos de funciones nos es sumamente til para que una funcin
pueda retornar ms de una variable entregando por referencia un arreglo.

Por ejemplo en un arreglo colocamos el nombre de un archivo ms su extensin, y queremos una
funcin que separe en dos arreglos distintos el nombre y la extensin:
Autor: Suky Web:www.infopic.comlu.com

1. void funci&#243;n(void){
2. char NombreMasExt[13]= &#8221;Tutorial.pdf&#8221;;
3. char Nombre[9],Ext[4];
4.
5. separamos(NombreMasExt,Nombre,Ext);
6. }
7.
8. void separamos(char *ptr,char *nptr,char *eptr){
9.
10. do{
11. *nptr++=*ptr++;
12. }while(*ptr!=&#8217;.&#8217;); // Hasta que se direccione el
&#8220;.&#8221;
13. *nptr=&#8217;\0&#8217;; // Siempre que se trabaje con string se
debe indicar finalizaci&#243;n con &#8216;\0&#8217;
14. *ptr++; // Pasamos a direccionar la siguiente letra, despu&#233;s
de &#8220;.&#8221;
15. do{
16. *eptr++=*ptr++;
17. }while(*ptr!=&#8217;\0&#8217;);
18. *eptr=&#8217;\0&#8217;;
19. }

Nota: Cuando se trabaja con string se debe tener en cuenta una posicin que indica final del string
\0.

También podría gustarte