Você está na página 1de 48

Microprocesadores y

Microcontroladores

Aplicaciones avanzadas del


PIC16F877
Ing. Daniel Galarza Q.
Uso del PWM (Pulse Width Modulation)
• El PIC16F877 posee un canal llamado CCP, que puede funcionar
como:
• Comparador
• Captura
• PWM
• Para configurar el PWM, se ha creado una librería para manejar tal
canal en modo PWM.
• La función siguiente contiene solo un parámetro para calcular, este es
el periodo o tiempo que deseamos
Void OpenPwm(const unsigned char periodo)
Ing. Daniel Galarza Q.
• El periodo se puede calcular con una simple fórmula
4
• 𝑃𝑊𝑀 𝑝𝑒𝑟𝑖𝑜𝑑 = (𝑝𝑒𝑟𝑖𝑜𝑑𝑜 + 1) (𝑇𝑀𝑅2𝑝𝑟𝑒𝑠𝑐𝑎𝑙𝑎𝑟)
𝑇𝑜𝑠𝑐
• PWM period = El tiempo propuesto por nosotros
• Periodo = El valor necesario para cargar en nuestra fórmula
• TMR2 prescalar = Es el valor que se ha propuesto para el timer2.
• Se deberá agregar la librería para trabajar con el timer2
• El timer2 es un contador de 8 bit parecido al timer0 pero solo contiene 3
prescalares.
• #define PRESCALE_1
• #define PRESCALE_4
• #define PRESCALE_16

Ing. Daniel Galarza Q.


• La función del timer2 se debe agregar antes de poner la línea de PWM
• Un ejemplo sencillo es hacer uso del PWM y que tenga una frecuencia de 1KHz teniendo
como prescalar en el timer2 un valor de 16 y un cristal interno corriendo a 4MHz.
• Si despejamos la fórmula para obtener el número periodo tenemos que:
1
𝑝𝑒𝑟𝑖𝑜𝑑𝑜 = −1
4
𝑓∗ ∗ 𝑝𝑟𝑒𝑠𝑐𝑎𝑙𝑎𝑟
𝐹𝑜𝑠𝑐

1
𝑝𝑒𝑟𝑖𝑜𝑑𝑜 = −1
4
1𝐾𝐻𝑧 ∗ ∗ 16
4𝑀𝐻𝑧
• Se debe cargar el valor de 61 a la función de PWM

Ing. Daniel Galarza Q.


• En el programa se cargaría lo siguiente
• OpenTimer2(PRESCALE_16)
• OpenPwm(61)
• Además tenemos una función para cambiar el ancho de pulso que es:
• void PwmDuty(unsigned char duty)
• duty = Es un valor de tipo unsigned char de 0 a 255, que corresponde de 0 a
100% de pulso.
• Si quisiérmos un ancho de pulso de 50% a 1KHz es simplemente cargar el
valor 255/2 = 127
• PwmDuty(127)
• Esto corresponde a usar un valor de 8 bit
• Más adelante se usará 10-bit para mejor precisión de ancho de pulso.

Ing. Daniel Galarza Q.


Programa de Ejemplo PWM
• Programa pwmejemplo1.c

Ing. Daniel Galarza Q.


Circuito

Ing. Daniel Galarza Q.


Ejercicio
• Modificar el circuito para que usando el puerto B pueda obtener 5
valores de frecuencia del PWM.
• Por ejemplo si coloco 0000 tendré el ciclo al 100%.
• Si coloco 0001 tendré el ciclo al 75%.
• Si coloco 0010 tendré el ciclo al 50%.
• Si coloco 0100 tendré el ciclo al 25%.
• Si coloco 1000 tendré el ciclo al 0%.

Ing. Daniel Galarza Q.


TIMER2 PIC16F877
• El timer2 solo puede ser utilizado como temporizador no como contador.
• Consta de 8 bits por lo que sus valores pueden aumentar desde 0 a 255.
• El registro TMR2 es el encargado de guardar los valores para el timer2.
• Este registro tiene asociado un registro llamado PR2 de 8 bits.
• Este registro se cargará el número de veces que se quiere que el registro TMR2
aumente de valor.
• Cuando el valor del registro TMR2 llegue a se igual al cargado en el registro PR2 el
registro TMR2 se pondrá a 0.
• Por ejemplo si el registro PR2 = 150, entonces el registro TMR2 aumentará su valor
en cada ciclo de instrucción hasta que se haga igual a 150.
• El registro TMR2 se pondrá a 0 y volverá a aumentar sus valores hasta llegar nuevamente a
150 tras lo cual volverá a reiniciarse a 0.

