SlideShare una empresa de Scribd logo
1 de 47
Descargar para leer sin conexión
República Bolivariana de Venezuela
Universidad Nacional Experimental Politécnica
Antonio José de Sucre
Vicerrectorado Luís Caballero Mejías
Programación de proyectos básicos en
microcontroladores PIC18 usando lenguaje C
Prof. Alexis Cabello
Caracas, Marzo 2013
ÍNDICE GENERAL
Compilador MPLAB C para PIC18 1
1. Proyecto 1 7
1.1. Programa Proyecto1.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.3. Simulación en PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2. Proyecto 2 11
2.1. Programa Proyecto2.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3. Proyecto 3 12
3.1. Programa Proyecto3.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4. Proyecto 4 14
4.1. Programa Proyecto4.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.2. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5. Proyecto 5 15
5.1. Convertidor analógico a digital . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.2. Programa Proyecto5.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.3. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
6. Proyecto 6 21
6.1. Programa proyecto6.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
6.2. Diseño en PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
7. Proyecto 7 25
7.1. Temporizador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
7.2. Programa proyecto7.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
7.3. Diseño en PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
8. Proyecto 8 29
8.1. Módulo CCP (Captura, Comparador y PWM) . . . . . . . . . . . . . . . . . . . . . . . 29
8.2. Programa proyecto8.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
8.3. Diseño en PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Anexo A. Manejo de la pantalla LCD 34
Anexo B. Manejo del teclado matricial 42
UNEXPO-LCM
Índice de algoritmos
1. proyecto1.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2. continuación de proyecto1.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3. proyecto2.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4. proyecto3.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5. proyecto4.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
6. proyecto5.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
7. continuación proyecto5.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
8. proyecto6.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
9. continuación de proyecto6.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
10. proyecto7.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
11. continuación de proyecto7.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
12. proyecto8.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
13. Archivo de encabezado LCD.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
14. lcdio.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
15. continuación lcdio.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
16. continuación lcdio.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
17. kdbio.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
PROF. ALEXIS CABELLO PÁGINA: 3
UNEXPO-LCM
Compilador MPLAB C para PIC18
Los proyectos mostrados a continuación son desarrollados en lenguaje C y se utiliza el programa
MPLAB C18 de Microchip como compilador. Se utiliza la versión MPLAB C for PIC18 in LITE
mode, la cual puede descargarse de la pagina web de Microchip en la siguiente dirección: http:
//depositfiles.org/files/vq6czsahj
A continuación se explica como crear un proyecto con este compilador dentro del entorno MPLAB.
Lo primero que se debe crear es un Workspace, o espacio de trabajo, para lo cual se ingresa en el menú
Project y se selecciona Project Wizard, Figura 1
Figura 1: Project Wirzard
Esta opción me proporciona un ayudante, se selecciona siguiente y se siguen los siguientes pasos:
1. Seleccionar en Device el dispositivo con el cual se va a trabajar, en nuestro caso el PIC18F4550.
Figura 2
PROF. ALEXIS CABELLO PÁGINA: 1
UNEXPO-LCM
Figura 2: Seleccionar Dispositivo
2. Seleccionar C18 como la herramienta con la que se desea trabajar. Figura 3
Figura 3: Seleccionar Conjunto de Lenguajes
3. Seleccionar el nombre del proyecto y la carpeta donde se creara el proyecto. Figura 4
PROF. ALEXIS CABELLO PÁGINA: 2
UNEXPO-LCM
Figura 4: Directorio de Archivos
4. Se deben añadir los archivos existentes y que deseemos agregar al proyecto, sin embargo en este
momento no se tienen archivos existentes, por lo que este paso se puede obviar, y se termina con
la creación del Workspace.
5. Crear un archivo nuevo, para lo cual se ingresa a File y se selecciona la opción New, allí se obtiene
una ventana en blanco donde se escribe el programa y luego se guarda con extensión .C. Figura
5
PROF. ALEXIS CABELLO PÁGINA: 3
UNEXPO-LCM
Figura 5: Nuevo Documento
6. Una vez nalizado el programa se debe añadir el archivo al Workspace creado, para lo cual se
ingresa en el menú Project y se selecciona la opción Add Files to Project; Figura 6, donde se
debe seleccionar el directorio donde se están guardando los archivos, Figura 7
Figura 6: Añadir nuevo Documento al Workspace
PROF. ALEXIS CABELLO PÁGINA: 4
UNEXPO-LCM
Figura 7: Selección del archivo .C
7. Finalizado todos estos pasos, se procede a compilar nuestro proyecto, para lo cual se ingresa a
Project y se selecciona Build All. Figura 8
8. Como resultado de la compilación podemos observar los posibles errores de sintaxis en las lineas
de programación y si todo esta correcto se obtiene un mensaje de compilación exitosa como se
muestra en Figura 9
PROF. ALEXIS CABELLO PÁGINA: 5
UNEXPO-LCM
Figura 8: Compilación del Proyecto
Figura 9: Compilación Exitosa
PROF. ALEXIS CABELLO PÁGINA: 6
UNEXPO-LCM
Una vez compilado de forma exitosa, se generan dos tipos de archivos .COF y .HEX. El primero contiene
información que permite realizar una simulación a nivel de código fuente. El .HEX sólo contiene el
código de máquina que se descarga al microcontrolador para su ejecución.
1. Proyecto 1
El proyecto uno se basa en aprender a manejar la conguración de los puertos para encender 8 LED
de forma simultanea e intermitente por un tiempo indenido. Para crear este proyecto se utilizará el
entorno de desarrollo MPLAB de microchip y el compilador de lenguaje C de microchip MPLAB C18,
Luego que se haya realizado este paso se realizará el diseño del proyecto en el entorno de simulación
ISIS de PROTEUS, se utilizará éste programa para probar a nivel de simulación el funcionamiento del
proyecto.
1.1. Programa Proyecto1.c
Para comenzar se debe incluir los archivos de encabezado (.h) y se programan los bits de congura-
ción mediante la instrucción pragma. Esto se muestra en el listado 1. Mediante los bits de conguración
se programan ciertas funciones del PIC, como son el Watchdog, el reloj que utilizará el CPU, protección
del código, etc. En este caso, se utiliza un cristal de 20Hz como entrada del Oscilador entre los pines 9
y 10 del PIC. Estos 20Mhz se dividen entre 5 para generar los 4Mhz necesarios para el PLL interno del
PIC. Esto se indica en la linea 3 donde se congura PLLDIV con 5. El PLL multiplica esta frecuencia
por 24 para obtener 96Mz, los cuales se dividen entre 2 para generar en denitiva el reloj del CPU y
del modulo USB. Esto se indica en las lineas 4 y 5 congurando CPUDIV y USBDIV respectivamente.
Luego se indica la fuente de entrada del oscilador congurando FOSC con HSPLL_HS y por ultimo
se deshabilita el uso del watchdog (WDT) y la programación con voltaje bajo (LVP).
Listado 1 proyecto1.c
#include p18cxxx.h
#include delays.h
#pragma config PLLDIV = 5 // (20 MHz crystal)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS
#pragma config WDT = OFF
#pragma config LVP = OFF
Para inicializar el programa se conguran todos los puertos como salidas, haciendo uso de TRISA,
TRISB, TRISC y TRISD. Para que el usuario pueda observar el encendido y apagado de los LED
se llama a la librería de retardo Delay10KTCYx (n). esta librería de retardo es suministrada por el
compilador MPLAB C18, y permite generar un retardo total de 10.000 ciclos de instrucción por el
numero suministrado como parámetro (n  256).
PROF. ALEXIS CABELLO PÁGINA: 7
UNEXPO-LCM
De esta forma y con las especicaciones dadas, se elabora el programa que será grabado en nuestro
dispositivo como se observa en el listado 2
Listado 2 continuación de proyecto1.c
void main()
{
TRISA=TRISB=TRISC=TRISD = 0x00; // set direction to be output
ADCON1 |= 0x0F;//A/D port as Digital
do {
PORTD = 0x00; // Turn OFF LEDs on PORTD
Delay10KTCYx (250); // delay
PORTD = 0xFF; // Turn ON LEDs on PORTD
Delay10KTCYx (250); // delay
} while(1);
}
En el listado anterior se puede observar que se genera una salida de uno lógico por cada bit del
puerto D (PORTD), por un tiempo determinado para encender los diodos LED y posteriormente se
genera una salida con ceros lógicos para poder apagar los diodos LED.
1.2. Diseño en el PROTEUS
Para la realización del diseño lo primero que se debe hacer es colocar los distintos componentes en
la hoja de trabajo, para ello se selecciona el modo componentes que se muestra en la gura 10 y, luego
realizar una pulsación sobre el botón P de la ventana de componentes que se muestra en la gura 11
Figura 10: Modo Componentes
Figura 11: Selección de Botón P
Luego de activar el botón P se abre la ventana para la selección y edición del componente y
comprobar sus características; el dispositivo que se quiere utilizar, en nuestro caso el PIC18F4550, al
localizar el componente deseado se realiza una doble pulsación en él de tal forma que aparezca en la
ventana de componentes y librerías como se muestra en la gura 12
PROF. ALEXIS CABELLO PÁGINA: 8
UNEXPO-LCM
Figura 12: Selección del Componente
Para situar el componente en el esquema de trabajo solo debemos seleccionarlo de la lista, y hacer
una pulsación sobre la ventana de trabajo y se colocará el componente.
Luego se conectan LEDs al puerto D del PIC, es decir los pines 19 al 30. Los cuales corresponden
a los congurados como salida en el programa y como se puede observar en la gura 13. Para este
proyecto se utilizan 8 LEDs y 8 resistencias de 470 ohm dispuestas como se muestra en la gura 14,
Figura 13: Dispositivo PIC 18F4550
PROF. ALEXIS CABELLO PÁGINA: 9
UNEXPO-LCM
D4
R4
470
D3
R3
470
D2
R2
470
D1
R1
470
OSC1
VDD
R20
4.7k
R8
470
D7
R7
470
D6
R6
470
D5
R5
470
RA0/AN0
2
RA1/AN1
3
RA2/AN2/VREF-/CVREF
4
RA3/AN3/VREF+
5
RA4/T0CKI/C1OUT/RCV
6
RA5/AN4/SS/LVDIN/C2OUT
7
RA6/OSC2/CLKO
14
OSC1/CLKI
13
RB0/AN12/INT0/FLT0/SDI/SDA
33
RB1/AN10/INT1/SCK/SCL
34
RB2/AN8/INT2/VMO
35
RB3/AN9/CCP2/VPO
36
RB4/AN11/KBI0/CSSPP
37
RB5/KBI1/PGM
38
RB6/KBI2/PGC
39
RB7/KBI3/PGD
40
RC0/T1OSO/T1CKI
15
RC1/T1OSI/CCP2/UOE
16
RC2/CCP1/P1A
17
VUSB
18
RC4/D-/VM
23
RC5/D+/VP
24
RC6/TX/CK
25
RC7/RX/DT/SDO
26
RD0/SPP0
19
RD1/SPP1
20
RD2/SPP2
21
RD3/SPP3
22
RD4/SPP4
27
RD5/SPP5/P1B
28
RD6/SPP6/P1C
29
RD7/SPP7/P1D
30
RE0/AN5/CK1SPP
8
RE1/AN6/CK2SPP
9
RE2/AN7/OESPP
10
RE3/MCLR/VPP
1
U1
PIC18F4550
OSC2
D8
L7
L6
L5
L4
L3
L1
L2
L0
L0
L1
L2
L3
L4
L5
L6
L7
Figura 14: Diseño Final
1.3. Simulación en PROTEUS
Una vez terminado el diseño y generado el archivo Hex abrimos el Proteus y hacemos click sobre
el PIC para cargar el programa compilado, se hace click en Program File y se selecciona el archivo.
Una vez cargado el programa en la parte inferior vemos los botones que nos permitirán poder correr
el programa, si presionamos Play se observa el funcionamiento del programa tal como se muestra en
la gura 15
D4
R4
470
D3
R3
470
D2
R2
470
D1
R1
470
OSC1
VDD
R20
4.7k
R8
470
D7
R7
470
D6
R6
470
D5
R5
470
RA0/AN0
2
RA1/AN1
3
RA2/AN2/VREF-/CVREF
4
RA3/AN3/VREF+
5
RA4/T0CKI/C1OUT/RCV
6
RA5/AN4/SS/LVDIN/C2OUT
7
RA6/OSC2/CLKO
14
OSC1/CLKI
13
RB0/AN12/INT0/FLT0/SDI/SDA
33
RB1/AN10/INT1/SCK/SCL
34
RB2/AN8/INT2/VMO
35
RB3/AN9/CCP2/VPO
36
RB4/AN11/KBI0/CSSPP
37
RB5/KBI1/PGM
38
RB6/KBI2/PGC
39
RB7/KBI3/PGD
40
RC0/T1OSO/T1CKI
15
RC1/T1OSI/CCP2/UOE
16
RC2/CCP1/P1A
17
VUSB
18
RC4/D-/VM
23
RC5/D+/VP
24
RC6/TX/CK
25
RC7/RX/DT/SDO
26
RD0/SPP0
19
RD1/SPP1
20
RD2/SPP2
21
RD3/SPP3
22
RD4/SPP4
27
RD5/SPP5/P1B
28
RD6/SPP6/P1C
29
RD7/SPP7/P1D
30
RE0/AN5/CK1SPP
8
RE1/AN6/CK2SPP
9
RE2/AN7/OESPP
10
RE3/MCLR/VPP
1
U1
PIC18F4550
OSC2
D8
L7
L6
L5
L4
L3
L1
L2
L0
L0
L1
L2
L3
L4
L5
L6
L7
Figura 15: Funcionamiento del Proyecto 1
PROF. ALEXIS CABELLO PÁGINA: 10
UNEXPO-LCM
2. Proyecto 2
El proyecto dos consiste básicamente en la misma lógica y en el mismo diseño del proyecto uno, la
diferencia se encuentra en que en este proyecto no se encenderán todos los 8 LEDs de forma simultanea,
si no por el contrario de forma secuencial, por lo que el programa en C sera totalmente diferente, sin
embargo se mantiene el mismo diseño en el PROTEUS.
2.1. Programa Proyecto2.c
Para comenzar se debe incluir los archivos de encabezado (.h) y se programan los bits de congu-
ración mediante la instrucción pragma, como se explicó en el proyecto 1 y se muestran en el listado
1.
Para inicializar el programa se conguran todos los bits de PORTD como salida, haciendo uso de
TRISD. Para que el usuario pueda observar el encendido y apagado de los LEDs se llama a la librería
de retardo Delay10KTCYx (n); esta librería de retardo es suministrada por el compilador MPLAB
C18, y permite generar un retardo total de 10.000 ciclos de instrucción por el numero suministrado
como parámetro (n  256).
De esta forma y con las especicaciones dadas, se elabora el programa, quedando como se muestra
en el listado 3
Listado 3 proyecto2.c
void main()
{
unsigned char led=0;
TRISD = 0x00; // set direction to be output
ADCON1 |= 0x0F;//A/D port as digital
do {
PORTD=(1  led);
led++;
if(led==8) led=0;
Delay10KTCYx(100); // delay
PORTD=0x0;
Delay10KTCYx(100); // delay
}while(1);
}
En este caso se utiliza la variable LED, que se inicializa con 0. Esta variable indicará cuantas
veces se va a rotar de derecha a izquierda el número 1. De esta forma se logra encender un solo LED a
la vez de forma secuencial de derecha a izquierda y no de forma simultanea como se hizo en el proyecto
1. Para observarlo grácamente se muestra un ejemplo en la tabla 1, con la variable LED en 3.
La variable LED se incrementa en uno y se repite el proceso mientras no llegue a 8. Cuando la
variable LED llegue a 8, se cumple la condición y la inicializamos en 0 nuevamente.
2.2. Diseño en el PROTEUS
El diseño de este proyecto es básicamente el mismo utilizado en el proyecto 1, donde se conectan
PROF. ALEXIS CABELLO PÁGINA: 11
UNEXPO-LCM
Bit7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
0 0 0 0 0 0 0 1
Número antes de rotar.
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
0 0 0 0 1 0 0 0
Número después de rotar 3 veces a la izquierda. Se enciende el LED 3
Tabla 1: Ejemplo del LED a encender
8 LEDs al puerto D del PIC, es decir los pines 19 al 30. Los cuales corresponden a los congurados
como salida en el programa.
Al momento de compilar el programa en MPLAB, se obtiene el archivo .HEX, que se debe cargar
en el PIC18F4550 y al ejecutar la simulación, se observa cómo con el mismo diseño, los LEDs ahora
encienden uno por uno a la vez, como se muestra en la gura 16, así continuamente hasta llegar al
LED 8 y comienza nuevamente en el 1.
D4
R4
470
D3
R3
470
D2
R2
470
D1
R1
470
OSC1
VDD
R20
4.7k
R8
470
D7
R7
470
D6
R6
470
D5
R5
470
RA0/AN0
2
RA1/AN1
3
RA2/AN2/VREF-/CVREF
4
RA3/AN3/VREF+
5
RA4/T0CKI/C1OUT/RCV
6
RA5/AN4/SS/LVDIN/C2OUT
7
RA6/OSC2/CLKO
14
OSC1/CLKI
13
RB0/AN12/INT0/FLT0/SDI/SDA
33
RB1/AN10/INT1/SCK/SCL
34
RB2/AN8/INT2/VMO
35
RB3/AN9/CCP2/VPO
36
RB4/AN11/KBI0/CSSPP
37
RB5/KBI1/PGM
38
RB6/KBI2/PGC
39
RB7/KBI3/PGD
40
RC0/T1OSO/T1CKI
15
RC1/T1OSI/CCP2/UOE
16
RC2/CCP1/P1A
17
VUSB
18
RC4/D-/VM
23
RC5/D+/VP
24
RC6/TX/CK
25
RC7/RX/DT/SDO
26
RD0/SPP0
19
RD1/SPP1
20
RD2/SPP2
21
RD3/SPP3
22
RD4/SPP4
27
RD5/SPP5/P1B
28
RD6/SPP6/P1C
29
RD7/SPP7/P1D
30
RE0/AN5/CK1SPP
8
RE1/AN6/CK2SPP
9
RE2/AN7/OESPP
10
RE3/MCLR/VPP
1
U1
PIC18F4550
OSC2
D8
L7
L6
L5
L4
L3
L1
L2
L0
L0
L1
L2
L3
L4
L5
L6
L7
Figura 16: Encendido del LED 1
3. Proyecto 3
El proyecto 3 se enfoca en el uso de las funciones de manejo de una pantalla LCD mediante
la programación del PIC 18F4550 para mostrar cadenas de caracteres en las diferentes líneas de la
pantalla.
3.1. Programa Proyecto3.c
Para comenzar a realizar el programa en C, esta vez se necesitan una serie de funciones adicionales o
subrutinas, para poder trabajar con la pantalla LCD. Estas rutinas se describen en el Anexo A. Primero
se debe incluir los archivos de encabezado (.h) y se programan los bits de conguración mediante la
instrucción pragma, como se explicó en el proyecto 1 y se muestran en el listado 1. En este proyecto
PROF. ALEXIS CABELLO PÁGINA: 12
UNEXPO-LCM
se debe agregar el archivo de encabezado (lcd.h) para poder hacer uso de las funciones de manejo del
LCD.
Listado 4 proyecto3.c
#include lcd.h
CHAR buffer1[16]=HELLO WORLD;
CHAR buffer2[16]=Hola Mundo;
void main() {
ADCON1 |= 0x0F; //A/D port as digital
PORTC = TRISC = 0x00;
PORTB = TRISB = 0x00;
lcd_init();
lcd_clear();
lcd_display(1,1,buffer1);
lcd_display(2,3,buffer2);
for(;;);
}
3.2. Diseño en el PROTEUS
En el diseño de proteus se agrega la pantalla LCD (LM016L9) y se conectan los terminales de datos
al puerto B, los terminales de control al puerto E, los terminales de alimentación de VDD a 5V, VSS y
VEE a GND para obtener el mayor contraste. El diseño nal y la simulación del proyecto se muestra
en la gura 17.
RE2
RB4
RB5
RB6
RB7
RE0
VDD
RE1
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9
D1
8
D0
7
E
6
RW
5
RS
4
VSS
1
VDD
2
VEE
3
LCD2
LM016L
D4
R4
470
D3
R3
470
D2
R2
470
D1
R1
470
OSC1
VDD
R20
4.7k
R8
470
D7
R7
470
D6
R6
470
D5
R5
470
RA0/AN0
2
RA1/AN1
3
RA2/AN2/VREF-/CVREF
4
RA3/AN3/VREF+
5
RA4/T0CKI/C1OUT/RCV
6
RA5/AN4/SS/LVDIN/C2OUT
7
RA6/OSC2/CLKO
14
OSC1/CLKI
13
RB0/AN12/INT0/FLT0/SDI/SDA
33
RB1/AN10/INT1/SCK/SCL
34
RB2/AN8/INT2/VMO
35
RB3/AN9/CCP2/VPO
36
RB4/AN11/KBI0/CSSPP
37
RB5/KBI1/PGM
38
RB6/KBI2/PGC
39
RB7/KBI3/PGD
40
RC0/T1OSO/T1CKI
15
RC1/T1OSI/CCP2/UOE
16
RC2/CCP1/P1A
17
VUSB
18
RC4/D-/VM
23
RC5/D+/VP
24
RC6/TX/CK
25
RC7/RX/DT/SDO
26
RD0/SPP0
19
RD1/SPP1
20
RD2/SPP2
21
RD3/SPP3
22
RD4/SPP4
27
RD5/SPP5/P1B
28
RD6/SPP6/P1C
29
RD7/SPP7/P1D
30
RE0/AN5/CK1SPP
8
RE1/AN6/CK2SPP
9
RE2/AN7/OESPP
10
RE3/MCLR/VPP
1
U1
PIC18F4550
OSC2
D8
L7
L6
L5
L4
L3
L1
L2
L0
L0
L1
L2
L3
L4
L5
L6
L7
RB4
RB5
RB6
RB7
RE0
RE2
RE1
Figura 17: Diseño del Proyecto 3
PROF. ALEXIS CABELLO PÁGINA: 13
UNEXPO-LCM
4. Proyecto 4
El proyecto 4 se enfoca en el uso de las funciones de manejo de un teclado matricial de 4x3 mediante
la programación del PIC 18F4550. Se realiza un programa de prueba que muestra en una pantalla LCD
la tecla presionada.
4.1. Programa Proyecto4.c
Para comenzar a realizar el programa en C, esta vez se necesitan una serie de funciones adicionales
o subrutinas, para poder trabajar con el Teclado. Estas rutinas se describen en el Anexo B. En este
proyecto se debe agregar las declaraciones de las funciones del teclado para poder hacer uso de estas,
tal como se muestra en el listado 5
Listado 5 proyecto4.c
CHAR buf1[16]=KEYPAD TEST;
CHAR buf2[16]=KEY: ;
CHAR keycodes[17] = {0,’#’,’0’,’*’,’-’,’9’,’8’,’7’,
’-’,’6’,’5’,’4’,’-’,’3’,’2’,’1’,’-’};
unsigned short kp,ka,led=1,sw=1;
int delay=0;
char keypadread(void);
char scankey(void);
VOID main() {
ADCON1 |= 0x0F;
PORTA = TRISA = 0x00;
PORTB = TRISB = 0x00;
INTCON2 = ~0x80; //conecta las resistencias pull-up al puerto B
lcd_init();
lcd_clear();
lcd_display(1,1,buf1);
Delay10KTCYx(250);
lcd_clear();
lcd_display(1,1,buf2);
do
{
kp=0;
do
{
kp = keypadread(); // Store key code in kp variable
Delay10KTCYx(12);
}while (!kp);
ka=keycodes[kp];
if(ka==’#’  led0x80) led=led1;
if(ka==’*’  led0x01) led=led1;
PORTD=led;
lcd_clear();
lcd_display(1,1,buf2);
lcd_char(ka); // Print key ASCII value on LCD
} while (1);
}
PROF. ALEXIS CABELLO PÁGINA: 14
UNEXPO-LCM
Como se muestra en el listado 5, se utiliza la función keypadread para leer una tecla, la cual retorna
el código de la tecla presionada (1 a 12). Este código se utiliza como el indice de la tabla keycodes,
la cual guarda el carácter ASCII de la tecla presionada. Luego se utiliza ese carácter ASCII para
mostrarlo en la pantalla LCD.
4.2. Diseño en el PROTEUS
En el diseño de proteus se agrega la pantalla LCD (LM016L9) y un teclado matricial (KEYPAD).
A las líneas de entrada al microcontrolador (RB1-RB3) se agregan resistencias de 10k conectadas al
VCC (Pull-ups ), esto con el n de detectar niveles alto cuando ninguna tecla sea presionada. Esto
sólo se requiere a nivel de simulación en proteus, puesto que cuando se implementa físicamente con el
microcontrolador se pueden utilizar las resistencias pull-up internas del microcontrolador a través de
la instrucción (INTCON2 = ~0x80). El simulador no procesa correctamente esta instrucción. En la
gura 18 se muestra el diseño nal y una simulación del proyecto.
RE2
RB4
RB5
RB6
RB7
RE0
VDD
RE1
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9
D1
8
D0
7
E
6
RW
5
RS
4
VSS
1
VDD
2
VEE
3
LCD2
LM016L
D4R4
470
D3R3
470
D2R2
470
D1R1
470
OSC1
VDD
R20
4.7k
R8
470
D7R7
470
D6R6
470
D5R5
470
RA0/AN0
2
RA1/AN1
3
RA2/AN2/VREF-/CVREF
4
RA3/AN3/VREF+
5
RA4/T0CKI/C1OUT/RCV
6
RA5/AN4/SS/LVDIN/C2OUT
7
RA6/OSC2/CLKO
14
OSC1/CLKI
13
RB0/AN12/INT0/FLT0/SDI/SDA
33
RB1/AN10/INT1/SCK/SCL
34
RB2/AN8/INT2/VMO
35
RB3/AN9/CCP2/VPO
36
RB4/AN11/KBI0/CSSPP
37
RB5/KBI1/PGM
38
RB6/KBI2/PGC
39
RB7/KBI3/PGD
40
RC0/T1OSO/T1CKI
15
RC1/T1OSI/CCP2/UOE
16
RC2/CCP1/P1A
17
VUSB
18
RC4/D-/VM
23
RC5/D+/VP
24
RC6/TX/CK
25
RC7/RX/DT/SDO
26
RD0/SPP0
19
RD1/SPP1
20
RD2/SPP2
21
RD3/SPP3
22
RD4/SPP4
27
RD5/SPP5/P1B
28
RD6/SPP6/P1C
29
RD7/SPP7/P1D
30
RE0/AN5/CK1SPP
8
RE1/AN6/CK2SPP
9
RE2/AN7/OESPP
10
RE3/MCLR/VPP
1
U1
PIC18F4550
OSC2
D8
L7
L6
L5
L4
L3
L1
L2
L0
L0
L1
L2
L3
L4
L5
L6
L7
RB4
RB5
RB6
RB7
RE0
RE2
RE1
1 2 3
4 5 6
7 8 9
0 #
1
2
3
A
B
C
DRB4
RB5
RB6
RB7
RB3 RB2 RB1
RB1
RB2
RB3
R9
10k
R10
10k
R12
10k
Figura 18: Diseño del proyecto 4
5. Proyecto 5
En el proyecto 5 se utiliza el convertidor analógico a digital (ADC) del PIC 18F4550 para leer el
valor de tensión de una señal analógica y mostrar ese valor expresado en milivoltios por la pantalla
LCD. Se emplea un potenciómetro para generar una señal analógica que puede variar entre 0 y 5V, la
cual se conecta al canal cero (AN0) del Convertidor ADC.
5.1. Convertidor analógico a digital
En la gura 19 se muestra un esquema del convertidor analógico a digital (ADC) del PIC 18F4550.
Este módulo permite la conversión de una señal analógica a su correspondiente valor digital de 10 bits.
El ADC tiene 13 entradas multiplexadas o canales y el canal a convertir se selecciona por medio de los
bits CHS3-CHS0 del registro ADCON0 tal como se muestra en la gura 20.
PROF. ALEXIS CABELLO PÁGINA: 15
UNEXPO-LCM
Figura 19: Convertidor Analógico a Digital
Registro ADCON0
ADONGo/DoneCHS0CHS1CHS2CHS3----
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
ADONGo/DoneCHS0CHS1CHS2CHS3----
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
ADON: ADC On bit
0= Convertidor deshabilitado 1: Convertidor habilitado
Go/Done: Bit de estatus de la conversión
0=Conversión lista 1= conversión en progreso
CHS0-CHS3: Bits de selección del canal
0000= Canal 0 (AN0)
0001= Canal 1 (AN1)
0010= Canal 2 (AN2)
0011= Canal 3 (AN3)
0100= Canal 4 (AN4)
0101= Canal 5 (AN5)
0110= Canal 6 (AN6)
0111= Canal 7 (AN7)
1000= Canal 8 (AN8)
1001= Canal 9 (AN9)
1010= Canal 10 (AN10)
1011= Canal 11 (AN11)
1100= Canal 12 (AN12)
Figura 20: Registro ADCON0
PROF. ALEXIS CABELLO PÁGINA: 16
UNEXPO-LCM
Registro ADCON1
PCFG0PCFG1PCFG2PCFG3VCFG0VCFG1----
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
PCFG0PCFG1PCFG2PCFG3VCFG0VCFG1----
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
PCFG3-0: Bits de configuración de los puertos analógicos.
VCFG0: Bit de configuración del voltaje de referencia negativo VREF-
0=VSS 1=AN2
VCFG1: Bit de configuración del voltaje de referencia positivo VREF+
0=VDD 1=AN3
DDDDDDDDDDDDD1111
ADDDDDDDDDDDD1110
AADDDDDDDDDDD1101
AAADDDDDDDDDD1100
AAAADDDDDDDDD1011
AAAAADDDDDDDD1010
AAAAAADDDDDDD1001
AAAAAAADDDDDD1000
AAAAAAAADDDDD0111
AAAAAAAAADDDD0110
AAAAAAAAAADDD0101
AAAAAAAAAAADD0100
AAAAAAAAAAAAD0011
AAAAAAAAAAAAA0010
AAAAAAAAAAAAA0001
AAAAAAAAAAAAA0000
AN0AN1AN2AN3AN4AN5AN6AN7AN8AN9AN10AN11AN12PFCG3-PCFG0
DDDDDDDDDDDDD1111
ADDDDDDDDDDDD1110
AADDDDDDDDDDD1101
AAADDDDDDDDDD1100
AAAADDDDDDDDD1011
AAAAADDDDDDDD1010
AAAAAADDDDDDD1001
AAAAAAADDDDDD1000
AAAAAAAADDDDD0111
AAAAAAAAADDDD0110
AAAAAAAAAADDD0101
AAAAAAAAAAADD0100
AAAAAAAAAAAAD0011
AAAAAAAAAAAAA0010
AAAAAAAAAAAAA0001
AAAAAAAAAAAAA0000
AN0AN1AN2AN3AN4AN5AN6AN7AN8AN9AN10AN11AN12PFCG3-PCFG0
Figura 21: Registro ADCON1
D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
Go
TAD
Adquisición Conversión
TACQ
1
(Fosc/n)
TAD= n=2,4,8,16,32,64
TACQ= m*TAD m=0,2,4,6,8,12,16,20
Figura 22: Tiempo de adquisición-conversión
PROF. ALEXIS CABELLO PÁGINA: 17
UNEXPO-LCM
Registro ADCON2
ADCS0ADCS1ADCS2ACQT0ACQT1ACQT2--ADFM
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
ADCS0ADCS1ADCS2ACQT0ACQT1ACQT2--ADFM
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
ADCS2-ADCS0:
Reloj de Conversión del ADC
000= Fosc/2
001= Fosc/8
010= Fosc/32
011= FRC (Oscilador RC Interno)
100= Fosc/4
101= Fosc/16
110= Fosc/64
111= FRC (Oscilador RC Interno)
ADFM: Formato del Resultado del ADC
0 = Justificado a la Izquierda
1 = Justificado a la derecha
ACQT2-ACQT0:
Tiempo de adquisición del ADC
000= 0 Tad
001= 2 Tad
010= 4 Tad
011= 6 Tad
100= 8 Tad
101= 12 Tad
110= 16 Tad
111= 20 Tad
Figura 23: Registro ADCON2
ADRESL
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
ADRESL
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
ADRESH: Byte alto del resultado de la conversión
ADRESL: Byte bajo del resultado de la conversión
ADRESH
Bit 8Bit 9
ADRESH
Bit 8Bit 9
Figura 24: Resultado justicado a la derecha
PROF. ALEXIS CABELLO PÁGINA: 18
UNEXPO-LCM
En las guras 21 y 23 se muestran el resto de los registros donde se congura el funcionamiento
del ADC. En el registro ADCON1 se congura el voltaje de referencia positivo a VDD y el negativo
a GND, así como se denen los terminales analógicos y digitales, en éste proyecto se conguran los
terminales AN0-AN3 como analógicos y el resto digitales.
En el registro ADCON2 se congura el tiempo de la conversión según se muestra en la gura 22.
El tiempo de conversión de cada bit (TAD) mínimo debe ser 0.8us y el tiempo de adquisición (TACQ)
mínimo debe ser de 1.4us según la hoja de especicaciones. Como se utiliza una Fosc de 48MHz, se
utiliza el divisor de 64 y 4 TAD para el TACQ para satisfacer los requerimientos. El resultado de la
conversión se obtiene en los registros ADRESH y ADRESL, la cual puede ser ajustado a la derecha o
a la izquierda. En la gura 24 se muestra el resultado justicado a la derecha, la cual es la utilizada
en este proyecto. Los valores de los registros se pueden apreciar en el listado 7 donde se congura la
rutina de conversión del ADC.
5.2. Programa Proyecto5.c
El listado 6 muestra la rutina principal del proyecto y el listado 7 muestra la rutina para leer el
valor de la conversión. A esta última se debe pasar como parámetro el canal del ADC que se quiere
leer, en este proyecto se lee la señal analógica conectada al canal cero (AN0).
Para mostrar el valor correspondiente en milivoltios con dos dígitos decimales por el LCD, se realiza
la conversión mostrada en la ecuación 1:
volts =
n · 5000 mV
1024
× 100 (1)
donde: n es el valor del ADC (0-1023) que corresponde a (0-5v). Se multiplica por 100 para tomar
dos decimales de precisión.
Luego se toma la parte entera diviendo los voltios entre 100 y se toma el resto de la división como
la parte decimal, y nalmente se convierten estos valores en un cadena de caracteres ASCII para su
visualización en la pantalla LCD.
5.3. Diseño en el PROTEUS
En la gura 25 se muestra el diseño en proteus del proyecto 5. Se utiliza el proyecto 4 como base
y se agrega un potenciómetro para generar la señal analógica. El cursor del potenciómetro se conecta
al terminal AN0 del PIC. La gura muestra el cursor del potenciómetro en 50 %, lo que corresponde a
un valor de 2493.68 mV, el cual se observa en la pantalla LCD. Al variar el cursor del potenciómetro
se puede apreciar como se actualiza el valor medido en la pantalla LCD, funcionando el sistema como
un voltímetro digital.
PROF. ALEXIS CABELLO PÁGINA: 19
UNEXPO-LCM
Listado 6 proyecto5.c
#include p18cxxx.h
#include delays.h
#include stdlib.h
#include lcd.h
#pragma config PLLDIV = 5 // (20 MHz crystal)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS //HSPLL_HS
#pragma config WDT = OFF
#pragma config MCLRE = ON
#pragma config LVP = OFF
CHAR lcd[16];
CHAR msg[]=mV= ;
unsigned int Vin,Vdec,Vfrac;
unsigned long volts;
unsigned int adc_read(unsigned char ch);
unsigned char ch1,ch2;
VOID main() {
ADCON1 |= 0x0F;
PORTE = TRISE = 0x00;
PORTB = TRISB = 0x00;
lcd_init();
TRISAbits.TRISA0 = 1; //AN0
for(;;) // Endless loop
{
lcd_clear();
Vin = adc_read(0); // Read from channel 0 (AN0)
lcd_display(1,1,msg); // Display mV = 
volts=Vin;
volts = 488*volts; // Scale up the result
Vdec = volts / 100; // Decimal part
Vfrac = volts % 100; // Fractional part
itoa(Vdec,lcd); // Convert Vdec to string in lcd
// Display result on LCD
//
lcd_display(1,6,lcd); // Output to LCD
lcd_char(’.’); // Display .
ch1 = Vfrac / 10; // Calculate fractional part
ch2 = Vfrac % 10; // Calculate fractional part
lcd_char(48+ch1); // Display fractional part
lcd_char(48+ch2); // Display fractional part
Delay10KTCYx(250); // delay
Delay10KTCYx(250); // delay
}
}
PROF. ALEXIS CABELLO PÁGINA: 20
UNEXPO-LCM
Listado 7 continuación proyecto5.c
unsigned int adc_read(unsigned char ch)
{
unsigned int result;
ADCON0 = (ch  0x0F)  2;
ADCON1 = 0x0B; //RA0-RA3 Analog inputs.
ADCON2 = 0x96; // right justify,TACQ=4*TAD, TAD=1/(FOSC/64)
ADCON0bits.ADON = 1; // ADC on
ADCON0bits.GO_DONE = 1; // start
while (ADCON0bits.GO_DONE == 1);
result = ((unsigned int)(ADRESH)  8) + ADRESL;
ADCON0bits.ADON = 0; // ADC Off
return result;
}
50%
RV1
10k
VDD
AN0
AN0
RE2
RB4
RB5
RB6
RB7
RE0
VDD
RE1
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9
D1
8
D0
7
E
6
RW
5
RS
4
VSS
1
VDD
2
VEE
3
LCD2
LM016L
OSC1
VDD
R20
4.7k
RA0/AN0
2
RA1/AN1
3
RA2/AN2/VREF-/CVREF
4
RA3/AN3/VREF+
5
RA4/T0CKI/C1OUT/RCV
6
RA5/AN4/SS/LVDIN/C2OUT
7
RA6/OSC2/CLKO
14
OSC1/CLKI
13
RB0/AN12/INT0/FLT0/SDI/SDA
33
RB1/AN10/INT1/SCK/SCL
34
RB2/AN8/INT2/VMO
35
RB3/AN9/CCP2/VPO
36
RB4/AN11/KBI0/CSSPP
37
RB5/KBI1/PGM
38
RB6/KBI2/PGC
39
RB7/KBI3/PGD
40
RC0/T1OSO/T1CKI
15
RC1/T1OSI/CCP2/UOE
16
RC2/CCP1/P1A
17
VUSB
18
RC4/D-/VM
23
RC5/D+/VP
24
RC6/TX/CK
25
RC7/RX/DT/SDO
26
RD0/SPP0
19
RD1/SPP1
20
RD2/SPP2
21
RD3/SPP3
22
RD4/SPP4
27
RD5/SPP5/P1B
28
RD6/SPP6/P1C
29
RD7/SPP7/P1D
30
RE0/AN5/CK1SPP
8
RE1/AN6/CK2SPP
9
RE2/AN7/OESPP
10
RE3/MCLR/VPP
1
U1
PIC18F4550
OSC2
L7
L6
L5
L4
L3
L1
L2
L0
RB4
RB5
RB6
RB7
RE0
RE2
RE1
RB1
RB2
RB3
R9
10k
R10
10k
R12
10k
Figura 25: Diseño del proyecto 5
6. Proyecto 6
En el proyecto 6 se utilizan las interrupciones para realizar un reloj digital a partir de una fuente
de alimentación de corriente alterna de 60Hz. La fuente alterna alimenta un circuito que genera un
pulso por cada cruce por cero de la señal (detector de cruce por cero) y esta señal se utiliza como una
fuente de interrupción externa para el conteo del tiempo.
PROF. ALEXIS CABELLO PÁGINA: 21
UNEXPO-LCM
50%
RV1
10k
VDD
AN0
AN0
RE2
RB4
RB5
RB6
RB7
RE0
VDD
RE1
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9
D1
8
D0
7
E
6
RW
5
RS
4
VSS
1
VDD
2
VEE
3
LCD2
LM016L
OSC1
VDD
R20
4.7k
RA0/AN0
2
RA1/AN1
3
RA2/AN2/VREF-/CVREF
4
RA3/AN3/VREF+
5
RA4/T0CKI/C1OUT/RCV
6
RA5/AN4/SS/LVDIN/C2OUT
7
RA6/OSC2/CLKO
14
OSC1/CLKI
13
RB0/AN12/INT0/FLT0/SDI/SDA
33
RB1/AN10/INT1/SCK/SCL
34
RB2/AN8/INT2/VMO
35
RB3/AN9/CCP2/VPO
36
RB4/AN11/KBI0/CSSPP
37
RB5/KBI1/PGM
38
RB6/KBI2/PGC
39
RB7/KBI3/PGD
40
RC0/T1OSO/T1CKI
15
RC1/T1OSI/CCP2/UOE
16
RC2/CCP1/P1A
17
VUSB
18
RC4/D-/VM
23
RC5/D+/VP
24
RC6/TX/CK
25
RC7/RX/DT/SDO
26
RD0/SPP0
19
RD1/SPP1
20
RD2/SPP2
21
RD3/SPP3
22
RD4/SPP4
27
RD5/SPP5/P1B
28
RD6/SPP6/P1C
29
RD7/SPP7/P1D
30
RE0/AN5/CK1SPP
8
RE1/AN6/CK2SPP
9
RE2/AN7/OESPP
10
RE3/MCLR/VPP
1
U1
PIC18F4550
OSC2
L7
L6
L5
L4
L3
L1
L2
L0
RB4
RB5
RB6
RB7
RE0
RE2
RE1
RB1
RB2
RB3
R12
10k
R14
10k R13
10k
A
K
C
E
B
1
2 4
5
6
U2
4N25
R11
240
VDD
R10
10k
RB0
BR1
2W08G
V1
VSINE
VO=0
VA=20
FREQ=60
K
RB0
Figura 26: Diseño del proyecto 6
6.1. Programa proyecto6.c
En los listados 8 y 9 se muestra el programa del proyecto6. Lo importante a destacar es la declaración
de las interrupciones en el compilador MPLAB C18. En los microcontroladores 18F existen dos vectores
de interrupción, uno de alta prioridad y otro de baja prioridad. El vector de alta prioridad se encuentra
en la dirección 0x08h y el de baja prioridad en el la dirección 0x18h. El bit IPEN del registro RCON
habilita las prioridades de las interrupciones. Si el bit IPEN=0 como es por defecto no se utilizan las
prioridades de las interrupciones y todas utilizan el vector de interrupción de alta prioridad (0x08h).
En este proyecto no se utilizan las prioridades y se emplea la directiva #pragma code para escribir en
el vector de interrupción de alta prioridad el salto a la rutina de interrupción y se utiliza la directiva
#pragma interrupt para indicar cual es la rutina de interrupción.
Como la frecuencia de la fuente de alimentación es de 60Hz, el circuito detector de cruce por cero
genera 120 pulsos en un segundo. Por esto, en la rutina de interrupción se acumula cada vez que se
genera una interrupción y cuando se alcanza 120 se pone en cero y se empienza a incrementar los
segundos. Igualmente se procede con los segundos, cuando se alcanzan los 60 se pone en cero y se
empiezan a incrementar los minutos hasta alcanzar los 60 minutos donde se pone en cero y empieza
de nuevo el reloj.
En la rutina principal del programa se habilita la interrupción INT0 y luego en un bucle innito se
convierten constantemente los minutos y segundos a ASCII y se muestra en la pantalla LCD el tiempo.
6.2. Diseño en PROTEUS
En la Figura 26 se muestra el diseño en proteus. Para la simulación se emplea una fuente alterna
de 13Vac y el circuito detector de cruce por cero aislado del microcontrolador por medio de un opto-
acoplador 4N25, la señal de salida del detector (RB0) se conecta al terminal de interrupción externa
(INT0). En la simulación se muestra el reloj indicando que ha transcurrido 1 minuto y 06 segundos.
PROF. ALEXIS CABELLO PÁGINA: 22
UNEXPO-LCM
Listado 8 proyecto6.c
#include p18cxxx.h
#include delays.h
#include stdlib.h
#include lcd.h
#pragma config PLLDIV = 5 // (20 MHz crystal)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS //HSPLL_HS
#pragma config WDT = OFF
#pragma config LVP = OFF
unsigned char tick=0,seg=0,min=0;
unsigned char ch1,ch2;
CHAR lcd_seg[16];
CHAR lcd_min[16];
CHAR msg[16]=Time:;
void InterruptHandlerHigh (void);
//----------------------------------------------------------------------------
// High priority interrupt vector
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh (void)
{
_asm
goto InterruptHandlerHigh //jump to interrupt routine
_endasm
}
//----------------------------------------------------------------------------
// High priority interrupt routine
#pragma code
#pragma interrupt InterruptHandlerHigh
void InterruptHandlerHigh ()
{
if (INTCONbits.INT0IF == 1)
{
INTCONbits.INT0IF = 0;
tick++;
if(tick==120)
{
tick=0;
seg++;
}
if(seg==60)
{
seg=0;
min++;
}
if(min==60) min=0;
}
}
PROF. ALEXIS CABELLO PÁGINA: 23
UNEXPO-LCM
Listado 9 continuación de proyecto6.c
void main() {
TRISA=TRISB=TRISC=TRISD = 0x00; // set direction to be output
PORTD=0x0;
ADCON1 = 0x0F;
lcd_init();
TRISBbits.RB0=1;
INTCONbits.GIE = 1; //enable global interrupts
INTCONbits.PEIE = 1; //enable peripherical interrupts
INTCONbits.INT0IE =1; //enable INT0 Interrupt
lcd_clear();
lcd_display(1,1,msg);
do{
setpos(1,7);
ch1 = min / 10; // digit1
ch2 = min % 10; // digit2
lcd_char(48+ch1); // Display digit1
lcd_char(48+ch2); // Display digit2
lcd_char(’:’);
ch1 = seg / 10; // digit1
ch2 = seg % 10; // digit2
lcd_char(48+ch1); // Display digit1
lcd_char(48+ch2); // Display digit2
}while(1);
}
PROF. ALEXIS CABELLO PÁGINA: 24
UNEXPO-LCM
7. Proyecto 7
En el proyecto 7 se muestra el uso del temporizador del microcontrolador para tener un control
exacto del tiempo y así generar una señal cuadrada de 120Hz. El ciclo de trabajo de la señal cuadrada
generada es de 50 % pero cambiando el valor en una variable se puede cambiar el ancho de pulso o
ciclo de trabajo.
7.1. Temporizador
El microcontrolador PIC 18F4550 tiene cuatro temporizadores TIMER0-3. En el siguiente proyecto
utilizamos el TIMER2 que es básicamente un contador de 8 bits (TMR2) con un divisor de pre-escalado
y uno de pos-escalado. En la gura 27 se muestra el esquema del TIMER2.
Figura 27: Temporizador 2
El contador TMR2 incrementa desde cero hasta que es igual al valor del registro PR2. Este incre-
mento depende del valor del divisor del reloj o pre-escalado (PRESCALER), el cual puede ser 1, 4, o
16. Para jar el periodo del temporizador (PR2) se puede utilizar la ecuación 2
T = (PR2 + 1) ∗ 4 ∗
1
Fosc
∗ PRESCALER ∗ POSTSCALER (2)
donde:
Fosc es la la frecuencia del oscilador.
PRESCALER es el valor del divisor del oscilador a la entrada del temporizador.
POSTCALER es el valor del divisor de la señal de salida del temporizador.
T es el periodo de la señal a generar.
PR2 es el registro del periodo.
El valor del contador TMR2 se compara con el valor del registro PR2 en cada ciclo de reloj y cuando
el contador TMR2 es igual al registro PR2 el comparador produce una señal que va al contador de
pos-escalado y pone en cero el contador TMR2. Dependiendo del valor prejado de pos-escalado se
activa la bandera de interrupción TMR2IF que se encuentra en el registro PIR1. En este proyecto
como el pos-escalado es igual a 1, la interrupción se genera cuando el valor de TMR2 es igual al valor
de PR2. Para habilitar la interrupción del temporizador 2 se utiliza el bit TMR2IE del registro PIE1.
Los valores de pre-escalado y pos-escalado se conguran en el registro T2CON tal como se muestra en
la gura 28.
PROF. ALEXIS CABELLO PÁGINA: 25
UNEXPO-LCM
Registro T2CON
T2CKPS0T2CKPS1TMR2ONT2OUTPS0T2OUTPS1T2OUTPS0T2OUTPS3--
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
T2CKPS0T2CKPS1TMR2ONT2OUTPS0T2OUTPS1T2OUTPS0T2OUTPS3--
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
T2CKPS1-0: Pre-escalar del reloj del Timer 2
00= 1:1
01= 1:4
1x= 1:16
TMR2ON: Activación del Timer2
1=Activado (ON)
0= Desactivado (OFF)
T2OUTPS3-0: Post-escalar de la salida del Timer 2
0000= 1:1
0001= 1:2
.
.
1111= 1:16
Figura 28: Registro T2CON
7.2. Programa proyecto7.c
En los listados 10 y 11 se muestra el programa proyecto7.c. El periodo de la señal a generar (8.33ms)
se divide entre 512 y se utiliza el temporizador 2 para generar una interrupción cada 16.275us. Para
generar la señal cuadrada con 50 % de ciclo de trabajo lo primero que se hace es incrementar un
contador por cada interrupción y cuando alcanza el valor medio de 256 se pone en bajo la señal y
cuando alcanza el valor máximo de 512 se pone en cero el contador y se pone la señal en alto.
Listado 10 proyecto7.c
#include p18cxxx.h
#include delays.h
#include stdlib.h
#include lcd.h
#pragma config PLLDIV = 5 // (20 MHz crystal)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS //HSPLL_HS
#pragma config WDT = OFF
unsigned int count=0;
void initTimer (void);
void InterruptHandlerHigh (void);
PROF. ALEXIS CABELLO PÁGINA: 26
UNEXPO-LCM
Listado 11 continuación de proyecto7.c
// High priority interrupt vector
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh (void)
{
_asm
goto InterruptHandlerHigh //jump to interrupt routine
_endasm
}
// High priority interrupt routine
#pragma code
#pragma interrupt InterruptHandlerHigh
void InterruptHandlerHigh ()
{
if (PIR1bits.TMR2IF == 1)
{
PIR1bits.TMR2IF = 0;
count++;
if(count==256) PORTD=0;
if(count==512)
{
PORTD=0xFF;
count=0;
}
}
}
void main() {
TRISA=TRISB=TRISC=TRISD = 0x00; // set direction to be output
PORTD=0x0;
ADCON1 = 0x0F;
INTCONbits.GIE = 1; //enable global interrupts
INTCONbits.PEIE = 1; //enable peripherical interrupts
initTimer();
while(1);
}
void initTimer (void)
{
PR2 = 194; // T = (PR2+1) * 4 *(1/Fosc)*PRESCALER
// 16.25us= (PR2+1)* 4*(1/Fosc)*PRESCALER : Fosc=48Mhz : PRESCALER=1
T2CON=0;
T2CONbits.T2CKPS1 = 0;
T2CONbits.T2CKPS0 = 0; // 1:1 - prescaler
IPR1bits.TMR2IP = 1; // high priority
PIR1bits.TMR2IF = 0;
PIE1bits.TMR2IE = 1; //1=enable Interrupt
T2CONbits.TMR2ON = 1;
}
PROF. ALEXIS CABELLO PÁGINA: 27
UNEXPO-LCM
7.3. Diseño en PROTEUS
En la Figura 29 se muestra el diseño en proteus del proyecto 7, solamente se ha agregado el
osciloscopio para observar la señal cuadrada. Se conecta la salida RD0 del puerto D del PIC al canal
A del osciloscopio. En la Figura 30 se muestra la pantalla del osciloscopio, en la cual se puede apreciar
el periodo de la señal.
50%
RV1
10k
VDD
AN0
AN0
RE2
RB4
RB5
RB6
RB7
RE0
VDD
RE1
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9
D1
8
D0
7
E
6
RW
5
RS
4
VSS
1
VDD
2
VEE
3
LCD2
LM016L
D4R4
470
D3R3
470
D2R2
470
D1R1
470
OSC1
VDD
R20
4.7k
R8
470
D7R7
470
D6R6
470
D5R5
470
RA0/AN0
2
RA1/AN1
3
RA2/AN2/VREF-/CVREF
4
RA3/AN3/VREF+
5
RA4/T0CKI/C1OUT/RCV
6
RA5/AN4/SS/LVDIN/C2OUT
7
RA6/OSC2/CLKO
14
OSC1/CLKI
13
RB0/AN12/INT0/FLT0/SDI/SDA
33
RB1/AN10/INT1/SCK/SCL
34
RB2/AN8/INT2/VMO
35
RB3/AN9/CCP2/VPO
36
RB4/AN11/KBI0/CSSPP
37
RB5/KBI1/PGM
38
RB6/KBI2/PGC
39
RB7/KBI3/PGD
40
RC0/T1OSO/T1CKI
15
RC1/T1OSI/CCP2/UOE
16
RC2/CCP1/P1A
17
VUSB
18
RC4/D-/VM
23
RC5/D+/VP
24
RC6/TX/CK
25
RC7/RX/DT/SDO
26
RD0/SPP0
19
RD1/SPP1
20
RD2/SPP2
21
RD3/SPP3
22
RD4/SPP4
27
RD5/SPP5/P1B
28
RD6/SPP6/P1C
29
RD7/SPP7/P1D
30
RE0/AN5/CK1SPP
8
RE1/AN6/CK2SPP
9
RE2/AN7/OESPP
10
RE3/MCLR/VPP
1
U1
PIC18F4550
OSC2
D8
L7
L6
L5
L4
L3
L1
L2
L0
L0
L1
L2
L3
L4
L5
L6
L7
RB4
RB5
RB6
RB7
RE0
RE2
RE1
RB1
RB2
RB3
R12
10k
R14
10k R13
10k
RB0
A
B
C
D
L0
Figura 29: Diseño del proyecto 7
Figura 30: Simulación del proyecto 7
PROF. ALEXIS CABELLO PÁGINA: 28
UNEXPO-LCM
Figura 31: Diagrama del módulo PWM
8. Proyecto 8
En el proyecto 8 se utiliza el módulo CCP1 del microcontrolador. Se congura el módulo CCP1 en
modo PWM estándar para generar una señal cuadrada de 4KHz con 50 % de ciclo de trabajo pero a
la cual se le puede modicar el ancho del pulso.
8.1. Módulo CCP (Captura, Comparador y PWM)
El microcontrolador PIC 18F4550 tiene dos módulos CCP. En este proyecto se utiliza el módulo
CCP1 en su modo de funcionamiento de PWM (modulador de ancho de pulso). En la gura 31 se
muestra un diagrama del módulo PWM. El módulo permite generar una señal PWM con 10 bits de
resolución. El módulo CCP genera los 10 bits de resolución del PWM uniendo los 8 bits del contador
TMR2 con 2 bits del divisor de pre-escalado, tal como se observa en la Nota 1 de la gura 31. Estos
10 bits se comparan con los 10 bit del ciclo de trabajo para generar la señal PWM. En la gura 32
se muestra una señal de salida PWM. La señal PWM tiene una base de tiempo jo o período y un
tiempo variable en que se encuentra en alto o ciclo de trabajo (ancho del pulso). Tal como se puede
apreciar en la gura 31, el módulo utiliza el TIMER2 como contador para generar la señal PWM. El
período de la señal se ja escribiendo el registro PR2 según la ecuación 2. El ciclo de trabajo puede
tener hasta 10 bits de resolución y se establece escribiendo en los registros CCPRxL y CCPxCON, tal
como se muestra en la gura 33. Para congurar el módulo CCP en modo PWM se escribe 1 en los
bits CCPxM2-3 del registro CCPxCON tal como se muestra en la gura 34.
PROF. ALEXIS CABELLO PÁGINA: 29
UNEXPO-LCM
Ciclo de trabajo
PERIODO
TMR2=PR2TMR2=PR2
TMR2=Ciclo de trabajo
Figura 32: Señal de salida del módulo PWM
Ciclo de trabajo
CCPxL
Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7Bit 8Bit 9
CCPxL
Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7Bit 8Bit 9
CCPxL: Byte mas significativo de los 10Bit del ciclo de trabajo.
CPxB0-CPxB1: 2 bits menos significativos de los 10Bits del ciclo de trabajo
CCPxCON
Bit 0Bit 1
CCPxCON
Bit 0Bit 1
Figura 33: Ciclo de trabajo del PWM
Registro CCPxCON
CCPxM0CCPxM1CCPxM2CCPxM3DCxB0DCxB1----
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
CCPxM0CCPxM1CCPxM2CCPxM3DCxB0DCxB1----
Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7
CCPxM0-M3: Selección del modo de operación
0000= Capture/compare/ PWM deshabilitado
0001= reservado
0010= comparador: Cambia la salida cuando sea igual
0011= reservado
0100= modo de captura: cada flanco de caida
0101= modo de captura: cada flanco de subida
0110= modo de captura: cada 4 flanco de subida
0111= modo de captura: cada 16 flanco de subida
1000= comparador: Cambia la salida cuando sea igual
1001= comparador: Cambia la salida cuando sea igual
1010= comparador: Genera interrupción cuando sea igual
1011= comparador: dispara un evento especial,
comienza la conversión ADC
11xx= modo PWM
DCxB0-DCxB1: Bit0 y Bit1 para el Ciclo de trabajo del PWM
Figura 34: Registro CCPxCON
PROF. ALEXIS CABELLO PÁGINA: 30
UNEXPO-LCM
8.2. Programa proyecto8.c
En el listado 12 se muestra el programa proyecto8.c. Para utilizar el módulo CCP1 en modo PWM
estándar se congura el registro CCP1CON, escribiendo los bits CCP1M3-CCP1M2 con 1 . El periodo
de la señal PWM lo determina el periodo del temporizador 2 y se congura escribiendo el registro PR2.
El periodo se calcula a través de la ecuación 2.
El módulo CCP permite producir una señal PWM hasta con 10bits de resolución. Para congurar
el ciclo de trabajo de trabajo se escribe en el registro CCPR1L los 8 bits mas signicativos y los otros
dos bits se escriben en los bit DC1B1-DC1B0 del registro CCP1CON. La salida de la señal PWM
se produce por el pin RC2 del puerto C, por lo que esta señal debe ser habilitada como salida para
obtener la señal PWM.
8.3. Diseño en PROTEUS
En la Figura 35 se muestra el diseño en proteus del proyecto 8, El diseño es básicamente el mismo
que el anterior, solo que se conecta la salida RC2 del puerto C al osciloscopio para poder observar la
señal PWM generada. La pantalla del osciloscopio donde se observa la señal PWM generada por el
programa se muestra en la Figura 36.
50%
RV1
10k
VDD
AN0
AN0
RE2
RB4
RB5
RB6
RB7
RE0
VDD
RE1
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9
D1
8
D0
7
E
6
RW
5
RS
4
VSS
1
VDD
2
VEE
3
LCD2
LM016L
D4R4
470
D3R3
470
D2R2
470
D1R1
470
OSC1
VDD
R20
4.7k
R8
470
D7R7
470
D6R6
470
D5R5
470
RA0/AN0
2
RA1/AN1
3
RA2/AN2/VREF-/CVREF
4
RA3/AN3/VREF+
5
RA4/T0CKI/C1OUT/RCV
6
RA5/AN4/SS/LVDIN/C2OUT
7
RA6/OSC2/CLKO
14
OSC1/CLKI
13
RB0/AN12/INT0/FLT0/SDI/SDA
33
RB1/AN10/INT1/SCK/SCL
34
RB2/AN8/INT2/VMO
35
RB3/AN9/CCP2/VPO
36
RB4/AN11/KBI0/CSSPP
37
RB5/KBI1/PGM
38
RB6/KBI2/PGC
39
RB7/KBI3/PGD
40
RC0/T1OSO/T1CKI
15
RC1/T1OSI/CCP2/UOE
16
RC2/CCP1/P1A
17
VUSB
18
RC4/D-/VM
23
RC5/D+/VP
24
RC6/TX/CK
25
RC7/RX/DT/SDO
26
RD0/SPP0
19
RD1/SPP1
20
RD2/SPP2
21
RD3/SPP3
22
RD4/SPP4
27
RD5/SPP5/P1B
28
RD6/SPP6/P1C
29
RD7/SPP7/P1D
30
RE0/AN5/CK1SPP
8
RE1/AN6/CK2SPP
9
RE2/AN7/OESPP
10
RE3/MCLR/VPP
1
U1
PIC18F4550
OSC2
D8
L7
L6
L5
L4
L3
L1
L2
L0
L0
L1
L2
L3
L4
L5
L6
L7
RB4
RB5
RB6
RB7
RE0
RE2
RE1
RB1
RB2
RB3
R12
10k
R14
10k R13
10k
RB0
A
B
C
D
RC2
RC2
Figura 35: Diseño del proyecto 8
PROF. ALEXIS CABELLO PÁGINA: 31
UNEXPO-LCM
Listado 12 proyecto8.c
#include p18cxxx.h
#include delays.h
#include stdlib.h
#pragma config PLLDIV = 5 // (20 MHz crystal)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS //HSPLL_HS
#pragma config WDT = OFF
unsigned int count=0;
void initPWM (void);
void main() {
TRISA=TRISB=TRISC=TRISD = 0x00; // set direction to be output
PORTD=0x0;
ADCON1 = 0x0F;
INTCONbits.GIE = 1; //enable global interrupts
INTCONbits.PEIE = 1; //enable peripherical interrupts
initPWM();
while(1);
}
void initPWM (void)
{
PR2 = 187; // T pwm = (PR2+1)*4*(1/FOSC)*PRESCALER
CCPR1L = 94; // 50 % duty cycle
T2CON=0;
T2CONbits.T2CKPS1 = 1;
T2CONbits.T2CKPS0 = 0; // 16 - prescaler
IPR1bits.TMR2IP = 0; // low priority
PIR1bits.TMR2IF = 0;
PIE1bits.TMR2IE = 0; //disable Interrupt
T2CONbits.TMR2ON = 1;
CCP1CON = 0;
CCP1CONbits.DC1B1=0;
CCP1CONbits.DC1B0=0; //Duty cicle
CCP1CONbits.CCP1M3=1;
CCP1CONbits.CCP1M2=1; //PWM mode
TRISCbits.TRISC2 = 0; //RC1 output
}
PROF. ALEXIS CABELLO PÁGINA: 32
UNEXPO-LCM
Figura 36: Simulación del proyecto 8
PROF. ALEXIS CABELLO PÁGINA: 33
UNEXPO-LCM
Anexo A
Manejo de la pantalla LCD
Las pantallas LCD son dispositivos que se utilizan para visualizar información. Los dispositivos
LCD poseen internamente un microcontrolador especico que sirven para regular el funcionamiento de
los mismos.
Las pantallas mas comunes están formados por una matriz de 5*7 pixels en una o en varías líneas,
en el siguiente proyecto se trabajará con una pantalla LCD que permite trabajar dos líneas de 16
caracteres cada una y, que posee un microcontrolador 44780. Esta pantalla que se muestra en la gura
37 posee 14 terminales que serán explicados con detalle a continuación.
RE2
RB4
RB5
RB6
RB7
RE0
VDD
RE1
D7
14
D6
13
D5
12
D4
11
D3
10
D2
9
D1
8
D0
7
E
6
RW
5
RS
4
VSS
1
VDD
2
VEE
3
Figura 37: LCD LM016L
Como se observan los 14 terminales son VSS, VDD, VEE, RS, RW, E, D0, D1, D2, D3, D4, D5, D6,
y D7, estos terminales se dividen en tres categorías, los tres primeros son los terminales de alimentación,
los siguientes tres terminales son los utilizados para control del LCD y los últimos 8 respectivamente,
son utilizados para transferir los datos.
Terminales de Alimentación
1. VSS: Se aplica la tierra
2. VDD: Se aplica la alimentación de 5 voltios
3. VEE: Normalmente este terminal se conecta a un potenciómetro que permita variar un voltaje
entre 0 a 5 voltios y así observar la diferencia de brillo y contraste que se puede tener en la
pantalla LCD. Si se conecta a tierra, se indica el mayor contraste.
Terminales de Control
1. RS: Por este terminal, se indica a la pantalla LCD si se va escribir un comando o una data, se
entiende por comandos todas aquellas instrucciones que sirven para inicializar la pantalla, borrar
pantalla, posicionar el cursor entre otras, para todo esto, se debe colocar un 0 en este terminal;
por el contrario si se conecta a 1 , lo que se envía es la data, generalmente el código ASCII del
carácter a mostrar.
PROF. ALEXIS CABELLO PÁGINA: 34
UNEXPO-LCM
2. RW: Este terminal corresponde a Read/Write, es decir, es el terminal que indica si vamos a leer
o a escribir de la pantalla LCD, siendo 1 para leer y 0 para escribir.
3. E: Enable, este terminal permite habilitar el proceso de escritura/lectura a la pantalla LCD. si
no se activa este terminal, la información en D0-D7 no se lee o escribe.
Terminales para Data Estos 8 terminales reciben los caracteres ASCII a representar, así como
ciertos códigos de control que regulan los efectos de visualización o para obtener información sobre el
estado interno del dispositivo.
El dispositivo LCD responde a una serie de comandos con los que se puede manipular sus distintas
opciones de trabajo, para lo cual se hace referencia a la tabla 2.
Comando RS R/W E D7 D6 D5 D4 D3 D2 D1 D0
Tiempo de
Ejecución
Clear Display 0 0 1 0 0 0 0 0 0 0 1 1.64 ms
Home 0 0 1 0 0 0 0 0 0 1 x 1.64 ms
Entry Mode Set 0 0 1 0 0 0 0 0 1 I/D S 40 us
Display On/O 0 0 1 0 0 0 0 1 D C B 40 us
Cursor Display Shift 0 0 1 0 0 0 1 S/C R/L x x 40 us
Function Set 0 0 1 0 0 1 DL N F x x 40 us
Set CGRAM Address 0 0 1 0 1 Dirección de la CGRAM 40 us
Set DDRAM Address 0 0 1 1 Dirección de la DDRAM 40 us
Read Busy Flags Address 0 1 1 BF Dirección de la CGRAM o DDRAM 40 us
Write Data to CG o DD 1 0 1 Código ASCII para la RAM 40 us
Read Data to CG o DD 1 1 1 Código Almacenado en RAM 40 us
Tabla 2: Códigos de los Comandos a los que responde el Dispositivo LCD
A continuación se explica con detalle todas las abreviaturas utilizadas en la tabla
S: Se reere a la visualización, si vale 1, indica que cada vez que escribe un dato, la visualización
se desplaza automáticamente a la siguiente posición, por el contrario si vale 0, funciona de forma
normal.
I/D: Se reere al cursor, si vale 1, el cursor se incrementa automáticamente de dirección luego
de escribir, si vale 0, éste se decrementa.
S/C: Si vale 1 se desplaza la visualización, si vale 0 se desplaza el cursor.
R/L: Si vale 1 el desplazamiento es a la derecha del LCD, si vale 0 es a la izquierda.
BF: si vale 1 el dispositivo LCD se encuentra en funcionamiento u ocupado, si se encuentra en
0, indica que esta disponible.
DL: Si vale 1 trabaja con un bus de datos de 8 bits, si vale 0 trabaja con bus de solo 4 bits,
que es el caso que se eligió en el proyecto.
N: Si vale 1 la presentación se hace en dos líneas, si vale 0 se hace en una sola línea.
F: Este indica el tamaño o la caja de los caracteres, si vale 1 es de 5x10 pixels, si vale 0, es
de 5x7.
PROF. ALEXIS CABELLO PÁGINA: 35
UNEXPO-LCM
B: Si vale 1, parpadeo del cursor encendido y si es 0 , parpadeo del cursor apagado.
C: Si vale 1, el cursor esta activado, si vale 0 el cursor esta desactivado.
D: Si vale 1, la pantalla esta activada, si vale 0 la pantalla esta desactivada.
X: Indeterminado
A continuación se describen la función de los comandos que controlan el dispositivo LCD
Clear Display: Este comando borra la pantalla del dispositivo LCD y coloca el cursor en la
primera posición, que es la dirección 0, por defecto coloca el bit I/D en 1 para autoincremento
de la posición del cursor.
Home: Pone el cursor en la dirección 0 y no varía el contenido de la memoria DDRAM que guarda
los datos y que queda direccionada desde la posición 0.
Entry Mode Set: Establece la dirección del movimiento del cursor, si coloca el bit S en 1 desplaza
la visualización cada vez que se escribe un dato, si S vale 0 la visualización es normal.
Display On/O: Activa o Desactiva al Display (D) y al cursos (C) y determina si éste es inter-
mitente o no.
Cursor Display Shift: Mueve el cursor y desplaza la visualización sin cambiar el contenido de la
memoria DDRAM.
Function Set: Establece el número de líneas que se van a utilizar, con el bus de datos, siendo
normalmente que sea de 8 bits, por lo que DL=1 y especíca el número de líneas de caracteres,
que para que sean dos se debe colocar N=1 y el formato del carácter si F=0 entonces es de 5x7
pixels.
Set CGRAM Adress: El dispositivo LCD tiene denidos los caracteres ASCII, sin embargo per-
mite que el usuario pueda denir un máximo de nueve caracteres nuevos. Éstos se guardan en
CGRRAM. Con este comando se indica la dirección de la CGRAM a partir de la cual se irán
almacenando los bytes que denen al nuevo carácter. Luego de ejecutar este comando todos los
datos que se lean o escriban posteriormente lo hacen desde esa posición de la CGRAM.
Set DDRAM Adress: Establece la dirección de la DDRAM, a partir de la cual todos los datos que
se lean o escriban posteriormente lo harán desde esta posición. Es los 16 caracteres del primer
renglón ocupan las direcciones 80H- 8FH y los del segundo desde C0H- CFH.
Read Busy Flags Adress: Se trata de un comando para la lectura de las bandera BUSY, que
indica si todavía se está ejecutando un comando previo en la pantalla, y además proporciona la
dirección de la CGRAM y DDRAM que se haya utilizado por última vez.
Write Data to CG o DD: Se escribe en la DDRAM los caracteres ASCII, que se desea visualizar.
También se escriben en la CGRAM los bytes de los nuevos caracteres creados por el usuario,
en caso de existir los mismo. Se usa una memoria u otra según haya sido la instrucción de
direccionamiento anterior, que hará que se reeje el contenido de la memoria DDRAM o CGRAM.
Read Data to CG o DD: Es muy parecido al comando anterior, pero en este caso es solo para
lectura de los datos que se encuentren en las memorias DDRAM o CGRAM.
En el archivo de encabezado se declaran los prototipos de las funciones del LCD y se denen los códigos
de los comandos principales mostrados en la tabla 2. El archivo de encabezado (lcd.h) se muestra en
el listado 13:
PROF. ALEXIS CABELLO PÁGINA: 36
UNEXPO-LCM
Listado 13 Archivo de encabezado LCD.h
typedef void VOID;
typedef int INT;
typedef signed char INT8;
typedef signed int INT16;
typedef signed long INT32;
typedef unsigned short WORD;
typedef char CHAR;
typedef unsigned char BYTE;
typedef double FLOAT;
typedef long LONG;
typedef INT8 BOOL;
//Display Config.
#define MAX_DISPLAY_CHAR 16
//LCD Registers addresses (PORT E)
#define LCD_CMD_WR 0x00
#define LCD_DATA_WR 0x01
#define LCD_BUSY_RD 0x02
#define LCD_DATA_RD 0x03
//LCD Commands
#define LCD_CLS 0x01
#define LCD_HOME 0x02
#define LCD_SETMODE 0x04
#define LCD_SETVISIBLE 0x08
#define LCD_SHIFT 0x10
#define LCD_SETFUNCTION 0x20
#define LCD_SETCGADDR 0x40
#define LCD_SETDDADDR 0x80
#define E_PIN_MASK 0x04
#define FALSE 0
#define TRUE 1
/************************************************************************
***** FUNCTION PROTOTYPES *****
******************************/
VOID lcd_display (CHAR y, CHAR x, CHAR *buf);
VOID lcd_char (CHAR ch);
VOID lcd_init(void);
VOID lcd_wait(void);
VOID wrcmd (CHAR data);
VOID wrdata(CHAR data);
VOID lcd_clear(void);
VOID lcd_reset(void);
VOID setpos(CHAR y, CHAR x);
PROF. ALEXIS CABELLO PÁGINA: 37
UNEXPO-LCM
Listado 14 lcdio.c
/*****************************************************************
***** PIC18F Driver for LCD in 4-bit mode *****
******************************************************************/
#include p18cxxx.h
#include delays.h
#include lcd.h
VOID wrcmd8 (CHAR cmdcode);
VOID lcd_init ()
// Initialise the LCD Display.
{
PORTB = TRISB = 0x0F;
PORTE = TRISE = 0;
Delay10KTCYx(25);
wrcmd8(LCD_SETFUNCTION+0x10); // Software reset.
wrcmd8(LCD_SETFUNCTION+0x10); //
wrcmd8(LCD_SETFUNCTION+0x12); //
#ifdef BIT8
wrcmd8(LCD_SETFUNCTION+0x18); // 8-bit mode - 2 line - 5x7 font.
#else
wrcmd8(LCD_SETFUNCTION+0x08); // 4-bit mode - 2 line - 5x7 font.
wrcmd(LCD_SETFUNCTION+0x08); // 4-bit mode - 2 line - 5x7 font.
#endif
wrcmd(LCD_SETVISIBLE+0x04); // Display, no cursor - no blink.
wrcmd(LCD_SETMODE+0x02); // Automatic Increment - No Display shift.
wrcmd(LCD_SETDDADDR+0x00); // Address DDRAM with 0 offset 80h.
}
VOID lcd_display (CHAR y, CHAR x, CHAR *buf)
{ INT8 i;
setpos(y,x);
for (i=0 ; buf[i] != 0; i++)
{ wrdata(buf[i]); }
}
VOID lcd_char (CHAR ch)
{ INT8 i;
wrdata(ch);
}
VOID lcd_clear()
// Clear the LCD Screen and reset
// initial position.
{ wrcmd(LCD_CLS);
wrcmd(LCD_SETDDADDR+0x0);
}
VOID setpos (CHAR y, CHAR x)
{
if(y==1)
wrcmd(LCD_SETDDADDR+(x-1));
else
wrcmd(LCD_SETDDADDR+0x40+(x-1));
}
PROF. ALEXIS CABELLO PÁGINA: 38
UNEXPO-LCM
Listado 15 continuación lcdio.c
VOID wrcmd8 (CHAR cmdcode)
// Write a command to the LCD display.
{ TRISB = 0x0F;
PORTB = cmdcode;
// Write to PORTB to latch data into the display.
// Toggle Pin ’E’ to send the command.
PORTE = LCD_CMD_WR;
PORTE |= E_PIN_MASK;
_asm
NOP
NOP
_endasm
PORTE = ~E_PIN_MASK;
lcd_wait();
}
/***** Utility Functions *****/
VOID wrcmd (CHAR cmdcode)
// Write a command to the LCD display.
// In 4-bit mode we send the MSN first and then
// the LSN. We then call the wait routine to hold
// until the busy flag is cleared.
{ TRISB = 0x0F;
#ifdef BIT8
PORTB = (cmdcode);
#else
PORTB = (cmdcode  0xF0); // Get the most significant nibble first.
#endif
PORTE = LCD_CMD_WR; // Specify a command write operation.
PORTE |= E_PIN_MASK; // Toggle the ’E’ pin to send the command.
_asm
NOP
NOP
_endasm
PORTE = ~E_PIN_MASK;
#ifdef BIT8
lcd_wait(); // Call the wait routine.
#else
TRISB = 0x0F;
PORTB = (cmdcode  4); // Repeat for least significant nibble.
PORTE = LCD_CMD_WR;
PORTE |= E_PIN_MASK;
_asm
NOP
NOP
_endasm
PORTE = ~E_PIN_MASK;
lcd_wait(); // Call the wait routine.
#endif
}
PROF. ALEXIS CABELLO PÁGINA: 39
UNEXPO-LCM
Listado 16 continuación lcdio.c
VOID wrdata (CHAR data)
// Write a Character to the LCD Display.
// In 4-bit mode we send the MSN first and then
// the LSN. We then call the wait routine to hold
// until the busy flag is cleared.
{ TRISB = 0x0F;
#ifdef BIT8
PORTB = data;
#else
PORTB = data  0xF0; // Get the most significant nibble first.
#endif
PORTE = LCD_DATA_WR; // Specify a data write operation.
PORTE |= E_PIN_MASK; // Toggle the ’E’ pin to send the command.
_asm
NOP
NOP
_endasm
PORTE = ~E_PIN_MASK;
#ifdef BIT8
lcd_wait(); // Call the wait routine.
#else
TRISB = 0x0F;
PORTB = (data  4); // Repeat for least significant nibble.
PORTE = LCD_DATA_WR;
PORTE |= E_PIN_MASK;
_asm
NOP
NOP
_endasm
PORTE = ~E_PIN_MASK;
lcd_wait(); // Call the wait routine.
#endif
}
VOID lcd_wait ()
{
Delay1KTCYx(10);
}
Rutina lcd_init() Esta rutina se utiliza para inicializar el LCD. Se puede inicializar para fun-
cionar en modo de transferencia de 4 bits o de 8 bits dependiendo si se dene la variable BIT8 por
medio del comando del preprocesador del compilador (#dene BIT8). Si esta denida la variable se
realizar la conguración para 8 bits y en caso contrario se congura para 4 bits.
Rutina lcd_display(y, x, string) Esta rutina permite mostrar en la pantalla LCD una cadena
de caracteres. Se debe pasar como parámetros las coordenadas de la pantalla (y, x) a partir de donde
se empieza a mostrar la cadena de caracteres.
y: número de la la o línea (1 o 2)
x: numero de la columna (1 a 16)
string: cadena de caracteres a mostrar.
PROF. ALEXIS CABELLO PÁGINA: 40
UNEXPO-LCM
Rutina lcd_char(char) Esta rutina permite mostrar un carácter en la posición actual del
cursor. El cursor se incrementa y queda en la siguiente posición de la pantalla.
char = carácter a mostrar.
Rutina lcd_clear() Esta rutina permite borrar toda la pantalla LCD y se posiciona el cursor
en coordenadas de inicio (1,1).
Rutina setpos(y,x) Esta rutina permite mover el cursor. Se debe pasar como parámetros las
coordenadas de la pantalla (y, x).
y: número de la la o línea (1 o 2).
x: número de la columna (1 a 16).
Las rutinas que se describen a continuación son las rutinas de bajo nivel que son utilizadas para
enviar los comandos y los datos a la pantalla LCD. Estas rutinas son utilizadas por las rutinas descritas
anteriormente por controlar las funciones de la pantalla LCD.
Rutina wrcmd8(comando) Esta rutina escribe el código de comando pasado como parámetro
a la pantalla LCD a través del modo de transferencia de 8 bits y espera a que el LCD termine de
ejecutar la operación. Esta rutina se utiliza en la función lcd_init() ya que al encender la pantalla esta
queda inicializada en modo de transferencia de 8 bits.
Rutina wrcmd(comando) Esta rutina escribe el código de comando pasado como parámetro
a la pantalla LCD a través del modo de transferencia congurado en la rutina lcd_init(), es decir en
4 bits o en 8 bits. La rutina espera a que el LCD termine de ejecutar la operación.
Rutina wrdata(char) Esta rutina escribe el carácter (char) pasado como parámetro a la pantalla
LCD.
Rutina lcd_wait() Esta rutina espera para que el LCD termine de procesar el comando enviado.
PROF. ALEXIS CABELLO PÁGINA: 41
UNEXPO-LCM
Anexo B
Manejo del Teclado Matricial
Un teclado matricial es un dispositivo de entrada de datos donde las líneas necesarias para detectar
la tecla pulsada se agrupan de forma matricial en las y columnas con el n de disminuir las líneas
requeridas. Para un teclado de 12 teclas solo se requieren de 7 líneas de entrada/salida del microcon-
trolador para manejar el teclado. En la gura 38 se muestra el esquema de un teclado matricial de 12
teclas.
RB7
RB6
RB4
RB5
B2
2
B4
4
B5
5
B6
6
B8
8
B3
3
B9
9
B7
7
B1
1
B12
#
B11
0
B10
*
RB3 RB2 RB1
Figura 38: Teclado Matricial de 4x3
Las líneas RB1-RB3 en la gura son leídas por el nible inferior del puerto B (RB1-RB3), por lo que
se tienen que congurar como entradas, mientras que las del nible superior (RB4-RB7) se conguran
como salidas y es donde se aplican el patrón de estados lógicos para ser leídos por el nible inferior.
El programa que se muestra en el listado 17 gestiona el manejo del teclado, en el mismo se saca
secuencialmente un nivel bajo por una de las 4 líneas de salida que se aplican a las las (RB4-RB7),
al mismo tiempo que se lee el nivel lógico que llega al nible inferior o columnas (RB1-RB3). Si al leer
este nible, una de las líneas se encuentra en nivel bajo, se deduce que la tecla asociada a dicha la y
dicha columna se encuentra presionada. Cada tecla tiene un código asociado desde el 1 al 12. Luego
estos códigos pueden ser sustituidos por un código ASCII por medio del uso de un tabla.
PROF. ALEXIS CABELLO PÁGINA: 42
UNEXPO-LCM
Listado 17 kdbio.c
#include p18cxxx.h
#include delays.h
char keypadread(void);
char scankey(void);
char keypadread()
// Find a key, wait for it to be released and return.
{ char key;
key = scankey();
if (key)
while (scankey() != 0);
return key;
}
char scankey()
// Scan the keypad for a keypress.
// Return 0 for no press.
{ char row,col,idx;
unsigned char wait,tmp;
idx=0;
TRISB=0x0F;
for (row=0; row  4; row++)
{ // Drive appropriate row low and read columns:
LATB = ~(1  (row+4));
for (wait=0; wait200; ++wait);
tmp = (PORTB  0x0F);
// See if any column is active (low):
for (col=1; col4; col++)
{
if ((tmp  (1col)) == 0)
{
idx = (row*4) + col;
break;
}
}
if(idx!=0) break;
}
TRISB=0x00;
return idx;
}
Rutina scankey() Esta rutina es la que realiza el barrido por las las y columnas del teclado
para detectar si se ha presionado una tecla. La rutina realiza un solo barrido y si una tecla es presionada
retorna el código de la misma, por el contrario si ninguna tecla es presionada la rutina retorna cero.
PROF. ALEXIS CABELLO PÁGINA: 43
UNEXPO-LCM
Rutina keypadread() Esta rutina llama a la rutina scankey y si una tecla fue presionada la
rutina espera hasta que la tecla deje de estar presionada y luego retorna el código del tecla.
PROF. ALEXIS CABELLO PÁGINA: 44

Más contenido relacionado

Similar a Libro de lenguaje c

Programación en c j. carlos lopez ardao
Programación en c   j. carlos lopez ardaoProgramación en c   j. carlos lopez ardao
Programación en c j. carlos lopez ardao
victdiazm
 
Electrónica digital: DIseño e implementacion de la plataforma Boole-Weblab-De...
Electrónica digital: DIseño e implementacion de la plataforma Boole-Weblab-De...Electrónica digital: DIseño e implementacion de la plataforma Boole-Weblab-De...
Electrónica digital: DIseño e implementacion de la plataforma Boole-Weblab-De...
SANTIAGO PABLO ALBERTO
 
Microcontroladores pic (josé mª angulo usategui, ignacio angulo martínez)
Microcontroladores pic (josé mª angulo usategui, ignacio angulo martínez)Microcontroladores pic (josé mª angulo usategui, ignacio angulo martínez)
Microcontroladores pic (josé mª angulo usategui, ignacio angulo martínez)
Miguel Angel Corona Lòpez
 
Microcontroladores pic diseño practico de aplicaciones
Microcontroladores pic diseño practico de aplicacionesMicrocontroladores pic diseño practico de aplicaciones
Microcontroladores pic diseño practico de aplicaciones
Carlos Tovar
 
pfc_jose_ignacio_perez_2007
pfc_jose_ignacio_perez_2007pfc_jose_ignacio_perez_2007
pfc_jose_ignacio_perez_2007
Jos P
 

Similar a Libro de lenguaje c (20)

Programación en c j. carlos lopez ardao
Programación en c   j. carlos lopez ardaoProgramación en c   j. carlos lopez ardao
Programación en c j. carlos lopez ardao
 
Proyecto final facultad de ingeniería.pdf
Proyecto final facultad de ingeniería.pdfProyecto final facultad de ingeniería.pdf
Proyecto final facultad de ingeniería.pdf
 
Introduccion a nodejs
Introduccion a nodejs Introduccion a nodejs
Introduccion a nodejs
 
Introduccion a nodejs_a_traves_de_koans_ebook
Introduccion a nodejs_a_traves_de_koans_ebookIntroduccion a nodejs_a_traves_de_koans_ebook
Introduccion a nodejs_a_traves_de_koans_ebook
 
MANUAL DE LENGUAJE C
MANUAL DE LENGUAJE CMANUAL DE LENGUAJE C
MANUAL DE LENGUAJE C
 
Microcontroladores: Tutorial de microcontroladores PIC
Microcontroladores: Tutorial de microcontroladores PIC Microcontroladores: Tutorial de microcontroladores PIC
Microcontroladores: Tutorial de microcontroladores PIC
 
Tutorial pic
Tutorial picTutorial pic
Tutorial pic
 
Tutorial pic
Tutorial picTutorial pic
Tutorial pic
 
MiCroControladores
MiCroControladoresMiCroControladores
MiCroControladores
 
Tutorial pic
Tutorial picTutorial pic
Tutorial pic
 
Tutorial Microprocesadores Pic iniciación rápida (Miguel Torres)
Tutorial Microprocesadores Pic  iniciación rápida  (Miguel Torres) Tutorial Microprocesadores Pic  iniciación rápida  (Miguel Torres)
Tutorial Microprocesadores Pic iniciación rápida (Miguel Torres)
 
Electrónica digital: DIseño e implementacion de la plataforma Boole-Weblab-De...
Electrónica digital: DIseño e implementacion de la plataforma Boole-Weblab-De...Electrónica digital: DIseño e implementacion de la plataforma Boole-Weblab-De...
Electrónica digital: DIseño e implementacion de la plataforma Boole-Weblab-De...
 
Guia analisis-de-algoritmos
Guia analisis-de-algoritmosGuia analisis-de-algoritmos
Guia analisis-de-algoritmos
 
Práctica III. Mostrar un mensaje en una pantalla LCD
Práctica III. Mostrar un mensaje en una pantalla LCDPráctica III. Mostrar un mensaje en una pantalla LCD
Práctica III. Mostrar un mensaje en una pantalla LCD
 
Microcontroladores pic (josé mª angulo usategui, ignacio angulo martínez)
Microcontroladores pic (josé mª angulo usategui, ignacio angulo martínez)Microcontroladores pic (josé mª angulo usategui, ignacio angulo martínez)
Microcontroladores pic (josé mª angulo usategui, ignacio angulo martínez)
 
Microcontroladores pic diseño practico de aplicaciones
Microcontroladores pic diseño practico de aplicacionesMicrocontroladores pic diseño practico de aplicaciones
Microcontroladores pic diseño practico de aplicaciones
 
Cypecad manual
Cypecad manualCypecad manual
Cypecad manual
 
Cypecad ejemplo
Cypecad   ejemploCypecad   ejemplo
Cypecad ejemplo
 
pfc_jose_ignacio_perez_2007
pfc_jose_ignacio_perez_2007pfc_jose_ignacio_perez_2007
pfc_jose_ignacio_perez_2007
 
LENGUAJE BASIC WILBER PINILLA
LENGUAJE BASIC WILBER PINILLALENGUAJE BASIC WILBER PINILLA
LENGUAJE BASIC WILBER PINILLA
 

Último

EPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial UninoveEPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial Uninove
FagnerLisboa3
 
Modulo-Mini Cargador.................pdf
Modulo-Mini Cargador.................pdfModulo-Mini Cargador.................pdf
Modulo-Mini Cargador.................pdf
AnnimoUno1
 

Último (11)

How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.
 
Refrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdf
Refrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdfRefrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdf
Refrigerador_Inverter_Samsung_Curso_y_Manual_de_Servicio_Español.pdf
 
EPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial UninoveEPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial Uninove
 
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptxEL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
 
Modulo-Mini Cargador.................pdf
Modulo-Mini Cargador.................pdfModulo-Mini Cargador.................pdf
Modulo-Mini Cargador.................pdf
 
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptxPROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
 
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
 
Avances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvanaAvances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvana
 
Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21
 
pruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITpruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNIT
 
Avances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estosAvances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estos
 

Libro de lenguaje c

  • 1. República Bolivariana de Venezuela Universidad Nacional Experimental Politécnica Antonio José de Sucre Vicerrectorado Luís Caballero Mejías Programación de proyectos básicos en microcontroladores PIC18 usando lenguaje C Prof. Alexis Cabello Caracas, Marzo 2013
  • 2. ÍNDICE GENERAL Compilador MPLAB C para PIC18 1 1. Proyecto 1 7 1.1. Programa Proyecto1.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.2. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.3. Simulación en PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2. Proyecto 2 11 2.1. Programa Proyecto2.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3. Proyecto 3 12 3.1. Programa Proyecto3.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.2. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 4. Proyecto 4 14 4.1. Programa Proyecto4.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4.2. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 5. Proyecto 5 15 5.1. Convertidor analógico a digital . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.2. Programa Proyecto5.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.3. Diseño en el PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 6. Proyecto 6 21 6.1. Programa proyecto6.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 6.2. Diseño en PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 7. Proyecto 7 25 7.1. Temporizador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 7.2. Programa proyecto7.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 7.3. Diseño en PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 8. Proyecto 8 29 8.1. Módulo CCP (Captura, Comparador y PWM) . . . . . . . . . . . . . . . . . . . . . . . 29 8.2. Programa proyecto8.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 8.3. Diseño en PROTEUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Anexo A. Manejo de la pantalla LCD 34 Anexo B. Manejo del teclado matricial 42
  • 3. UNEXPO-LCM Índice de algoritmos 1. proyecto1.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2. continuación de proyecto1.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 3. proyecto2.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 4. proyecto3.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5. proyecto4.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 6. proyecto5.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 7. continuación proyecto5.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 8. proyecto6.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 9. continuación de proyecto6.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 10. proyecto7.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 11. continuación de proyecto7.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 12. proyecto8.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 13. Archivo de encabezado LCD.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 14. lcdio.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 15. continuación lcdio.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 16. continuación lcdio.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 17. kdbio.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 PROF. ALEXIS CABELLO PÁGINA: 3
  • 4. UNEXPO-LCM Compilador MPLAB C para PIC18 Los proyectos mostrados a continuación son desarrollados en lenguaje C y se utiliza el programa MPLAB C18 de Microchip como compilador. Se utiliza la versión MPLAB C for PIC18 in LITE mode, la cual puede descargarse de la pagina web de Microchip en la siguiente dirección: http: //depositfiles.org/files/vq6czsahj A continuación se explica como crear un proyecto con este compilador dentro del entorno MPLAB. Lo primero que se debe crear es un Workspace, o espacio de trabajo, para lo cual se ingresa en el menú Project y se selecciona Project Wizard, Figura 1 Figura 1: Project Wirzard Esta opción me proporciona un ayudante, se selecciona siguiente y se siguen los siguientes pasos: 1. Seleccionar en Device el dispositivo con el cual se va a trabajar, en nuestro caso el PIC18F4550. Figura 2 PROF. ALEXIS CABELLO PÁGINA: 1
  • 5. UNEXPO-LCM Figura 2: Seleccionar Dispositivo 2. Seleccionar C18 como la herramienta con la que se desea trabajar. Figura 3 Figura 3: Seleccionar Conjunto de Lenguajes 3. Seleccionar el nombre del proyecto y la carpeta donde se creara el proyecto. Figura 4 PROF. ALEXIS CABELLO PÁGINA: 2
  • 6. UNEXPO-LCM Figura 4: Directorio de Archivos 4. Se deben añadir los archivos existentes y que deseemos agregar al proyecto, sin embargo en este momento no se tienen archivos existentes, por lo que este paso se puede obviar, y se termina con la creación del Workspace. 5. Crear un archivo nuevo, para lo cual se ingresa a File y se selecciona la opción New, allí se obtiene una ventana en blanco donde se escribe el programa y luego se guarda con extensión .C. Figura 5 PROF. ALEXIS CABELLO PÁGINA: 3
  • 7. UNEXPO-LCM Figura 5: Nuevo Documento 6. Una vez nalizado el programa se debe añadir el archivo al Workspace creado, para lo cual se ingresa en el menú Project y se selecciona la opción Add Files to Project; Figura 6, donde se debe seleccionar el directorio donde se están guardando los archivos, Figura 7 Figura 6: Añadir nuevo Documento al Workspace PROF. ALEXIS CABELLO PÁGINA: 4
  • 8. UNEXPO-LCM Figura 7: Selección del archivo .C 7. Finalizado todos estos pasos, se procede a compilar nuestro proyecto, para lo cual se ingresa a Project y se selecciona Build All. Figura 8 8. Como resultado de la compilación podemos observar los posibles errores de sintaxis en las lineas de programación y si todo esta correcto se obtiene un mensaje de compilación exitosa como se muestra en Figura 9 PROF. ALEXIS CABELLO PÁGINA: 5
  • 9. UNEXPO-LCM Figura 8: Compilación del Proyecto Figura 9: Compilación Exitosa PROF. ALEXIS CABELLO PÁGINA: 6
  • 10. UNEXPO-LCM Una vez compilado de forma exitosa, se generan dos tipos de archivos .COF y .HEX. El primero contiene información que permite realizar una simulación a nivel de código fuente. El .HEX sólo contiene el código de máquina que se descarga al microcontrolador para su ejecución. 1. Proyecto 1 El proyecto uno se basa en aprender a manejar la conguración de los puertos para encender 8 LED de forma simultanea e intermitente por un tiempo indenido. Para crear este proyecto se utilizará el entorno de desarrollo MPLAB de microchip y el compilador de lenguaje C de microchip MPLAB C18, Luego que se haya realizado este paso se realizará el diseño del proyecto en el entorno de simulación ISIS de PROTEUS, se utilizará éste programa para probar a nivel de simulación el funcionamiento del proyecto. 1.1. Programa Proyecto1.c Para comenzar se debe incluir los archivos de encabezado (.h) y se programan los bits de congura- ción mediante la instrucción pragma. Esto se muestra en el listado 1. Mediante los bits de conguración se programan ciertas funciones del PIC, como son el Watchdog, el reloj que utilizará el CPU, protección del código, etc. En este caso, se utiliza un cristal de 20Hz como entrada del Oscilador entre los pines 9 y 10 del PIC. Estos 20Mhz se dividen entre 5 para generar los 4Mhz necesarios para el PLL interno del PIC. Esto se indica en la linea 3 donde se congura PLLDIV con 5. El PLL multiplica esta frecuencia por 24 para obtener 96Mz, los cuales se dividen entre 2 para generar en denitiva el reloj del CPU y del modulo USB. Esto se indica en las lineas 4 y 5 congurando CPUDIV y USBDIV respectivamente. Luego se indica la fuente de entrada del oscilador congurando FOSC con HSPLL_HS y por ultimo se deshabilita el uso del watchdog (WDT) y la programación con voltaje bajo (LVP). Listado 1 proyecto1.c #include p18cxxx.h #include delays.h #pragma config PLLDIV = 5 // (20 MHz crystal) #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2 #pragma config FOSC = HSPLL_HS #pragma config WDT = OFF #pragma config LVP = OFF Para inicializar el programa se conguran todos los puertos como salidas, haciendo uso de TRISA, TRISB, TRISC y TRISD. Para que el usuario pueda observar el encendido y apagado de los LED se llama a la librería de retardo Delay10KTCYx (n). esta librería de retardo es suministrada por el compilador MPLAB C18, y permite generar un retardo total de 10.000 ciclos de instrucción por el numero suministrado como parámetro (n 256). PROF. ALEXIS CABELLO PÁGINA: 7
  • 11. UNEXPO-LCM De esta forma y con las especicaciones dadas, se elabora el programa que será grabado en nuestro dispositivo como se observa en el listado 2 Listado 2 continuación de proyecto1.c void main() { TRISA=TRISB=TRISC=TRISD = 0x00; // set direction to be output ADCON1 |= 0x0F;//A/D port as Digital do { PORTD = 0x00; // Turn OFF LEDs on PORTD Delay10KTCYx (250); // delay PORTD = 0xFF; // Turn ON LEDs on PORTD Delay10KTCYx (250); // delay } while(1); } En el listado anterior se puede observar que se genera una salida de uno lógico por cada bit del puerto D (PORTD), por un tiempo determinado para encender los diodos LED y posteriormente se genera una salida con ceros lógicos para poder apagar los diodos LED. 1.2. Diseño en el PROTEUS Para la realización del diseño lo primero que se debe hacer es colocar los distintos componentes en la hoja de trabajo, para ello se selecciona el modo componentes que se muestra en la gura 10 y, luego realizar una pulsación sobre el botón P de la ventana de componentes que se muestra en la gura 11 Figura 10: Modo Componentes Figura 11: Selección de Botón P Luego de activar el botón P se abre la ventana para la selección y edición del componente y comprobar sus características; el dispositivo que se quiere utilizar, en nuestro caso el PIC18F4550, al localizar el componente deseado se realiza una doble pulsación en él de tal forma que aparezca en la ventana de componentes y librerías como se muestra en la gura 12 PROF. ALEXIS CABELLO PÁGINA: 8
  • 12. UNEXPO-LCM Figura 12: Selección del Componente Para situar el componente en el esquema de trabajo solo debemos seleccionarlo de la lista, y hacer una pulsación sobre la ventana de trabajo y se colocará el componente. Luego se conectan LEDs al puerto D del PIC, es decir los pines 19 al 30. Los cuales corresponden a los congurados como salida en el programa y como se puede observar en la gura 13. Para este proyecto se utilizan 8 LEDs y 8 resistencias de 470 ohm dispuestas como se muestra en la gura 14, Figura 13: Dispositivo PIC 18F4550 PROF. ALEXIS CABELLO PÁGINA: 9
  • 13. UNEXPO-LCM D4 R4 470 D3 R3 470 D2 R2 470 D1 R1 470 OSC1 VDD R20 4.7k R8 470 D7 R7 470 D6 R6 470 D5 R5 470 RA0/AN0 2 RA1/AN1 3 RA2/AN2/VREF-/CVREF 4 RA3/AN3/VREF+ 5 RA4/T0CKI/C1OUT/RCV 6 RA5/AN4/SS/LVDIN/C2OUT 7 RA6/OSC2/CLKO 14 OSC1/CLKI 13 RB0/AN12/INT0/FLT0/SDI/SDA 33 RB1/AN10/INT1/SCK/SCL 34 RB2/AN8/INT2/VMO 35 RB3/AN9/CCP2/VPO 36 RB4/AN11/KBI0/CSSPP 37 RB5/KBI1/PGM 38 RB6/KBI2/PGC 39 RB7/KBI3/PGD 40 RC0/T1OSO/T1CKI 15 RC1/T1OSI/CCP2/UOE 16 RC2/CCP1/P1A 17 VUSB 18 RC4/D-/VM 23 RC5/D+/VP 24 RC6/TX/CK 25 RC7/RX/DT/SDO 26 RD0/SPP0 19 RD1/SPP1 20 RD2/SPP2 21 RD3/SPP3 22 RD4/SPP4 27 RD5/SPP5/P1B 28 RD6/SPP6/P1C 29 RD7/SPP7/P1D 30 RE0/AN5/CK1SPP 8 RE1/AN6/CK2SPP 9 RE2/AN7/OESPP 10 RE3/MCLR/VPP 1 U1 PIC18F4550 OSC2 D8 L7 L6 L5 L4 L3 L1 L2 L0 L0 L1 L2 L3 L4 L5 L6 L7 Figura 14: Diseño Final 1.3. Simulación en PROTEUS Una vez terminado el diseño y generado el archivo Hex abrimos el Proteus y hacemos click sobre el PIC para cargar el programa compilado, se hace click en Program File y se selecciona el archivo. Una vez cargado el programa en la parte inferior vemos los botones que nos permitirán poder correr el programa, si presionamos Play se observa el funcionamiento del programa tal como se muestra en la gura 15 D4 R4 470 D3 R3 470 D2 R2 470 D1 R1 470 OSC1 VDD R20 4.7k R8 470 D7 R7 470 D6 R6 470 D5 R5 470 RA0/AN0 2 RA1/AN1 3 RA2/AN2/VREF-/CVREF 4 RA3/AN3/VREF+ 5 RA4/T0CKI/C1OUT/RCV 6 RA5/AN4/SS/LVDIN/C2OUT 7 RA6/OSC2/CLKO 14 OSC1/CLKI 13 RB0/AN12/INT0/FLT0/SDI/SDA 33 RB1/AN10/INT1/SCK/SCL 34 RB2/AN8/INT2/VMO 35 RB3/AN9/CCP2/VPO 36 RB4/AN11/KBI0/CSSPP 37 RB5/KBI1/PGM 38 RB6/KBI2/PGC 39 RB7/KBI3/PGD 40 RC0/T1OSO/T1CKI 15 RC1/T1OSI/CCP2/UOE 16 RC2/CCP1/P1A 17 VUSB 18 RC4/D-/VM 23 RC5/D+/VP 24 RC6/TX/CK 25 RC7/RX/DT/SDO 26 RD0/SPP0 19 RD1/SPP1 20 RD2/SPP2 21 RD3/SPP3 22 RD4/SPP4 27 RD5/SPP5/P1B 28 RD6/SPP6/P1C 29 RD7/SPP7/P1D 30 RE0/AN5/CK1SPP 8 RE1/AN6/CK2SPP 9 RE2/AN7/OESPP 10 RE3/MCLR/VPP 1 U1 PIC18F4550 OSC2 D8 L7 L6 L5 L4 L3 L1 L2 L0 L0 L1 L2 L3 L4 L5 L6 L7 Figura 15: Funcionamiento del Proyecto 1 PROF. ALEXIS CABELLO PÁGINA: 10
  • 14. UNEXPO-LCM 2. Proyecto 2 El proyecto dos consiste básicamente en la misma lógica y en el mismo diseño del proyecto uno, la diferencia se encuentra en que en este proyecto no se encenderán todos los 8 LEDs de forma simultanea, si no por el contrario de forma secuencial, por lo que el programa en C sera totalmente diferente, sin embargo se mantiene el mismo diseño en el PROTEUS. 2.1. Programa Proyecto2.c Para comenzar se debe incluir los archivos de encabezado (.h) y se programan los bits de congu- ración mediante la instrucción pragma, como se explicó en el proyecto 1 y se muestran en el listado 1. Para inicializar el programa se conguran todos los bits de PORTD como salida, haciendo uso de TRISD. Para que el usuario pueda observar el encendido y apagado de los LEDs se llama a la librería de retardo Delay10KTCYx (n); esta librería de retardo es suministrada por el compilador MPLAB C18, y permite generar un retardo total de 10.000 ciclos de instrucción por el numero suministrado como parámetro (n 256). De esta forma y con las especicaciones dadas, se elabora el programa, quedando como se muestra en el listado 3 Listado 3 proyecto2.c void main() { unsigned char led=0; TRISD = 0x00; // set direction to be output ADCON1 |= 0x0F;//A/D port as digital do { PORTD=(1 led); led++; if(led==8) led=0; Delay10KTCYx(100); // delay PORTD=0x0; Delay10KTCYx(100); // delay }while(1); } En este caso se utiliza la variable LED, que se inicializa con 0. Esta variable indicará cuantas veces se va a rotar de derecha a izquierda el número 1. De esta forma se logra encender un solo LED a la vez de forma secuencial de derecha a izquierda y no de forma simultanea como se hizo en el proyecto 1. Para observarlo grácamente se muestra un ejemplo en la tabla 1, con la variable LED en 3. La variable LED se incrementa en uno y se repite el proceso mientras no llegue a 8. Cuando la variable LED llegue a 8, se cumple la condición y la inicializamos en 0 nuevamente. 2.2. Diseño en el PROTEUS El diseño de este proyecto es básicamente el mismo utilizado en el proyecto 1, donde se conectan PROF. ALEXIS CABELLO PÁGINA: 11
  • 15. UNEXPO-LCM Bit7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 0 0 0 0 0 0 0 1 Número antes de rotar. Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 0 0 0 0 1 0 0 0 Número después de rotar 3 veces a la izquierda. Se enciende el LED 3 Tabla 1: Ejemplo del LED a encender 8 LEDs al puerto D del PIC, es decir los pines 19 al 30. Los cuales corresponden a los congurados como salida en el programa. Al momento de compilar el programa en MPLAB, se obtiene el archivo .HEX, que se debe cargar en el PIC18F4550 y al ejecutar la simulación, se observa cómo con el mismo diseño, los LEDs ahora encienden uno por uno a la vez, como se muestra en la gura 16, así continuamente hasta llegar al LED 8 y comienza nuevamente en el 1. D4 R4 470 D3 R3 470 D2 R2 470 D1 R1 470 OSC1 VDD R20 4.7k R8 470 D7 R7 470 D6 R6 470 D5 R5 470 RA0/AN0 2 RA1/AN1 3 RA2/AN2/VREF-/CVREF 4 RA3/AN3/VREF+ 5 RA4/T0CKI/C1OUT/RCV 6 RA5/AN4/SS/LVDIN/C2OUT 7 RA6/OSC2/CLKO 14 OSC1/CLKI 13 RB0/AN12/INT0/FLT0/SDI/SDA 33 RB1/AN10/INT1/SCK/SCL 34 RB2/AN8/INT2/VMO 35 RB3/AN9/CCP2/VPO 36 RB4/AN11/KBI0/CSSPP 37 RB5/KBI1/PGM 38 RB6/KBI2/PGC 39 RB7/KBI3/PGD 40 RC0/T1OSO/T1CKI 15 RC1/T1OSI/CCP2/UOE 16 RC2/CCP1/P1A 17 VUSB 18 RC4/D-/VM 23 RC5/D+/VP 24 RC6/TX/CK 25 RC7/RX/DT/SDO 26 RD0/SPP0 19 RD1/SPP1 20 RD2/SPP2 21 RD3/SPP3 22 RD4/SPP4 27 RD5/SPP5/P1B 28 RD6/SPP6/P1C 29 RD7/SPP7/P1D 30 RE0/AN5/CK1SPP 8 RE1/AN6/CK2SPP 9 RE2/AN7/OESPP 10 RE3/MCLR/VPP 1 U1 PIC18F4550 OSC2 D8 L7 L6 L5 L4 L3 L1 L2 L0 L0 L1 L2 L3 L4 L5 L6 L7 Figura 16: Encendido del LED 1 3. Proyecto 3 El proyecto 3 se enfoca en el uso de las funciones de manejo de una pantalla LCD mediante la programación del PIC 18F4550 para mostrar cadenas de caracteres en las diferentes líneas de la pantalla. 3.1. Programa Proyecto3.c Para comenzar a realizar el programa en C, esta vez se necesitan una serie de funciones adicionales o subrutinas, para poder trabajar con la pantalla LCD. Estas rutinas se describen en el Anexo A. Primero se debe incluir los archivos de encabezado (.h) y se programan los bits de conguración mediante la instrucción pragma, como se explicó en el proyecto 1 y se muestran en el listado 1. En este proyecto PROF. ALEXIS CABELLO PÁGINA: 12
  • 16. UNEXPO-LCM se debe agregar el archivo de encabezado (lcd.h) para poder hacer uso de las funciones de manejo del LCD. Listado 4 proyecto3.c #include lcd.h CHAR buffer1[16]=HELLO WORLD; CHAR buffer2[16]=Hola Mundo; void main() { ADCON1 |= 0x0F; //A/D port as digital PORTC = TRISC = 0x00; PORTB = TRISB = 0x00; lcd_init(); lcd_clear(); lcd_display(1,1,buffer1); lcd_display(2,3,buffer2); for(;;); } 3.2. Diseño en el PROTEUS En el diseño de proteus se agrega la pantalla LCD (LM016L9) y se conectan los terminales de datos al puerto B, los terminales de control al puerto E, los terminales de alimentación de VDD a 5V, VSS y VEE a GND para obtener el mayor contraste. El diseño nal y la simulación del proyecto se muestra en la gura 17. RE2 RB4 RB5 RB6 RB7 RE0 VDD RE1 D7 14 D6 13 D5 12 D4 11 D3 10 D2 9 D1 8 D0 7 E 6 RW 5 RS 4 VSS 1 VDD 2 VEE 3 LCD2 LM016L D4 R4 470 D3 R3 470 D2 R2 470 D1 R1 470 OSC1 VDD R20 4.7k R8 470 D7 R7 470 D6 R6 470 D5 R5 470 RA0/AN0 2 RA1/AN1 3 RA2/AN2/VREF-/CVREF 4 RA3/AN3/VREF+ 5 RA4/T0CKI/C1OUT/RCV 6 RA5/AN4/SS/LVDIN/C2OUT 7 RA6/OSC2/CLKO 14 OSC1/CLKI 13 RB0/AN12/INT0/FLT0/SDI/SDA 33 RB1/AN10/INT1/SCK/SCL 34 RB2/AN8/INT2/VMO 35 RB3/AN9/CCP2/VPO 36 RB4/AN11/KBI0/CSSPP 37 RB5/KBI1/PGM 38 RB6/KBI2/PGC 39 RB7/KBI3/PGD 40 RC0/T1OSO/T1CKI 15 RC1/T1OSI/CCP2/UOE 16 RC2/CCP1/P1A 17 VUSB 18 RC4/D-/VM 23 RC5/D+/VP 24 RC6/TX/CK 25 RC7/RX/DT/SDO 26 RD0/SPP0 19 RD1/SPP1 20 RD2/SPP2 21 RD3/SPP3 22 RD4/SPP4 27 RD5/SPP5/P1B 28 RD6/SPP6/P1C 29 RD7/SPP7/P1D 30 RE0/AN5/CK1SPP 8 RE1/AN6/CK2SPP 9 RE2/AN7/OESPP 10 RE3/MCLR/VPP 1 U1 PIC18F4550 OSC2 D8 L7 L6 L5 L4 L3 L1 L2 L0 L0 L1 L2 L3 L4 L5 L6 L7 RB4 RB5 RB6 RB7 RE0 RE2 RE1 Figura 17: Diseño del Proyecto 3 PROF. ALEXIS CABELLO PÁGINA: 13
  • 17. UNEXPO-LCM 4. Proyecto 4 El proyecto 4 se enfoca en el uso de las funciones de manejo de un teclado matricial de 4x3 mediante la programación del PIC 18F4550. Se realiza un programa de prueba que muestra en una pantalla LCD la tecla presionada. 4.1. Programa Proyecto4.c Para comenzar a realizar el programa en C, esta vez se necesitan una serie de funciones adicionales o subrutinas, para poder trabajar con el Teclado. Estas rutinas se describen en el Anexo B. En este proyecto se debe agregar las declaraciones de las funciones del teclado para poder hacer uso de estas, tal como se muestra en el listado 5 Listado 5 proyecto4.c CHAR buf1[16]=KEYPAD TEST; CHAR buf2[16]=KEY: ; CHAR keycodes[17] = {0,’#’,’0’,’*’,’-’,’9’,’8’,’7’, ’-’,’6’,’5’,’4’,’-’,’3’,’2’,’1’,’-’}; unsigned short kp,ka,led=1,sw=1; int delay=0; char keypadread(void); char scankey(void); VOID main() { ADCON1 |= 0x0F; PORTA = TRISA = 0x00; PORTB = TRISB = 0x00; INTCON2 = ~0x80; //conecta las resistencias pull-up al puerto B lcd_init(); lcd_clear(); lcd_display(1,1,buf1); Delay10KTCYx(250); lcd_clear(); lcd_display(1,1,buf2); do { kp=0; do { kp = keypadread(); // Store key code in kp variable Delay10KTCYx(12); }while (!kp); ka=keycodes[kp]; if(ka==’#’ led0x80) led=led1; if(ka==’*’ led0x01) led=led1; PORTD=led; lcd_clear(); lcd_display(1,1,buf2); lcd_char(ka); // Print key ASCII value on LCD } while (1); } PROF. ALEXIS CABELLO PÁGINA: 14
  • 18. UNEXPO-LCM Como se muestra en el listado 5, se utiliza la función keypadread para leer una tecla, la cual retorna el código de la tecla presionada (1 a 12). Este código se utiliza como el indice de la tabla keycodes, la cual guarda el carácter ASCII de la tecla presionada. Luego se utiliza ese carácter ASCII para mostrarlo en la pantalla LCD. 4.2. Diseño en el PROTEUS En el diseño de proteus se agrega la pantalla LCD (LM016L9) y un teclado matricial (KEYPAD). A las líneas de entrada al microcontrolador (RB1-RB3) se agregan resistencias de 10k conectadas al VCC (Pull-ups ), esto con el n de detectar niveles alto cuando ninguna tecla sea presionada. Esto sólo se requiere a nivel de simulación en proteus, puesto que cuando se implementa físicamente con el microcontrolador se pueden utilizar las resistencias pull-up internas del microcontrolador a través de la instrucción (INTCON2 = ~0x80). El simulador no procesa correctamente esta instrucción. En la gura 18 se muestra el diseño nal y una simulación del proyecto. RE2 RB4 RB5 RB6 RB7 RE0 VDD RE1 D7 14 D6 13 D5 12 D4 11 D3 10 D2 9 D1 8 D0 7 E 6 RW 5 RS 4 VSS 1 VDD 2 VEE 3 LCD2 LM016L D4R4 470 D3R3 470 D2R2 470 D1R1 470 OSC1 VDD R20 4.7k R8 470 D7R7 470 D6R6 470 D5R5 470 RA0/AN0 2 RA1/AN1 3 RA2/AN2/VREF-/CVREF 4 RA3/AN3/VREF+ 5 RA4/T0CKI/C1OUT/RCV 6 RA5/AN4/SS/LVDIN/C2OUT 7 RA6/OSC2/CLKO 14 OSC1/CLKI 13 RB0/AN12/INT0/FLT0/SDI/SDA 33 RB1/AN10/INT1/SCK/SCL 34 RB2/AN8/INT2/VMO 35 RB3/AN9/CCP2/VPO 36 RB4/AN11/KBI0/CSSPP 37 RB5/KBI1/PGM 38 RB6/KBI2/PGC 39 RB7/KBI3/PGD 40 RC0/T1OSO/T1CKI 15 RC1/T1OSI/CCP2/UOE 16 RC2/CCP1/P1A 17 VUSB 18 RC4/D-/VM 23 RC5/D+/VP 24 RC6/TX/CK 25 RC7/RX/DT/SDO 26 RD0/SPP0 19 RD1/SPP1 20 RD2/SPP2 21 RD3/SPP3 22 RD4/SPP4 27 RD5/SPP5/P1B 28 RD6/SPP6/P1C 29 RD7/SPP7/P1D 30 RE0/AN5/CK1SPP 8 RE1/AN6/CK2SPP 9 RE2/AN7/OESPP 10 RE3/MCLR/VPP 1 U1 PIC18F4550 OSC2 D8 L7 L6 L5 L4 L3 L1 L2 L0 L0 L1 L2 L3 L4 L5 L6 L7 RB4 RB5 RB6 RB7 RE0 RE2 RE1 1 2 3 4 5 6 7 8 9 0 # 1 2 3 A B C DRB4 RB5 RB6 RB7 RB3 RB2 RB1 RB1 RB2 RB3 R9 10k R10 10k R12 10k Figura 18: Diseño del proyecto 4 5. Proyecto 5 En el proyecto 5 se utiliza el convertidor analógico a digital (ADC) del PIC 18F4550 para leer el valor de tensión de una señal analógica y mostrar ese valor expresado en milivoltios por la pantalla LCD. Se emplea un potenciómetro para generar una señal analógica que puede variar entre 0 y 5V, la cual se conecta al canal cero (AN0) del Convertidor ADC. 5.1. Convertidor analógico a digital En la gura 19 se muestra un esquema del convertidor analógico a digital (ADC) del PIC 18F4550. Este módulo permite la conversión de una señal analógica a su correspondiente valor digital de 10 bits. El ADC tiene 13 entradas multiplexadas o canales y el canal a convertir se selecciona por medio de los bits CHS3-CHS0 del registro ADCON0 tal como se muestra en la gura 20. PROF. ALEXIS CABELLO PÁGINA: 15
  • 19. UNEXPO-LCM Figura 19: Convertidor Analógico a Digital Registro ADCON0 ADONGo/DoneCHS0CHS1CHS2CHS3---- Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 ADONGo/DoneCHS0CHS1CHS2CHS3---- Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 ADON: ADC On bit 0= Convertidor deshabilitado 1: Convertidor habilitado Go/Done: Bit de estatus de la conversión 0=Conversión lista 1= conversión en progreso CHS0-CHS3: Bits de selección del canal 0000= Canal 0 (AN0) 0001= Canal 1 (AN1) 0010= Canal 2 (AN2) 0011= Canal 3 (AN3) 0100= Canal 4 (AN4) 0101= Canal 5 (AN5) 0110= Canal 6 (AN6) 0111= Canal 7 (AN7) 1000= Canal 8 (AN8) 1001= Canal 9 (AN9) 1010= Canal 10 (AN10) 1011= Canal 11 (AN11) 1100= Canal 12 (AN12) Figura 20: Registro ADCON0 PROF. ALEXIS CABELLO PÁGINA: 16
  • 20. UNEXPO-LCM Registro ADCON1 PCFG0PCFG1PCFG2PCFG3VCFG0VCFG1---- Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 PCFG0PCFG1PCFG2PCFG3VCFG0VCFG1---- Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 PCFG3-0: Bits de configuración de los puertos analógicos. VCFG0: Bit de configuración del voltaje de referencia negativo VREF- 0=VSS 1=AN2 VCFG1: Bit de configuración del voltaje de referencia positivo VREF+ 0=VDD 1=AN3 DDDDDDDDDDDDD1111 ADDDDDDDDDDDD1110 AADDDDDDDDDDD1101 AAADDDDDDDDDD1100 AAAADDDDDDDDD1011 AAAAADDDDDDDD1010 AAAAAADDDDDDD1001 AAAAAAADDDDDD1000 AAAAAAAADDDDD0111 AAAAAAAAADDDD0110 AAAAAAAAAADDD0101 AAAAAAAAAAADD0100 AAAAAAAAAAAAD0011 AAAAAAAAAAAAA0010 AAAAAAAAAAAAA0001 AAAAAAAAAAAAA0000 AN0AN1AN2AN3AN4AN5AN6AN7AN8AN9AN10AN11AN12PFCG3-PCFG0 DDDDDDDDDDDDD1111 ADDDDDDDDDDDD1110 AADDDDDDDDDDD1101 AAADDDDDDDDDD1100 AAAADDDDDDDDD1011 AAAAADDDDDDDD1010 AAAAAADDDDDDD1001 AAAAAAADDDDDD1000 AAAAAAAADDDDD0111 AAAAAAAAADDDD0110 AAAAAAAAAADDD0101 AAAAAAAAAAADD0100 AAAAAAAAAAAAD0011 AAAAAAAAAAAAA0010 AAAAAAAAAAAAA0001 AAAAAAAAAAAAA0000 AN0AN1AN2AN3AN4AN5AN6AN7AN8AN9AN10AN11AN12PFCG3-PCFG0 Figura 21: Registro ADCON1 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 Go TAD Adquisición Conversión TACQ 1 (Fosc/n) TAD= n=2,4,8,16,32,64 TACQ= m*TAD m=0,2,4,6,8,12,16,20 Figura 22: Tiempo de adquisición-conversión PROF. ALEXIS CABELLO PÁGINA: 17
  • 21. UNEXPO-LCM Registro ADCON2 ADCS0ADCS1ADCS2ACQT0ACQT1ACQT2--ADFM Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 ADCS0ADCS1ADCS2ACQT0ACQT1ACQT2--ADFM Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 ADCS2-ADCS0: Reloj de Conversión del ADC 000= Fosc/2 001= Fosc/8 010= Fosc/32 011= FRC (Oscilador RC Interno) 100= Fosc/4 101= Fosc/16 110= Fosc/64 111= FRC (Oscilador RC Interno) ADFM: Formato del Resultado del ADC 0 = Justificado a la Izquierda 1 = Justificado a la derecha ACQT2-ACQT0: Tiempo de adquisición del ADC 000= 0 Tad 001= 2 Tad 010= 4 Tad 011= 6 Tad 100= 8 Tad 101= 12 Tad 110= 16 Tad 111= 20 Tad Figura 23: Registro ADCON2 ADRESL Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 ADRESL Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 ADRESH: Byte alto del resultado de la conversión ADRESL: Byte bajo del resultado de la conversión ADRESH Bit 8Bit 9 ADRESH Bit 8Bit 9 Figura 24: Resultado justicado a la derecha PROF. ALEXIS CABELLO PÁGINA: 18
  • 22. UNEXPO-LCM En las guras 21 y 23 se muestran el resto de los registros donde se congura el funcionamiento del ADC. En el registro ADCON1 se congura el voltaje de referencia positivo a VDD y el negativo a GND, así como se denen los terminales analógicos y digitales, en éste proyecto se conguran los terminales AN0-AN3 como analógicos y el resto digitales. En el registro ADCON2 se congura el tiempo de la conversión según se muestra en la gura 22. El tiempo de conversión de cada bit (TAD) mínimo debe ser 0.8us y el tiempo de adquisición (TACQ) mínimo debe ser de 1.4us según la hoja de especicaciones. Como se utiliza una Fosc de 48MHz, se utiliza el divisor de 64 y 4 TAD para el TACQ para satisfacer los requerimientos. El resultado de la conversión se obtiene en los registros ADRESH y ADRESL, la cual puede ser ajustado a la derecha o a la izquierda. En la gura 24 se muestra el resultado justicado a la derecha, la cual es la utilizada en este proyecto. Los valores de los registros se pueden apreciar en el listado 7 donde se congura la rutina de conversión del ADC. 5.2. Programa Proyecto5.c El listado 6 muestra la rutina principal del proyecto y el listado 7 muestra la rutina para leer el valor de la conversión. A esta última se debe pasar como parámetro el canal del ADC que se quiere leer, en este proyecto se lee la señal analógica conectada al canal cero (AN0). Para mostrar el valor correspondiente en milivoltios con dos dígitos decimales por el LCD, se realiza la conversión mostrada en la ecuación 1: volts = n · 5000 mV 1024 × 100 (1) donde: n es el valor del ADC (0-1023) que corresponde a (0-5v). Se multiplica por 100 para tomar dos decimales de precisión. Luego se toma la parte entera diviendo los voltios entre 100 y se toma el resto de la división como la parte decimal, y nalmente se convierten estos valores en un cadena de caracteres ASCII para su visualización en la pantalla LCD. 5.3. Diseño en el PROTEUS En la gura 25 se muestra el diseño en proteus del proyecto 5. Se utiliza el proyecto 4 como base y se agrega un potenciómetro para generar la señal analógica. El cursor del potenciómetro se conecta al terminal AN0 del PIC. La gura muestra el cursor del potenciómetro en 50 %, lo que corresponde a un valor de 2493.68 mV, el cual se observa en la pantalla LCD. Al variar el cursor del potenciómetro se puede apreciar como se actualiza el valor medido en la pantalla LCD, funcionando el sistema como un voltímetro digital. PROF. ALEXIS CABELLO PÁGINA: 19
  • 23. UNEXPO-LCM Listado 6 proyecto5.c #include p18cxxx.h #include delays.h #include stdlib.h #include lcd.h #pragma config PLLDIV = 5 // (20 MHz crystal) #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2 #pragma config FOSC = HSPLL_HS //HSPLL_HS #pragma config WDT = OFF #pragma config MCLRE = ON #pragma config LVP = OFF CHAR lcd[16]; CHAR msg[]=mV= ; unsigned int Vin,Vdec,Vfrac; unsigned long volts; unsigned int adc_read(unsigned char ch); unsigned char ch1,ch2; VOID main() { ADCON1 |= 0x0F; PORTE = TRISE = 0x00; PORTB = TRISB = 0x00; lcd_init(); TRISAbits.TRISA0 = 1; //AN0 for(;;) // Endless loop { lcd_clear(); Vin = adc_read(0); // Read from channel 0 (AN0) lcd_display(1,1,msg); // Display mV = volts=Vin; volts = 488*volts; // Scale up the result Vdec = volts / 100; // Decimal part Vfrac = volts % 100; // Fractional part itoa(Vdec,lcd); // Convert Vdec to string in lcd // Display result on LCD // lcd_display(1,6,lcd); // Output to LCD lcd_char(’.’); // Display . ch1 = Vfrac / 10; // Calculate fractional part ch2 = Vfrac % 10; // Calculate fractional part lcd_char(48+ch1); // Display fractional part lcd_char(48+ch2); // Display fractional part Delay10KTCYx(250); // delay Delay10KTCYx(250); // delay } } PROF. ALEXIS CABELLO PÁGINA: 20
  • 24. UNEXPO-LCM Listado 7 continuación proyecto5.c unsigned int adc_read(unsigned char ch) { unsigned int result; ADCON0 = (ch 0x0F) 2; ADCON1 = 0x0B; //RA0-RA3 Analog inputs. ADCON2 = 0x96; // right justify,TACQ=4*TAD, TAD=1/(FOSC/64) ADCON0bits.ADON = 1; // ADC on ADCON0bits.GO_DONE = 1; // start while (ADCON0bits.GO_DONE == 1); result = ((unsigned int)(ADRESH) 8) + ADRESL; ADCON0bits.ADON = 0; // ADC Off return result; } 50% RV1 10k VDD AN0 AN0 RE2 RB4 RB5 RB6 RB7 RE0 VDD RE1 D7 14 D6 13 D5 12 D4 11 D3 10 D2 9 D1 8 D0 7 E 6 RW 5 RS 4 VSS 1 VDD 2 VEE 3 LCD2 LM016L OSC1 VDD R20 4.7k RA0/AN0 2 RA1/AN1 3 RA2/AN2/VREF-/CVREF 4 RA3/AN3/VREF+ 5 RA4/T0CKI/C1OUT/RCV 6 RA5/AN4/SS/LVDIN/C2OUT 7 RA6/OSC2/CLKO 14 OSC1/CLKI 13 RB0/AN12/INT0/FLT0/SDI/SDA 33 RB1/AN10/INT1/SCK/SCL 34 RB2/AN8/INT2/VMO 35 RB3/AN9/CCP2/VPO 36 RB4/AN11/KBI0/CSSPP 37 RB5/KBI1/PGM 38 RB6/KBI2/PGC 39 RB7/KBI3/PGD 40 RC0/T1OSO/T1CKI 15 RC1/T1OSI/CCP2/UOE 16 RC2/CCP1/P1A 17 VUSB 18 RC4/D-/VM 23 RC5/D+/VP 24 RC6/TX/CK 25 RC7/RX/DT/SDO 26 RD0/SPP0 19 RD1/SPP1 20 RD2/SPP2 21 RD3/SPP3 22 RD4/SPP4 27 RD5/SPP5/P1B 28 RD6/SPP6/P1C 29 RD7/SPP7/P1D 30 RE0/AN5/CK1SPP 8 RE1/AN6/CK2SPP 9 RE2/AN7/OESPP 10 RE3/MCLR/VPP 1 U1 PIC18F4550 OSC2 L7 L6 L5 L4 L3 L1 L2 L0 RB4 RB5 RB6 RB7 RE0 RE2 RE1 RB1 RB2 RB3 R9 10k R10 10k R12 10k Figura 25: Diseño del proyecto 5 6. Proyecto 6 En el proyecto 6 se utilizan las interrupciones para realizar un reloj digital a partir de una fuente de alimentación de corriente alterna de 60Hz. La fuente alterna alimenta un circuito que genera un pulso por cada cruce por cero de la señal (detector de cruce por cero) y esta señal se utiliza como una fuente de interrupción externa para el conteo del tiempo. PROF. ALEXIS CABELLO PÁGINA: 21
  • 25. UNEXPO-LCM 50% RV1 10k VDD AN0 AN0 RE2 RB4 RB5 RB6 RB7 RE0 VDD RE1 D7 14 D6 13 D5 12 D4 11 D3 10 D2 9 D1 8 D0 7 E 6 RW 5 RS 4 VSS 1 VDD 2 VEE 3 LCD2 LM016L OSC1 VDD R20 4.7k RA0/AN0 2 RA1/AN1 3 RA2/AN2/VREF-/CVREF 4 RA3/AN3/VREF+ 5 RA4/T0CKI/C1OUT/RCV 6 RA5/AN4/SS/LVDIN/C2OUT 7 RA6/OSC2/CLKO 14 OSC1/CLKI 13 RB0/AN12/INT0/FLT0/SDI/SDA 33 RB1/AN10/INT1/SCK/SCL 34 RB2/AN8/INT2/VMO 35 RB3/AN9/CCP2/VPO 36 RB4/AN11/KBI0/CSSPP 37 RB5/KBI1/PGM 38 RB6/KBI2/PGC 39 RB7/KBI3/PGD 40 RC0/T1OSO/T1CKI 15 RC1/T1OSI/CCP2/UOE 16 RC2/CCP1/P1A 17 VUSB 18 RC4/D-/VM 23 RC5/D+/VP 24 RC6/TX/CK 25 RC7/RX/DT/SDO 26 RD0/SPP0 19 RD1/SPP1 20 RD2/SPP2 21 RD3/SPP3 22 RD4/SPP4 27 RD5/SPP5/P1B 28 RD6/SPP6/P1C 29 RD7/SPP7/P1D 30 RE0/AN5/CK1SPP 8 RE1/AN6/CK2SPP 9 RE2/AN7/OESPP 10 RE3/MCLR/VPP 1 U1 PIC18F4550 OSC2 L7 L6 L5 L4 L3 L1 L2 L0 RB4 RB5 RB6 RB7 RE0 RE2 RE1 RB1 RB2 RB3 R12 10k R14 10k R13 10k A K C E B 1 2 4 5 6 U2 4N25 R11 240 VDD R10 10k RB0 BR1 2W08G V1 VSINE VO=0 VA=20 FREQ=60 K RB0 Figura 26: Diseño del proyecto 6 6.1. Programa proyecto6.c En los listados 8 y 9 se muestra el programa del proyecto6. Lo importante a destacar es la declaración de las interrupciones en el compilador MPLAB C18. En los microcontroladores 18F existen dos vectores de interrupción, uno de alta prioridad y otro de baja prioridad. El vector de alta prioridad se encuentra en la dirección 0x08h y el de baja prioridad en el la dirección 0x18h. El bit IPEN del registro RCON habilita las prioridades de las interrupciones. Si el bit IPEN=0 como es por defecto no se utilizan las prioridades de las interrupciones y todas utilizan el vector de interrupción de alta prioridad (0x08h). En este proyecto no se utilizan las prioridades y se emplea la directiva #pragma code para escribir en el vector de interrupción de alta prioridad el salto a la rutina de interrupción y se utiliza la directiva #pragma interrupt para indicar cual es la rutina de interrupción. Como la frecuencia de la fuente de alimentación es de 60Hz, el circuito detector de cruce por cero genera 120 pulsos en un segundo. Por esto, en la rutina de interrupción se acumula cada vez que se genera una interrupción y cuando se alcanza 120 se pone en cero y se empienza a incrementar los segundos. Igualmente se procede con los segundos, cuando se alcanzan los 60 se pone en cero y se empiezan a incrementar los minutos hasta alcanzar los 60 minutos donde se pone en cero y empieza de nuevo el reloj. En la rutina principal del programa se habilita la interrupción INT0 y luego en un bucle innito se convierten constantemente los minutos y segundos a ASCII y se muestra en la pantalla LCD el tiempo. 6.2. Diseño en PROTEUS En la Figura 26 se muestra el diseño en proteus. Para la simulación se emplea una fuente alterna de 13Vac y el circuito detector de cruce por cero aislado del microcontrolador por medio de un opto- acoplador 4N25, la señal de salida del detector (RB0) se conecta al terminal de interrupción externa (INT0). En la simulación se muestra el reloj indicando que ha transcurrido 1 minuto y 06 segundos. PROF. ALEXIS CABELLO PÁGINA: 22
  • 26. UNEXPO-LCM Listado 8 proyecto6.c #include p18cxxx.h #include delays.h #include stdlib.h #include lcd.h #pragma config PLLDIV = 5 // (20 MHz crystal) #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2 #pragma config FOSC = HSPLL_HS //HSPLL_HS #pragma config WDT = OFF #pragma config LVP = OFF unsigned char tick=0,seg=0,min=0; unsigned char ch1,ch2; CHAR lcd_seg[16]; CHAR lcd_min[16]; CHAR msg[16]=Time:; void InterruptHandlerHigh (void); //---------------------------------------------------------------------------- // High priority interrupt vector #pragma code InterruptVectorHigh = 0x08 void InterruptVectorHigh (void) { _asm goto InterruptHandlerHigh //jump to interrupt routine _endasm } //---------------------------------------------------------------------------- // High priority interrupt routine #pragma code #pragma interrupt InterruptHandlerHigh void InterruptHandlerHigh () { if (INTCONbits.INT0IF == 1) { INTCONbits.INT0IF = 0; tick++; if(tick==120) { tick=0; seg++; } if(seg==60) { seg=0; min++; } if(min==60) min=0; } } PROF. ALEXIS CABELLO PÁGINA: 23
  • 27. UNEXPO-LCM Listado 9 continuación de proyecto6.c void main() { TRISA=TRISB=TRISC=TRISD = 0x00; // set direction to be output PORTD=0x0; ADCON1 = 0x0F; lcd_init(); TRISBbits.RB0=1; INTCONbits.GIE = 1; //enable global interrupts INTCONbits.PEIE = 1; //enable peripherical interrupts INTCONbits.INT0IE =1; //enable INT0 Interrupt lcd_clear(); lcd_display(1,1,msg); do{ setpos(1,7); ch1 = min / 10; // digit1 ch2 = min % 10; // digit2 lcd_char(48+ch1); // Display digit1 lcd_char(48+ch2); // Display digit2 lcd_char(’:’); ch1 = seg / 10; // digit1 ch2 = seg % 10; // digit2 lcd_char(48+ch1); // Display digit1 lcd_char(48+ch2); // Display digit2 }while(1); } PROF. ALEXIS CABELLO PÁGINA: 24
  • 28. UNEXPO-LCM 7. Proyecto 7 En el proyecto 7 se muestra el uso del temporizador del microcontrolador para tener un control exacto del tiempo y así generar una señal cuadrada de 120Hz. El ciclo de trabajo de la señal cuadrada generada es de 50 % pero cambiando el valor en una variable se puede cambiar el ancho de pulso o ciclo de trabajo. 7.1. Temporizador El microcontrolador PIC 18F4550 tiene cuatro temporizadores TIMER0-3. En el siguiente proyecto utilizamos el TIMER2 que es básicamente un contador de 8 bits (TMR2) con un divisor de pre-escalado y uno de pos-escalado. En la gura 27 se muestra el esquema del TIMER2. Figura 27: Temporizador 2 El contador TMR2 incrementa desde cero hasta que es igual al valor del registro PR2. Este incre- mento depende del valor del divisor del reloj o pre-escalado (PRESCALER), el cual puede ser 1, 4, o 16. Para jar el periodo del temporizador (PR2) se puede utilizar la ecuación 2 T = (PR2 + 1) ∗ 4 ∗ 1 Fosc ∗ PRESCALER ∗ POSTSCALER (2) donde: Fosc es la la frecuencia del oscilador. PRESCALER es el valor del divisor del oscilador a la entrada del temporizador. POSTCALER es el valor del divisor de la señal de salida del temporizador. T es el periodo de la señal a generar. PR2 es el registro del periodo. El valor del contador TMR2 se compara con el valor del registro PR2 en cada ciclo de reloj y cuando el contador TMR2 es igual al registro PR2 el comparador produce una señal que va al contador de pos-escalado y pone en cero el contador TMR2. Dependiendo del valor prejado de pos-escalado se activa la bandera de interrupción TMR2IF que se encuentra en el registro PIR1. En este proyecto como el pos-escalado es igual a 1, la interrupción se genera cuando el valor de TMR2 es igual al valor de PR2. Para habilitar la interrupción del temporizador 2 se utiliza el bit TMR2IE del registro PIE1. Los valores de pre-escalado y pos-escalado se conguran en el registro T2CON tal como se muestra en la gura 28. PROF. ALEXIS CABELLO PÁGINA: 25
  • 29. UNEXPO-LCM Registro T2CON T2CKPS0T2CKPS1TMR2ONT2OUTPS0T2OUTPS1T2OUTPS0T2OUTPS3-- Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 T2CKPS0T2CKPS1TMR2ONT2OUTPS0T2OUTPS1T2OUTPS0T2OUTPS3-- Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 T2CKPS1-0: Pre-escalar del reloj del Timer 2 00= 1:1 01= 1:4 1x= 1:16 TMR2ON: Activación del Timer2 1=Activado (ON) 0= Desactivado (OFF) T2OUTPS3-0: Post-escalar de la salida del Timer 2 0000= 1:1 0001= 1:2 . . 1111= 1:16 Figura 28: Registro T2CON 7.2. Programa proyecto7.c En los listados 10 y 11 se muestra el programa proyecto7.c. El periodo de la señal a generar (8.33ms) se divide entre 512 y se utiliza el temporizador 2 para generar una interrupción cada 16.275us. Para generar la señal cuadrada con 50 % de ciclo de trabajo lo primero que se hace es incrementar un contador por cada interrupción y cuando alcanza el valor medio de 256 se pone en bajo la señal y cuando alcanza el valor máximo de 512 se pone en cero el contador y se pone la señal en alto. Listado 10 proyecto7.c #include p18cxxx.h #include delays.h #include stdlib.h #include lcd.h #pragma config PLLDIV = 5 // (20 MHz crystal) #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2 #pragma config FOSC = HSPLL_HS //HSPLL_HS #pragma config WDT = OFF unsigned int count=0; void initTimer (void); void InterruptHandlerHigh (void); PROF. ALEXIS CABELLO PÁGINA: 26
  • 30. UNEXPO-LCM Listado 11 continuación de proyecto7.c // High priority interrupt vector #pragma code InterruptVectorHigh = 0x08 void InterruptVectorHigh (void) { _asm goto InterruptHandlerHigh //jump to interrupt routine _endasm } // High priority interrupt routine #pragma code #pragma interrupt InterruptHandlerHigh void InterruptHandlerHigh () { if (PIR1bits.TMR2IF == 1) { PIR1bits.TMR2IF = 0; count++; if(count==256) PORTD=0; if(count==512) { PORTD=0xFF; count=0; } } } void main() { TRISA=TRISB=TRISC=TRISD = 0x00; // set direction to be output PORTD=0x0; ADCON1 = 0x0F; INTCONbits.GIE = 1; //enable global interrupts INTCONbits.PEIE = 1; //enable peripherical interrupts initTimer(); while(1); } void initTimer (void) { PR2 = 194; // T = (PR2+1) * 4 *(1/Fosc)*PRESCALER // 16.25us= (PR2+1)* 4*(1/Fosc)*PRESCALER : Fosc=48Mhz : PRESCALER=1 T2CON=0; T2CONbits.T2CKPS1 = 0; T2CONbits.T2CKPS0 = 0; // 1:1 - prescaler IPR1bits.TMR2IP = 1; // high priority PIR1bits.TMR2IF = 0; PIE1bits.TMR2IE = 1; //1=enable Interrupt T2CONbits.TMR2ON = 1; } PROF. ALEXIS CABELLO PÁGINA: 27
  • 31. UNEXPO-LCM 7.3. Diseño en PROTEUS En la Figura 29 se muestra el diseño en proteus del proyecto 7, solamente se ha agregado el osciloscopio para observar la señal cuadrada. Se conecta la salida RD0 del puerto D del PIC al canal A del osciloscopio. En la Figura 30 se muestra la pantalla del osciloscopio, en la cual se puede apreciar el periodo de la señal. 50% RV1 10k VDD AN0 AN0 RE2 RB4 RB5 RB6 RB7 RE0 VDD RE1 D7 14 D6 13 D5 12 D4 11 D3 10 D2 9 D1 8 D0 7 E 6 RW 5 RS 4 VSS 1 VDD 2 VEE 3 LCD2 LM016L D4R4 470 D3R3 470 D2R2 470 D1R1 470 OSC1 VDD R20 4.7k R8 470 D7R7 470 D6R6 470 D5R5 470 RA0/AN0 2 RA1/AN1 3 RA2/AN2/VREF-/CVREF 4 RA3/AN3/VREF+ 5 RA4/T0CKI/C1OUT/RCV 6 RA5/AN4/SS/LVDIN/C2OUT 7 RA6/OSC2/CLKO 14 OSC1/CLKI 13 RB0/AN12/INT0/FLT0/SDI/SDA 33 RB1/AN10/INT1/SCK/SCL 34 RB2/AN8/INT2/VMO 35 RB3/AN9/CCP2/VPO 36 RB4/AN11/KBI0/CSSPP 37 RB5/KBI1/PGM 38 RB6/KBI2/PGC 39 RB7/KBI3/PGD 40 RC0/T1OSO/T1CKI 15 RC1/T1OSI/CCP2/UOE 16 RC2/CCP1/P1A 17 VUSB 18 RC4/D-/VM 23 RC5/D+/VP 24 RC6/TX/CK 25 RC7/RX/DT/SDO 26 RD0/SPP0 19 RD1/SPP1 20 RD2/SPP2 21 RD3/SPP3 22 RD4/SPP4 27 RD5/SPP5/P1B 28 RD6/SPP6/P1C 29 RD7/SPP7/P1D 30 RE0/AN5/CK1SPP 8 RE1/AN6/CK2SPP 9 RE2/AN7/OESPP 10 RE3/MCLR/VPP 1 U1 PIC18F4550 OSC2 D8 L7 L6 L5 L4 L3 L1 L2 L0 L0 L1 L2 L3 L4 L5 L6 L7 RB4 RB5 RB6 RB7 RE0 RE2 RE1 RB1 RB2 RB3 R12 10k R14 10k R13 10k RB0 A B C D L0 Figura 29: Diseño del proyecto 7 Figura 30: Simulación del proyecto 7 PROF. ALEXIS CABELLO PÁGINA: 28
  • 32. UNEXPO-LCM Figura 31: Diagrama del módulo PWM 8. Proyecto 8 En el proyecto 8 se utiliza el módulo CCP1 del microcontrolador. Se congura el módulo CCP1 en modo PWM estándar para generar una señal cuadrada de 4KHz con 50 % de ciclo de trabajo pero a la cual se le puede modicar el ancho del pulso. 8.1. Módulo CCP (Captura, Comparador y PWM) El microcontrolador PIC 18F4550 tiene dos módulos CCP. En este proyecto se utiliza el módulo CCP1 en su modo de funcionamiento de PWM (modulador de ancho de pulso). En la gura 31 se muestra un diagrama del módulo PWM. El módulo permite generar una señal PWM con 10 bits de resolución. El módulo CCP genera los 10 bits de resolución del PWM uniendo los 8 bits del contador TMR2 con 2 bits del divisor de pre-escalado, tal como se observa en la Nota 1 de la gura 31. Estos 10 bits se comparan con los 10 bit del ciclo de trabajo para generar la señal PWM. En la gura 32 se muestra una señal de salida PWM. La señal PWM tiene una base de tiempo jo o período y un tiempo variable en que se encuentra en alto o ciclo de trabajo (ancho del pulso). Tal como se puede apreciar en la gura 31, el módulo utiliza el TIMER2 como contador para generar la señal PWM. El período de la señal se ja escribiendo el registro PR2 según la ecuación 2. El ciclo de trabajo puede tener hasta 10 bits de resolución y se establece escribiendo en los registros CCPRxL y CCPxCON, tal como se muestra en la gura 33. Para congurar el módulo CCP en modo PWM se escribe 1 en los bits CCPxM2-3 del registro CCPxCON tal como se muestra en la gura 34. PROF. ALEXIS CABELLO PÁGINA: 29
  • 33. UNEXPO-LCM Ciclo de trabajo PERIODO TMR2=PR2TMR2=PR2 TMR2=Ciclo de trabajo Figura 32: Señal de salida del módulo PWM Ciclo de trabajo CCPxL Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7Bit 8Bit 9 CCPxL Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7Bit 8Bit 9 CCPxL: Byte mas significativo de los 10Bit del ciclo de trabajo. CPxB0-CPxB1: 2 bits menos significativos de los 10Bits del ciclo de trabajo CCPxCON Bit 0Bit 1 CCPxCON Bit 0Bit 1 Figura 33: Ciclo de trabajo del PWM Registro CCPxCON CCPxM0CCPxM1CCPxM2CCPxM3DCxB0DCxB1---- Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 CCPxM0CCPxM1CCPxM2CCPxM3DCxB0DCxB1---- Bit 0Bit 1Bit 2Bit 3Bit 4Bit 5Bit 6Bit 7 CCPxM0-M3: Selección del modo de operación 0000= Capture/compare/ PWM deshabilitado 0001= reservado 0010= comparador: Cambia la salida cuando sea igual 0011= reservado 0100= modo de captura: cada flanco de caida 0101= modo de captura: cada flanco de subida 0110= modo de captura: cada 4 flanco de subida 0111= modo de captura: cada 16 flanco de subida 1000= comparador: Cambia la salida cuando sea igual 1001= comparador: Cambia la salida cuando sea igual 1010= comparador: Genera interrupción cuando sea igual 1011= comparador: dispara un evento especial, comienza la conversión ADC 11xx= modo PWM DCxB0-DCxB1: Bit0 y Bit1 para el Ciclo de trabajo del PWM Figura 34: Registro CCPxCON PROF. ALEXIS CABELLO PÁGINA: 30
  • 34. UNEXPO-LCM 8.2. Programa proyecto8.c En el listado 12 se muestra el programa proyecto8.c. Para utilizar el módulo CCP1 en modo PWM estándar se congura el registro CCP1CON, escribiendo los bits CCP1M3-CCP1M2 con 1 . El periodo de la señal PWM lo determina el periodo del temporizador 2 y se congura escribiendo el registro PR2. El periodo se calcula a través de la ecuación 2. El módulo CCP permite producir una señal PWM hasta con 10bits de resolución. Para congurar el ciclo de trabajo de trabajo se escribe en el registro CCPR1L los 8 bits mas signicativos y los otros dos bits se escriben en los bit DC1B1-DC1B0 del registro CCP1CON. La salida de la señal PWM se produce por el pin RC2 del puerto C, por lo que esta señal debe ser habilitada como salida para obtener la señal PWM. 8.3. Diseño en PROTEUS En la Figura 35 se muestra el diseño en proteus del proyecto 8, El diseño es básicamente el mismo que el anterior, solo que se conecta la salida RC2 del puerto C al osciloscopio para poder observar la señal PWM generada. La pantalla del osciloscopio donde se observa la señal PWM generada por el programa se muestra en la Figura 36. 50% RV1 10k VDD AN0 AN0 RE2 RB4 RB5 RB6 RB7 RE0 VDD RE1 D7 14 D6 13 D5 12 D4 11 D3 10 D2 9 D1 8 D0 7 E 6 RW 5 RS 4 VSS 1 VDD 2 VEE 3 LCD2 LM016L D4R4 470 D3R3 470 D2R2 470 D1R1 470 OSC1 VDD R20 4.7k R8 470 D7R7 470 D6R6 470 D5R5 470 RA0/AN0 2 RA1/AN1 3 RA2/AN2/VREF-/CVREF 4 RA3/AN3/VREF+ 5 RA4/T0CKI/C1OUT/RCV 6 RA5/AN4/SS/LVDIN/C2OUT 7 RA6/OSC2/CLKO 14 OSC1/CLKI 13 RB0/AN12/INT0/FLT0/SDI/SDA 33 RB1/AN10/INT1/SCK/SCL 34 RB2/AN8/INT2/VMO 35 RB3/AN9/CCP2/VPO 36 RB4/AN11/KBI0/CSSPP 37 RB5/KBI1/PGM 38 RB6/KBI2/PGC 39 RB7/KBI3/PGD 40 RC0/T1OSO/T1CKI 15 RC1/T1OSI/CCP2/UOE 16 RC2/CCP1/P1A 17 VUSB 18 RC4/D-/VM 23 RC5/D+/VP 24 RC6/TX/CK 25 RC7/RX/DT/SDO 26 RD0/SPP0 19 RD1/SPP1 20 RD2/SPP2 21 RD3/SPP3 22 RD4/SPP4 27 RD5/SPP5/P1B 28 RD6/SPP6/P1C 29 RD7/SPP7/P1D 30 RE0/AN5/CK1SPP 8 RE1/AN6/CK2SPP 9 RE2/AN7/OESPP 10 RE3/MCLR/VPP 1 U1 PIC18F4550 OSC2 D8 L7 L6 L5 L4 L3 L1 L2 L0 L0 L1 L2 L3 L4 L5 L6 L7 RB4 RB5 RB6 RB7 RE0 RE2 RE1 RB1 RB2 RB3 R12 10k R14 10k R13 10k RB0 A B C D RC2 RC2 Figura 35: Diseño del proyecto 8 PROF. ALEXIS CABELLO PÁGINA: 31
  • 35. UNEXPO-LCM Listado 12 proyecto8.c #include p18cxxx.h #include delays.h #include stdlib.h #pragma config PLLDIV = 5 // (20 MHz crystal) #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2 #pragma config FOSC = HSPLL_HS //HSPLL_HS #pragma config WDT = OFF unsigned int count=0; void initPWM (void); void main() { TRISA=TRISB=TRISC=TRISD = 0x00; // set direction to be output PORTD=0x0; ADCON1 = 0x0F; INTCONbits.GIE = 1; //enable global interrupts INTCONbits.PEIE = 1; //enable peripherical interrupts initPWM(); while(1); } void initPWM (void) { PR2 = 187; // T pwm = (PR2+1)*4*(1/FOSC)*PRESCALER CCPR1L = 94; // 50 % duty cycle T2CON=0; T2CONbits.T2CKPS1 = 1; T2CONbits.T2CKPS0 = 0; // 16 - prescaler IPR1bits.TMR2IP = 0; // low priority PIR1bits.TMR2IF = 0; PIE1bits.TMR2IE = 0; //disable Interrupt T2CONbits.TMR2ON = 1; CCP1CON = 0; CCP1CONbits.DC1B1=0; CCP1CONbits.DC1B0=0; //Duty cicle CCP1CONbits.CCP1M3=1; CCP1CONbits.CCP1M2=1; //PWM mode TRISCbits.TRISC2 = 0; //RC1 output } PROF. ALEXIS CABELLO PÁGINA: 32
  • 36. UNEXPO-LCM Figura 36: Simulación del proyecto 8 PROF. ALEXIS CABELLO PÁGINA: 33
  • 37. UNEXPO-LCM Anexo A Manejo de la pantalla LCD Las pantallas LCD son dispositivos que se utilizan para visualizar información. Los dispositivos LCD poseen internamente un microcontrolador especico que sirven para regular el funcionamiento de los mismos. Las pantallas mas comunes están formados por una matriz de 5*7 pixels en una o en varías líneas, en el siguiente proyecto se trabajará con una pantalla LCD que permite trabajar dos líneas de 16 caracteres cada una y, que posee un microcontrolador 44780. Esta pantalla que se muestra en la gura 37 posee 14 terminales que serán explicados con detalle a continuación. RE2 RB4 RB5 RB6 RB7 RE0 VDD RE1 D7 14 D6 13 D5 12 D4 11 D3 10 D2 9 D1 8 D0 7 E 6 RW 5 RS 4 VSS 1 VDD 2 VEE 3 Figura 37: LCD LM016L Como se observan los 14 terminales son VSS, VDD, VEE, RS, RW, E, D0, D1, D2, D3, D4, D5, D6, y D7, estos terminales se dividen en tres categorías, los tres primeros son los terminales de alimentación, los siguientes tres terminales son los utilizados para control del LCD y los últimos 8 respectivamente, son utilizados para transferir los datos. Terminales de Alimentación 1. VSS: Se aplica la tierra 2. VDD: Se aplica la alimentación de 5 voltios 3. VEE: Normalmente este terminal se conecta a un potenciómetro que permita variar un voltaje entre 0 a 5 voltios y así observar la diferencia de brillo y contraste que se puede tener en la pantalla LCD. Si se conecta a tierra, se indica el mayor contraste. Terminales de Control 1. RS: Por este terminal, se indica a la pantalla LCD si se va escribir un comando o una data, se entiende por comandos todas aquellas instrucciones que sirven para inicializar la pantalla, borrar pantalla, posicionar el cursor entre otras, para todo esto, se debe colocar un 0 en este terminal; por el contrario si se conecta a 1 , lo que se envía es la data, generalmente el código ASCII del carácter a mostrar. PROF. ALEXIS CABELLO PÁGINA: 34
  • 38. UNEXPO-LCM 2. RW: Este terminal corresponde a Read/Write, es decir, es el terminal que indica si vamos a leer o a escribir de la pantalla LCD, siendo 1 para leer y 0 para escribir. 3. E: Enable, este terminal permite habilitar el proceso de escritura/lectura a la pantalla LCD. si no se activa este terminal, la información en D0-D7 no se lee o escribe. Terminales para Data Estos 8 terminales reciben los caracteres ASCII a representar, así como ciertos códigos de control que regulan los efectos de visualización o para obtener información sobre el estado interno del dispositivo. El dispositivo LCD responde a una serie de comandos con los que se puede manipular sus distintas opciones de trabajo, para lo cual se hace referencia a la tabla 2. Comando RS R/W E D7 D6 D5 D4 D3 D2 D1 D0 Tiempo de Ejecución Clear Display 0 0 1 0 0 0 0 0 0 0 1 1.64 ms Home 0 0 1 0 0 0 0 0 0 1 x 1.64 ms Entry Mode Set 0 0 1 0 0 0 0 0 1 I/D S 40 us Display On/O 0 0 1 0 0 0 0 1 D C B 40 us Cursor Display Shift 0 0 1 0 0 0 1 S/C R/L x x 40 us Function Set 0 0 1 0 0 1 DL N F x x 40 us Set CGRAM Address 0 0 1 0 1 Dirección de la CGRAM 40 us Set DDRAM Address 0 0 1 1 Dirección de la DDRAM 40 us Read Busy Flags Address 0 1 1 BF Dirección de la CGRAM o DDRAM 40 us Write Data to CG o DD 1 0 1 Código ASCII para la RAM 40 us Read Data to CG o DD 1 1 1 Código Almacenado en RAM 40 us Tabla 2: Códigos de los Comandos a los que responde el Dispositivo LCD A continuación se explica con detalle todas las abreviaturas utilizadas en la tabla S: Se reere a la visualización, si vale 1, indica que cada vez que escribe un dato, la visualización se desplaza automáticamente a la siguiente posición, por el contrario si vale 0, funciona de forma normal. I/D: Se reere al cursor, si vale 1, el cursor se incrementa automáticamente de dirección luego de escribir, si vale 0, éste se decrementa. S/C: Si vale 1 se desplaza la visualización, si vale 0 se desplaza el cursor. R/L: Si vale 1 el desplazamiento es a la derecha del LCD, si vale 0 es a la izquierda. BF: si vale 1 el dispositivo LCD se encuentra en funcionamiento u ocupado, si se encuentra en 0, indica que esta disponible. DL: Si vale 1 trabaja con un bus de datos de 8 bits, si vale 0 trabaja con bus de solo 4 bits, que es el caso que se eligió en el proyecto. N: Si vale 1 la presentación se hace en dos líneas, si vale 0 se hace en una sola línea. F: Este indica el tamaño o la caja de los caracteres, si vale 1 es de 5x10 pixels, si vale 0, es de 5x7. PROF. ALEXIS CABELLO PÁGINA: 35
  • 39. UNEXPO-LCM B: Si vale 1, parpadeo del cursor encendido y si es 0 , parpadeo del cursor apagado. C: Si vale 1, el cursor esta activado, si vale 0 el cursor esta desactivado. D: Si vale 1, la pantalla esta activada, si vale 0 la pantalla esta desactivada. X: Indeterminado A continuación se describen la función de los comandos que controlan el dispositivo LCD Clear Display: Este comando borra la pantalla del dispositivo LCD y coloca el cursor en la primera posición, que es la dirección 0, por defecto coloca el bit I/D en 1 para autoincremento de la posición del cursor. Home: Pone el cursor en la dirección 0 y no varía el contenido de la memoria DDRAM que guarda los datos y que queda direccionada desde la posición 0. Entry Mode Set: Establece la dirección del movimiento del cursor, si coloca el bit S en 1 desplaza la visualización cada vez que se escribe un dato, si S vale 0 la visualización es normal. Display On/O: Activa o Desactiva al Display (D) y al cursos (C) y determina si éste es inter- mitente o no. Cursor Display Shift: Mueve el cursor y desplaza la visualización sin cambiar el contenido de la memoria DDRAM. Function Set: Establece el número de líneas que se van a utilizar, con el bus de datos, siendo normalmente que sea de 8 bits, por lo que DL=1 y especíca el número de líneas de caracteres, que para que sean dos se debe colocar N=1 y el formato del carácter si F=0 entonces es de 5x7 pixels. Set CGRAM Adress: El dispositivo LCD tiene denidos los caracteres ASCII, sin embargo per- mite que el usuario pueda denir un máximo de nueve caracteres nuevos. Éstos se guardan en CGRRAM. Con este comando se indica la dirección de la CGRAM a partir de la cual se irán almacenando los bytes que denen al nuevo carácter. Luego de ejecutar este comando todos los datos que se lean o escriban posteriormente lo hacen desde esa posición de la CGRAM. Set DDRAM Adress: Establece la dirección de la DDRAM, a partir de la cual todos los datos que se lean o escriban posteriormente lo harán desde esta posición. Es los 16 caracteres del primer renglón ocupan las direcciones 80H- 8FH y los del segundo desde C0H- CFH. Read Busy Flags Adress: Se trata de un comando para la lectura de las bandera BUSY, que indica si todavía se está ejecutando un comando previo en la pantalla, y además proporciona la dirección de la CGRAM y DDRAM que se haya utilizado por última vez. Write Data to CG o DD: Se escribe en la DDRAM los caracteres ASCII, que se desea visualizar. También se escriben en la CGRAM los bytes de los nuevos caracteres creados por el usuario, en caso de existir los mismo. Se usa una memoria u otra según haya sido la instrucción de direccionamiento anterior, que hará que se reeje el contenido de la memoria DDRAM o CGRAM. Read Data to CG o DD: Es muy parecido al comando anterior, pero en este caso es solo para lectura de los datos que se encuentren en las memorias DDRAM o CGRAM. En el archivo de encabezado se declaran los prototipos de las funciones del LCD y se denen los códigos de los comandos principales mostrados en la tabla 2. El archivo de encabezado (lcd.h) se muestra en el listado 13: PROF. ALEXIS CABELLO PÁGINA: 36
  • 40. UNEXPO-LCM Listado 13 Archivo de encabezado LCD.h typedef void VOID; typedef int INT; typedef signed char INT8; typedef signed int INT16; typedef signed long INT32; typedef unsigned short WORD; typedef char CHAR; typedef unsigned char BYTE; typedef double FLOAT; typedef long LONG; typedef INT8 BOOL; //Display Config. #define MAX_DISPLAY_CHAR 16 //LCD Registers addresses (PORT E) #define LCD_CMD_WR 0x00 #define LCD_DATA_WR 0x01 #define LCD_BUSY_RD 0x02 #define LCD_DATA_RD 0x03 //LCD Commands #define LCD_CLS 0x01 #define LCD_HOME 0x02 #define LCD_SETMODE 0x04 #define LCD_SETVISIBLE 0x08 #define LCD_SHIFT 0x10 #define LCD_SETFUNCTION 0x20 #define LCD_SETCGADDR 0x40 #define LCD_SETDDADDR 0x80 #define E_PIN_MASK 0x04 #define FALSE 0 #define TRUE 1 /************************************************************************ ***** FUNCTION PROTOTYPES ***** ******************************/ VOID lcd_display (CHAR y, CHAR x, CHAR *buf); VOID lcd_char (CHAR ch); VOID lcd_init(void); VOID lcd_wait(void); VOID wrcmd (CHAR data); VOID wrdata(CHAR data); VOID lcd_clear(void); VOID lcd_reset(void); VOID setpos(CHAR y, CHAR x); PROF. ALEXIS CABELLO PÁGINA: 37
  • 41. UNEXPO-LCM Listado 14 lcdio.c /***************************************************************** ***** PIC18F Driver for LCD in 4-bit mode ***** ******************************************************************/ #include p18cxxx.h #include delays.h #include lcd.h VOID wrcmd8 (CHAR cmdcode); VOID lcd_init () // Initialise the LCD Display. { PORTB = TRISB = 0x0F; PORTE = TRISE = 0; Delay10KTCYx(25); wrcmd8(LCD_SETFUNCTION+0x10); // Software reset. wrcmd8(LCD_SETFUNCTION+0x10); // wrcmd8(LCD_SETFUNCTION+0x12); // #ifdef BIT8 wrcmd8(LCD_SETFUNCTION+0x18); // 8-bit mode - 2 line - 5x7 font. #else wrcmd8(LCD_SETFUNCTION+0x08); // 4-bit mode - 2 line - 5x7 font. wrcmd(LCD_SETFUNCTION+0x08); // 4-bit mode - 2 line - 5x7 font. #endif wrcmd(LCD_SETVISIBLE+0x04); // Display, no cursor - no blink. wrcmd(LCD_SETMODE+0x02); // Automatic Increment - No Display shift. wrcmd(LCD_SETDDADDR+0x00); // Address DDRAM with 0 offset 80h. } VOID lcd_display (CHAR y, CHAR x, CHAR *buf) { INT8 i; setpos(y,x); for (i=0 ; buf[i] != 0; i++) { wrdata(buf[i]); } } VOID lcd_char (CHAR ch) { INT8 i; wrdata(ch); } VOID lcd_clear() // Clear the LCD Screen and reset // initial position. { wrcmd(LCD_CLS); wrcmd(LCD_SETDDADDR+0x0); } VOID setpos (CHAR y, CHAR x) { if(y==1) wrcmd(LCD_SETDDADDR+(x-1)); else wrcmd(LCD_SETDDADDR+0x40+(x-1)); } PROF. ALEXIS CABELLO PÁGINA: 38
  • 42. UNEXPO-LCM Listado 15 continuación lcdio.c VOID wrcmd8 (CHAR cmdcode) // Write a command to the LCD display. { TRISB = 0x0F; PORTB = cmdcode; // Write to PORTB to latch data into the display. // Toggle Pin ’E’ to send the command. PORTE = LCD_CMD_WR; PORTE |= E_PIN_MASK; _asm NOP NOP _endasm PORTE = ~E_PIN_MASK; lcd_wait(); } /***** Utility Functions *****/ VOID wrcmd (CHAR cmdcode) // Write a command to the LCD display. // In 4-bit mode we send the MSN first and then // the LSN. We then call the wait routine to hold // until the busy flag is cleared. { TRISB = 0x0F; #ifdef BIT8 PORTB = (cmdcode); #else PORTB = (cmdcode 0xF0); // Get the most significant nibble first. #endif PORTE = LCD_CMD_WR; // Specify a command write operation. PORTE |= E_PIN_MASK; // Toggle the ’E’ pin to send the command. _asm NOP NOP _endasm PORTE = ~E_PIN_MASK; #ifdef BIT8 lcd_wait(); // Call the wait routine. #else TRISB = 0x0F; PORTB = (cmdcode 4); // Repeat for least significant nibble. PORTE = LCD_CMD_WR; PORTE |= E_PIN_MASK; _asm NOP NOP _endasm PORTE = ~E_PIN_MASK; lcd_wait(); // Call the wait routine. #endif } PROF. ALEXIS CABELLO PÁGINA: 39
  • 43. UNEXPO-LCM Listado 16 continuación lcdio.c VOID wrdata (CHAR data) // Write a Character to the LCD Display. // In 4-bit mode we send the MSN first and then // the LSN. We then call the wait routine to hold // until the busy flag is cleared. { TRISB = 0x0F; #ifdef BIT8 PORTB = data; #else PORTB = data 0xF0; // Get the most significant nibble first. #endif PORTE = LCD_DATA_WR; // Specify a data write operation. PORTE |= E_PIN_MASK; // Toggle the ’E’ pin to send the command. _asm NOP NOP _endasm PORTE = ~E_PIN_MASK; #ifdef BIT8 lcd_wait(); // Call the wait routine. #else TRISB = 0x0F; PORTB = (data 4); // Repeat for least significant nibble. PORTE = LCD_DATA_WR; PORTE |= E_PIN_MASK; _asm NOP NOP _endasm PORTE = ~E_PIN_MASK; lcd_wait(); // Call the wait routine. #endif } VOID lcd_wait () { Delay1KTCYx(10); } Rutina lcd_init() Esta rutina se utiliza para inicializar el LCD. Se puede inicializar para fun- cionar en modo de transferencia de 4 bits o de 8 bits dependiendo si se dene la variable BIT8 por medio del comando del preprocesador del compilador (#dene BIT8). Si esta denida la variable se realizar la conguración para 8 bits y en caso contrario se congura para 4 bits. Rutina lcd_display(y, x, string) Esta rutina permite mostrar en la pantalla LCD una cadena de caracteres. Se debe pasar como parámetros las coordenadas de la pantalla (y, x) a partir de donde se empieza a mostrar la cadena de caracteres. y: número de la la o línea (1 o 2) x: numero de la columna (1 a 16) string: cadena de caracteres a mostrar. PROF. ALEXIS CABELLO PÁGINA: 40
  • 44. UNEXPO-LCM Rutina lcd_char(char) Esta rutina permite mostrar un carácter en la posición actual del cursor. El cursor se incrementa y queda en la siguiente posición de la pantalla. char = carácter a mostrar. Rutina lcd_clear() Esta rutina permite borrar toda la pantalla LCD y se posiciona el cursor en coordenadas de inicio (1,1). Rutina setpos(y,x) Esta rutina permite mover el cursor. Se debe pasar como parámetros las coordenadas de la pantalla (y, x). y: número de la la o línea (1 o 2). x: número de la columna (1 a 16). Las rutinas que se describen a continuación son las rutinas de bajo nivel que son utilizadas para enviar los comandos y los datos a la pantalla LCD. Estas rutinas son utilizadas por las rutinas descritas anteriormente por controlar las funciones de la pantalla LCD. Rutina wrcmd8(comando) Esta rutina escribe el código de comando pasado como parámetro a la pantalla LCD a través del modo de transferencia de 8 bits y espera a que el LCD termine de ejecutar la operación. Esta rutina se utiliza en la función lcd_init() ya que al encender la pantalla esta queda inicializada en modo de transferencia de 8 bits. Rutina wrcmd(comando) Esta rutina escribe el código de comando pasado como parámetro a la pantalla LCD a través del modo de transferencia congurado en la rutina lcd_init(), es decir en 4 bits o en 8 bits. La rutina espera a que el LCD termine de ejecutar la operación. Rutina wrdata(char) Esta rutina escribe el carácter (char) pasado como parámetro a la pantalla LCD. Rutina lcd_wait() Esta rutina espera para que el LCD termine de procesar el comando enviado. PROF. ALEXIS CABELLO PÁGINA: 41
  • 45. UNEXPO-LCM Anexo B Manejo del Teclado Matricial Un teclado matricial es un dispositivo de entrada de datos donde las líneas necesarias para detectar la tecla pulsada se agrupan de forma matricial en las y columnas con el n de disminuir las líneas requeridas. Para un teclado de 12 teclas solo se requieren de 7 líneas de entrada/salida del microcon- trolador para manejar el teclado. En la gura 38 se muestra el esquema de un teclado matricial de 12 teclas. RB7 RB6 RB4 RB5 B2 2 B4 4 B5 5 B6 6 B8 8 B3 3 B9 9 B7 7 B1 1 B12 # B11 0 B10 * RB3 RB2 RB1 Figura 38: Teclado Matricial de 4x3 Las líneas RB1-RB3 en la gura son leídas por el nible inferior del puerto B (RB1-RB3), por lo que se tienen que congurar como entradas, mientras que las del nible superior (RB4-RB7) se conguran como salidas y es donde se aplican el patrón de estados lógicos para ser leídos por el nible inferior. El programa que se muestra en el listado 17 gestiona el manejo del teclado, en el mismo se saca secuencialmente un nivel bajo por una de las 4 líneas de salida que se aplican a las las (RB4-RB7), al mismo tiempo que se lee el nivel lógico que llega al nible inferior o columnas (RB1-RB3). Si al leer este nible, una de las líneas se encuentra en nivel bajo, se deduce que la tecla asociada a dicha la y dicha columna se encuentra presionada. Cada tecla tiene un código asociado desde el 1 al 12. Luego estos códigos pueden ser sustituidos por un código ASCII por medio del uso de un tabla. PROF. ALEXIS CABELLO PÁGINA: 42
  • 46. UNEXPO-LCM Listado 17 kdbio.c #include p18cxxx.h #include delays.h char keypadread(void); char scankey(void); char keypadread() // Find a key, wait for it to be released and return. { char key; key = scankey(); if (key) while (scankey() != 0); return key; } char scankey() // Scan the keypad for a keypress. // Return 0 for no press. { char row,col,idx; unsigned char wait,tmp; idx=0; TRISB=0x0F; for (row=0; row 4; row++) { // Drive appropriate row low and read columns: LATB = ~(1 (row+4)); for (wait=0; wait200; ++wait); tmp = (PORTB 0x0F); // See if any column is active (low): for (col=1; col4; col++) { if ((tmp (1col)) == 0) { idx = (row*4) + col; break; } } if(idx!=0) break; } TRISB=0x00; return idx; } Rutina scankey() Esta rutina es la que realiza el barrido por las las y columnas del teclado para detectar si se ha presionado una tecla. La rutina realiza un solo barrido y si una tecla es presionada retorna el código de la misma, por el contrario si ninguna tecla es presionada la rutina retorna cero. PROF. ALEXIS CABELLO PÁGINA: 43
  • 47. UNEXPO-LCM Rutina keypadread() Esta rutina llama a la rutina scankey y si una tecla fue presionada la rutina espera hasta que la tecla deje de estar presionada y luego retorna el código del tecla. PROF. ALEXIS CABELLO PÁGINA: 44