Ing. Daniel Galarza Q.


Timer2 como temporizador
• El temporizador cuenta con un prescalar y también un postescalar.
• El postescalar solo hace su trabajo cuando el timer2 es utilizado con
interrupciones,
• El prescalar y el postescalar hacen que la frecuencia de trabajo Fosc
se divida por este prescalar y a la vez por el postescalar.
• Si se utilizan ambos a la vez se logra que el temporizador timer2 tarde
un poco más en aumentar su valor en una unidad.
• El registro encargado de controlar el desempeño del timer2 es el
registro T2CON

Ing. Daniel Galarza Q.


Registro de control para el timer2 T2CON

• El bit 7 del registro no es usado, por lo cual se lo pone a 0.


• Los bits de 6 al 3 son usados para elegir el postescalar.
• Puede tener valores del 1 al 16.
• El bit 2 sirve para habilitar el uso del timer2.
• Si se pone a 0, el timer2 estará deshabilitado.
• Los bits 1 y 0 sirven para escoger el prescalar que puede tener valores
de 1, 4 y 16.

Ing. Daniel Galarza Q.


• En la siguiente tabla se ve los valores que hay que dar a estos bits
para obtener los diferentes valores de prescalar y postescalar para el
timer2

Ing. Daniel Galarza Q.


• Si el prescalador es por ejemplo de 4 y el postescalador de 16 cuando
la Fosc = 4MHz, entonces la frecuencia de trabajo del temporizador
Ftem será:
𝐹𝑜𝑠𝑐
• 𝐹𝑡𝑒𝑚𝑝 =
4∗𝑝𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟∗𝑝𝑜𝑠𝑡𝑠𝑐𝑎𝑙𝑒
• El tiempo que tardará ahora el temporizador timer2 en aumentar una
unidad será la inversa de este valor lo que se conoce como período
del temporizador.
• En este caso
4 ∗ 𝑝𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 ∗ 𝑝𝑜𝑠𝑡𝑒𝑠𝑐𝑎𝑙𝑒 4 ∗ 4 ∗ 16
𝑇𝑡𝑒𝑚𝑝 = = = 64𝑢𝑆
𝐹𝑜𝑠𝑐 4𝑀ℎ𝑧
Ing. Daniel Galarza Q.
• Esto quiere decir que el temporizador aumentará una unidad cada
64us t en este caso entonces el registro TMR2 para ir de 0 hasta el
valor cargado en registro PR2 = 150 tardará
• 150 ∗ 𝑇𝑡𝑒𝑚𝑝 = 150 ∗ 64𝑢𝑠 = 9600𝑢𝑠 = 9,6𝑚𝑠
• Al utilizar el prescalar y postescalar, se tiene la ventaja de temporizar
tiempos más largos pero muchas veces se vuelven demasiado largos.
• Para lograr una temporización por ejemplo de 50ms se tendría que
usar un prescalar y un postescalar adecuado además de un valor en
PR2 adecuado.

Ing. Daniel Galarza Q.


• Un ejemplo de configuración del registro T2CON sería el siguiente.
• Configuro el bit 7 en 0 por lo que no se usa-
• El postescalar en un modo sin interrupciones no tiene efecto por lo que en las
combinaciones de los bits 6 al 3 se puede utilizar cualquiera.
• Usaremos 1111.
• El bit2 se pondrá 1 para habilitar el uso del timer2.
• Para obtener los 4ms el prescalar tendrá que ser de 16 por lo que la
combinación de los bits 1 y 0 será 10.
• El registro tendrá el valor T2CON = 0b01111110
• En el ejemplo anterior de MPLABX usamos el valor para T2CON
=(PRES|POSTSCALE_1)&0XFF.
• Qué significa eso?

Ing. Daniel Galarza Q.


Valores ADC (Conversor Análogo - Digital)
• El conversor análogo – digital convierte un valor de voltaje a un
número entero de 8 o 10-bits.
• Si es un valor de 8 bit corresponde a un valor de 0 a 255.
• Si es de 10 bit entonces será de 0 a 1023.
• La exactitud la darán los bits.
• Mientras más bits tenga un ADC, entonces tendremos un valor más cercano al
valor que hemos medido.
• Por ejemplo el ADC del PIC16F877 puede ser configurado de 8 o 10
bits.

Ing. Daniel Galarza Q.


• Podemos usar un conversor de 8 bits para hacer un ejemplo en el que
midamos un voltaje de 2.456 V.
• El ADC hace lo siguiente:
• Si tenemos como referencia el valor de la alimentación en este caso con +5V,
entonces tenemos un rango de 0 a 5 Voltios.
𝑣𝑎𝑙𝑜𝑟 𝑚𝑒𝑑𝑖𝑑𝑜 ∗ 255 2.456 ∗ 255
𝑎𝑑𝑐 = =
5 5
𝑎𝑑𝑐 = 125.256 ≅ 125
• Como vemos se ha redondeado ya que lo que entrega el ADC es un
valor entero de tipo unsigned char.

Ing. Daniel Galarza Q.


• Si usamos un conversor de 10 bit
𝑣𝑎𝑙𝑜𝑟 𝑚𝑒𝑑𝑖𝑑𝑜∗1024 2.456∗1023
• 𝑎𝑑𝑐 = =
5 5
• 𝑎𝑑𝑐 = 502.9888 ≅ 503
• Para comparar se hace las operaciones inversamente:
𝑎𝑑𝑐∗5 125∗5
• Para 8 bits: 𝑣𝑜𝑙𝑡𝑠 = =
255 255
• 𝑣𝑜𝑙𝑡𝑠 = 2.45
𝑎𝑑𝑐∗5 503∗5
• Para 10 bits: 𝑣𝑜𝑙𝑡𝑠 = =
1023 1024
• 𝑣𝑜𝑙𝑡𝑠 = 2.456
• Como vemos al usar un conversor de 8 bit se a perdido 6mV, mientras el
conversor de 10 bit no perdió nada ya que el valor se encuentra en rango.

Ing. Daniel Galarza Q.


• Las operaciones anteriores lo hace automáticamente un conversor y
nosotros simplemente pedimos el valor obtenido.
• La función que vamos a usar para la configuración ADC es la siguiente.
• Void OpenADC (unsigned char FOSC, const unsigned char an0, const
unsigned char an1)
• Donde:
• Fosc = tiempo de conversión, se puede tomar un valor de los siguientes:
• FOSC_2
• FOSC_8
• FOSC_32
• FOSC_FRC – Para un tiempo preestablecido de 2uS a 6uS
• An0 = son los canales que vamos a usar como ADC del puerto A

Ing. Daniel Galarza Q.


• El canal ADC contiene un multiplexor que hace la función de
establecer el canal por el cual pedimos el ADC.
• Selección del canal
• Cuando se cambia a un canal es necesario hacer un retardo específico, esto
puede ser 1 uS o 1mS.
• Por ejemplo:
• Delay_mS(1); // Retardo de 1 milisegundo
• Seleccionar canal (CANAL);
• Para hacer esta acción se ha creado una función que pueda cambiar el canal
fácilmente.
• Void channelADC(unsigned char ch);

Ing. Daniel Galarza Q.


• ch es un valor que puede variar entre 0 a 15.
• Este corresponde al máximo de canales que puede tener en este caso el
microcontrolador PIC 16F886
• Se debe tener en cuenta que si se establece solo dos canales, se refiere a que
simplemente usará un rango de 0 a 1 y así sucesivamente.
• Después de seleccionar el canal se debe de empezar la conversión, en
este caso se ha creado la función de “startADC”
• Void startADC(void);
• Después de empezar el ADC a funcionar se debe de esperar hasta que
termine, usando una instrucción adicional.
• While (GO_DONE!=0);

Ing. Daniel Galarza Q.


• Esta función hace que se realice un ciclo para que termine la
conversión.
• Al terminar la conversión se puede leer el dato que por default tiene
un valor de 10 bit.
• Para ello se necesitará una variable de 16 bit para guardar el valor (unsigned
int)
• Además tenemos la función para leer el dato analógico.
• Unsigned int readADC()
• Esta función es llamada y devuelve un valor de 10 bit de un valor
análogo obtenido.
Ing. Daniel Galarza Q.
• En el siguiente ejemplo configuraremos al ADC para que trabaje con un oscilador
interno.
• Usaremos las entradas analógicas AN0, AN1, AN2.
• Configuraremos al USART para que trabaje a una velocidad de 9600 baud.
• Al empezar el programa principal, seleccionaremos el canal que vamos a usar con
un ciclo for.
• Implementamos un retardo de 1ms
• Comenzamos la conversión, y esperamos a que termine.
• Con un arreglo de datos de tipo int guardamos el dato análogo.
• Una vez que salimos del ciclo for, el arreglo contendrá las 3 lecturas de los 3
canales análogos.
• Finalmente los visualizamos con una función printf();

Ing. Daniel Galarza Q.


Ejemplo ADC
• Programa adc1.c

Ing. Daniel Galarza Q.


Circuito

Ing. Daniel Galarza Q.


Registro ADCON0
• Nos ayuda a configurar parte de la función de conversión analógica a digital del microcontrolador PIC.

• Bit 7-6 ADCS1:ADCS0: Selección del reloj para la conversión A/D


• 00 = Fosc/2
• 01 = Fosc/8
• 10 = Fosc/32
• 11 = Frc
• Bit 5-3 CHS2:CHS0 Selección del canal de conversión
• 000 – 111 : Canal 0 al Canal 7
• GO/DONE : Estado de la conversión
• Si ADON = 1
• 1= Conversión en progreso
• 0 = Conversión finalizada
• ADON = Bit de encendido del conversor A/D
• 1= Módulos A/D Encendido
• 0 = Módulo A/D apagado

Ing. Daniel Galarza Q.


Registro ADCON1
• Nos ayuda a configurar al puerto A como entrada Analógica o E/S Digital

• Bit 7 ADFM: Selección de formato del resultado


• 1 = Ajuste a la derecha
• 0 = Ajuste a la izquierda
• Bit 3 – 0 PCFG3:PCFG0: Configuración de las entradas A/D

Ing. Daniel Galarza Q.


Ejercicio
• Mostrar por medio de un terminal virtual el valor insertado de voltaje
analógico.

Ing. Daniel Galarza Q.


Uso del LCD
• Los LCDs pueden adherir una gran variedad de aplicaciones en
términos de promover una interfaz para el usuario.
• Puede proporcionarnos por ejemplo una depuración para alguna
aplicación o también dar una buena vista para nuestro proyecto.
• El LCD más común es el Hitachi 44780, el cual da una simple interfaz
entre el procesador y un LCD.
• El uso de esta interfaz puede ser un poco complicado para nuevos
diseñadores y programadores porque no existen buenas
documentaciones sobre la interfaz.
• Iniciarla también podría ser un problema

Ing. Daniel Galarza Q.


• Para el uso sencillo del LCD se han creado funciones para manejarlos,
basándose en la información y tabla siguiente.

Ing. Daniel Galarza Q.


• Para establecer el Display/Cursor:
• D – Prende el lcd (1)/ Apaga LCD (0)
• C - Cursor activado (1) / Desactivado (0)
• B – Parpadeo del cursor activado (1) / Desactivado (0)
• Mover Cursor / Recorrer cursor:
• SC – Corrimiento del display activado (1) / Desactivado (0)
• RL – Corrimiento hacia derecha (1) / Izquierda (0)
• Establecer tamaño del interfaz:
• DL – Dato de 8 bit (1) / 4 bit (0)
• N – Número de líneas del Display 1 (0) / 2 (1)
• F – Tamaño de la letra 5 x10 (1) / 5 x 7 (0)
• Estado del bit BUSY:
• BF – Bit en UNO cuando este en proceso de algo
• Mover cursor a la posición de la RAM:
• A – Dirección
• Leer/Escribir en el LCD:
• H - DATOS

Ing. Daniel Galarza Q.


• Antes de enviar cualquier comando o datos hacia el LCD, el módulo debe
ser inicializado.
• En este caso se trabajará con un modo de 8 bit.
• Esto es hecho usando las siguientes instrucciones:
• 1. Esperar 1ms después de conectar la alimentación
• 2. Escribir 0x30 hacia el LCD y esperar 5ms antes de otra instrucción.
• 3. Escribir 0x30 hacia el LCD y esperar 160us antes de otra instrucción.
• 4. Establecer LCD
• Escribe el modo a usar 8 o 4 bit
• Escribe 0x01 para apagar display
• Escribe 0x01 para limpiar display
• Escribe la dirección del cursor
• Escribe prender display/cursor

Ing. Daniel Galarza Q.


• Todo lo anterior se resume a usar la función:
• Lcd_init (unsigned char config); //Inicializamos LCD
• Config = Puede ser dos opciones
• CURSOR_ON Prende el cursor y parpadea
• CURSOR_OFF Apaga el cursor
• Hay otras funciones públicas, esto se refiere a que el usuario puede
llamarlas sabiendo que son especialmente para lo ques.
• Las funciones públicas son las siguientes:
• //writeCLDCD(unsigned char c);
• Función que escribe un carácter en el LCD

Ing. Daniel Galarza Q.


• writeSLCD (unsigned char *dir);
• Escribe una cadena de caracteres guardadas en la RAM
• WriteRSLCD (const unsigned char *string)
• Escribe una cadena de caracteres guardadas en la ROM
• gotoXYLCD (usnigned char x, unsigned char y)
• Posiciona el cursor en el lugar elegido

Ing. Daniel Galarza Q.


• Para dar un pequeño ejemplo del uso del módulo LCD, desarrollamos lo
siguiente:
• Al iniciar la simulación, se escribirá la letra ‘A’ demostrando la función write CLCD();
• Después se borrará la pantalla con la instrucción send_byte(CLEAR)
• Esta no es una instrucción pública pero se usa para limpiar la pantalla.
• Después escribiremos una string guardada en la ROM comprobando la función
writeRSLCD()
• Luego con un ciclo for se hará contar de 0 a 100 y será mostrado en el LCD estos
valores con una nueva función
• sprintf(arreglo, “datos en string %si hay valores a transformar”, valor a transformar a string)
• Esta instrucción hará uso de la librería stdio.h
• Por último será proyectado al LCD con el uso de la instrucción writeSLCD()

Ing. Daniel Galarza Q.


Ejemplo
• Programa lcd1.c

Ing. Daniel Galarza Q.


Circuito

Ing. Daniel Galarza Q.


Ejercicio
• Escribir un programa para que muestre el nombre de cada uno de los
integrantes del grupo en el LCD cada 5 segundos. Mostrar el conteo
regresivo de los 5 segundos y al final limpiar la pantalla del LCD.

Ing. Daniel Galarza Q.


Lector de Voltaje
• Juntaremos el display LCD con un convertidor análogo – digital.
• Para este ejercicio leeremos un dato análogo y después lo transformaremos a
un valor de voltaje.
• Como el rango máximo es de 0 a 5V solo usaremos un canal, por
ejemplo el AN0
• Usaremos un potenciómetro para variar el voltaje de entrada, por
ejemplo uno de 1Kohm o 500Kohm.
• Conectamos el terminal del potenciómetro en la entrada análoga AN0
y finalmente el LCD en el puerto C.

Ing. Daniel Galarza Q.


Ejemplo
• Programa adclcd.c

Ing. Daniel Galarza Q.


Circuito

Ing. Daniel Galarza Q.


Selector de canal analógo con Teclado 4x4
• Veremos el funcionamiento del teclado 4x4, el funcionamiento es
sencillo.
• Este teclado funciona a base de una matriz tiene conexiones fila y
columna.
• De esta manera es más eficiente el uso de los pines y la programación
es más sencilla.
• Para esto tenemos una librería que nos simplifica el funcionamiento e
implementación del teclado.
• Una librería de uso de teclado 4 x4 debería contar con los siguientes
pasos:
• Seleccionar el puerto a usar
• Si el puerto contiene resistencias pull-up mucho mejor
• Hacer al nibble más alto como entrada y el nibble más bajo como salida.
• Si se tiene resistencia pull-up en el puerto se debe activarlas.
• Sino se debe colocar externamente las resitencias en el nibble de entrada hacia +5V.
• Inicilizar la salida como encendido, y después apagar el pin1110eeee y hacer
un corrimiento de mayor a menor
11011111
10111111
01111111
• En cada transición de corrimiento debe de haber un retardo de 5ms, y un
guardado del dato.
• Luego se debe leer el puerto para saber si hubo algún cambio.
• Hay dos opciones para tomar una letra cuando se presiona y cuando
no se presiona
• Si no presiona ninguna letra procure regresar un valor que usted conozca y
que no esté en rango de las letras que se vaya a usar.
• Si se presiona una tecla guarde el valor obtenido, y decodifique ese valor con
una letra establecida por nosotros y regrese y salga del ciclo y use la letra o
valor obtenido a su antojo.
• Estos pasos también pueden funcionar para teclados de otro valor,
por ejemplo 4x10, 10x12, etc.
• Se ha creado dos funciones necesarias para el uso del teclado 4x4, son las
siguientes:
• void key_init(void)
• Esta llamamamos antes de la siguiente función
• unsigned char getkey(unsigned char kdb)
• Esta función lee el dato del teclado
• kdb debe ser un valor 0 para inicializar la función de leer teclado.
• Esta función devuelve el valor de tipo unsigned char (0 - 255)
• Para hacer una prueba de funcionamiento, el siguiente ejemplo tendrá 4
opciones en la pantalla LCD.
• Estás funciones indicarán que canal análogo queremos ver.
• La selección lo haremos con el uso del teclado.
Ejemplo teclado
• Programa tecladoadc.c
Circuito

Você também pode gostar