-
Mis primeros programas en ASM. PIC16F84A y PIC16F628A/648A
La idea de este tutorial es ayudar a los que recién están empezando, aquí mostraremos como comenzar. Usaremos en primer lugar el microcontrolador PIC16F84A, porque es el que por lo general se usa en la enseñanza. Comenzaremos explicando como esta constituido, los terminales, manejo de corrientes de los puertos, osciladores externos, circuito de reset, memoria de programa y memoria de datos. Luego iremos a lo interesante, que es la programación, nuestros primeros programitas, de los cuales se tratará de explicarlos detalladamente, el funcionamiento y los registros que se usan en cada caso.-
INDICE
El PIC16F84A
- Introducción (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201393#msg201393)
- Mi Primer Programa, control de un led (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201396#msg201396)
- Creación de Demoras, Led titilando (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201398#msg201398)
- Creación de Tablas, Control Display 7 Segmentos (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201401#msg201401)
- Direccionamiento Indirecto, Control Display 7 Segmentos (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201402#msg201402)
- Control de varios Displays 7 Segmentos con multiplexión (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201403#msg201403)
- Control de varios Displays 7 Segmentos con 74LS164 (http://www.todopic.com.ar/foros/index.php?topic=24720.msg213264#msg213264)
- Interrupciones, Registros y guardado temporario de STATUS y W (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201405#msg201405)
- Interrupción TMR0, modo Temporizador (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201407#msg201407)
- Interrupción TMR0, modo Contador (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201408#msg201408)
- Interrupción RB0, Control de Led (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201409#msg201409)
- Interrupción RB4 a RB7, Control Teclado Matricial (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201410#msg201410)
- Control del LCD, Pantalla de Cristal Liquido (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201411#msg201411)
- Comunicación RS232 (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201413#msg201413)
Todas las simulaciones hechas en proteus, aqui (http://www.mediafire.com/?rxcjmjvl1jm) (Para el PIC16F84A)
El PIC16F628A/648A
- Introducción (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204908#msg204908)
- Timer1 + Ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204910#msg204910)
- Timer2 + Ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204912#msg204912)
- Módulo de comunicación serie (Usart) + Ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204913#msg204913)
- Comparadores analógicos + Ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204915#msg204915)
- Módulo CCP. Introducción (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204920#msg204920)
- Modo Captura + Ejemplo: Medir Frecuencia (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204920#msg204920)
- Modo Comparación + Ejemplo: Señal de frecuencia variable (http://www.todopic.com.ar/foros/index.php?topic=24720.msg207734#msg207734)
- Modo PWM + Ejemplo: Señal de 2 Frecuencias distintas (http://www.todopic.com.ar/foros/index.php?topic=24720.msg207737#msg207737)
- 2º Ejemplo PWM. Variando el Ciclo de Trabajo.- (http://www.todopic.com.ar/foros/index.php?topic=24720.msg207739#msg207739)
- Más Información (http://www.todopic.com.ar/foros/index.php?topic=24720.msg207741#msg207741)
- COMUNICACIÓN IR - PIC16F628 Y PIC12F629 (http://www.todopic.com.ar/foros/index.php?topic=24720.msg224696#msg224696) realizado por beto1234 (http://www.todopic.com.ar/foros/index.php?action=profile;u=21383)
Herramientas
Software para escribir nuestro código y compilar: MPLAB (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002)
Software para simular: Proteus (http://www.labcenter.co.uk/download/prodemo_download.cfm)
Una plaquita programadora.
Software para grabar nuestro PIC, se puede usar el WinPic800 (http://www.winpic800.com) o el Icprog (http://www.ic-prog.com/download.html)
:-) Aquí dejo un tutorial de como crear un proyecto en MPLAB, compilar y simular. Un programador de PIC sencillo que pueden armar (Programador JDM – Serial)(circuito, PCB para hacer la plaqueta y una pequeña explicación de cómo grabar con WinPIC800) y un tutorial para crear placas de circuito impreso (PCB) por el método de la plancha ---> Tutoriales (http://www.mediafire.com/file/ak3zio5hl2e/Para Comenzar.rar)
Datasheets
DATASHEET del PIC16F84A (http://ww1.microchip.com/downloads/en/devicedoc/35007b.pdf)
DATASHEET del PIC16F628A/648A (http://host.nigde.edu.tr/muzam/PIC16F648A.pdf)
ConfigPIC (http://www.mediafire.com/file/z2o1jym5zzm/ConfigPIC.rar): Software para realizar el código automáticamente a partir de una interfase de configuración.
(http://img135.imageshack.us/img135/3100/54953366.th.jpg) (http://img135.imageshack.us/my.php?image=54953366.jpg)
-
Introduccion:
El PIC16F84A esta fabricado en tecnología CMOS, posee memoria FLASH, y consumo bajo de potencia. Está compuesto básicamente de una memoria ROM (1024 palabras de memoria de programa), una memoria RAM (de acceso aleatorio, 68 bytes), líneas de entrada y salida (2 Puertos) y una lógica de control que coordina la interacción de los demás bloques.
Estos micros pertenecen a la gama media y dispones de un set de 35 instrucciones, tipo RISC (Computador con Set de Instrucciones Reducido) pocas pero muy poderosas.-
Algunas funciones especiales que dispone este PIC:
- Temporizador programable (Timer). Si se quiere medir periodos de tiempo entre eventos, generar temporizaciones o salidas con frecuencia específica, etc.
- Perro Guardián o Watchdog. Consiste en un temporizador que, cuando se desborda ya pasa por 0, provoca un reset automático, utilizado para sistemas que no tienen control de un supervisor, y al bloquearse el micro se resetea. Si se utiliza el código debe resetearlo antes de que se desborde.
- Memoria EEPROM de 64 bytes, para guardar datos que no se alteran a pesar de quitar la alimentación.
- Interrupciones, cuando una señal externa, o una condición interna activa una línea de interrupción, dejando de lado la tarea que esta ejecutando, atiende dicha interrupción y luego continúa con lo que estaba haciendo.
- Protección ante fallo de alimentación. Se trata de un circuito que resetea al micro cuando el voltaje Vdd es inferior al mínimo.
- Estado de bajo consumo. Sleep. Si el micro debe esperar mucho tiempo sin hacer nada, posee una instrucción especial, Sleep, que lo pasa al estado de reposo. Al activarse una interrupción se “despierta” y reanuda su trabajo. (Reset externo, desbordamiento de Watchdog, interrupción por RB0, interrupción por cambio de nivel en RB4 a RB7, interrupción por escritura completada en EEPROM)
Veamos el diagrama de pines, para ver como están distribuidos sus pines. Este microcontrolador cuenta con dos puertos configurables como estradas y salidas, y consta de 18 pines los cuales se encuentran asignados de la siguiente manera:
(http://img150.imageshack.us/img150/3674/pic16f84aab3.jpg)
El puerto A tiene solo cinco pines, el pin 3, ósea, RA4/TOCKI puede ser configurado a su vez como entrada/salida o como temporizador/contador. Cuando es salida se comporta como colecto abierto, por lo tanto debemos poner una resistencia Pull-up a Vdd de 1 Kohm. Cuando se configura como entrada, funciona como disparador Schmitt Trigger por lo que puede reconocer señales con un poco de distorsión.
El puerto B tiene 8 pines que pueden ser configurados como entrada/salida. RB0 puede programarse además como entrada de interrupción externa. Los pines RB4 a RB7 pueden programarse para responder a interrupciones por cambio de estado y los pines RB6 y RB7 se corresponden con líneas de entrada de reloj y entrada de datos cuando esta en modo programación.
MCLR/Vpp, es la entrada de reset si esta a nivel bajo, también es habilitador de tensión de programación. Cuando su tensión es Vdd el PIC funciona normalmente.
Vss y Vdd, son los pines de masa y alimentación. La tensión de alimentación esta comprendida entre los 2 y 5.5 Volt.
OSC1/CLKIN y OSC2/CLKOUT, pines de entrada externa de reloj y salida de oscilador a cristal respectivamente.-
Capacidad de corriente de los puertos.
La máxima capacidad de corriente de cada uno de los pines de los puertos en modo sumidero es de 25 mA y modo fuente de 20 mA. La máxima capacidad de corriente total de los puestos es,
Puerto A: Modo sumidero 80 mA; Modo fuente 50 mA.
Puerto B: Modo sumidero 150 mA; Modo fuente 100 mA.
El Oscilador externo.
Es un circuito externo que le indica al microcontrolador la velocidad a la que debe trabajar. Puede utilizar cuatro tipos distintos:
RC, Oscilador con resistencia y condensador (Poco preciso)
XT, Cristal de cuarzo.
HS, Cristal de alta velocidad
LP, Cristal de baja frecuencia y bajo consumo de potencia.
Al momento de programar un micro se debe especificar que tipo de oscilador se usa.
Internamente la frecuencia del oscilador es dividida por 4, así que si temeos un oscilador de 4 MHz, la frecuencia de trabajo es de 1 MHz, por lo que cada instrucción se ejecuta cada 1 us.
Aquí utilizaremos un cristal XT de 4 MHz que debe ir acompañado de dos condensadores:
(http://img264.imageshack.us/img264/7666/osciladorcy3.bmp)
Reset.
El PIC 16F84A posee un temporizador interno conectado al pin de reset, que funciona cuando se da alimentación al microcontrolador. Esto hace que al encender el sistema el microcontrolador quede en reset por un tiempo mientras se estabilizan todas las señales del circuito. Para tener control sobre el reset se utiliza el siguiente circuito:
(http://img156.imageshack.us/img156/801/resetze3.bmp)
-
Estructura interna del Microcontrolador.
Arquitectura del PIC, existen dos arquitecturas, la clásica de Von Neumann y la arquitectura Harvard, esta ultima es la que usan los PIC’s. Dispone de dos memorias independientes, una que contiene solo instrucciones y la otra solo contiene datos. Ambas disponen de sus respectivos buses de acceso y es posible realizar operaciones de acceso simultáneamente en ambas.
(http://img217.imageshack.us/img217/4196/arquitecturapicxy4.jpg)
Memoria del programa.
Aquí almacenamos nuestro programa o código que debe ejecutar, en el PIC16F84A es FLASH, es rápida, de bajo consumo y alta capacidad de almacenamiento. Se divide en 2048 posiciones, pero este PIC solo tiene implementadas 1024 posiciones, de 0x00 hasta 0x3FF.
(http://img204.imageshack.us/img204/7706/memoriadelprogramawk8.jpg)
Cuando ocurre un reset, el contador de programa (PC) apunta a la dirección 0x00, y el micro inicia nuevamente. Aquí se debe escribir todo lo relacionado con la iniciación del mismo, por ejemplo configuración de puertos, etc.
Si ocurre una interrupción PC apunta a la dirección 0x04, y aquí debemos escribir el código necesario para atender a dicha interrupción.
Memoria RAM estática.
Donde se encuentran los 24 registros específicos (SFR) y 68 registros de propósito general (GPR). Se halla dividida en 2 Bancos de 128 bytes cada uno.
(http://img516.imageshack.us/img516/7530/memoriaramii2.jpg)
Algo que se debe tener en cuenta es la pila o Stack, que consta de 8 posiciones, cada posición contiene la dirección y datos de la instrucción que se esta ejecutando, así cuando se ejecuta una llamada call o una interrupción, el PC sabe donde regresar. (Limitar las llamadas anidadas)
-
Comenzando con la creación de nuestro código:
A continuación vamos a desarrollar nuestro primer programa. Considero que se tiene conocimiento del lenguaje Assembler, si no es así se puede leer el tutorial ASM desde cero (http://www.todopic.com.ar/foros/index.php?topic=23623.0) de este mismo foro.
Este activará un led conectado a RB0 siempre que el interruptor conectado a RA0 este cerrado. Para ello vamos a necesitar el siguiente circuito:
(http://img217.imageshack.us/img217/282/hardcontrolledja0.bmp)
En RA0 tenemos conectado un pulsador de forma que cuando lo pulsemos se introduzca un cero lógico en el pin y cuando no lo pulsemos se introduzca un uno lógico. Tenemos un Led con su correspondiente resistencia limitadora de corriente en el pin RB0.
Diagrama de Flujo:
(http://img19.imageshack.us/img19/7125/controlledtz4.jpg)
Primero que nada debemos especificar con que microcontrolador estamos trabajando, esto lo realizamos es las dos primeras líneas:
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
En el archive P16F84A.inc se encuentran las definiciones de las direcciones de los registros específicos, los bits utilizados en cada registro y los fusibles del micro.
Configuración de fusibles. Hay ciertos aspectos del PIC que han de ser activados o desactivados mediante hardware a la hora de programarlo. Esto quiere decir que no se pueden volver a cambiar hasta que el chip no se reprograme de nuevo. El PIC16F84A dispone de 4 fuses (los modelos superiores tienen más). Cada fuse activa o desactiva una opción de funcionamiento.
OSC: Este fuse controla el modo de oscilación que usará el PIC para funcionar. Como ya sabemos, el oscilador se puede configurar de 4 maneras distintas, dependiendo de la velocidad y del tipo de circuito oscilador empleado.
WDT: El famoso "perro guardián" del PIC se configura aquí. Esta es una capacidad del microcontrolador de autorresetearse.
PWRT: Si activamos este fuse, lo que conseguimos es que se genere un retardo en la inicialización del microcontrolador.
CP: Activando este fuse tendremos la garantía de que el código que escribamos en el PIC no pueda ser leído por otra persona, para que no nos lo copien, modifiquen, etc. (Code Protection). Esto no impide que el PIC funcione como siempre, ni que no se pueda sobrescribir su contenido
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
Definición de variables que utilizaremos en nuestro proyecto. En este caso solo definiremos bits, por ejemplo Led y Pulsador.
Para organizar nuestro programa lo estructuraremos de la siguiente manera:
Nivel Directiva Operandos ; Comentarios
;**** Definicion de variables ****
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
Pulsador equ 0 ; Definimos Pulsador como el bit 0, en este caso sera para PORTA
Configuración de puertos.
Para la configuración necesitamos los siguientes registros:
STATUS > 0x03; PORTA > 0x05; PORTB > 0x06; TRISA > 0x86 y TRISB > 0x86.
Por defecto los puertos quedan configurados como entradas de datos y si se quiere cambiar hay que configurarlos. Esto se realiza con los registros TRISA y TRISB, teniendo en cuenta que si se asigna un cero (0) a un pin, quedara como salida y si se asigna un uno (1), quedara como entrada.
En nuestro caso se necesita colocar TRISA igual a 11111 (o se puede dejar por default) y TRISB 11111110. Ahora bien, cuando el PIC arranca se encuentra en el Banco 0, TRISA y TRISB se encuentran en el Banco 1, entonces debemos cambiar de Banco. Esto se realiza con el bit RP0 del registro STATUS. Si este se pone un cero a RP0, estaremos en el Banco 0. Si se coloca un uno, estaremos en el Banco 1.
Registro W: es el registro más importante que tiene el microcontrolador y es denominado ACUMULADOR.
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del código de programa.-
Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111' ; Muevo 11111 a W.-
movwf TRISA ; Cargo en TRISA.-
movlw b'11111110'
movwf TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
bcf PORTB,Led ; Comienza apagado.-
Ya configurado nuestro PIC, vamos a realizar la rutina que ejecutara.
;**** Control de Led ****
Bucle btfsc PORTA,Pulsador ; Preguntamos si esta en 0 logico.-
goto Apagar ; Esta a 1 logico, Apagamos Led.-
bsf PORTB,Led ; Esta a 0 logico, Encendemos Led.-
goto Bucle ; Testeamos nuevamente la condicion del Pulsador.-
Apagar bcf PORTB,Led ;Apagamos Led.-
goto Bucle ; Testeamos nuevamente la condicion del Pulsador.-
end
Aquí solamente en un bucle infinito testeamos continuamente el estado del pulsador, y según su estado se encenderá o apagará el Led.-
:-/
-
Programa completo:
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
Pulsador equ 0 ; Definimos Pulsador como el bit 0, en este caso sera para PORTA
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111' ; Muevo 11111 a W.-
movwf TRISA ; Cargo en TRISA.-
movlw b'11111110'
movwf TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
bcf PORTB,Led ; Comienza apagado.-
;**** Control de Led ****
Bucle btfsc PORTA,Pulsador ; Preguntamos si esta en 0 logico.-
goto Apagar ; Esta a 1 logico, Apagamos Led.-
bsf PORTB,Led ; Esta a 0 logico, Encendemos Led.-
goto Bucle ; Testeamos nuevamente la condicion del Pulsador.-
Apagar bcf PORTB,Led ;Apagamos Led.-
goto Bucle ;Testeamos nuevamente la condicion del Pulsador.-
end
Bueno aquí ya tenemos nuestro programita terminado, solo falta compilarlo y simularlo para detectar errores, esto esta mínimamente explicado en el tutorial del Utilitario MPLAB adjuntado al principio.-
Se adjunta el circuito realizado en Proteus para simulación.-
-
Creación de Demoras:
Ciclo de maquina:
Es la unidad básica de tiempo que utiliza el microcontrolador y equivale a 4 ciclos de reloj. Ósea, si tenemos un oscilador de 4 MHz, el ciclo de reloj seria de 250 ns y el ciclo maquina de 1 us.
Las instrucciones del microcontrolador necesitan 1 ciclo maquina excepto algunas excepciones, como son los comandos que incluyen saltos (goto, call, btfss, btfsc, return, etc) que necesitan dos ciclos maquina.
Demoras mediante lazo simple
Demora_xxus
movlw 0xXX ; Cargamos valor XX que controla duración (1)
movwf Contador ; Iniciamos Contador (1)
Repeticion
Decfsz Contador ; Decrementa contador y si es cero sale (1 si no sale, 2 si sale)
goto Repeticion ; No es 0, repetimos (2)
return ; Regresamos de la subrutina (2)
Entre paréntesis se muestra el número de ciclos que demora cada instrucción.-
De manera que el número de ciclos de instrucción Tsub consumidos por la rutina, incluyendo los 2 ciclos de la llamada (CALL) serán
Tsub = [2 + 1 + 1 + (0xXX - 1)*(1 + 2) + 2 + 2] ciclos = (3*0xXX + 5) *Tcy
Donde Tcy es la duración en segundos de un ciclo de instrucción. Utilizando un oscilador de 4 MHz la mayor duración posible es de 770 us, con 0xXX = 0xFF.-
Demoras mediante Lazos anidados
Para lograr demoras de mayor duración deben utilizarse lazos anidados, poniendo un lazo de demora dentro de otro.
Demora_xx
movlw 0xXX ; (1)
movwf Contador1 ; (1)
Repeticion1
movlw 0xYY ; (1)
movwf Contador2 ; (1)
Repeticion2
decfsz Contador2,1 ; (1 si no sale, 2 si sale)
goto Repeticion2 ; (2)
decfsz Contador1,1 ; (1 si no sale, 2 si sale)
goto Repeticion1 ; (2)
return ; (2)
La duración de esta rutina en ciclos de reloj será
Tsub = 2 + 1 + 1 + (0xXX)*[1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 1 + 2] + [1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 2 + 2] ciclos
Lo cual se puede simplificar como sigue
Tsub = [0xXX*((0xYY - 1)*3 + 7) + 5] Tcy
En este caso el máximo que se puede conseguir es de aprox. 196 milisegundos.-
Bueno ahora que se entiende como se realizan las demoras, les adjunto un programita que obtiene el código necesario para una pausa, ingresando el valor de la misma y la frecuencia del oscilador utilizado.-
-
Ejemplo:
En este ejemplo se explicará como calcular demoras. Se hará titilar un led conectado a RB0 siempre que el interruptor conectado a RA0 este cerrado.
Diagrama de Flujo:
(http://img19.imageshack.us/img19/9232/ledtitilandosy4.jpg)
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Contador1 equ 0x0C ; Seleccionamos posicion en la memoria RAM (GPR) para guardar
; registro utilizado para demora.-
Contador2 equ 0x0D ; Registro utilizado en demora.-
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
Pulsador equ 0 ; Definimos Pulsador como el bit 0, en este caso sera para PORTA
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111' ; Muevo 11111 a W.-
movwf TRISA ; Cargo en TRISA.-
movlw b'11111110'
movwf TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
bcf PORTB,Led ; Comienza apagado.-
;**** Control de Led ****
Bucle btfsc PORTA,Pulsador ; Preguntamos si esta en 0 logico.-
goto Apagar ; Esta a 1 logico, Apagamos Led.-
bsf PORTB,Led ; Esta a 0 logico, Encendemos Led.-
call Demora_150ms ; Mantenemos prendido 150 milisegundos
bcf PORTB,Led ; Apagamos Led
call Demora_150ms ; Apagamos durante 150 ms, Ya realizamos un titilo.-
goto Bucle ; Testeamos nuevamente la condicion del Pulsador
Apagar bcf PORTB,Led ;Apagamos Led.-
goto Bucle ; Testeamos nuevamente la condicion del Pulsador.-
;**** Demora ****
Demora_150ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0xC3 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
end
-
Creación de Tablas: Control de un Display de 7 Segmentos.
Un Display es una colección de Leds ubicados de forma estratégica. Si se los agrupa uniendo sus cátodos será de CÁTODO COMUN, o bien agrupando sus ánodos, un Display de ANODO COMUN.
Por otro lado estos Leds pueden ser fabricados en forma de Puntos o Segmentos, tal es así que se encuentran Display de 7 segmentos, como los de la imagen:
(http://img89.imageshack.us/img89/8063/display7segnp1.jpg)
El programa que realizaremos leerá la cantidad de veces que se activa un pulsador y mostraremos el resultado. Conectaremos el Display en forma directa, es decir conectando el puerto B del micro a los pines del Display, y luego encender cada uno de los segmentos del Display para visualizar el valor correspondiente. Para ello crearemos una tabla que contenga los distintos códigos para el numero que necesitemos visualizar.
(http://img516.imageshack.us/img516/3756/harddisplaysimplewb0.bmp)
Es obvio que con un solo display solamente podremos contar de 0 a 9.
Diagrama de Flujo:
(http://img4.imageshack.us/img4/8099/displaysimpleth3.th.jpg) (http://img4.imageshack.us/my.php?image=displaysimpleth3.jpg)
Antes de continuar tratare de explicar algunos registros importantes:
El PC. Direccionamiento del programa: Especifica la dirección de la instrucción que se ejecutará. Consta de 13 bits, con lo que es posible direccionar hasta 8K palabras, pero en el 16F84A solo se implementa 1k.
(http://img204.imageshack.us/img204/4632/contadorpcnr4.jpg)
La parte alta del contador de programa (PCH) no se puede acceder directamente, ella debe cargarse desde los 5 bits más bajos del registro llamado PCLATCH (dirección 0x08).
En la creación de tablas, la posición a leer de la misma se realiza con el control del registro PCL. Este registro es de 8 bits, por lo que direcciona solo 256 posiciones, por ello se debe tener en cuenta la posición de la tabla en la memoria de programa o también controlar los bits mas significativos de PC (Si nuestra tabla tiene mas de 255 posiciones, si o si debemos manejar estos bits [PCLATCH]).
Para devolver el valor direccionado se utiliza retlw, esta instrucción devuelve un valor en el acumulador al retornar de una subrutina. La creación de la tabla se hará de la siguiente forma:
Tabla
addwf PCL,f
retlw Valor0
retlw Valor1
retlw Valor2
retlw Valor3
; ....
Donde Valor0, Valor1, Valor2... etc. son los valores que queremos almacenar en la tabla.
La estrategia a seguir para consultar algún valor de la tabla es cargar en el acumulador (W) la dirección de la tabla donde se encuentra el valor que quieres leer y después llamar a la subrutina TABLA (con un CALL).
Advertencia: la carga de W no puede superar el número de valores de la tabla, sino se estará ejecutando una instrucción errónea provocando un mal funcionamiento del programa.-
Explicado lo necesario pasamos al código del ejemplo:
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Contador equ 0x0C ; Registro para almacenar conteo
Contador1 equ 0x0D ; Registro utilizado en demora.-
Contador2 equ 0x0E ; Registro utilizado en demora.-
Pulsador equ 7 ; Definimos Pulsador como el bit 7, en este caso sera para PORTB
;**** Inicio del Micro ****
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Tabla de conversion BCD a 7 Segmentos ****
; Se coloca al inicio para asegurar ubicacion en Pagina.-
org 0x05 ; Origen del codigo de tabla.-
BCD7SEG: ; retlw b'gfedcba' para display catodo comun
addwf PCL,1 ; Se incrementa el contador del programa.-
retlw b'0111111' ; 0
retlw b'0000110' ; 1
retlw b'1011011' ; 2
retlw b'1001111' ; 3
retlw b'1100110' ; 4
retlw b'1101101' ; 5
retlw b'1111101' ; 6
retlw b'0000111' ; 7
retlw b'1111111' ; 8
retlw b'1101111' ; 9
clrf Contador ; Si llega 10, se resetea contador
retlw b'0111111' ; 0
;**** Programa principal ****
;**** Configuración de puertos ****
Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'10000000' ; RB7 como entrada y los demas como salida.-
movwf TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
movlw b'0111111' ; Comienza en cero.-
movwf PORTB
clrf Contador
;**** Testeo de Pulsador ****
Testeo
btfss PORTB,Pulsador ; Testeamos si esta a 1 logico.-
goto Testeo ; No, seguimos testeando.-
call Demora_20ms ; Eliminamos Efecto rebote
btfss PORTB,Pulsador ; Testeamos nuevamente.-
goto Testeo ; Falsa Alarma, seguimos testeando.-
incf Contador,1 ; Se ha pulsado, incrementamos contador.-
movfw Contador ; pasamos contador a W
call BCD7SEG ; Llamamos tabla.-
movwf PORTB ; Cargamos valor recibido por Tabla en PORTB
btfsc PORTB,Pulsador ; Esperamos a que se suelte el pulsador -**-
goto $-1 ; No, PCL - 1, --> btfss PORTA,Pulsador.-
call Demora_20ms ; Eliminamos efecto rebote.-
btfsc PORTB,Pulsador ; Testeamos nuevamente.-
goto $-4 ; No, Falsa alarma, volvemos a testear a que se suelte (**).-
goto Testeo ; Si, Testeamos nuevamente.-
;**** Demora ****
Demora_20ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0x19 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
end
Una manera más cómoda de escribir la tabla de instrucciones RETLW puede lograrse usando la directiva DT (Define Table) del ensamblador, la cual nos permite definir una tabla de datos que será sustituida por una lista de instrucciones RETLW; así, la tabla anterior puede quedar como sigue:
BCD7SEG: ; retlw b'gfedcba' para display catodo comun
addwf PCL,1 ; Se incrementa el contador del programa.-
DT 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0xFF, 0x6F
clrf Contador
retlw 0x3F
Rutinas de Lectura de una Tabla en Memoria de Programa, sin importar donde esté ubicada (http://www.todopic.com.ar/foros/index.php?topic=12345.msg74300#msg74300)
Aquí hay ejemplos de como trabajar para colocar una tabla en cualquier lugar de la memoria de programa.
Control anti rebote:
En el momento de presionar un botón pulsador o cualquier conmutador electromecánico es inevitable que se produzca un pequeño arco eléctrico durante el breve instante en que las placas del contacto se aproximan o se alejan de sus puntos de conexión.
(http://img205.imageshack.us/img205/1919/antirrebote.jpg)
La duración de este depende de la calidad de los switches y la velocidad de accionamiento, pero no dura más de 20 milisegundos.
Se adjunta simulación.-
-
Otra forma de crear una tabla. Direccionamiento Indirecto.-
En la programación de los microcontroladores PIC la mayoría de las instrucciones emplean direccionamiento directo, pero también es posible que operen en un modo de direccionamiento directo. Para el direccionamiento indirecto se emplean dos registros especiales: el FSR y el INDF (este ultimo no es un registro físico). El registro FSR se emplea para “señalar o apuntar” a una dirección de la memoria RAM cuyo contenido puede ser leído o escrito de forma indirecta empleando cualquier instrucción que use como operando al registro INDF.
Esta forma de direccionamiento es particularmente útil cuando se manejan tablas o arreglos de datos.-
Directo vs Indirecto.
; DIRECTO:
; Definimos registro en la memoria de datos.-
MyRegistro equ 0x10 ; Ubicado en 0x10.-
; Cargamos dato en el registro.-
movlw 0x8A ;
movwf MyRegistro ; MyRegistro = 0x8a.-
; Leemos dato del registro.-
movfw MyRegistro ; Movemos el valor que tenga MyRegistro a W.-
movwf PORTB ; Por ejemplo, lo cargamos en PORTB.-
; INDIRECTO:
; Cargamos dato en el registro.-
movlw 0x10 ;
movwf FSR ; Direccionamos Registro de datos ubicado en 0x10.-
movlw 0x8A ;
movwf INDF ; Cargamos registro direccionado con el valor 0x8A.-
; Leemos dato en el registro.-
movlw 0x10 ;
movwf FSR ; Direccionamos Registro de datos ubicado en 0x10.-
movfw INDF ; Movemos el valor que tenga el registro seleccionado a W.-
movwf PORTB ; Por ejemplo, lo cargamos en PORTB.-
Utilizaremos el direccionamiento Indirecto para crear la tabla de control del Display. Aquí no utilizaremos el pulsador, solo se hará el contador automático de 0 a 9.- Al iniciar el microcontrolador cargaremos el código de 7 Segmentos para controlar el Display en la memoria de Datos con direccionamiento indirecto.
Luego, al realizar el conteo leeremos el código correspondiente almacenado y lo enviaremos al PORTB.-
Aquí utilizamos el registro STATUS nuevamente, pero para control de las operaciones aritméticas. Nosotros guardaremos el código de 7 Segmentos del 0 al 9, en los registros 0x10 a 0x19. Si nuestro contador nos direcciona el registro ubicado en 0x1A, que seria el “10”, lo reseteamos y direccionamos el “0”, ósea registro 0x10. Esto lo hacemos realizando la resta del registro seleccionado y 0x1A, FSR – 0x1A, y si el resultado es cero, reseteamos.
El bit Z (Zero) del registro STATUS, este indica si una operación lógica o aritmética realizada da como resultado cero. También tenemos el bit C (Carry) (0), que en instrucciones aritméticas se activa cuando se presenta un acarreo desde el bit mas significativo del resultado, el bit DC (Digit Carry), que en operaciones aritméticas se activa si ocurre acarreo entre el bit 3 y bit 4.-
Código completo:
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Contador equ 0x0C ; Seleccionamos posición en la memoria RAM (GPR) para guardar
; registro utilizado para demora.-
Contador1 equ 0x0D ; Registro utilizado en demora.-
Contador2 equ 0x0E
Pulsador equ 7 ; Definimos Pulsador como el bit 0, en este caso será para PORTA
Reset
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Programa principal ****
;**** Configuracion de puertos ****
Inicio
bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
clrf TRISB ; PORTB como salida.-
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
call Config_Tabla ; Cargamos registros con Codigo de 7 segmentos.-
movfw INDF ; Leemos codigo de 7 Segmentos para el CERO.-
movwf PORTB ; Mostramos el CERO.-
;**** Testeo de Pulsador ****
Bucle
call Demora_190ms ; Demora para visualizar Display
incf FSR,1 ; Incrementamos Puntero.-
movlw 0x1A ; Consulamos si se pide codigo para mostrar "10",
subwf FSR,0 ; si es asi reseteamos FSR, apunta a 0x10--> "0".-
btfss STATUS,Z ; Si Z=1 --> 0x1A - FSR = 0.-
goto Muestro_Display ; No, muestro display.-
movlw 0x10 ; Si reseteo puntero.-
movwf FSR ;
Muestro_Display
movfw INDF ; Leo Registro que apunta FSR.-
movwf PORTB ; Lo cargo en PORTB.-
goto Bucle ; Continuo conteo.-
;**** Demora ****
Demora_190ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0xFF ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;**** Cargamos tabla en memoria ****
Config_Tabla
movlw 0x10 ;
movwf FSR ; Direccionamos el registro 0x10 de la memoria RAM (GPR).-
movlw 0x3F ; Cargamos el codigo para mostrar el CERO.-
movwf INDF ; Lo guardamos donde apunta FSR --> 0x10.-
;....................
incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x11.-
movlw 0x06 ; Cargamos codigo para UNO.-
movwf INDF ; Lo guardamos donde apunta FSR.-
;....................
incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x12.-
movlw 0x5B ; Cargamos codigo para DOS.-
movwf INDF ; Lo guardamos donde apunta FSR.-
;....................
incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x13.-
movlw 0x4F ; Cargamos codigo para TRES.-
movwf INDF ; Lo guardamos donde apunta FSR.-
;....................
incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x14.-
movlw 0x66 ; Cargamos codigo para CUATRO.-
movwf INDF ; Lo guardamos donde apunta FSR.-
;....................
incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x15.-
movlw 0x6D ; Cargamos codigo para CINCO.-
movwf INDF ; Lo guardamos donde apunta FSR.-
;....................
incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x16.-
movlw 0x7D ; Cargamos codigo para SEIS.-
movwf INDF ; Lo guardamos donde apunta FSR.-
;....................
incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x17.-
movlw 0x07 ; Cargamos codigo para SIETE.-
movwf INDF ; Lo guardamos donde apunta FSR.-
;....................
incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x18.-
movlw 0xFF ; Cargamos codigo para OCHO.-
movwf INDF ; Lo guardamos donde apunta FSR.-
;....................
incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x19.-
movlw 0x6F ; Cargamos codigo para NUEVE.-
movwf INDF ; Lo guardamos donde apunta FSR.-
;....................
movlw 0x10 ;
movwf FSR ; Direccionamos Registro del CERO.-
return ; Cargado los valores, retornamos.-
;..................................................................
end
-
Control de varios Display
Para el control de varios display la idea es multiplexar la señal enviada por el microcontrolador, con él administraremos el encendido de cada display y sus segmentos (lo cual se hace por programa).
Para ejemplificar haremos un contador automático de 0 a 999:
El hardware necesario es el siguiente:
(http://img90.imageshack.us/img90/4061/hard3displayiv2.bmp)
Diagramas de Flujo:
(http://img4.imageshack.us/img4/9899/3displaymainev2.th.jpg) (http://img4.imageshack.us/my.php?image=3displaymainev2.jpg)
(http://img4.imageshack.us/img4/2979/3displayrutinafa2.th.jpg) (http://img4.imageshack.us/my.php?image=3displayrutinafa2.jpg)
Se observa que el Puerto B se utiliza para enviar los datos a mostrar en cada display, mientras que por el Puerto A seleccionas el display que mostrará ese dato. Supongamos que quiero mostrar "231", pues muy fácil, pongo el puerto B en 0000110 (código para el 1), y activo ahora el 3º transistor por un periodo de tiempo corto, desactivamos este transistor, cargamos el puerto B con 1001111 y activamos el 2º transistor por un tiempito, lo mismo hacemos para mostrar “1”. Repetimos esta misma secuencia mientras se quiera mostrar este valor. La secuencia es tan rápida que el observador no nota el momento en que cambias de display.
(http://img147.imageshack.us/img147/3754/3displaysiw2.jpg)
Control de conteo:
Para realizar el conteo incrementamos continuamente Unidad, cuando está llega a 10, las reseteamos a 0, e incrementamos en 1 Decena. La misma operación se realiza con Decena, al llegar a 10 se lleva a 0 y se incrementa Centena.-
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Unidad equ 0x0C ; Guardamos conteo unidad
Decena equ 0x0D ;
Centena equ 0x0E ;
Contador1 equ 0x0F ; Registro utilizado en demora.-
Contador2 equ 0x10 ; Registro utilizado en demora.-
Contador equ 0x11 ; Control de Refresco de Display.-
MuestroU equ 2 ; Para control del 1º Display
MuestroD equ 1 ; Para control del 2º Display
MuestroC equ 0 ; Para control del 3º Display
;**** Inicio del Micro ****
Reset
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Tabla de conversion BCD a 7 Segmentos ****
; Se coloca al inicio para asegurar ubicacion en Pagina.-
org 0x05 ; Origen del código de tabla.-
BCD7SEG ; retlw b'gfedcba' para display catodo comun
addwf PCL,1 ; Se incrementa el contador del programa.-
DT 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0xFF, 0x6F
;**** Programa principal ****
;**** Configuracion de puertos ****
Inicio
bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
clrf TRISA ; PORTA como salida
clrf TRISB ; PORTB como salida.-
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
clrf PORTA ; Desactivo todos los Displays
clrf Unidad ; Comienza en cero --> 0 0 0.-
clrf Decena
clrf Centena
goto Actualizo_Display ; Esta rutina multiplexa los displays.-
;**** Testeo de Pulsador ****
Bucle
incf Unidad,1 ; Incremeto Unidad.
movlw d'10' ; Si es 10 reseteo e incremento Decena
subwf Unidad,0 ;
btfss STATUS,Z ;
goto Actualizo_Display ; no es 10
clrf Unidad ; Si, reseteo.-
incf Decena,1 ; Incremento Decena.-
movlw d'10' ; Si Decena = 10, reseteo e incremento Centena
subwf Decena,0 ;
btfss STATUS,Z ;
goto Actualizo_Display ; No es 10.-
clrf Decena ; Si, reseteo.-
incf Centena,1 ; Incremento Centena.-
movlw d'10' ; Si es 10 Reseteo.-
subwf Centena,0
btfss STATUS,Z
goto Actualizo_Display ; No es 10.-
clrf Centena ; Si, reseto
;**** Se multiplexan los Display ****
Actualizo_Display
movlw d'20' ; Cargo Contador = 20
movwf Contador ; Para repeticiones de visualizacion del mismo valor
; durante 150 ms.-
Refresco
movfw Unidad ; Obtengo codigo de 7 Segmentos para Unidad.-
call BCD7SEG ;
bcf PORTA,MuestroC ; Apago Display de Centena, Se entiende al mirar rutina.-
movwf PORTB ; Cargo unidad en PORTB.-
bsf PORTA,MuestroU ; Enciendo Display de Unidad.-
call Demora_5ms
movfw Decena ; Obtengo codigo 7 Segmentos para Decena.-
call BCD7SEG
bcf PORTA,MuestroU ; Apago Display de Unidad.-
movwf PORTB ; Cargo PORTB con Decena.-
bsf PORTA,MuestroD ; Enciendo Display de Decena.-
call Demora_5ms
movfw Centena ; Obtengo codigo de 7 Segmentos para Centena.-
call BCD7SEG
bcf PORTA,MuestroD ; Apago Display de Decena.-
movwf PORTB ; Cargo PORTB con Centena.-
bsf PORTA,MuestroC ; Enciendo Display Centena.-
call Demora_5ms
decfsz Contador,1 ; Pregunto si ya se ha repetido 10 veces el ciclo?
goto Refresco ; No, repito.-
goto Bucle ; Si, actualizo cuenta.-
;**** Demora ****
Demora_5ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0x05 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
end
En este ejemplo se mantiene la visualización del mismo valor durante aprox. 300 ms, se puede determinar ya que utilizamos 3 demoras de 5 ms despreciando los ciclos utilizados en los comandos, que son aprox. 30 (30 us). Entonces por ciclo tenemos 15 ms, y por 20 repeticiones, 300 ms.-
Al final de este hilo se ha agregado un ejemplo de control de 3 display con el registro de desplazamiento 74LS164.
Ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg213264#msg213264)
-
Decodificador BCD.
La otra posibilidad es utilizar un decodificador BCD como el 74LS47 o el 74LS249, o el CD4511. Estos integrados disponen de 4 entradas correspondientes a un código binario BCD, y 7 salidas que se conectan a un Display.
(http://img204.imageshack.us/img204/5091/harddisplayconversorox1.bmp)
Lo importante de este integrado, es que posee 4 pines de entrada y 7 de salida, mas unos cuantos de configuración. El hecho es que, los 4 pines de entrada (A, B, C y D) serán los que reciban el código en binario enviado por el micro. Una vez recibido el dato, el integrado se hará cargo de decodificarlo y enviarlo por los pines de salida (a, b, c, d, e, f y g) para mostrarlo en el display. Lo que nos falta saber, es que dato deberé enviar al decodificador.
| DCBA | Valor que muestra el Display |
| 0000 | 0 |
| 0001 | 1 |
| 0010 | 2 |
| 0011 | 3 |
| 0100 | 4 |
| 0101 | 5 |
| 0110 | 6 |
| 0111 | 7 |
| 1000 | 8 |
| 1001 | 9 |
-
INTERRUPCIONES
Una de las características más importante de los microcontroladores y que mencionamos al inicio del tutorial, es que tienen la posibilidad de manejar interrupciones. Se trata de un acontecimiento que hace que el micro deje de lado lo que se encuentra realizando, atienda ese suceso y luego regrese y continúe con lo suyo.
Hay dos tipos de interrupciones posibles, una es mediante una acción externa (es decir por la activación de uno de sus pines), la otra es interna (por ejemplo cuando ocurre el desbordamiento de uno de sus registros)
En el 16F84A hay 4 fuentes de interrupción:
- Por el pin RB0/INT, que regresa al PIC del modo SLEEP (interrupción externa).
- Por los pines RB4 a RB7, configurados como entrada y en caso de que alguno de ellos cambie de estado (interrupción externa).
- Por desbordamiento del registro TMR0, cuando este registro pasa de 255 a 0 en decimal (interrupción interna).
- Al completar la escritura de la EEPROM de datos (interrupción interna).
Cada fuente de interrupción esta controlada por 2 bits. Un bit local de interrupciones (Terminado en E) de permiso o prohibición de ejecución. Si esta en 0 bloqueará la solicitud de interrupción, y si esta en 1 permitirá la ejecución. Un bit que actúa como señalizador (Terminado en F) el cual es activado (puesto a 1) si se ha producido la interrupción. Además existe 1 bit de control global, el bit GIE (INTCON <7>) el cual si esta desactivado bloquea todas las solicitudes de interrupción.
Lo anterior descrito puede entenderse observando el diagrama lógico de la siguiente figura:
(http://img3.imageshack.us/img3/4032/logicadeinterrupciones8.jpg)
El bit GIE se borra automáticamente cuando se reconoce una interrupción para evitar que se produzca otra mientras se está atendiendo a la primera y al retornar de la interrupción con la instrucción RETFIE, el bit GIE se vuelve a activar poniéndose a 1. En cambio los bits señalizadores o banderas de interrupción deben ser puestos a cero por el tratamiento de la interrupción realizada por el usuario (Programador)
Cuando una interrupción está habilitada (su bit local de habilitación está activado, el bit GIE está activado) y ocurre el evento que la activa, el valor de PC se guarda en la PILA y en éste se carga el 0x04 (único vector de interrupción). Es a partir de esta dirección que se debe colocar el tratamiento de la interrupción, detectando por medio de los bits banderas cual de los eventos ha ocurrido y actuar según sea el caso.
Nota: El único registro que se salva en la PILA es PC, para preservar algún otro registro debe ser el propio programa de atención a la interrupción el que se encargue de salvar su estado al inicio de la rutina y de devolverlos al final del mismo.
Resumiendo, las acciones que se realizan automáticamente el microcontrolador y las que el programador debe tener en cuenta en sus programas son las siguientes:
- Cuando se activa una posible causa de interrupción, el flag correspondiente se activa. Si el bit de permiso correspondiente está a 1 y el bit de habilitación de todas las interrupciones (GIE) está a 1, se produce la interrupción.
- Para evitar que se produzca otra interrupción mientras se está atendiendo a otra anterior, el bit GIE se pone a 0.
- El valor del PC se guarda en la PILA
- El PC se carga con el valor 0x04, que es el vector de interrupciones
- El programador, debe comenzar la rutina de atención a la interrupción con un salto a la posición de memoria donde se encuentra el programa, seguidamente se guardan todos los registros que puedan ser modificados por esta, seguidamente si están habilitadas varias vías de interrupción, se debe explorar el valor de las banderas para determinar la causa de la interrupción.
- Dependiendo de la causa de la interrupción, la rutina de interrupción se bifurca a la subrutina correspondiente.
- Se deben devolver los valores que tenían los registros antes de producirse la interrupción y se deben borrar por software las banderas que indican las fuentes de las interrupciones, antes del retorno al programa principal.
- Cuando se llega a la última instrucción de la rutina de interrupción, RETURN, se carga el PC con el valor que se guardó inicialmente en la PILA y el bit GIE se pone automáticamente a 1.
Bits utilizados.
- INTF para RB0/INT, bit 1 de INTCON, si es 1 ocurrió interrupción externa
- RBIF para los pines B4 a RB7, bit 0 de INTCON, si es 1 por lo menos un pin cambio de estado
- T0IF para TMR0, bit 2 de INTCON, si es 1 TMR0 desbordado
- EEIF para la EEPROM, bit 4 de EECON1, si es 1 se ha completado escritura
- GIE, bit 7 de INTCON, si es 1 habilita todas las interrupciones
- EEIE, bit 6 de INTCON, si es 1 se activa interrupciones de periféricos
- T0IE, bit 5 de INTCON, si es 1 int. TMR0 activada
- INTE, bit 4 de INTCON, si es 1 int. Externa activada
- RBIE, bit 3, si es 1 int. Por RB4 a RB7 activada
Todos estos bits al resetearse o iniciarse el micro se encuentran en 0.
Rutina de Servicio de Interrupciones:
Primero debes guardar el contenido del registro W, el problema de mover W a otro registro (haciendo uso de movf) es que esta instrucción corrompe la bandera Z, modificando el registro de STATUS. Según la hoja de datos otorgada por Microchip, en uno de sus apartados recomienda una secuencia de código que permite guardar y restaurar los registros sin modificarlos.
;**** Rutina de servicio de Interrupcion ****
; Guardado de registro W y STATUS.-
Inicio_ISR
movwf W_Temp ; Copiamos W a un registro Temporario.-
swapf STATUS, W ;Invertimos los nibles del registro STATUS.-
movwf STATUS_Temp ; Guardamos STATUS en un registro temporal.-
ISR
; Atendemos la interrupción.-
; Restauramos los valores de W y STATUS.-
Fin_ISR
swapf STATUS_Temp,W ; Invertimos lo nibles de STATUS_Temp.-
movwf STATUS
swapf W_Temp, f ; Invertimos los nibles y lo guardamos en el mismo registro.-
swapf W_Temp,W ; Invertimos los nibles nuevamente y lo guardamos en W.-
retfie ; Salimos de interrupción.-
Los registros W_Temp y STATUS_Temp son registros alternativos para guardar temporariamente sus valores correspondientes.-
-
INTERRUPCION POR TMR0
El Timer 0 es un contador / temporizador de 8 bits. El registro principal de este módulo es TMR0 (0x01). Este registro se incrementa continuamente a una frecuencia seleccionable manejada por un preescalador y el reloj interno Fosc/4 (modo temporizador) o bien, por un preescalador y una señal externa (modo contador).
En la siguiente figura se muestra un diagrama de bloques de este módulo, en donde se indican los bits que afectan su operación y la manera en que lo hacen.
(http://img90.imageshack.us/img90/149/tmr0aa6.jpg)
El modo Temporizador
En el modo temporizador la señal de reloj que controla el incremento del registro TMR0 es la frecuencia Fcy = Fosc/4, la cual puede ser dividida opcionalmente por el preescalador si así se desea. Como se puede ver en la figura anterior, este modo es seleccionado al limpiar el bit T0CS (OPTION_REG<5>). En este modo, el contenido del registro TMR0 se incrementará a la frecuencia Fcy dividida de acuerdo al preescalador, sin embargo, si se realiza una escritura al registro TMR0, su incremento es inhibido por los siguientes dos ciclos de instrucción (Tcy).
El modo Contador
En el modo contador, la señal que controla los incrementos del registro TMR0 es una señal externa que proviene de la patita T0CKI. En la figura anterior se puede ver que este modo se selecciona poniendo el bit T0CS en alto. Se puede seleccionar la transición que provoca los incrementos mediante el bit “Timer0 Source Edge Select“ T0SE (OPTION_REG<4>), limpiando este bit se selecciona la transición de subida, mientras que al ponerlo en alto se selecciona la de bajada.
Observación: En este modo, la señal conectada a TOCKI es muestreada durante los ciclos Q2 y Q4 del reloj interno, por ello es necesario que permanezca en alto al menos por 2 Tosc más un pequeño retardo de 20nseg y lo mismo en bajo. (Es decir, señales demasiado estrechas (rápidas) no podrán ser detectadas).
El preescalador
El preescalador es un divisor de frecuencia de módulo seleccionable. Como se puede ver en la figura anterior, el preescalador está compartido entre el timer0 y el módulo Watchdog, sin embargo sólo puede conectarse a uno de los dos y esto se establece mediante el bit PSA (OPTION_REG<3>), así, con este bit en alto el preescalador es asignado al reloj del Watchdog, mientras que con un nivel bajo en PSA el preescalador dividirá la frecuencia que maneja al Timer 0.
La selección del módulo (valor de división de frecuencia) del preescalador se puede realizar mediante los bits PS2,PS1,PS0 (OPTION_REG<2:0>) de acuerdo a la siguiente tabla:
| PS2 PS1 PS0 | Divisor |
| 000 | 1/2 |
| 001 | 1/4 |
| 010 | 1/8 |
| 011 | 1/16 |
| 100 | 1/32 |
| 101 | 1/64 |
| 110 | 1/128 |
| 111 | 1/256 |
NOTA: Si se necesita el timer en 1:1 solo hay que asociar el preescaler al Watchdog.
-
Ejemplo modo temporizador.
Para calcular una temporización se necesita el tiempo de un ciclo de instrucción (es decir 1 microsegundo, si estas trabajando con un XT de 4 Mhz), el valor del Divisor de Frecuencia (el que seleccionabas con los bits PS2, PS1 y PS0), y finalmente el complemento del valor cargado en TMR0 (es decir 255-TMR0). Entonces tenemos: Temporización = Ciclo de instrucción. (256-TMR0) .Divisor de Frecuencia
De este modo si queremos temporizar 4 ms con un divisor de frecuencia de 32, tendríamos:
\mathrm{TMR0}=256-\left(\frac{4000us}{1us\cdot32}\right)
\mathrm{TMR0}=131
Vemos que la máxima temporización posible es con TMR0 = 0, y Divisor de Frecuencia en 256, lográndose unos 65.5 ms aprox.
Para ejemplificar el uso de esta interrupción haremos titilar un led conectado al PIN RB0 cada 200 ms, para ello haremos una temporización con TMR0 de 50ms y contaremos 4 desbordes del mismo para lograr los 200 ms necesarios. Lo interesante de usar interrupción es que con el micro se puede estar ejecutando cualquier tarea y no ocupar este tiempo en un bucle de demora. El hardware necesario es equivalente al primer ejemplo realizado.-
Diagrama de Flujo:
(http://img7.imageshack.us/img7/6682/tmr0temporizadorva1.th.jpg) (http://img7.imageshack.us/my.php?image=tmr0temporizadorva1.jpg)
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Contador equ 0x0C ; Contador para detectar 4 desbordes de TMR0.-
W_Temp equ 0x0D ; Registro para guardar temporalmente W.-
STATUS_Temp equ 0x0E ; Registro para guardar temporalmente STATUS
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
;**** Inicio del Micro ****
Reset
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
org 0x04 ; Atiendo Interrupcion.-
goto Inicio_ISR
; **** Programa Principal ****
;**** Configuracion de puertos ***
org 0x05 ; Origen del código de programa.-
Inicio
bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111110' ; RB0 como salida.-
movwf TRISB
movlw b'00000111' ; Se selecciona TMR0 modo temporizador y preescaler de 1/256.-
movwf OPTION_REG
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
bcf PORTB,Led ; El Led comienza apagado.-
movlw 0x3D ; Cargamos 61 en TMR0 para lograr aprox. 50ms.-
movwf TMR0
clrf Contador ; Iniciamos contador.-
movlw b'10100000' ; Habilitamos GIE y T0IE (interrupción del TMR0)
movwf INTCON
;**** Bucle ****
Bucle
nop ; Aqui el micro puede ejecutar cualquier otra tarea
goto Bucle ; sin necesidad de utilizar tiempo en un bucle de demora.-
;**** Rutina de servicio de Interrupcion ****
;---> Aqui haremos copia de respaldo para mostrar como se hace aunque no es
; necesario ya que el micro no hace otra tarea mientras tanto <---
; Guardado de registro W y STATUS.-
Inicio_ISR
movwf W_Temp ; Copiamos W a un registro Temporario.-
swapf STATUS, W ;Invertimos los nibles del registro STATUS.-
movwf STATUS_Temp ; Guardamos STATUS en un registro temporal.-
;**** Interrupcion por TMR0 ****
ISR
btfss INTCON,T0IF ; Consultamos si es por TMR0.-
goto Fin_ISR ; No, entonces restauramos valores.-
incf Contador ; Si, Incrementamos contador
movlw 0x04 ; Consultamos si se han producido 4 desbordes
subwf Contador,0 ; para obtener 200 ms.-
btfss STATUS,Z ;
goto Actualizo_TMR0 ; No, cargo TMR0 si salgo.-
clrf Contador ; Si, reseteo Contador y controlo Led.-
btfss PORTB,Led ; Si esta apagado, prendo y viseversa.-
goto Prendo_led
bcf PORTB,Led ; Apago Led.-
Actualizo_TMR0 ; Actualizo TMR0 para obtener una temporizacion de 50 ms.-
movlw 0x3D ; d'61'
movwf TMR0
bcf INTCON,T0IF ; Borro bandera de control de Interrupcion.-
goto Fin_ISR ; Restauro valores.-
Prendo_led
bsf PORTB,Led ; prendo Led.-
goto Actualizo_TMR0
; Restauramos los valores de W y STATUS.-
Fin_ISR
swapf STATUS_Temp,W ; Invertimos lo nibles de STATUS_Temp.-
movwf STATUS
swapf W_Temp, f ; Invertimos los nibles y lo guardamos en el mismo registro.-
swapf W_Temp,W ; Invertimos los nibles nuevamente y lo guardamos en W.-
retfie ; Salimos de interrupción.-
;..........................................
end
Una ayuda adicional :wink:
El programita presentado en el primer post, tiene una utilidad que nos ayudará en el cálculo del preescaler y valor inicial del Timer para obtener una temporización deseada, aparte de generar el código.
(http://img139.imageshack.us/img139/8141/21115051.th.jpg) (http://img139.imageshack.us/my.php?image=21115051.jpg)
-
Ejemplo modo contador.
El siguiente programa realiza el conteo del número de veces que produce una transición de bajo a alto en la patita T0CKI. El valor del contador se incrementará una vez por cada dos transiciones, y al detectarse 10 cambiamos el estado del Led conectado a RB0.
(http://img132.imageshack.us/img132/6776/tmrocontadornm7.bmp)
Diagrama de Flujo:
(http://img297.imageshack.us/img297/9327/tmr0contadorzi5.th.jpg) (http://img297.imageshack.us/my.php?image=tmr0contadorzi5.jpg)
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Contador equ 0x0C ; Contador para detectar 4 desbordes de TMR0.-
W_Temp equ 0x0D ; Registro para guardar temporalmente W.-
STATUS_Temp equ 0x0E ; Registro para guardar temporalmete STATUS
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
;**** Inicio del Micro ****
Reset
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
org 0x04 ; Atiendo Interrupcion.-
goto Inicio_ISR
; **** Programa Principal ****
;**** Configuracion de puertos ***
org 0x05 ; Origen del código de programa.-
Inicio
bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111110' ; RB0 como salida.-
movwf TRISB
movlw b'00100000' ; Se selecciona TMR0 modo Contador, transicion positiva
movwf OPTION_REG ; y preescaler de 1/2.-
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
bcf PORTB,Led ; El Led comienza apagado.-
movlw 0xFB ; Cargamos 251 en TMR0 para contar 10 pulsos en RA4/TOCKI.-
movwf TMR0
movlw b'10100000' ; Habilitamos GIE y T0IE (interrupción del TMR0)
movwf INTCON
;**** Bucle ****
Bucle
nop ; Aqui el micro puede ejecutar cualquier otra tarea
goto Bucle ; sin necesidad de utilizar tiempo en un bucle de demora.-
;**** Rutina de servicio de Interrupcion ****
;---> Aqui haremos copia de respaldo para mostrar como se hace aunque no es
; necesario ya que el micro no hace otra tarea mientras tanto <---
; Guardado de registro W y STATUS.-
Inicio_ISR
movwf W_Temp ; Copiamos W a un registro Temporario.-
swapf STATUS, W ;Invertimos los nibles del registro STATUS.-
movwf STATUS_Temp ; Guardamos STATUS en un registro temporal.-
;**** Interrupcion por TMR0 ****
ISR
btfss INTCON,T0IF ; Consultamos si es por TMR0.-
goto Fin_ISR ; No, entonces restauramos valores.-
btfss PORTB,Led ; Si, Controlamos Led.Si esta apagado, prendo y viseversa.-
goto Prendo_led
bcf PORTB,Led ; Apago Led.-
Actualizo_TMR0 ; Cargamos 251 en TMR0 para contar 10 pulsos en RA4/TOCKI.-
movlw 0xFB ; d'251'
movwf TMR0
bcf INTCON,T0IF ; Borro bandera de control de Interrupcion.-
goto Fin_ISR ; Restauro valores.-
Prendo_led
bsf PORTB,Led ; prendo Led.-
goto Actualizo_TMR0
; Restauramos los valores de W y STATUS.-
Fin_ISR
swapf STATUS_Temp,W ; Invertimos lo nibles de STATUS_Temp.-
movwf STATUS
swapf W_Temp, f ; Invertimos los nibles y lo guardamos en el mismo registro.-
swapf W_Temp,W ; Invertimos los nibles nuevamente y lo guardamos en W.-
retfie ; Salimos de interrupción.-
;..........................................
end
-
INTERRUPCION EXTERNA, RB0/INT
Para el control de la interrupción externa se necesitan dos bits más, ellos son RPBU (OPTION_REG<7>), que activa o desactiva las resistencias Pull-Up internas del PORTB, en caso de que el dispositivo conectado al puerto sea de colector abierto y el más importante INTEDG (OPTION_REG<6>), si esta en 1, la interrupción se genera por flanco ascendente, y en 0, la interrupción se genera por flanco descendente.-
Para mostrar su uso haremos un ejemplo sencillo que muestre como se configura, el cual al presionar un pulsador conectado a RB0 cambiará el estado de un led conectado a RB1, para ello configuramos que la interrupción de genere por flanco ascendente:
(http://img5.imageshack.us/img5/1977/intrb0mb7.bmp)
Diagrama de Flujo:
(http://img4.imageshack.us/img4/4408/rb0wx0.th.jpg) (http://img4.imageshack.us/my.php?image=rb0wx0.jpg)
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Contador1 equ 0x0C
Contador2 equ 0x0D
Pulsador equ 0 ; pin RB0
Led equ 1 ; pin RB1
;**** Inicio del Micro ****
Reset
org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
org 0x04 ; Atiendo Interrupcion.-
goto ISR
; **** Programa Principal ****
;**** Configuracion de puertos ***
org 0x05 ; Origen del codigo de programa.-
Inicio
bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111101' ; RB0 como entrada y RB1 como salida.-
movwf TRISB
movlw b'01000000' ; Config. Por flanco Ascendente.-
movwf OPTION_REG
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
bcf PORTB,Led ; El Led comienza apagado.-
movlw b'10010000' ; Habilitamos GIE y INTE (interrupción por RB0)
movwf INTCON
;**** Bucle infinito ****
Bucle
nop ;
goto Bucle ;
;.............................................
;**** Rutina de servicio de Interrupcion ****
;**** Interrupcion por RB0 ****
ISR
btfss INTCON,INTF ; Consultamos si es por RB0.-
retfie ; No, Salimos de interrupción.-
call Demora_20ms ; Comprueba si es rebote.-
btfss PORTB,Pulsador
goto Fin_ISR ; Es rebote, entonces salimos.-
btfss PORTB,Led ; Si esta prendido, lo apagamos.-
goto Prender_Led
bcf PORTB,Led ; Apagamos Led
goto Fin_ISR
Prender_Led
bsf PORTB,Led ; Encendemos Led
Fin_ISR
bcf INTCON,INTF ; Limpiamos bandera.-
retfie ; Salimos de interrupción.-
;..........................................
;**** Demora ****
Demora_20ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0x19 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
end
-
INTERRUPCION EXTERNA, RB4 a RB7
Aprovecharemos esta interrupción para detectar cuando se ha presionado una tecla de un Teclado Matricial. Un teclado matricial es un simple arreglo de botones conectados en filas y columnas, de modo que se pueden leer varios botones con el mínimo número de pines requeridos. Un teclado matricial 4×3 solamente ocupa 4 líneas de un puerto para las filas y otras 3 líneas para las columnas, de este modo se pueden leer 12 teclas utilizando solamente 7 líneas de un microcontrolador.
Para detectar la tecla presionada se utilizara el siguiente hardware:
(http://img132.imageshack.us/img132/8633/hardwaretecladoar6.bmp)
Configuraremos RB0 a RB3 como salida y las colocaremos a nivel bajo. RB4 y RB7 configuradas como entradas, y en estado normal (sin presión de teclas) estarán a nivel alto. Al presionar una tecla se conecta una fila con una columna, se produce un cambio de nivel en alguna de las columnas (De nivel alto a bajo), y se genera la interrupción. Para detectar que tecla se ha presionado, se colocan RB0 a RB3 a nivel alto, y se pasan a nivel bajo de a una por vez, detectando si se produce algún cambio en las columnas.
(http://img132.imageshack.us/img132/7404/tecladomatricialex4.jpg)
Se utiliza una variable que se incrementa con la cuenta de las teclas revisadas, de este modo al detectar una pulsación el valor de la cuenta será el valor de la tecla presionada. Si al final no se presionó ninguna tecla la variable se pone a cero y la cuenta vuelve a comenzar.
En nuestro ejemplo representaremos la tecla presionada en forma binaria con leds conectados al puerto A.
Diagrama de Flujo:
(http://img4.imageshack.us/img4/39/tecladomatricialnu0.th.jpg) (http://img4.imageshack.us/my.php?image=tecladomatricialnu0.jpg)
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
NTecla equ 0x0C ; Seleccionamos posición en la memoria RAM (GPR) para guardar
W_Temp equ 0x0D ; Registro para guardar temporalmente W.-
STATUS_Temp equ 0x0E ; Registro para guardar temporalmete STATUS
;**** Inicio del Micro ****
Reset
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
org 0x04 ; Atiendo Interrupcion.-
goto Inicio_ISR
;**** Programa principal ****
;**** Configuracion de puertos ****
Inicio
bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
clrf TRISA ; PORTA como Salida.-
movlw b'11110000' ; Nible bajo como Salida y Nible alto como Entrada.-
movwf TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
clrf PORTB
bcf INTCON,RBIF ; Borramos bandera de Interrupcion.-
movlw b'10001000' ; Habilitamos GIE y RBIE (interrupción RB4 a RB7)
movwf INTCON
clrf NTecla
;**** Bucle ****
Bucle
nop
goto Bucle
;**** Rutina de servicio de Interrupcion ****
;---> Aqui haremos copia de respaldo para mostrar como se hace aunque no es
; necesario ya que el micro no hace otra tarea mientras tanto <---
; Guardado de registro W y STATUS.-
Inicio_ISR
movwf W_Temp ; Copiamos W a un registro Temporario.-
swapf STATUS, W ;Invertimos los nibles del registro STATUS.-
movwf STATUS_Temp ; Guardamos STATUS en un registro temporal.-
;**** Interrupcion por TMR0 ****
ISR
btfss INTCON,RBIF ; Consultamos si es por RB4 a RB7.-
goto Fin_ISR ; No, entonces restauramos valores.-
call Tecla_Presionada ; Se detecta que tecla fue presionada
movfw NTecla
movwf PORTA ; Mostarmos en diplay tecla Presionada.-
; Restauramos los valores de W y STATUS.-
Fin_ISR
swapf STATUS_Temp,W ; Invertimos lo nibles de STATUS_Temp.-
movwf STATUS
swapf W_Temp, f ; Invertimos los nibles y lo guardamos en el mismo registro.-
swapf W_Temp,W ; Invertimos los nibles nuevamente y lo guardamos en W.-
retfie ; Salimos de interrupción.-
;**** Rutinas *****
; Rastreamos Tecla presionada.-
Tecla_Presionada
clrf NTecla ; Borra Numero de Tecla y
incf NTecla,1 ; prepara NTecla para primer codigo.
movlw b'00001110' ; Saca 0 a la primera fila
movwf PORTB ; de la Puerta B
nop ; Para estabilizacion de señal.
Test_Columnas
btfss PORTB,4 ; Primera columna = 0
goto Suelta_tecla ; Sale si se ha pulsado tecla.
incf NTecla,1 ; Si no tecla pulsada, incrementa nº tecla.
btfss PORTB,5 ; Segunda columna = 0
goto Suelta_tecla ; Sale si se ha pulsado tecla.
incf NTecla,1 ; Si no tecla pulsada, incrementa nº tecla.
btfss PORTB,6 ; Tercera columna = 0
goto Suelta_tecla ; Sale si se ha pulsado tecla.
incf NTecla,1 ; Si no tecla pulsada, incrementa nº tecla.
; En este caso no se Usa teclado 3x4.-
; btfss PORTB,7 ; Cuarta columna = 0
; goto Suelta_tecla ; Sale si se ha pulsado tecla.
; incf NTecla,1 ; Si no tecla pulsada,incrementa nº Tecla.
Ultima_tecla
btfss PORTB,3 ; Ya se revisaron todas las filas?
goto Null_tecla ; Si, Falsa alarma, no se ha presionado ninguna.-
bsf STATUS,C ; No, seguimos con la siguiente.Pone a 1 Bit C
rlf PORTB,1 ; asi la Fila 1 pasa a 1 con la rotaci¢n a izqda.
goto Test_Columnas
Null_tecla
clrf NTecla ; Coloca variable Tecla a 0 (Ninguna)
bcf INTCON,RBIF ; Borramos bandera de Interrupcion.-
clrf PORTB ; Dejamos Puerto para recibir otra tecla.-
return ; y regresa.
Suelta_tecla
; Ahora se espera a que la tecla sea soltada para evitar rebotes
; y reactivaciones de tecla
Espera1
btfss PORTB,4 ; Si no se suelta la tecla FILA 1
goto Espera1 ; vuelve a esperar.
Espera2
btfss PORTB,5 ; Si no se suelta la tecla FILA 2
goto Espera2 ; vuelve a esperar.
Espera3
btfss PORTB,6 ; Si no se suelta la tecla FILA 3
goto Espera3 ; vuelve a esperar.
Espera4
btfss PORTB,7 ; Si no se suelta la tecla FILA 4
goto Espera4 ; vuelve a esperar.
bcf INTCON,RBIF ; Borramos bandera de Interrupcion.-
clrf PORTB ; Dejamos Puerto para recibir otra tecla.-
return ; vuelve al programa principal que hizo la llamada.
;..........................................
end
También con la variable NTecla (Numero de Tecla presionada) se puede utilizar como entrada a una tabla para codificar en ASCKII la tecla presionada:
movfw NTecla
call Tabla_TMatricial
;Codificacion de Tecla presionada:
Tabla_TMatricial
addwf PCL,1
DT "1","2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"
-
Control del LCD
Descripción: La pantalla de cristal liquido o LCD (Liquid Crystal Display) es un dispositivo µControlado de visualización grafico para la presentación de caracteres, símbolos o incluso dibujos (en algunos modelos). En este caso dispone de 2 filas de 16 caracteres cada una y cada carácter dispone de una matriz de 5x7 puntos (pixels), aunque los hay de otro número de filas y caracteres. Este dispositivo esta gobernado internamente por un microcontrolador Hitachi 44780 y regula todos los parámetros de presentación, este modelo es el mas comúnmente usado y la información que se adjunta se basará en el manejo de este u otro LCD compatible.
Conexión del modulo LCD al PIC16F84A mediante bus de 4 bits.
(http://img90.imageshack.us/img90/8066/hardwarelcdal7.bmp)
En este ejemplo haremos uso de dos directivas más de ensamblador. Estas son #DEFINE y macro.
#DEFINE es empleado para crear sustituciones dentro del texto del programa que lo simplifiquen. La forma correcta es #DEFINE NOMBRE TEXTO, con lo que, cada vez que el compilador encuentre la orden NOMBRE, la sustituirá por el texto. El problema que se nos plantea es que, si bien es más flexible que la directiva EQU, puesto que esta sólo nos permitía asignar un valor, sólo se nos permite con #DEFINE una línea de texto, y esta debe ser fija.
#DEFINE LCD_E LCD_PORT_Control,E
Este problema se soluciona mediante macro. Esta directiva tiene la siguiente forma:
NOMBRE macro ARGUMENTO1, ARGUMENTO2, ETC
TEXTO
TEXTO...
endm
De este modo NOMBRE será sustituido como comando por la secuencia completa definida tras macro hasta endm, y los sucesivos argumentos serán, a su vez, sustituidos dentro del texto.
En nuestro ejemplo lo utilizaremos para enviar un carácter o un comando al LCD, de la siguiente manera:
LCD_Putc macro Carac
movlw Carac
call LCD_Caracter
endm
LCD_Putd macro Coman
movlw Coman
call LCD_Comando
endm
Rutinas de Control:
LCD_Config_puertos: Configura los puertos del PIC para el uso del modulo LCD, solo afecta a los pines utilizados.-
LCD_Init: Inicializa el módulo LCD para su correcto funcionamiento. Es necesario ejecutar esta subrutina al principio de los programas que vayan a utilizar la visualización mediante LCD.
LCD_Bandera: Explora el estado de la bandera Busy (ocupado) del módulo LCD y espera que termine cualquier comando previo antes de volver a la rutina que le llamo.-
LCD_Enable: Habilita el módulo LCD durante 2us para recepción de datos o envío.-
LCD_Comando: Configura módulo LCD para recibir un comando mediante rutina LCD_Envio_Data.-
LCD_Caracter: Configura módulo LCD para recibir un carácter mediante rutina LCD_Envio_Data.-
LCD_Envio_Data: Envía dato al LCD, Cargando el nible alto y luego el nible bajo.-
Nota: Observar que las líneas de control y bus de datos es fácilmente modificable en Declaración de bits para control LCD y Declaración de Bytes del LCD.
-
Como ejemplo de aplicación se muestra un ejemplo donde se visualiza un mensaje (“Todo Pic”):
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;///////////////////////////////////////////////////////////////////
;**** Declaración de Registros ****
LCD_Dato equ 0x0C ;registro para guardar dato a enviar al LCD
Loop equ 0x0D ;registro para inicializacion del LCD
Contador1 equ 0x0E ;registro para demoras
Contador2 equ 0x0F ;registro para demoras
;**** Declaracion de bits para control LCD ****
RS equ 0
RW equ 1
E equ 2
BACK equ 3
D4 equ 4
D5 equ 5
D6 equ 6
D7_BF equ 7
;**** Declaracion de Bytes del LCD ****
LCD_PORT_Control equ 0x05 ; PORTA para control del LCD
LCD_PORT_Data equ 0x06 ; PORTB para envio de Datos al LCD
LCD_TRIS_Control equ 0x85 ; TRISA
LCD_TRIS_Data equ 0x86 ; TRISB
; **** Comandos de Software para la LCD ****
LCDLinea1 equ 0x80 ; Dirección comienzo línea1
LCDLinea2 equ 0xC0 ; Dirección comienzo línea2
LCDClr equ 0x01 ; Borra pantalla, cursor a Inicio
LCDInicio equ 0x02 ; Cursor a Inicio, DDRAM sin cambios
LCDInc equ 0x06 ; Modo incrementa cursor
LCDDec equ 0x04 ; Modo decrementa cursor
LCDOn equ 0x0C ; Pantalla On
LCDOff equ 0x08 ; Pantalla Off
CursOn equ 0x0E ; Pantalla On, cursor On
CursOff equ 0x0C ; Pantalla On, cursor Off
CursBlink equ 0x0F ; Pantalla On, Cursor parpadeante
CurIzda equ 0x10 ; Mueve cursor a la izquierda
CurDecha equ 0x14 ; Mueve cursor a la derecha
DisIzda equ 0x18 ; Mueve Display a la izquierda
DisDecha equ 0x1C ; Mueve Display a la Derecha
LCDBus_4_2 equ 0x28 ; Bus 4 bits, 2 líneas, 5x7
;**** Definiciones para el ensamblador ****
#DEFINE LCD_E LCD_PORT_Control,E
#DEFINE LCD_RS LCD_PORT_Control,RS
#DEFINE LCD_RW LCD_PORT_Control,RW
#DEFINE LCD_D4 LCD_PORT_Data,D4
#DEFINE LCD_D5 LCD_PORT_Data,D5
#DEFINE LCD_D6 LCD_PORT_Data,D6
#DEFINE LCD_D7_BF LCD_PORT_Data,D7_BF
#DEFINE CD_backlight LCD_PORT_Control,BACK ; Control Backligth.-
;**** Definición de macros ****
LCD_Putc macro Carac
movlw Carac
call LCD_Caracter
endm
LCD_Putd macro Coman
movlw Coman
call LCD_Comando
endm
;//////////////////////////////////////////////////////////
;**** Inicio del Micro ****
org 0x00
goto Inicio
;**** Programa principal ****
org 0x05
Inicio
call LCD_Config_puertos ; Configuramos Puertos a utilizar por LCD.-
call LCD_Init ; Inicializamos LCD.-
bsf LCD_backlight ; Prendemos Backlight.-
LCD_Putd CursBlink ; Cursor Parpadeante.-
LCD_Putc 'T' ; Escribimos en LCD.-
LCD_Putc 'o'
LCD_Putc 'd'
LCD_Putc 'o'
LCD_Putc ' '
LCD_Putc 'P'
LCD_Putc 'I'
LCD_Putc 'C'
Bucle
nop
goto Bucle ; Bucle Infinito.-
;**** Subrutinas de Control ****
;**** Configuracion de puertos ****
LCD_Config_puertos
bsf STATUS,RP0 ; Seleccionamos Banco 1.-
bcf LCD_RS ; Colocamos todas las lineas de control y bus como Salidas.-
bcf LCD_RW
bcf LCD_E
bcf LCD_D4
bcf LCD_D5
bcf LCD_D6
bcf LCD_D7_BF
bcf LCD_backlight
bcf STATUS,RP0 ; Volvemos an Banco 0.-
bcf LCD_RS
bcf LCD_RW
bcf LCD_E
bcf LCD_D4
bcf LCD_D5
bcf LCD_D6
bcf LCD_D7_BF
bcf LCD_backlight
return
;...................................
;**** Inicializacion de LCD ****
LCD_Init
bcf STATUS,RP0 ; Aseguramos Banco 0.-
movlw 0x03
movwf Loop
bsf LCD_D4 ;<D7 D6 D5 D4> = 0011.-
bsf LCD_D5
;.... se ejecuta 3 veces el siguiente bloque ....
bsf LCD_E
call Demora_5ms
bcf LCD_E
call Demora_5ms
decfsz Loop
goto $-5
;.... Interfase de 4 bits ....
bcf LCD_D4 ;<D7 D6 D5 D4> = 0010.-
bsf LCD_E
call Demora_5ms
bcf LCD_E
call Demora_5ms
;.... Sistema -> << Bus de 4 bits, 2 lineas, 5x7>>.-
movlw LCDBus_4_2
call LCD_Comando
;....Limpia display y retorna al origen ....
movlw LCDClr
call LCD_Comando
return
;.........................................
;**** Lee Estado del LCD ****
LCD_Bandera
bcf LCD_RW
bcf LCD_RS
bcf LCD_E
bcf LCD_D4
bcf LCD_D5
bcf LCD_D6
bcf LCD_D7_BF
nop
bsf LCD_RW ; Modo Lectura.-
bsf STATUS,RP0 ; Banco 1.-
bsf LCD_D7_BF ; Configura TRIS para recibir estado del LCD.-
bcf STATUS,RP0 ; Banco 1.-
bsf LCD_E
nop
btfsc LCD_D7_BF ; Lee estado del LCD, 1-> Ocupado.-
goto $-1 ; Esperamos a que se desocupe.-
bcf LCD_E ; LCD_D7/BF->0, seguimos adelante.-
bsf STATUS,RP0 ; Banco 1.-
bcf LCD_D7_BF ; Reconfigura TRIS para envio de Data.-
bcf STATUS,RP0 ; Banco 1.-
return
;.............................
;**** Envia pulso Enable ****
LCD_Enable
bsf LCD_E
nop
nop
bcf LCD_E
return
;.............................
;**** Envia Dato al LCD ****
;*** Previamente configurado como Comando o como Caracter.-
LCD_Envio_Data
movwf LCD_Dato ; Guardamos Dato a enviar.-
; CARGAMOS NIBLE ALTO EN PUERTO.-
bcf LCD_D4 ; Cargamos un cero.-
btfsc LCD_Dato,4 ; Si es 1, modificamos a uno, sino seguimos.-
bsf LCD_D4
bcf LCD_D5 ;
btfsc LCD_Dato,5
bsf LCD_D5
bcf LCD_D6 ;
btfsc LCD_Dato,6
bsf LCD_D6
bcf LCD_D7_BF ;
btfsc LCD_Dato,7
bsf LCD_D7_BF
call LCD_Enable ; Habilitamos LCD para recepcion de Data.-
; CARGAMOS NIBLE BAJO EN PUERTO.-
bcf LCD_D4 ; Cargamos un cero.-
btfsc LCD_Dato,0 ; Si es 1, modificamos a uno, sino seguimos.-
bsf LCD_D4
bcf LCD_D5 ;
btfsc LCD_Dato,1
bsf LCD_D5
bcf LCD_D6 ;
btfsc LCD_Dato,2
bsf LCD_D6
bcf LCD_D7_BF ;
btfsc LCD_Dato,3
bsf LCD_D7_BF
call LCD_Enable ; Habilitamos LCD para recepcion de Data.-
return
;.............................
;**** Envia Comando al LCD ****
LCD_Comando
call LCD_Bandera ;Controla si el LCD esta en condiciones de recibir un nuevo dato.-
bcf LCD_RW ; Modo escritura.-
bcf LCD_RS ; Se enviara Comando.-
call LCD_Envio_Data ; Envio Comando.-
return
;.............................
;**** Envia Caracter al LCD ****
LCD_Caracter
call LCD_Bandera ;Controla si el LCD esta en condiciones de recibir un nuevo dato.-
bcf LCD_RW ; Modo escritura.-
bsf LCD_RS ; Se enviara Caracter.-
call LCD_Envio_Data ; Envio Caracter.-
return
;..............................
;**** Demora ****
Demora_5ms
movlw 0xC8 ; 200
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0x07 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;...............................
end
Tengo que ser sincero, no logre simularlo con Proteus. Pero con elementos reales, lo probé en varias configuraciones de líneas de control y bus de datos, por lo que debería funcionar sin problemas.-
-
Comunicación RS232
El RS232 es un estándar de comunicaciones propuesto por la Asociación de Industrias Electrónicas (EIA) la cual define la interfase mecánica, los pines, las señales y los protocolos que debe cumplir la comunicación serial. La velocidad se mide en baudios (bits/segundo) y esta normalizada a 2400, 4800, 9600, 19200, 38400, etc. Y sólo son necesarios dos cables, uno de transmisión y otro de recepción.
Todas las normas RS-232 cumplen con los siguientes niveles de voltaje:
- Un “1” lógico es un voltaje comprendido entre –5v y –15v
- Un “0” lógico es un voltaje comprendido entre +5v y +15 v
(http://img26.imageshack.us/img26/7751/rs1ha7.jpg)
Los puertos series son accesibles mediante conectores. La norma RS232 establece dos tipos de conectores llamados DB-25 y DB-9, machos y hembras. La norma RS232 se estableció para conectar un ordenador con un modem, por lo que aparecen muchas patillas en los conectores DB-25 que en otro tipo de aplicaciones no se utilizan y en las que es mas común utilizar el conector DB-9.
Cada una de las patillas del conector RS232 tiene una función específica. Patillas del DB-9:
(http://img10.imageshack.us/img10/5564/db9ld3.jpg)
Los pines que portan los datos son RxD y TxD los demás se encargan de otros trabajos, el DTR indica que el ordenador esta encendido, DSR que el dispositivo conectado al puerto esta encendido, RTS que el ordenador al no estar ocupado puede recibir datos, al revés de CTS que lo que informa es que es el dispositivo el que puede recibir datos, DCD detecta que existen presencia de datos, etc.
Formato de un byte:
El protocolo establecido por la norma RS232 envia la información estructurada en 4 partes:
- Bit de inicio o arranque (START). Es un paso de -12V a +12V, es decir de un “1” a un “0” lógico en la lógica negativa de la norma RS232.
- Bits de datos (Datas) Los bits de datos son enviados al receptor después del bit Start. El bit de menos peso LSB es trasmitido primero. Un carácter de datos suele consistir en 7 u 8 bits.
- Bit de Paridad (Parity) Dependiendo de la configuración de la transmisión un bit de paridad puede ser enviado después de los bits de datos. Con este bit se suele descubrir errores en la transmisión, puede dar paridad par o impar.
- Bit de Parada (STOP) la línea que a -12V después del ultimo bit enviado, es decir queda a “1” en lógica negativa de la norma. El protocolo permite 1, 1.5 o 2 bits de parada.
MAX 232.
En el mercado hay muchos circuitos integrados que permiten la conversión entre niveles TTL y niveles RS232. El más destacado es el transceptor MAX232:
(http://img25.imageshack.us/img25/5108/rs232sx1.bmp)
Este convierte los niveles RS232 <+12 y -12> a voltajes TTL <0 y +5> y viceversa sin requerir mas que una fuente de +5V y un par de capacitores.
-
Para ejemplificar el uso de este protocolo para establecer comunicación con la PC, haremos un programita que reciba la data de la PC y se la reenviaremos inmediatamente.
(http://img8.imageshack.us/img8/3884/hardwarers232td3.bmp)
Para la recepción de datos aprovecharemos la interrupción externa por RB0, configurada en flanco descendente (Detectara cuando la PC envié un bit de Start). Deja pasar un tiempo una y media veces mayor que el periodo de transmisión para saltarse el bit de Start y lee el primer bit en su mitad. Lee el resto de los bits de datos, esperando un tiempo igual a la duración del periodo entre lectura y lectura para testearlos en mitad del bit. Kbhit indica si ha llegado o no un dato desde PC. <<RS232_LeerDato>>
Para el envío de datos se envía un "0" durante un tiempo igual al periodo de la velocidad de transmisión. Este es el bit de "Start". Luego se envía el bit correspondiente al dato a enviar: Si va a enviar un "0" permanece en bajo durante el periodo correspondiente y si se va a escribir un "1" permanece en alto durante el periodo correspondiente. Al enviar los 8 bits de datos se envía un bit de Stop, nivel alto durante un periodo. <<RS232_EnviaDato>>
Los parámetros adoptados para la comunicación son los siguientes:
- Velocidad 9600 baudios
- Dato de 8 bits
- Sin Paridad
- 1 bit de Stop
Para establecer comunicación con el microcontrolador utilizaremos el software Siow (http://www.mediafire.com/file/jhrzmdnmozz/Siow.rar), es un monitor del puerto serie muy sencillo de usar, solo hay que configurar los parámetros de comunicación. (También se puede usar el Hyperterminal de Windows)
(http://img23.imageshack.us/img23/7941/siowvj1.jpg)
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Declaración de Registros ****
RS232_ContBits equ 0x0C
RS232_Dato equ 0x0D
Flags equ 0x0E
Contador equ 0x0F
;**** Definiciones para el ensamblador ****
#DEFINE RS232_RX PORTB,0 ; Línea por la que se reciben los datos.
#DEFINE RS232_TX PORTB,1 ; Línea por la que se envían los datos.
#DEFINE Kbhit Flags,0 ; Indica si se ha recibido algun dato.-
;**** Definición de macros ****
; Se envia la data de un registro a PC.-
Putreg macro Registro
movfw Registro
call RS232_EnviaDato
endm
; Se envia un literal a PC.-
Putc macro ACKII
movlw ACKII
call RS232_EnviaDato
endm
;//////////////////////////////////////////
;**** Inicio del Micro ****
Reset
org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
org 0x04 ; Atiendo Interrupcion.-
goto ISR
; **** Programa Principal ****
;**** Configuracion de puertos ***
org 0x05 ; Origen del codigo de programa.-
Inicio
call RS232_Puerto ; Se inicializa el puerto e interrupcion para enviar y recibir datos RS232.-
;**** Espera a recibir Dato ****
Bucle
btfss Kbhit ; ¿Se recibio Dato?
goto $-1 ; No, seguimos esperando.-
bcf Kbhit ; Si, borramos bandera.-
Putreg RS232_Dato ; Enviamos lo guardado en RS232_Dato.-
goto Bucle ;
;.............................................
;**** Rutina de servicio de Interrupcion ****
;**** Interrupcion por RB0 ****
; Se lee dato enviado por PC.-
; En este caso no es necesario hacer copias de respaldo de W y STATUS.-
;----------------------------------------------------------------------------------------------
; El 1º bit recibido se guarda en RS232_Dato,7; al rotarse 7 veces (Se recibe el byte completo)
; este queda en RS232_Dato,0.-
;----------------------------------------------------------------------------------------------
ISR
btfss INTCON,INTF ; Consultamos si es por RB0.-
retfie ; No, Salimos de interrupción.-
RS232_LeerDato
movlw d'7' ; Número de rotaciones.
movwf RS232_ContBits
call Demora_150us ; El primer bit debe leerlo un tiempo igual a una
; vez y media el periodo de transmisión.
LeeBit
bcf RS232_Dato,7 ; Ahora lee el pin. En principio supone que es 0.
btfsc RS232_RX ; ¿Realmente es cero?
bsf RS232_Dato,7 ; No, pues cambia a "1".
rrf RS232_Dato,1 ; Rotamos para recibir el siguiente bit.-
call Demora_100us ; Los siguientes bits los lee un periodo más tarde.
decfsz RS232_ContBits,1 ; Comprueba que es el último bit.
goto LeeBit ; No es el último, pasa a leer el siguiente.
bcf RS232_Dato,7 ; Ahora lee ultimo bit enviado.Supone que es 0.
btfsc RS232_RX ; ¿Realmente es cero?
bsf RS232_Dato,7 ; No, pues cambia a "1".
call Demora_100us ; Espera un tiempo igual al bit de Stop.
bsf Kbhit ; Se indica que ha llegado dato.-
Fin_ISR ; El dato recibido se guarda en <<RS232_Dato>>
bcf INTCON,INTF ; Limpiamos bandera.-
retfie ; Salimos de interrupción.-
;.................................................
;**** Rutinas ****
;*** Configura las líneas de salida y entrada ****
RS232_Puerto
bsf STATUS,RP0
bsf RS232_RX ; Esta línea se configura como entrada.
bcf RS232_TX ; Esta línea se configura como salida.
clrf OPTION_REG ; Config. Por flanco Descendente Interrupcion RB0.-
bcf STATUS,RP0
bsf RS232_TX ; Condicion de no transmision de datos.-
movlw b'10010000' ; Habilitamos GIE y INTE (interrupción por RB0)
movwf INTCON
bcf Kbhit ; Borramos bandera.-
return
;**** Se envia Dato ****+
;-----------------------------------------------------------------------------------------
; 1º se envia el LSB, luego se va rotando a la derecha y se envian los bits de mayor peso.-
;-----------------------------------------------------------------------------------------
RS232_EnviaDato
movwf RS232_Dato ; Guarda el contenido del byte a transmitir.
movlw d'8' ; Número de bits a transmitir.
movwf RS232_ContBits
bcf RS232_TX ; Se genera bit de Start.
call Demora_100us
EnviaBit ; Comienza a enviar datos.
btfss RS232_Dato,0 ; ¿Es un "1" el bit a transmitir?
bcf RS232_TX ; No, pues envía un "0".
btfsc RS232_Dato,0 ; ¿Es un "1" el bit a transmitir?
bsf RS232_TX ; Si, Transmite un "1".
rrf RS232_Dato,1 ; Rota para envia siguiente bit.-
call Demora_100us ; Este es el tiempo que estará en alto o bajo.
decfsz RS232_ContBits,1 ; Comprueba si es el último bit.
goto EnviaBit ; No es el último bit repite la operación.
bsf RS232_TX ; Envía bit de Stop.
call Demora_100us
return
;**** Demoras ****
Demora_100us
movlw d'31'
movwf Contador
decfsz Contador
goto $-1
return
Demora_150us
movlw d'48'
movwf Contador
decfsz Contador
goto $-1
return
;.....................................
end
-
Felicidades Suky!
Seguro que los compañeros que empiezan agradecen mucho tu trabajo :mrgreen:
Un saludo desde Alicante.
-
Gracias!!! La idea fue exponer lo que necesitaba cuando yo comence con los micros. Teoria y un ejemplo de aplicación. Cuando tenga un poco de tiempo voy agregar alguna que otra cosita.
Saludos desde Bariloche!
-
Coincido con Azicuetano, muy completo el aporte.
Le he colocado una chincheta y espera que sigas agregando mas.
Saludos
Hugo
-
Wow :shock: excelente...
Felicitaciones por aportar tanto esfuerzo a la comunidad
-
gracias por este excelente tutorial , sigue adelante
-
PIC16F628A/648A
Haré una introducción a los micros y realizare ejemplos para los módulos que no trae el PIC16F84A.
Características principales
- Conjunto reducido de instrucciones (RISC). Solamente 35 instrucciones que aprender a utilizar
- Oscilador interno de 4MHz
- Opera con una frecuencia de reloj externa de hasta 20 MHz (ciclo de máquina de 200 ns)
- Memoria de programa: 2048 locaciones de 14 bits
- Memoria de datos: Memoria RAM de 224 bytes (8 bits por registro)
- Memoria EEPROM: 128 bytes (8 bits por registro)
- Stack de 8 niveles
- 16 Terminales de I/O que soportan corrientes de hasta 25 mA
- 3 Temporizadores
- Módulo de comunicación serie (Usart
- Módulo CCP (captura/comparación/PWM)
- 2 Comparadores analógicos, una referencia de voltaje programable
Nota: Los módulos descriptos para el PIC16F628A son idénticos a los del PIC16F648A, lo único que varía entre ellos son las siguientes características:
- Memoria de programa: PIC16F648A-4096 locaciones de 14 bits
- Memoria de datos: PIC16F648A-Memoria RAM de 256 bytes (8 bits por registro)
- Memoria EEPROM: PIC16F648A-256 bytes (8 bits por registro)
De aquí en adelante me refiero al PIC16F628A pero los ejemplos son aplicables al PIC16F648A haciendo el cambio de encabezado:
; **** Encabezado ****
list p=16f648A ; list directive to define processor
#include <p16f648A.inc> ; processor specific variable definitions
(http://img7.imageshack.us/img7/6121/pindiagram.png)
Puertos
Los PIC16F628/648A cuentan con dos puertos PORTA y PORTB, algunos pines de estos puertos de entrada/salida son multiplexados con una función alternativa de los periféricos del dispositivo. Cuando un periférico es activado el pin no puede ser usado para propósitos generales de e/s.
El PUERTO A es un puerto de entrada de 8 bits. Todos los pines, excepto RA5, pueden ser configurados como entrada o salida con la respectiva configuración del registro TRISA. El pin RA4 esta multiplexado con la entrada de reloj T0CKI y como salida se comporta como colecto abierto, por lo tanto debemos poner una resistencia Pull-up a Vdd. El pin RA5 es un disparador Schmitt solo de entrada y no cuenta con controladores de salida, según la configuración puede ser usado como Mclr (Reset externo), y además sirve también para entrar en el modo de programación cuando se aplica una tensión igual a Vpp (13,4V mínimo). Los demás pines del puerto trabajan de entrada como disparador de Schmitt Trigger y como salida lógica CMOS. Los pines RA0-RA3 sirven de entrada para el comparador analógico.
Importante: Si se utiliza en puerto A como I/O Digital, se debe deshabilitar los Comparadores Analógicos, cargando un 0x07 en CMCON.
El PORTB es un puerto bidireccional de 8 bits, del cual por software se pueden habilitar resistencias de pull-up internas. El PORTB es multiplexado con interrupciones externas, tales como detección de flanco por RB0, cambio de nivel por RB4 a RB7, USART, el módulo CCP y el reloj de entrada/salida TMR1.
Otros pines
- VDD: Pin de alimentación positiva. De 2 a 5,5 Vcc
- VSS: Pin de alimentación negativa. Se conecta a tierra o a 0 Vcc
- MCLR: Master Clear (Reset). Si el nivel lógico de este terminal es bajo (0 Vcc), el microcontrolador permanece inactivo. Este Reset se controla mediante la palabra de configuración del PIC
- OSC1/CLKIN: Entrada de oscilador externo
- OSC2/CLKOUT: Salida del oscilador. Dependiendo de cómo se configure puede proporcionar una salida de reloj por medio de este pin
Organización de la memoria.
El PIC16F628 posee un contador de programa de 13 bits, capaz de direccionar un espacio de memoria de 8Kx14. Sin embargo, únicamente los primeros 2Kx14, desde 0000h hasta 07FFh, están implementados. Los vectores de reset e interrupción están en las direcciones 0000h y 0004h, respectivamente. La pila (stack) es de 8 niveles, lo cual significa que puede soportar hasta 8 direcciones de retorno de subrutina.
(http://img10.imageshack.us/img10/7742/memorg.jpg)
El PIC16F628 posee un espacio de memoria RAM de datos de 512x8, dividido en 4 bancos de 128 bytes cada uno. Sin embargo, sólo están implementados 330 bytes, correspondiendo 224 al área de los registros de propósito general (GPR) y 36 al área de los registros de función especial (SFR). Los restantes 70 bytes implementados son espejos de algunos SFR de uso frecuente, así como de los últimos 16 GPR del banco 0. Por ejemplo, las posiciones 0Bh, 8Bh, 10Bh y 18Bh corresponden al registro INTCON, de modo que una operación hecha en cualquiera de ellos, se refleja automáticamente en los otros. Se dice, entonces, que las posiciones 8Bh, 10Bh y 18Bh están mapeadas en la posición 0Bh. Esta característica agiliza el acceso a estos registros, puesto que no siempre es necesario especificar el banco donde se encuentran. La selección del banco de ubicación de un SFR o un GPR particular se hace mediante los bits 6 (RP1) y 5 (RP0) del registro STATUS.
(http://img14.imageshack.us/img14/8660/memprog.jpg)
Interrupciones:
Registros utilizados:
INTCON: Registro de lectura y escritura que contiene varios bits de señalización y habilitación para el desbordamiento del TMR0, cambio sobre el puerto RB e interrupción externa en la patilla RB0/INT.
0. RBIF: Indicador de interrupción por cambio de estado RB4-RB7
1. INTF: Indicador de interrupción externa
2. T0IF: Indicador de interrupción por desbordamiento de Timer 0
3. RBIE: Habilitación de interrupción por cambio de estado RB4-RB7
4. INTE: Habilitación de interrupción externa
5. T0IE: Habilitación de interrupción por desbordamiento de Timer 0
6. PEIE: Habilitación de interrupción de periféricos
7. GIE: Habilitación general de interrupciones
PIR1: El registro PIR1 contiene los bits de señalización individual de las interrupciones de periféricos
0. TMR1IF: Indicador de interrupción por desbordamiento de Timer 1
1. TMR2IF: Indicador de interrupción por desbordamiento de Timer 2
2. CCP1IF: Indicador de interrupción del módulo de Captura/Comparación.
a) Modo Comparador: Coincidencia entre TMR1 y CCP1
b) Modo Captura: Ha ocurrido una captura de TMR1
3. No Implementado.
4. TXIF: Indicador de interrupción de fin de transmisión USART
5. RCIF: Indicador de interrupción de llegada de datos USART
6. CMIF: Indicador de interrupción por cambio de estado de alguna de las salidas de los comparadores.
7. EEIF: Indicador de interrupción de fin de escritura eeprom interna.
PIE1: Registro que posee los bits de habilitación individual para las interrupciones de periféricos. El bit PEIE del registro INTCON debe ser 1 para permitir la habilitación de cualquier interrupción de periférico.
0. TMR1IE: Habilitación de interrupción por desbordamiento de Timer 1
1. TMR2IE: Habilitación de interrupción por desbordamiento de Timer 2
2. CCP1IE: Habilitación de interrupción del módulo de Captura/Comparación/PWM.
3. No Implementado.
4. TXIE: Habilitación de interrupción de fin de transmisión USART
5. RCIE: Habilitación de interrupción de llegada de datos USART
6. CMIE: Habilitación de interrupción por cambio de estado de alguna de las salidas de los comparadores.
7. EEIE: Habilitación de interrupción de fin de escritura eeprom interna.
Lógica de Interrupciones:
(http://img3.imageshack.us/img3/4549/logicadeinterrupciones6.jpg)
-
Palabra de Configuración
Los PIC16F628A/648A han sido construidos con características tales que se pueden configurar para funcionar en modos de operación que no necesitan componentes externos tales como el circuito de reloj o de reset. Esto implica que es necesario configurar su modo de operación a través de una palabra de configuración.
La palabra de configuración se encuentra mapeada en la dirección 2007h de la memoria de programa y solo puede ser accesada durante la programación de dispositivo.
(http://img7.imageshack.us/img7/5917/configz.jpg)
CP1:CP0:Bits de protección de código
Los bits 13-10 encargados de proteger la memoria de programa.
CPD: Bit de protección para código de datos
1 = Protección deshabilitada de la memoria de datos.
0 = Protección habilitada en la memoria de datos.
LVP: Habilitación de la programación por voltaje bajo
1 = LVP habilitado, la terminal RB4/PGM tiene tal función.
0 = LCP: deshabilitado, RB4/PGM es una terminal I/O.
BODEN: Bit de reset por voltaje de alimentación bajo
1 = Reset por BOD habilitado
0 = Reset por BOD deshabilitado
MCLRE: Habilitacion del terminal de reset
1 = Terminal de reset en RA5.
0 = MCLR conectado internamente a Vdd, RA5 es un pin I/O.
PWRTEN : Bit de habilitación de temporizador al energizar
1 = PWRT habilitado.
0 = PWRT deshabilitado.
WDTEN: Bits de habilitación de Watch-Dog
1 = WDT habilitado
0 = WDT deshabilitado.
FOSC2:FOSC1:FOSC0: Bits de selección del tipo de oscilador
(http://img189.imageshack.us/img189/7517/configosciladores.jpg)
-
El Módulo del Timer 0.
Idéntico al del PIC16F84.
El Módulo del Timer 1.
El Timer 1 a diferencia del Timer 0 es un contador / temporizador de 16 bits. El conteo es realizado por dos registros de 8 bits: (TMR1H (0Fh) y TMR1L (0Eh) ), estos dos registros son tanto leíbles como escribibles.
Así, el registro TMR1 se incrementa de 0000h a FFFFh y en la siguiente cuenta se reinicia en 0000h y así sucesivamente, al reciclarse se activa (en alto) la bandera TMR1IF (PIR1<0>), la cual puede ser utilizada para generar una interrupción, o bien, para ser consultada por poleo, teniendo las mismas precauciones que ya se explicaron antes para la bandera T0IF.
En la siguiente figura se muestra un diagrama de bloques de este módulo, en donde se indican los bits que afectan su operación y la manera en que lo hacen.
(http://img8.imageshack.us/img8/9830/timer10.jpg)
Modo temporizador
En este modo el Timer se incrementa (si no se considera preescalador) en cada ciclo de instrucción (a la frecuencia Fosc/4). Este modo se selecciona limpiando el bit TMR1CS (T1CON<1>).
El preescalador que se puede intercalar entre el reloj Fosc/4 y el registro TMR1 puede tener sólo uno de 4 valores: 1/1, 1/2, 1/4 y 1/8.
En este caso la temporización de calcula:
Temporización = Ciclo de instrucción. (65536-TMR1) .Divisor de Frecuencia
Vemos que la máxima temporización posible es con TMR1 = 0, y Divisor de Frecuencia en 8, lográndose unos 524.3 ms aprox.
Modo contador
El Timer 1 también puede operar como contador, en este último caso, la entrada a contar se toma de la patita externa RB6/T1OSO/T1CKI.
Configuraciones:
El Timer 1 posee un bit para habilitación / deshabilitación, este es el bit TMR1ON (T1CON<0>) y habilita en alto.
Además, el Timer 1 posee una entrada interna de RESET, el cual puede ser activado por uno cualquiera de los módulos CCP que.
A continuación se describe el principal registro relacionado con el Timer 1 y todos sus bits, excepto los que tienen que ver con el modo contador:
Registro T1CON (10h)
(http://img9.imageshack.us/img9/1343/timer11.jpg)
bits 5:4
T1CKPS1:T1CKPS0.- Bits de selección del valor del divisor de frecuencia del preescalador:
1 1 = divisor 1/8
1 0 = divisor 1/4
0 1 = divisor 1/2
0 0 = divisor 1/1
bit 1
TMR1CS.- Bit de selección de la fuente de reloj
1 = Modo contador (fuente de reloj: patita RC0/T1OSO/T1CKI)
0 = Modo Temporizador (fuente de reloj Fosc/4)
bit 0
TMR1ON.- Bit de habilitación / deshabilitación del Timer 1:
1 = habilita Timer 1
0 = Deshabilita Timer 1
ConfigPIC traé una herramienta adicional que nos ayuda a seleccionar el preescaler y valor inicial del Timer para obtener una temporización deseada:
(http://img139.imageshack.us/img139/8141/21115051.th.jpg) (http://img139.imageshack.us/my.php?image=21115051.jpg)
-
Para ejemplificar haremos un simple ejemplo donde lo utilizamos como temporizador. Se hará titilar un led conectado al PIN RB0 cada 300 ms. Como se puede ver es idéntico al ejemplo realizado para Timer 0 del PIC16F84A, solo que en este caso no necesitaremos un registro adicional para lograr la demora deseada.
Hardware:
(http://img17.imageshack.us/img17/5300/tmr1.bmp)
; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definiciones para el ensamblador ****
#DEFINE Led PORTB,0 ; Led ubicado en Puerto B, bit 0.-
;//////////////////////////////////////////
;**** Inicio del Micro ****
Reset
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
org 0x04 ; Atiendo Interrupcion.-
goto ISR
; **** Programa Principal ****
;**** Configuracion de puertos ***
org 0x05 ; Origen del código de programa.-
Inicio
bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111110' ; RB0 como salida.-
movwf TRISB
bcf STATUS,RP0 ; Banco 0.-
movlw b'00110001' ; Se selecciona TMR1, preescaler de 1/8, modo temporizador.-
movwf T1CON
bcf Led ; El Led comienza apagado.-
movlw 0x6D ; Cargamos 28036 en TMR1 para lograr 300ms.-
movwf TMR1H ; Byte alto de TMR1.-
movlw 0x84
movwf TMR1L ; Byte bajo de TMR1.-
bsf STATUS,RP0 ; Banco 1.-
bsf PIE1,TMR1IE ; Activar interrupción por TMR1.
bsf INTCON,GIE ; Habilitacion general de interrupciones.-
bsf INTCON,PEIE ; Habilitacion de Interrupcion por perifericos.-
bcf STATUS,RP0 ; Banco 0.-
;**** Control de Led ****
Bucle
nop ; Aqui el micro puede ejecutar cualquier otra tarea
goto Bucle ; sin necesidad de utilizar tiempo en un bucle de demora.-
;**** Rutina de servicio de Interrupcion ****
;**** Interrupcion por TMR1 ****
ISR
btfss PIR1,TMR1IF ; Consultamos si es por TMR1.-
retfie ; No, salimos de interrupcion.-
btfss Led ; Si, Controlamos Led. Si esta apagado, prendo y viseversa.-
goto Prendo_led
bcf Led ; Apago Led.-
Actualizo_TMR1 ; Actualizo TMR1 para obtener una temporizacion de 300 ms.-
movlw 0x6D ; Cargamos 28036 en TMR1.-
movwf TMR1H ; Byte alto de TMR1.-
movlw 0x84
movwf TMR1L ; Byte bajo de TMR1.-
goto Fin_ISR ; Restauro valores.-
Prendo_led
bsf Led ; Prendo Led.-
goto Actualizo_TMR1
Fin_ISR
bcf PIR1,TMR1IF ; Borro bandera de control de Interrupcion.-
retfie ; Salimos de interrupción.-
;..........................................
end
-
El Módulo del Timer 2.
El Timer es un temporizador (sin opción de trabajar como contador) de 8 bits. Su registro principal denominado TMR2 (11h) es un registro de 8 bits que se incrementa continuamente a la frecuencia seleccionada de Fosc/4 dividida por un preescalador. En la siguiente figura se muestra un diagrama de bloques del módulo del Timer2.
(http://img10.imageshack.us/img10/1640/timer20.jpg)
El preescalador
La frecuencia que incrementa al registro TMR2 puede ser dividida por un preescalador por un factor de 1/1, 1/4 o 1/16, seleccionable por los bits T2CKPS1:T2CKPS0 (T2CON<1:0>)
El Registro de comparación o de Periodo
En operación, el contenido del registro TMR2 se compara continuamente con un registro de periodo denominado PR2 (92h) cuyo valor podemos establecer por software.
Cada vez que la cuenta de TMR2 es igual a PR2, se reinicia el conteo en TMR2 desde cero, y además se genera una señal de salida, la cual es tratada por un postescalador, para poder generar una señal TMR2IF (PIR1<1>) que puede ser usada para solicitar una interrupción, o para ser leída por poleo.
El Postescalador
El postescalador divide la frecuencia con que ocurre una activación de la bandera TMR2IF, es decir, si el valor del postescalador es 1/1, esta bandera se activará cada vez que TMR2 se reinicie, en cambio, si es 1/16 (por ejemplo), TMR2IF se activará cada 16 reinicios de TMR2. En forma similar a los otros dos Timers, esta bandera debe ser limpiada previamente, si se quiere detectar su activación, esto puede ser hecho en la rutina de atención a la interrupción, o bien en la rutina que la detecta por poleo.
El valor de división del postescalador puede establecerse por software mediante los bits T2OUPS3:T2OUPS0 (T2CON<6:3>).
En este caso la temporización de calcula:
Temporización = Ciclo de instrucción. (PR2-TMR2) .Divisor de Frecuencia Pre. Divisor de frecuencia Post
Vemos que la máxima temporización posible es con TMR2 = 0, y Divisor de Frecuencia Pre en 16, Divisor de frecuencia Post en 16, lográndose unos 65.5 ms aprox.
A continuación se describe el principal registro relacionado con el Timer 2 y todos sus bits.
Registro T2CON (12h)
(http://img14.imageshack.us/img14/8921/timer21.jpg)
bits 6:3
T2OUPS3:T2OUPS0.- Bits de selección del valor del divisor de frecuencia del postescalador, de acuerdo a la siguiente tabla:
0 0 0 0 = divisor 1/1
0 0 0 1 = divisor 1/2
0 0 1 0 = divisor 1/3
1 1 1 1 = divisor 1/16
bit 2
TMR2ON.- Bit de encendido del Timer 2
1 = Enciende (energiza) el Timer 2
0 = Apaga (desconecta) el Timer 2
bits 1:0
T2CKPS1:T2CKPS0.- Bits de configuración del valor del preescalador de acuerdo a la siguiente tabla:
0 0 = divisor 1/1
0 1 = divisor 1/4
1 x = divisor 1/16
Ejemplo de configuración para lograr una temporización de 20 ms:
bcf STATUS,RP0 ; Banco 0.-
movlw b'01000110' ; Se selecciona TMR2, preescaler de 1/16, postescaler 1/8.-
movwf T2CON
bsf STATUS,RP0 ; Banco 1.-
movlw 0x9D ; Cargamos 157 en PR2 para lograr 20ms.-
movwf PR2
bsf PIE1,TMR2IE ; Activar interrupción por TMR2.
bsf INTCON,GIE ; Habilitacion general de interrupciones.-
bsf INTCON,PEIE ; Habilitacion de Interrupcion por perifericos.-
bcf STATUS,RP0 ; Banco 0.-
Control de interrupción:
ISR
btfss PIR1,TMR2IF ; Consultamos si es por TMR2.-
retfie ; No, salimos de interrupcion.-
. ; Si, rutina de interrupcion.
.
.
Fin_ISR
bcf PIR1,TMR2IF ; Borro bandera de control de Interrupcion.-
retfie ; Salimos de interrupcion.-
-
La USART del PIC16F628/648A
La USART puede configurarse como sistema asíncrono -full dúplex-, que puede comunicarse con dispositivos periféricos como ordenadores personales u otros microcontroladores, o puede configurarse como sistema síncrono -half dúplex-, que puede comunicarse con periféricos tales como circuitos integrados convertidores A/D y D/A, EEPROMs serie, etc.
La USART del PIC puede ser configurada para operar en tres modos:
• Modo Asíncrono (Full dúplex, transmisión y recepción simultaneas)
• Modo síncrono Maestro (Hald duplex)
• Modo síncrono Esclavo (Hald duplex)
Aquí solo trataré el modo asíncrono.
Modo Asíncrono.
En este modo la USART usa un formato estándar NRZ asíncrono, el cual para la sincronización usa: 1 bit de inicio (I), 8 o 9 bits de datos y 1 bit de paro (P). Mientras no se están transmitiendo datos la USART envía continuamente un bit de marca. El modo asíncrono se selecciona limpiando el bit SYNC del registro TXSTA (98H). El modo asíncrono es deshabilitado durante el modo SLEEP.
Cada dato es transmitido y recibido comenzando por el LSB. El hardware no maneja bit de Paridad, pero el noveno bit puede ser usado para este fin y manejado por software.
El módulo Asíncrono de la USART consta de 3 módulos fundamentales:
• El circuito de muestreo
• El generador de frecuencia de transmisión (Baud Rate)
• El transmisor asíncrono
• El receptor asíncrono.
El circuito de muestreo: El dato en la patita de recepción (RB1/RX/DT) es muestreado tres veces para poder decidir mediante un circuito de mayoría, si se trata de un nivel alto o un nivel bajo.
El Generador de Baud Rate (BRG)
Este generador consiste de un contador/divisor de frecuencia de 8 bits controlado por el registro SPBRG (99H).
De tal manera que la frecuencia de transmisión se calcula de acuerdo a la siguiente tabla:
(http://img8.imageshack.us/img8/2130/usart0.jpg)
En esta tabla X=valor de 8 bits en el registro del divisor, SPBRG. El bit BRGH corresponde a TXSTA<2>.
En el datasheet del PIC16F628/648A hay tablas donde se muestran algunos valores baud estándares, el divisor necesario (X=SPBRG) bajo diferentes frecuencias Fosc y el error producido en porcentaje.
El transmisor asíncrono
En la siguiente figura se muestra el diagrama de bloques del transmisor de la USART.
(http://img7.imageshack.us/img7/9805/usar1.jpg)
El corazón de este módulo es el registro de corrimiento TSR y la única manera de acceder al registro TSR es a través del registro TXREG (19H).
Para transmitir un dato, el programa deberá ponerlo primero en el registro TXREG. En cuanto el TSR termina de enviar el dato que tenía, enviando el bit de paro, se transfiere el dato contenido en TXREG (si hay alguno). En cuanto el dato de TXREG es transferido al TSR el TXREG queda vacío y esta condición se indicada mediante el bit bandera TXIF (PIR1<4>), el cual se pone en alto. Este bit NO puede ser limpiado por software, solamente se borrará cuando un nuevo dato se cargue en el registro TXREG. Si se escribe un dato seguido de otro a TXREG el primero se transfiere inmediatamente a TSR y el otro tiene que esperar hasta que el TSR termine de enviar el bit de Stop del primero. Durante esta espera TXIF permanece en bajo. Mientras el bit indicador TXIF señala el estado del registro TXREG, otro bit, TRMT (TXSTA<1>), muestra el estado del registro TSR. El bit de estado TRMT es de lectura, y se activa cuando el registro TSR está vacío. Ninguna interrupción está unida a este bit por lo que TRMT está pensado para ser consultado por “poleo” (sin usar interrupciones).
Para habilitar el módulo de transmisión es necesario poner en alto el bit TXEN (TXSTA<5>), mientras no se habilite el módulo, la patita de transmisión (RB2/TX/CK) se mantiene en alta impedancia. Si TXEN es deshabilitada a la mitad de una transmisión, está será abortada y el transmisor será reseteado.
Para seleccionar una transmisión a 9 bits, el bit TX9 (TXSTA<6>) deberá activarse, y el noveno bit deberá escribirse en TX9D (TXSTA<0>). El noveno bit se escribirá antes de cargar los 8 bits de datos en el registro TXREG. Esto es necesario, porque al escribir un dato en el registro TXREG puede tener lugar una transferencia inmediata del dato al registro TSR (si TSR está vacío). En este caso, se habrá cargado un dato incorrecto de nueve bits en el registro TSR.
De acuerdo a lo anterior, la inicialización del módulo de transmisión consiste en los siguientes pasos:
1. Inicializar baud rate escribiendo al registro SPBRG el divisor adecuado y opcionalmente al bit BRGH.
2. Habilitar comunicación asíncrona limpiando el bit SYNC y poniendo el bit SPEN.
3. Si se van a usar interrupciones, poner el bit TXIE (PIE<4>).
4. Poner el bit TX9 si se desea transmitir datos de 9 bits
5. Habilitar transmisión poniendo el bit TXEN, lo cual pondrá el bit TXIF.
6. Colocar el noveno bit del dato en TX9D si se están usando datos de 9 bits.
7. Cargar el dato al registro TXREG (inicia la transmisión).
El receptor asíncrono
El módulo de recepción es similar al de transmisión, en la siguiente figura se muestran los bloques que lo constituyen.
(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=24720.0;attach=10359)
Una vez que se ha seleccionado el modo asíncrono, la recepción se habilita poniendo en alto el bit CREN (RCSTA<4>)
El dato es recibido mediante la línea RB1/RX/DT y se conduce hasta el bloque Data Recovery (Recuperación de dato), la cual maneja un registro de corrimiento de alta velocidad (16 veces el Baud rate).
El corazón del receptor es el registro de corrimiento RSR. Este registro no es accesible por software, pero al capturar del bit de STOP el dato de RSR es transferido automáticamente al registro RCREG (1Ah) si éste está vacío y al mismo tiempo es puesto en alto la bandera de recepción RCIF (PIR1<5>). La única manera de limpiar la bandera RCIF es leyendo el/los datos del registro RCREG. El RCREG es un registro de doble buffer (una FIFO de dos posiciones).
Si las dos posiciones del registro RCREG están llenas (no han sido leídas) y se detecta el bit de Stop de un tercer dato de recepción, lo cual ocasiona un transferencia automática del dato recibido a RCREG, esto destruirá el primer dato recibido y activará el indicador de desbordamiento OERR (RCSTA<1>).
La única manera de limpiar el bit OERR una vez que ha sido activado es reseteando el módulo de recepción (limpiando CREN y volviéndolo a poner). Si el bit OERR está en 1, se inhibe la transferencia desde el registro RSR hasta el registro RCREG, por lo que es vital borrar el bit OERR, si estuviese activado.
El error de concordancia FERR (RCSTA<2>) se activa si un bit de STOP se lee en nivel bajo. Tanto este indicador como el noveno bit RX9D se memorizan en el mismo canal que el dato recibido, de manera que al leer RCREG se actualizan FERR y RX9D con nuevos valores, por lo cual estos bits deberán ser leídos antes de leer RCREG para no perder su información.
De acuerdo a lo anterior, la inicialización del módulo de recepción es como sigue:
1. Inicializar el baud rate escribiendo al registro SPBRG el divisor adecuado y opcionalmente al bit BRGH .
2. Habilitar el puerto serie asíncrono limpiando el bit SYNC y poniendo el bit SPEN.
3. Si se van a usar interrupciones, poner el bit RCIE (PIE<5>).
4. Si se desea recepción de datos de 9 bits se deberá poner el bit RX9 (RCSTA<0>).
5. Habilitar la recepción poniendo el bit CREN (RCSTA<4>)
6. El bit RCIF se pondrá cuando la recepción de un dato se complete y se generará una interrupción si RCIE está puesto.
7. Leer el registro RCSTA para obtener el noveno bit (si se están recibiendo datos de 9 bits) o para determinar si ha ocurrido un error de recepción.
8. Leer los 8 bits del dato recibido leyendo el registro RCREG.
9. Si ocurrió algún error este se limpia al limpiar el bit CREN, el cual deberá volver a ponerse si se desea continuar la recepción.
ConfigPIC permite seleccionar algunos parámetros para configurar el módulo USART del pic, y generar el código de ayuda ;)
(http://img139.imageshack.us/img139/2733/80990777.th.jpg) (http://img139.imageshack.us/my.php?image=80990777.jpg)
-
Ejemplo:
En este caso usando el módulo Usart del PIC16F628A y la interrupción que genera el mismo al recibir un dato haremos un ejemplo donde esperamos dato desde PC, lo recibimos y lo reenviamos inmediatamente.
Hardware necesario:
(http://img9.imageshack.us/img9/7292/hardrs232.bmp)
; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definicion de variables ****
DATA_RS232 equ 0x20 ; Dato recibido desde PC.-
Flags equ 0x21 ;
;**** Definiciones para el ensamblador ****
#DEFINE Kbhit Flags,0 ; Indica si se ha recibido algun dato.-
;**** Definición de macros ****
; Se envia la data de un registro a PC.-
Putreg macro Registro
movfw Registro
call RS232_EnviaDato
endm
; Se envia un literal a PC.-
Putc macro ACKII
movlw ACKII
call RS232_EnviaDato
endm
;/////////////////////////////////
;**** Inicio del Micro ****
Reset.
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
org 0x04 ; Atiendo Interrupcion.-
goto ISR
; **** Programa Principal ****
org 0x05
Inicio
bsf STATUS,RP0 ; Banco 1
movlw 0x02
movwf TRISB ; Configuo pines para Usart.-
movlw 0x04
movwf TXSTA ; Configura modo asincrono, baud rate de alta velocidad
movlw 0x19 ; Configura velocidad a 9600 baudios con cristal de 4 Mhz
movwf SPBRG
bsf PIE1,RCIE ; Habilita interrupcion de puerto serie para recepcion
bsf INTCON,GIE ; Habilitacion general interrupciones
bsf INTCON,PEIE ; Habilitacion de interrupciones por perifericos
; Activar recepcion, transmision.-
bsf TXSTA,TXEN ; Habilita transmision
bcf STATUS,RP0 ; Banco 0
bsf RCSTA,SPEN ; Habilitacion puerto serie
bsf RCSTA,CREN ; Habilita recepcion
bcf Kbhit ; Limpiamos bandera.
Bucle
btfss Kbhit ; ¿Se recibio Dato?
goto $-1 ; No, seguimos esperando.-
bcf Kbhit ; Si, borramos bandera.-
Putreg DATA_RS232 ; Enviamos lo guardado en DATA_RS232.-
goto Bucle ;
;.............................................
;**** Rutina de servicio de Interrupcion ****
;**** Interrupcion por Usart (Recepcion de Dato)****
ISR
btfss PIR1,RCIF ; Consultamos si es Usart.-
retfie ; No, Salimos de interrupción.-
movfw RCREG ; Llego dato, lo guardamos en un registro.
movwf DATA_RS232
bsf Kbhit ; Indicamos que ha llegado Dato.-
Fin_ISR
bcf PIR1,RCIF ; Limpiamos bandera.
retfie ; Salimos de interrupción.-
;..............................................
;**** Rutinas ****
;**** Se envia Dato ****
RS232_EnviaDato
bsf STATUS,RP0 ; Banco 1
btfss TXSTA,TRMT ; chequea si esta listo
goto $-1 ; Esperamos a que se desocupe.-
bcf STATUS,RP0 ; Banco 0
movwf TXREG ; envia Dato.-
return
;...............................................
end
-
Módulos de comparación analógica y tensión de referencia
El Módulo Comparador
Dispone de dos comparadores analógicos C1 y C2 cuyas entradas pueden ser seleccionadas entre los pines RA0 a RA3 y cuyas salidas pueden utilizarse para lectura digital interna o bien conectarse a dos pines de salida: RA4 y RA5. También podría ser posible emplear un nivel de tensión configurable y generado por otro bloque, el denominado Módulo de Referencia de Tensión.
El multiplexado para la selección de las entradas a comparar y las salidas a generar depende del registro de control de comparación CMCON (0x1F).
Existen 8 configuraciones posibles de entradas y salidas de comparación que se seleccionan con los 3 bits menos significativos (CM2-CM1-CM0). En ese mismo registro se pueden leer los estados en la salida de cada uno de los comparadores C1 y C2 y si se desea invertir o no la lógica del resultado de la comparación que aparece a la salida.
Registro CMCOM
(http://img10.imageshack.us/img10/7134/comanalogico.jpg)
Bit 7.
C2OUT: Bit de salida del Comparador 2.
Cuando C2INV = 0:
Si C2Vin+>C2Vin- = 1
Si C2Vin+<C2Vin- = 0
Cuando C2INV = 1:
Si C2Vin+>C2Vin- = 0
Si C2Vin+<C2Vin- = 1
Bit 6.
C1OUT: bit de salida del Comparador 1.
Cuando C1INV = 0:
Si C1Vin+>C1Vin- = 1
Si C1Vin+<C1Vin- = 0
Cuando CINV = 1:
Si C1Vin+>C1Vin- = 0
Si C1Vin+<C1Vin- = 1
Bit5.
C2INV: Bit de inversión de la salida del Comparador 2.
1 = C2 Salida invertida.
0 = C2 Salida no invertida.
Bit 4.
C1INV: Bit de inversión de la salida del Comparador 1.
1 = C1 Salida invertida.
0 = C1 Salida no invertida.
Bit 3.
CIS: Selector de pin de entrada al Comparador.
Cuando CM<2:0> = 001:
1 = C1Vin- conectado a RA3.
0 = C1Vin- conectado a RA0.
Cuando CM<2:0> = 010:
1 = C1Vin- conectado a RA3.
C2Vin- conectado a RA2.
0 = C1Vin- conectado a RA0.
C2Vin- conectado a RA1.
Bit 2-0.
CM<2:0>: bits de selección de configuración de los Comparadores.
(http://img3.imageshack.us/img3/5291/comanalogico2.jpg)
Modo de Trabajo de los Comparadores
- Si la entrada analógica VIN+ es mayor que la entrada analógica VIN-, entonces
la salida del comparador será un estado digital alto - Si la entrada analógica VIN+ es menor que la entrada analógica VIN-, entonces
la salida del comparador será un estado digital bajo
(http://img3.imageshack.us/img3/6232/comanalogico3.jpg)
Las áreas sombreadas de la salida del comparador en la figura representan la incertidumbre debido a tensiones de desviación y tiempo de respuesta.
Referencias de Comparación
La referencia de tensión para la comparación puede ser:
Externa: se conectará a cualquiera de los pines de entrada externos del comparador y esa tensión deberá estar comprendida entre VDD y VSS
Interna: se puede emplear una referencia de tensión generada a nivel interno por parte de un módulo interno específico presente dentro del microcontrolador cuando se configuran los bits CM<2:0> con la combinación 110
Módulo de Referencia de Tensión para Comparación
Se trata de un divisor resistivo a partir de la tensión de alimentación del microcontrolador.
Registro VRCON (9Fh)
(http://img9.imageshack.us/img9/5961/comanalogico5.jpg)
(http://img3.imageshack.us/img3/3337/comanalogico4.jpg)
VR<3:0> Selección de la tensión de referencia:
Si VRR = 1:
\mathrm{Vref}=\frac{\mathrm{VR<3:0>.Vdd}}{24}
Si VRR = 0:
\mathrm{Vref}=\left(\mathrm{Vdd}.\frac{1}{4}\right)+\frac{\mathrm{VR<3:0>.Vdd}}{32}
Interrupciones del Módulo de Comparación
El módulo de comparación puede generar una interrupción por activación del flag CMIF (Flag de Interrupción del Comparador) presente en el registro PIR1. El flag CMIF se pondrá a 1 si se produce un cambio en la salida de cualquiera de los dos comparadores (C1OUT ó C2OUT) desde la última lectura que se realizó del registro CMCON.
El flag debe ponerse a cero por software pero además debe realizarse previamente una operación de lectura (o escritura) del registro CMCON para que deje de darse la discrepancia entre el valor actual y el valor leído. Para que se produzca la interrupción deben encontrarse activadas la máscara particular (CMIE en PIE2), la de periféricos (PEIE) y la global (GIE).
Característica especial del Módulo Comparador
Si un comparador se encuentra activo y se sitúa al microcontrolador en modo de bajo consumo (SLEEP), el comparador permanecerá activo y las interrupciones si están activadas mediante sus máscaras serán funcionales y podrán sacar al micro de su modo de bajo consumo si cambia la salida de alguno de los comparadores desde la última lectura.
ConfigPIC permite seleccionar la configuración del módulo comparador analógico y tensión de referencia, generando el código de configuración.
(http://img15.imageshack.us/img15/8679/18884242.th.jpg) (http://img15.imageshack.us/my.php?image=18884242.jpg)
-
A modo de ejemplo conectaremos un potenciómetro al comparador 1, fijando una tensión de referencia interna a 3.59 Volt e invirtiendo la salida del comparador. Cuando la tensión sobre el pin RA0 (C1Vin-) sea mayor a 3.59 Volt haremos titilar un led 10 veces a modo de alarma.
Hardware necesario:
(http://img14.imageshack.us/img14/9623/companalogico.bmp)
Diagrama de Flujo:
(http://img8.imageshack.us/img8/7638/flujocomp.jpg)
; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definicion de variables ****
Contador1 equ 0x20 ; Registro utilizado para demora.-
Contador2 equ 0x21 ; Registro utilizado para demora.-
Loop equ 0x22 ;
;**** Definiciones para el ensamblador ****
#DEFINE Led PORTB,0 ; Led ubicado en Puerto B, bit 0.-
;/////////////////////////////////
;**** Inicio del Micro ****
Reset.
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
org 0x04 ; Atiendo Interrupcion.-
goto ISR
; **** Programa Principal ****
org 0x05
Inicio
movlw 0x12 ; Seleccionamos 2 comparadores con Vref interna.
; C1Vin- -> RA0, C2Vin- -> RA1.
; Salida de comparador 1 invertida.
movwf CMCON
bsf STATUS,RP0 ; Banco 1
movlw 0x03 ; RA0 y RA1 como entrada.-
movwf TRISA
clrf TRISB ; PORTB como salida.-
movlw 0xAF ; Vref activado, Low, VR<3:0>=15 (Vref=3.59 Volt).-
movwf VRCON
bcf STATUS,RP0 ; Banco 0.-
clrf PORTB
movf CMCON,f ; Operacion de lectura.-
bcf PIR1,CMIF ; Limpiamos bandera.-
bsf STATUS,RP0 ; Banco 1.-
bsf PIE1,CMIE ; Habilitamos interrupcion por comparador analogico.
bsf INTCON,PEIE ; Habilitacion de Interrupcion por perifericos.-
bsf INTCON,GIE ; Habilitacion general de interrupciones.-
bcf STATUS,RP0 ; Banco 0.-
Bucle
nop
goto Bucle
;.............................................
;**** Rutina de servicio de Interrupcion ****
;**** Interrupcion por Comparador Analogico****
ISR
btfss PIR1,CMIF ; Interrupcion por Comparador?
retfie ; No, salimos de interrupcion.-
btfss CMCON,C1OUT ; Consultamos estado del comparador.-
goto Fin_ISR ; Si es 0 salimos de interrupcion.-
call Alarma ; Si es 1, indicamos una alarma.-
Fin_ISR
movf CMCON,f ; Operacion de lectura.-
bcf PIR1,CMIF ; Limpiamos bandera.-
retfie
;..............................................
;**** Rutinas ****
Alarma
movlw 0x0A ; Hacemos titilar 10 veces el Led.-
movwf Loop
bsf Led
call Demora_150ms
bcf Led
call Demora_150ms
decfsz Loop
goto $-5
return
;**** Demora ****
Demora_150ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0xC3 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;.................................................
end
-
Módulo CCP
Introducción
Los microcontroladores PIC16F628A/648A disponen de un modulo de Captura/Comparación/PWM que en conjunto con los temporizadores, permite realizar en forma sencilla las tareas de medición de tiempo y frecuencia, y generación de señales digitales.
El modulo CCP tiene 3 modos de funcionamiento, que se describen a continuación:
- Modo captura: Permite capturar el valor que tiene en registro TMR1 cuando ocurre un evento especial en la terminal RB3/CCP1.
- Modo comparación: Permite comparar el valor de 16 bits del TMR1 con un valor previamente definido en los registros CCPRL1H y CCPR1L
- Modo PWM: Permite generar señales digitales moduladas en ancho de pulso
A continuación se da un breve resumen de los registros relacionados con cada módulo:
El registro principal de este módulo se compone de dos registros de 8 bits, denominados CCPR1H (16h) (parte más significativa) y CCPR1L (15h) (parte menos significativa). La operación del módulo se controla mediante el registro CCP1CON (17h) y el disparo de evento especial, el cual es generado al alcanzarse la igualdad en un registro de comparación reseteará el Timer 1.
Selección del modo de operación:
La selección del modo en que trabajara el módulo CCP se realiza mediante los cuatro bits menos significativos del registro CCP1CON, es decir, mediante los bits CCP1M3:CCP1M0 (CCP1CON<3:0>) de acuerdo a lo siguiente:
- 0000 Captura/Comparación/PWM deshabilitados
- 0100 Captura cada transición de bajada
- 0101 Captura cada transición de subida
- 0110 Captura cada cuarta transición de subida
- 0111 Captura cada 16 transiciones de subida
- 1000 Comparación, pone salida cada coincidencia
- 1001 Comparación, limpia salida cada coincidencia
- 1010 Comparación, genera interrupción cada coincidencia (Se setea bit CCP1IF, salida inalterada)
- 1011 Comparación, dispara evento especial (Se setea bit CCP1IF , resetea TMR1(TMR1IF inalterado) )
- 11xx Modo PWM
El Modo de Captura
En el modo de captura el registro CCPR1 (CCPR1H:CCPR1L) captura el valor de 16 bits registro TMR1 cuando ocurre un evento en la patita RB3/CCP1. El evento en cuestión puede especificarse previamente como alguno de los siguientes:
- Cada transición de bajada
- Cada transición de subida
- Cada cuarta transición de subida
- Cada dieciseisava transición de subida
Además de que el valor de TMR1 es capturado, la bandera de solicitud de interrupción CCP1IF es activada, la cual deberá ser limpiada por software para poder detectarla si se está consultando por poleo.
El tipo de acción que se desea detectar en esta patita se configura mediante los bits de control CCP1M3:CCP1M0 (CCP1CON<3:0>). Si ocurre otro evento de captura antes de que haya sido leído el registro CCPR1, el valor capturado anterior se perderá, ya que con la nueva captura este registro es reescrito.
En la figura siguiente se muestra un diagrama de bloques en donde se ilustra la manera en que trabaja el módulo CCP en modo de captura:
(http://img9.imageshack.us/img9/1541/ccp6280.jpg)
El preescalador del CCP
El valor del preescalador se configura mediante los bits CCP1M3:CCP1M0. Sin embargo, al realizar un cambio en la configuración del preescalador se puede generar una interrupción falsa, para evitar lo anterior se deberá apagar el modulo CCP (limpiando el registro CCP1CON) previamente al cambio de valor del preescalador.
Este preescalador es independiente al preescalador del Timer 1 (el cual puede usarse como ya se explicó con sus posibles divisores de 1/1, 1/2, 1/4, 18).
Configuraciones:
- Se debe configurar el CCP1 como entrada a través del registro TRISB
- El Timer1 debe estar en modo temporizador o modo contador sincronizado
- Al cambiar el modo de captura hay que tener inhabilitadas las interrupciones y borrar el flag para evitar interrupciones espúreas.
- Si el pin RB3/CCP1 es configurado como salida, se deberá tener en cuenta que una escritura al puerto B puede causar una condición de captura.
-
Ejemplo:
Para ejemplificar el uso del modulo CCP en modo captura vamos a realizar la medida del periodo de una onda cuadrada para así determinar su frecuencia. La forma de trabajar va a ser la siguiente:
Configuramos CCP modo captura con cada transición de subida del pin RB3/CCP1 con Timer1 modo temporizador 1/1.
Al llegar un flanco ascendente, reseteamos Timer1 y esperamos al siguiente flanco ascendente, en el cual se guarda el valor capturado y lo enviamos a la PC para poder determinar la frecuencia de la señal. Lo que hemos capturado es la cantidad de ciclos de reloj transcurridos en un ciclo de la señal a medir. Con este valor y el Tosc al cual trabaja el microcontrolador podemos determinar el periodo de la señal.
\mathrm{Periodo[s]}=\left(\frac{4}{\mathrm{20MHz}}\right)\cdot\mathrm{CCPR1}
\mathrm{Frecuencia[Hz]}=\frac{1}{\mathrm{Periodo}}
Con un cristal de 20 MHz podemos medir desde aprox. 77Hz hasta los 500kHz, claro que a más frecuencia más error en las mediciones. Por ejemplo, con algunos ensayos que he realizado a 1kHz se tiene un error de +-1Hz, 10kHz +-5Hz, 100kHz +- 0.5kHz, 200kHz +- 2kHz, etc.
Para determinar la frecuencia adjunto un programita hecho en Visual Basic que toma 10 valores enviados desde el microcontrolador, calcula un promedio del periodo y determina la frecuencia. Se hace de este modo para reducir el error cometido a altas frecuencias.
(http://img10.imageshack.us/img10/347/frecuencimetro.jpg)
Hardware necesario:
(http://img16.imageshack.us/img16/5455/hardrs232ccp.png)
; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definicion de variables ****
Msb equ 0x20 ; Guarda Byte alto de Captura para enviar por RS232
Lsb equ 0x21 ; Guarda byte bajo de Captura para enviar por RS232
Contador1 equ 0x22 ; Para demora
Contador2 equ 0x23 ; Para demora
;**** Definiciones para el ensamblador ****
;**** Definición de macros ****
; Se envia la data de un registro a PC.-
Putreg macro Registro
movfw Registro
call RS232_EnviaDato
endm
;/////////////////////////////////
;**** Inicio del Micro ****
Reset.
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
; **** Programa Principal ****
org 0x05
Inicio
bsf STATUS,RP0 ; Banco 1
movlw b'00001010' ; RB1 entrada, RB2 salida, RB3 entrada.
movwf TRISB
movlw 0x04
movwf TXSTA ; Configura modo asincrono, baud rate de alta velocidad
movlw 0x81 ; Configura velocidad a 9600 baudios con cristal de 20 Mhz
movwf SPBRG
bsf TXSTA,TXEN ; Habilita transmision
bcf STATUS,RP0 ; Banco 0.-
bsf RCSTA,SPEN ; Habilitacion puerto serie
movlw b'00000001' ; Se selecciona TMR1, preescaler de 1/1, modo temporizador.-
movwf T1CON
movlw b'00000101' ; Se configura CCP modo captura cada flanco de subida.-
movwf CCP1CON
Bucle
bcf PIR1,CCP1IF ; Borramos bandera
btfss PIR1,CCP1IF ; Testeamos bandera.-
goto $-1 ; Si no se activo seguimos esperando
bcf PIR1,CCP1IF ; Se activo, la borramos.-
clrf TMR1H ; Borramos Timer1.-
clrf TMR1L ;
btfss PIR1,CCP1IF ; Volvemos a testear bandera.-
goto $-1 ; No se activo, seguimos esperando.-
movfw CCPR1L ; Copiamos el valor capturado.-
movwf Lsb
movfw CCPR1H
movwf Msb
Putreg Msb ; Enviamos lo guardado en el registro Msb.-
Putreg Lsb ; Enviamos lo guardado en el registro Lsb.-
call Demora_30ms
goto Bucle ;
;..............................................
;**** Rutinas ****
;**** Se envia Dato ****
RS232_EnviaDato
bsf STATUS,RP0 ; Banco 1
btfss TXSTA,TRMT ; chequea si esta listo
goto $-1 ; Esperamos a que se desocupe.-
bcf STATUS,RP0 ; Banco 0
movwf TXREG ; envia Dato.-
return
;...............................................
; *** Demora****
Demora_30ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0xC3 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;...............................................
end
-
El Modo Comparador
En el modo de comparación el registro de 16 bits CCPR1 (CCPR1H:CCPR1L) se compara constantemente con el valor del registro de 16 bits TMR1. De manera que cuando sus valores coinciden además de activarse la bandera para solicitar interrupción CCP1IF (PIR1<2>), puede ocurrir en la patita RB3/CCP1 (previa configuración) alguna de las siguientes acciones:
- RB3/CCP1 Se pone en alto
- RB3/CCP1 Se pone en Bajo
- RB3/CCP1 no cambia
La acción que ocurra en esta patita se configura mediante los bits de control CCP1M3:CCP1M0 (CCP1CON<3:0>). En la figura siguiente se muestra un diagrama de bloques en donde se ilustra la manera en que trabaja el módulo CCP en modo comparador
(http://img15.imageshack.us/img15/6833/ccp6281.jpg)
Configuraciones:
- El pin RB3/CCP1 debe configurarse como salida limpiando el bit TRISB<3>
- El Timer 1 debe estar corriendo en modo temporizador (o en modo contador sincronizado)
- Al limpiar el registro CCP1CON el latch de salida de la patita RB3/CCP1 se forza a su valor “default” de cero.
- En el modo “interrupción software” no se realiza ninguna acción en el pin RB3/CCP1.
- El modo “Special Event Trigger” ocurre inmediatamente al igualarse el par de registros TMR1H, TMR1L al par de registros CCPR1H, CCPR1L. El par de registros TMR1H, TMR1L no se resetean hasta el próximo flanco ascendente del clock de Timer1. Esto permite que el registro CCPR1 sea un registro de periodo programable para el Timer1
Ejemplo:
En este programa se hace uso del modo de comparación para realizar la conmutación de una señal cada vez que transcurre un tiempo, el cual se ajusta al oprimir un pulsador de incremento o uno de decremento.
Hardware necesario:
(http://img17.imageshack.us/img17/9763/comparacionhard.png)
[/list]; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definicion de variables ****
decre equ 0 ; Pulsador para decrementar periodo
incre equ 1 ; Pulsador para incrementar periodo
;/////////////////////////////////
;**** Inicio del Micro ****
Reset.
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
; **** Programa Principal ****
org 0x05
Inicio
movlw 0x07 ; Para deshabilitar comparadores analogicos.-
movwf CMCON
bsf STATUS,RP0 ; Banco 1
bsf TRISA,decre ; Como entrada.-
bsf TRISA,incre ; Como entrada.-
bcf TRISB,3 ; RB3 como Salida.
bcf STATUS,RP0 ; Banco 0.-
movlw b'00000001' ; Se selecciona TMR1, preescaler de 1/1, modo temporizador.-
movwf T1CON
movlw 0x80 ; Inicia periodo de comparacion a mitad de rango.-
movwf CCPR1H
movlw 0x00
movwf CCPR1L
movlw b'00001000' ; Se configura CCP modo comparación, setea salida con coincidencia.-
movwf CCP1CON
clrf TMR1H ; Comenzamos generacion de señal.-
clrf TMR1L
Bucle
bcf PIR1,CCP1IF ; Borramos bandera
btfss PIR1,CCP1IF ; Testeamos bandera.
goto $-1 ; Si no se activo seguimos esperando
bcf PIR1,CCP1IF ; Se activo, la borramos.
movlw b'00000001' ; Invertimos ultimo bit, para pasar de setear a resetear...
xorwf CCP1CON,1 ; o viceversa.-
clrf TMR1H ; Reseteamos cuenta Timer1.
clrf TMR1L ;
btfsc PORTA,decre ; Testea pulsador para decrementar periodo.-
call Decrementa
btfsc PORTA,incre ; Testea pulsador para incrementar periodo.-
call Incrementa
goto Bucle ;
;..............................................
;**** Rutinas ****
Decrementa
decf CCPR1L,1 ; Decrementa parte baja.-
comf CCPR1L,w ; Carga el negado a W, si CCPR1L=0xFF -> W=0x00.-
btfss STATUS,Z ; Si W=0x00 decrementamos parte alta.-
return ; No.-
decf CCPR1H,1 ; Decrementa parte alta.-
return
;..............................................
Incrementa
incf CCPR1L,1 ; Incrementa parte baja.-
btfss STATUS,Z ; CCPR1L=0x00?
return ; No.-
incf CCPR1H,1 ; Si, incrementa parte alta
return
;...............................................
end
-
Modo PWM (Modulación de Ancho de Pulso).
Con este modo de trabajo se consiguen impulsos lógicos cuya anchura del nivel alto es de duración variable, que son de enorme aplicación en el control de dispositivos tan populares como los motores y triacs.
El pin RB3/CCP1 esta configurado como salida y cambia entre los niveles 0 y 1 a intervalos de tiempos variables, logrando un pulso cuyo nivel alto tiene un ancho variable dentro del intervalo del periodo de trabajo:
(http://img23.imageshack.us/img23/5449/ccp6283.jpg)
La base de tiempos es el Timer2 más dos bits adicionales para tener los 10.
El periodo se determina con el registro PR2, ya que cuando TMR2=PR2:
- Se borra el TMR2
- Se pone a “1” el pin CCP1
- Se pasa el valor del CCPR1L al CCPR1H (para evitar glitch)
(http://img14.imageshack.us/img14/9973/ccp6282.jpg)
De esta manera, de acuerdo a la figura anterior, el siguiente valor de comparación para TMR2 en el comparador de 10 bits es el Ciclo de Trabajo, el cual al alcanzarse limpiará la patita CCP1.
El ciclo de trabajo se determina con el contenido del CCPR1L y los dos bits de CCP1CON (CCP1X y CCP1Y).
Periodo del PWM
\mathrm{PeriodoPWM}=\left(\mathrm{PR2} + 1 \right)\cdot 4\cdot\mathrm{Tosc}\cdot\mathrm{TMR2 Preescaler}
\mathrm{FrecuenciaPWM}=\frac {1}{\mathrm{PeriodoPWM}}
Ciclo de Trabajo del PWM
El ciclo de Trabajo se especifica escribiendo un valor de 10 bits al registro CCPR1L (los 8 bits más significativos (msb)) y los dos bits menos significativos (lsb) a CCP1CON<5:4>.
\mathrm{CTPWM}=\left(\mathrm{CCPR1L:CCP1CON<5:4>}\right)\cdot\mathrm{Tosc}\cdot\mathrm{TMR2 Preescaler}
Como se puede ver en la figura anterior, el valor que determina la duración de C.T. del PWM no es el cargado en CCPR1L, sino en CCPR1H, el cual sólo se actualiza en el momento en que TMR2 alcanza el valor de PR2 (es decir, cada vez que se completa un periodo). Por ello, aunque CCPR1L puede ser escrito en cualquier momento, el Ciclo de Trabajo solo se actualiza hasta que termina el periodo que está en transcurso.
No hay otra manera de escribir al registro CCPR1H, ya que este es un registro de sólo lectura.
El número de divisiones que se pueden tener en un Ciclo de Trabajo será 2^{n}
, donde n es el número de bits usados, por lo tanto su duración máxima será:
\mathrm{CTPWM}=2^{n}\cdot\mathrm{Tosc}\cdot\mathrm{TMR2 Preescaler}
Sin embargo, dependiendo del valor de Ciclo de trabajo máximo (CT_PWM) deseado, no será posible realizar las 2^{n}
divisiones y por lo tanto no se podrán usar los n bits de resolución. O al revés, si se elige una resolución deseada n no será posible tener cualquier Ciclo de Trabajo máximo (CT_PWM) Deseado.
De la ecuación anterior se puede despejar cual es la resolución máxima:
\mathrm{ResolucionPWM}=\frac{\log\left(\frac{\mathrm{CTPWM}}{\mathrm{Tosc}\cdot\mathrm{TMR2 Preescaler}}\right)}{\log 2}
Veamos con un ejemplo, si fijamos PR2 en 100 y usamos preescaler 1/4 con un oscilador de 20 MHz, tendremos un PWM de periodo 80.8us. El ciclo de trabajo no puede superar este valor por lo que despejando de las ecuaciones anteriores, CCPR1L:CCP1CON<5:4> no puede ser mayor a 404. Aquí se ve claramente que no se pueden usar los 10 bits de resolución, sino “8.66” bits. Caso contario el pin RB3/CCP1 nunca será reseteado.
En la siguiente tabla se resumen diversas elecciones de resolución n y la correspondiente frecuencia F_PWM máxima, así como el valor de PR2 con el que se logra (para un frecuencia del cristal de 20 Mhz).
(http://img11.imageshack.us/img11/2681/ccp6284.jpg)
Secuencia de configuración del PWM
A continuación se resumen los pasos para realizar la configuración inicial del PWM:
- Establecer el periodo del PWM escribiendo al registro PR2.
- Establecer el Ciclo de Trabajo del PWM escribiendo al registro CCPR1L y a los bits CCP1CON<5:4>.
- Configurar como salida el pin CCP1, limpiando el bit TRISB<3>.
- Configurar el preescalador del Timer 2 y habilitar el Timer 2, escribiendo al registro T2CON.
- Configurar el módulo CCP1 para operación PWM. Poniendo en alto los bits CCP1CON <2:3>.
-
Ejemplo:
Como ejemplo generaremos dos frecuencias distintas seleccionables mediante la acción de un pulsador conectador a RB0. Una de las señales será de 500Hz y la otra de 2kHz, con ciclo de trabajo de 50%.
Con oscilador de 4MHz y preescaler 1/16 tendremos:
| Señal de 500Hz | PR2=124 (0x7C) | CCPR1L&2bits=250(0xFA) | CCPR1L=0x3E & 2bits=10 |
| Señal de 2kHz | PR2=30 (0x1E) | CCPR1L&2bits=62 (0x3E) | CCPR1L=0x0F & 2bits=10 |
Hardware necesario:
(http://img17.imageshack.us/img17/9135/pwm.png)
; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definicion de variables ****
Flags equ 0x20 ; Registro para guardar banderas.-
Selec equ 0 ; Bit para indicar seleccion(Selec=1->500Hz; Selec=0->2kHz).-
;**** Definiciones para el ensamblador ****
#define Signal Flags,Selec
;/////////////////////////////////
;**** Inicio del Micro ****
Reset.
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
; **** Programa Principal ****
org 0x05
Inicio
bsf STATUS,RP0 ; Banco 1
bsf TRISB,0 ; Como Entrada.-
bcf TRISB,3 ; RB3 como Salida.
bcf STATUS,RP0 ; Banco 0.-
movlw b'00000110' ; Se selecciona TMR2, preescaler de 1/16.-
movwf T2CON
bsf STATUS,RP0 ; Banco 1
movlw 0x7C ; Inicia periodo de 500Hz.-
movwf PR2
bcf STATUS,RP0 ; Banco 0.-
bsf Signal
movlw 0x3E ; Ciclo de trabajo 50%
movwf CCPR1L
bsf CCP1CON,CCP1X
bcf CCP1CON,CCP1Y
bsf CCP1CON,CCP1M3 ; Configura modulo CCP modo PWM.-
bsf CCP1CON,CCP1M2
Bucle
btfss PORTB,0 ; Testea si se quiere cambiar de Frecuencia.-
goto $-1 ; No se quiere cambiar.-
btfss Signal ; A cual cambiar?
goto Cambiar500Hz
Cambiar2kHz
bsf STATUS,RP0 ; Banco 1
movlw 0x1E
movwf PR2
bcf STATUS,RP0 ; Banco 0
bcf Signal ; Señal de 2kHz
movlw 0x0F ; Ciclo de trabajo 50%
movwf CCPR1L
goto Bucle ;
Cambiar500Hz
bsf STATUS,RP0 ; Banco 1
movlw 0x7C ; Inicia periodo de 500Hz.-
movwf PR2 ; Señal de 500 Hz.-
bcf STATUS,RP0 ; Banco 0.-
bsf Signal
movlw 0x3E ; Ciclo de trabajo 50%
movwf CCPR1L
goto Bucle
;...............................................
end
-
Otro ejemplo:
En este se fija la frecuencia de PWM en 2 kHz y se varía el ciclo de trabajo con 2 pulsadores de control conectados a RB0 y RB1. Solo se modifica en byte alto del CT, ósea el registro CCPR1L con lo que CT se varía de 4 en 4.
Hardware necesario:
(http://img9.imageshack.us/img9/2410/pwm2.png)
; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definicion de variables ****
Contador1 equ 0x20 ;
Contador2 equ 0x21 ;
decre equ 0 ; Pulsador para decrementar Ciclo de Trabajo
incre equ 1 ; Pulsador para incrementar Ciclo de Trabajo
;/////////////////////////////////
;**** Inicio del Micro ****
Reset.
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
; **** Programa Principal ****
org 0x05
Inicio
bsf STATUS,RP0 ; Banco 1
bsf TRISB,incre ; Como Entrada.-
bsf TRISB,decre ; Como Entrada.-
bcf TRISB,3 ; RB3 como Salida.
bcf STATUS,RP0 ; Banco 0.-
movlw b'00000110' ; Se selecciona TMR2, preescaler de 1/16.-
movwf T2CON
bsf STATUS,RP0 ; Banco 1
movlw 0x1E ; Señal de 2kHz
movwf PR2
bcf STATUS,RP0 ; Banco 0
clrf CCPR1L ; Ciclo de trabajo 0%
bcf CCP1CON,CCP1X
bcf CCP1CON,CCP1Y
bsf CCP1CON,CCP1M3 ; Configura modulo CCP modo PWM.-
bsf CCP1CON,CCP1M2
Bucle
btfsc PORTB,decre ; Testea si se quiere reducir CT.-
goto Decrementa
btfsc PORTB,incre ; Testea si se quiere aumentar CT.-
goto Incrementa
goto Bucle
Incrementa
incf CCPR1L,1
call Demora_50ms
goto Bucle
Decrementa
decf CCPR1L,1
call Demora_50ms
goto Bucle
;**** Demora ****
Demora_50ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0x40 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;..............................................
end
-
Excelente Suky, vaya que te has tomado trabajo y dedicación con este aporte. :) Te felicito.
-
Mas info:
- Generación Automática del código de configuración, PIC16F84A/PIC16F628A/PIC16F648A (http://www.todopic.com.ar/foros/index.php?topic=25660.0)
- Más ejemplos en Asembler para PIC16F84A (http://www.todopic.com.ar/foros/index.php?topic=12345.0)
- Comunicación con Teclado PS/2 en asm (http://www.todopic.com.ar/foros/index.php?topic=24517.0)
- Módulo de conversión Analógico/Digital (http://www.todopic.com.ar/foros/index.php?topic=27929.0)
- Rutinas Bus I2C (http://www.todopic.com.ar/foros/index.php?topic=24307.0)
- Rutinas para compartir (http://www.todopic.com.ar/foros/index.php?topic=23812.msg191686#msg191686)
- Pequeños proyectos (http://www.todopic.com.ar/foros/index.php?topic=24397.0)
- Base de tiempo de 1 seg. muy exacta (http://www.todopic.com.ar/foros/index.php?topic=24381.0)
-
Suky..muchas gracias por tu valioso aporte a la comunidad, estoy mur agradecido contigo...de verdad que si pudiera te envitaba a un buen par de cervezas..como se nota que trabajas para enseñar..trabajas más que le registro W :mrgreen:..
Saludos y de nuevo mil gracias.
-
de verdad que si pudiera te envitaba a un buen par de cervezas..
Venga, venga! :D :D :D
Saludos!!!
-
Suky te has mandado con este excelente y completo tutorial
Mi reconocimiento a gran esfuerzo de tu parte
-
Suki, y demas participantes del foro, muchas gracias por este tutorial; para mi que estoy empezando es una buena forma de ser guiado paso a paso.
Les animo a que sigan compartiendo la información y los conocimientos, que ya nos llegará el momento, a los que somos nuevos, de compartir y enseñar.
Guido.
-
Muy buena info sobre los perifericos del PIC16F628A... queria saber si tienes idea de cuanto es el valor maximo de tension que soportan las entradas analogicas del pic para usarlo como comparador. supongo que es vdd pero no estoy seguro. muchas gracias
-
Muy buena info sobre los perifericos del PIC16F628A... queria saber si tienes idea de cuanto es el valor maximo de tension que soportan las entradas analogicas del pic para usarlo como comparador. supongo que es vdd pero no estoy seguro. muchas gracias
Si exactamente, entre Vss y Vdd. Fíjate en el datasheet del micro que internamente tiene 2 diodos en serie que limitan la tensión de entrada entre -0.3V y 5.3V...
-
Muy buen aporte para personas como yo que estan empezando en esto de los PICs, gracias por tu aporte.
Solo que tengo la siguiente duda. Encontre el siguiente programador PIC JDM, creen que funcione para un 16F628A? o hay que modificar algo para que funcione bien?.
(http://img11.imageshack.us/img11/3193/diagramajdm.jpg)
-
Al principio del hilo, donde esta el índice, deje un comprimido con un JDM más general. Te conviene armarte ese ya que tiene casi los mismos componentes y vas a poder grabar mayor variedad de micros (Para el futuro). :wink:
-
Al principio del hilo, donde esta el índice, deje un comprimido con un JDM más general. Te conviene armarte ese ya que tiene casi los mismos componentes y vas a poder grabar mayor variedad de micros (Para el futuro). :wink:
Gracias por responder. En efecto armare el programador que tu tienes ya que lo tienes probado para un 16F628A-I/P.
Otra duda: ¿Crees que funcione de igual forma si le pongo el sustituto de los Transistores?
-
A que sustituto te refieres? Igual no creo que haya problemas...
-
Control de Displays con 74LS164
Aquí realizo un nuevo ejemplo de manejo de varios displays de 7 segmentos. En este caso realizaremos el control de 3 displays con la ayuda del registro de desplazamiento 74LS164. Las ventajas que conlleva el uso de este CI es que no necesitaremos multiplexar la señal enviada a los displays, algo que limita mucho al microcontrolador, ya que debe refrescarlos continuamente. Y la desventaja es que necesitaremos un 74LS164 por cada display.
Hardware: (los pines 7 y 14 del 74LS164 van a GND y 5V, y se debe agregar una resistencia a cada linea que une el 74LS164 con el display)
(http://img206.imageshack.us/img206/451/74ls164displays.th.png) (http://img206.imageshack.us/my.php?image=74ls164displays.png)
Con este circuito se pueden manejar 3 displays + los 3 puntos. El primer bit que ingresa será empujado por los demás. Ejemplo para enviar 12.7:
(http://img526.imageshack.us/img526/1757/001hvs.jpg)
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Display1 equ 0x0C ; Valor que luego de convertido se enviara al Display 1
Display2 equ 0x0D ; Valor que luego de convertido se enviara al Display 2
Display3 equ 0x0E ; Valor que luego de convertido se enviara al Display 3
DataEnviar equ 0x0F ; Dato convertido a codigo 7 Segmentos a enviar
ContBits equ 0x10 ; Para controlar el envio de bits
Desc equ 0 ; Definimos Pulsador descendente.-
Asc equ 1 ; Definimos Pulsador ascendente.-
BClock equ 0 ; Pin reloj del 74LS164
BData equ 1 ; Pin data del 74LS164
BReset equ 2 ; Pin Reset del 74LS164
Pto equ 0 ; Bit punto, Con este indicamos si se muestra punto.-
Resett org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Tabla de conversion BCD a 7 Segmentos ****
; Se coloca al inicio para asegurar ubicacion en Pagina.-
org 0x05 ; Origen del código de tabla.-
BCD7SEG: ; retlw b'abcdefg0' para display catodo comun
addwf PCL,1 ; Se incrementa el contador del programa.-
DT 0xFC , 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6
;**** Programa principal ****
;**** Configuracion de puertos ****
Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111000' ; RB7 como entrada y los demas como salida.-
movwf TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
clrf Display1
clrf Display2
clrf Display3
bsf PORTB,BReset ; Habilitamos 74LS164.-
bcf PORTB,BData
bsf PORTB,BClock ; Seteamos Clock.-
goto ActualizoDisplays
;**** Testeo de Pulsador ****
Testeo
btfss PORTA,Desc ; Testeamos si esta a 1 logico.-
goto Descender ; No
btfss PORTA,Asc ; Testeamos si esta a 1 logico.-
goto Ascender
goto Testeo ; Si, Testeamos nuevamente.-
;**** Rutinas ****
Descender
btfss PORTA,Desc ;
goto $-1 ; Esperamos hasta que se suelte.-
decf Display1,1 ; Decremento Display1.
movlw d'255' ; Si paso de 0 a 255...
subwf Display1,0 ; decremento Display2
btfss STATUS,Z ;
goto ActualizoDisplays ; no es 255
movlw d'9'
movwf Display1 ; Si, cargo 9.-
decf Display2,1 ; Decremento Display2.-
movlw d'255' ; Si paso de 0 a 255...
subwf Display2,0 ; decremento display3
btfss STATUS,Z ;
goto ActualizoDisplays ; No es 10.-
movlw d'9'
movwf Display2 ; Si, cargo 9.-
decf Display3,1 ; Decremento Display3.-
movlw d'255' ; Si paso de 0 a 255...
subwf Display3,0
btfss STATUS,Z
goto ActualizoDisplays ; No es 10.-
movlw d'9'
movwf Display3 ; Si, cargo 9.-
goto ActualizoDisplays
;.........................................................
Ascender
btfss PORTA,Asc ;
goto $-1 ; Esperamos hasta que se suelte.-
incf Display1,1 ; Incremeto Display1.
movlw d'10' ; Si es 10 reseteo e incremento Display2
subwf Display1,0 ;
btfss STATUS,Z ;
goto ActualizoDisplays ; no es 10
clrf Display1 ; Si, reseteo.-
incf Display2,1 ; Incremento Display2.-
movlw d'10' ; Si Decena = 10, reseteo e incremento Display3
subwf Display2,0 ;
btfss STATUS,Z ;
goto ActualizoDisplays ; No es 10.-
clrf Display2 ; Si, reseteo.-
incf Display3,1 ; Incremento Display3.-
movlw d'10' ; Si es 10 Reseteo.-
subwf Display3,0
btfss STATUS,Z
goto ActualizoDisplays ; No es 10.-
clrf Display3 ; Si, reseto
goto ActualizoDisplays
;...................................................
ActualizoDisplays
movfw Display1
call BCD7SEG ; Convertimos BCD a codigo 7 Segmentos.-
movwf DataEnviar ; Cargamos dato a enviar devuelto x BCD7SEG.-
call EnviaDato
movfw Display2
call BCD7SEG ; Convertimos BCD a codigo 7 Segmentos.-
movwf DataEnviar ; Cargamos dato a enviar devuelto x BCD7SEG.-
bsf DataEnviar,Pto ; A ejemplo cargamos punto a enviar.-
call EnviaDato
movfw Display3
call BCD7SEG ; Convertimos BCD a codigo 7 Segmentos.-
movwf DataEnviar ; Cargamos dato a enviar devuelto x BCD7SEG.-
call EnviaDato
goto Testeo
;**** Se envia Dato a los registros de desplazamiento ****
;-----------------------------------------------------------------------------------------
; 1º se envia el LSB, luego se va rotando a la derecha y se envian los bits de mayor peso.-
;-----------------------------------------------------------------------------------------
EnviaDato
movlw d'8' ; Número de bits a transmitir.
movwf ContBits
EnviaBit ; Comienza a enviar datos.
btfss DataEnviar,0 ; ¿Es un "1" el bit a transmitir?
bcf PORTB,BData ; No, pues envía un "0".
btfsc DataEnviar,0 ; ¿Es un "1" el bit a transmitir?
bsf PORTB,BData ; Si, Transmite un "1".
bcf PORTB,BClock ; Clock=0.-
nop
bsf PORTB,BClock ; Clock=1.-
rrf DataEnviar,1 ; Rota para envia siguiente bit.-
decfsz ContBits,1 ; Comprueba si es el último bit.
goto EnviaBit ; No es el último bit repite la operación.
return ; Retornamos.-
;.................................................................................
end
-
Gracias, muchas gracias. Literalmente aplaudí al finalizar de leer las primeras aplicaciones con el PIC16F84A. Saludos desde Colombia. A propósito, sabes donde puedo encontrar información para iniciarme en las comunicaciones PIC-Ethernet? Gracias de nuevo.
-
En este mismo foro hay mucha información, mira aquí (http://www.google.com.ar/search?client=firefox-a&rls=org.mozilla%3Aes-AR%3Aofficial&channel=s&hl=es&q=site%3Awww.todopic.com.ar%2Fforos%2F+-printpage+-bookmark+Ethernet&meta=&btnG=Buscar+con+Google).
Saludos!
-
Otro ejemplo:
En este se fija la frecuencia de PWM en 2 kHz y se varía el ciclo de trabajo con 2 pulsadores de control conectados a RB0 y RB1. Solo se modifica en byte alto del CT, ósea el registro CCPR1L con lo que CT se varía de 4 en 4.
Hardware necesario:
(http://img9.imageshack.us/img9/2410/pwm2.png)
; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definicion de variables ****
Contador1 equ 0x20 ;
Contador2 equ 0x21 ;
decre equ 0 ; Pulsador para decrementar Ciclo de Trabajo
incre equ 1 ; Pulsador para incrementar Ciclo de Trabajo
;/////////////////////////////////
;**** Inicio del Micro ****
Reset.
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
; **** Programa Principal ****
org 0x05
Inicio
bsf STATUS,RP0 ; Banco 1
bsf TRISB,incre ; Como Entrada.-
bsf TRISB,decre ; Como Entrada.-
bcf TRISB,3 ; RB3 como Salida.
bcf STATUS,RP0 ; Banco 0.-
movlw b'00000110' ; Se selecciona TMR2, preescaler de 1/16.-
movwf T2CON
bsf STATUS,RP0 ; Banco 1
movlw 0x1E ; Señal de 2kHz
movwf PR2
bcf STATUS,RP0 ; Banco 0
clrf CCPR1L ; Ciclo de trabajo 0%
bcf CCP1CON,CCP1X
bcf CCP1CON,CCP1Y
bsf CCP1CON,CCP1M3 ; Configura modulo CCP modo PWM.-
bsf CCP1CON,CCP1M2
Bucle
btfsc PORTB,decre ; Testea si se quiere reducir CT.-
goto Decrementa
btfsc PORTB,incre ; Testea si se quiere aumentar CT.-
goto Incrementa
goto Bucle
Incrementa
incf CCPR1L,1
call Demora_50ms
goto Bucle
Decrementa
decf CCPR1L,1
call Demora_50ms
goto Bucle
;**** Demora ****
Demora_50ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0x40 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;..............................................
end
En este ejemplo ¿la frecuencia que estas utilizando es de 4Mhz, lo que es lo del oscilador interno.? Tengo una pregunta: ¿Puedes cambiar la frecuencia de oscilacion a 48khz? ¿Como puedo cambiar el duty cycle no de 4 en 4 si no de 1 en 1? ¿Tendras algun ejemplo para controlar el angulo de disparo del TRIAC o SCR? Gracias
-
Si exactamente, utilizo el oscilador interno. Para cambiarlo a 48kHz debes configurar el bit OSCF en el registro PCON(8Eh)
1 = Selección de 4MHz para el oscilador interno.
0 = Selección de 48kHz para el oscilador interno.
Con respecto a variar CT en 1 en 1 hay que trabajar con los bits CCP1X y CCP1Y. No me he dado el tiempo para hacer un ejemplo, pero cuando pueda lo are.
-
Se puede limitar el ciclo de trabajo de este ejemplo ya que cuando llega a 0% de Duty Cycle, le das otro decremento, se dispara a 1 logico. Es decir, darle un rango de maximo y minimos, decrementos e incrementos. Gracias :)
-
Claro que si, fíjate en este ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg213264#msg213264) como se hace un control de estos.
-
Suky con como podría programar un dimmer para que al momento de apretar el botón se prenda el foco y al momento de soltarlo el foco vaya disminuyendo su intensidad te lo agradecería tu ayuda.
-
Suky con como podría programar un dimmer para que al momento de apretar el botón se prenda el foco y al momento de soltarlo el foco vaya disminuyendo su intensidad te lo agradecería tu ayuda.
En este caso utilizaría PWM, dale una miradita al ultimo ejemplo del PIC16F628 y yo creo que se te va a ser muy fácil diseñar un código.
-
Oye discupla ese programa de interrupcion en TMR0 que tienes en primeros programas como lo adaptarias a un 16f628a, cuando lo simulo no me funciona podrias ayudarme
Para utilizar ese mismo código el el PIC16F628 solo hay que cambiar el encabezado y la posición de nuestras variables:
; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definicion de variables ****
Contador equ 0x20 ; Contador para detectar 4 desbordes de TMR0.-
W_Temp equ 0x21 ; Registro para guardar temporalmente W.-
STATUS_Temp equ 0x22 ; Registro para guardar temporalmente STATUS
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
Otra cosa que debes tener en cuenta cuando migras un código del PIC16F84 al PIC16F628 es la configuración de los comparadores analógicos, para utilizar los pines RA0-RA3 como I/O digitales debes colocar:
Mientras se este en el banco 0.
-
ah gracias
-
Hola.
Deseo saber si esta afirmacion que expusiste es correcta:
Reset.El PIC 16F84A posee un temporizador interno conectado al pin de reset, que funciona cuando se da alimentación al microcontrolador. Esto hace que al encender el sistema el microcontrolador quede en reset por un tiempo mientras se estabilizan todas las señales del circuito.
Gracias.
-
Fe de Erratas:
Dice:
Memoria de programa: 2048 locaciones de 14 bits
Debe decir:
Memoria de programa: 1024 locaciones de 14 bits
-
Hola.
Deseo saber si esta afirmacion que expusiste es correcta:
Reset.El PIC 16F84A posee un temporizador interno conectado al pin de reset, que funciona cuando se da alimentación al microcontrolador. Esto hace que al encender el sistema el microcontrolador quede en reset por un tiempo mientras se estabilizan todas las señales del circuito.
Gracias.
Es cuando se habilta el fuse Power-up Timer, este mantiene resteado el PIC durante un tiempo, y permite que se estabilice la tensión.
Fe de Erratas:
Dice:
Memoria de programa: 2048 locaciones de 14 bits
Debe decir:
Memoria de programa: 1024 locaciones de 14 bits
Error, El pic 16F628 es de 2048 words:
Mirando el Datasheet:
(http://img33.imageshack.us/img33/4910/caractes.jpg)
-
HOLA Suky SABES QUE COMPILE EL PROGRAMA
TUYO DEL EJEMPLO DE PWM CON EL MOTORCITO Y LO HICE EN PROTEUS (TENGO 7.5)
Y NO HACE NADA , ME PUEDES AYUDAR PARA SABER
QUE HAGO MAL
SALUDOS DE CHILE :-/ :-/ :-/ :D
-
Por favor no escribas en mayúscula, en un foro es elevar el tono :x
Después, he leído que la versión 7.5 tiene problemas para simular el PWM, puede ser eso.
Saludos!
-
disculpame suky porfavor por las mayusculasn ,
no lei las reglas del foro , no fue un improperio.
pero porque este proteus genera este problema.
osea que en el proto me deberia funcionar
saludos
-
disculpame suky porfavor por las mayusculasn ,
no lei las reglas del foro , no fue un improperio.
pero porque este proteus genera este problema.
osea que en el proto me deberia funcionar
saludos
No debería dar problemas, en vez de colocar un motor (el cual necesita driver de potencia) prueba colocando simplemente un led y prueba como varia su luminosidad.
Saludos!
-
hola!
muy buen tutorial para empezar....pero tuve un problema....
no me anduve el ejercicio del led tildando...nose que pasa....pero el led se queda prendido...no prende y apaga..
que problema puede ser....del programador o algo que puedo estar haciendo mal?
muchas gracias!
-
hola!
muy buen tutorial para empezar....pero tuve un problema....
no me anduve el ejercicio del led tildando...nose que pasa....pero el led se queda prendido...no prende y apaga..
que problema puede ser....del programador o algo que puedo estar haciendo mal?
muchas gracias!
Como estas realizando las pruebas? Si es un protoboard asegúrate que las conexiones estén bien fijas. Que el pin Mclr este a Vcc mediante una resistencia, que el oscilador este con sus capacitores lo más próximo al microcontrolador, etc.
Saludos!
-
COMUNICACIÓN IR - PIC16F628 Y PIC12F629
Hola amigos PICLISTEROS, voy a explicar como hacer la comunicación de dos PIC por medio de infrarrojo. En este ejemplo voy a codificar la señal con el pic12f629 y lo decodificaré con el pic16f628a, la codificación de pulsos que puse es muy facíl pero eficiente ya q no detecta otros controles IR. Al comprobar q el código es el correcto hacemos titilar un led 10veces.
INFORMACIÓN DE INTERNET:
http://heli.xbot.es/fd/ir.htm (http://heli.xbot.es/fd/ir.htm)
http://r-luis.xbot.es/sensores/ir.html (http://r-luis.xbot.es/sensores/ir.html)
HERRAMIENTAS QUE USE:
Soft-MPLAB IDE V8.X (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002#P140_5618)
MCE PDX USB -080609 (Programador y Debugger Express) (http://www.mcelectronics.com.ar/pdx/)
Soft- Pickit 2 Develooment (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023805)
EMISOR IR
Nombre de los componentes Importantes:
PIC12F629 (http://www.datasheetcatalog.org/datasheet/microchip/41190c.pdf)
Transitor BC337 (http://www.datasheetcatalog.org/datasheet/fairchild/BC337.pdf)
LED EMISOR L-53F3BT (http://www.datasheetcatalog.org/datasheets2/85/85702_1.pdf)
(http://beto123456789.webcindario.com/emisor.jpg)
INCLUDE <P12F629.INC>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT
cblock 0x20 ; programación moderna para designar registros
Contador1
Contador2
endc
org 0x00
goto INICIO
ORG 0x05
INICIO
BCF STATUS,RP0 ;Bank 0
CLRF GPIO ;Init GPIO
MOVLW 07h ;Ponemos como I/O digital
MOVWF CMCON
BSF STATUS,RP0 ;Bank 1
movlw b'00000010'
movwf TRISIO ; puertos gpx como salidas menos gp1 q es entrada
banksel GPIO ; programación moderna para posiscionar en un banco especifico
clrf Contador1 ; limpiamos
clrf Contador2 ; limpiamos
clrf GPIO ;limpiamos
BUCLE
nop;no hacemos nada
btfsc GPIO,1 ;si el boton esta presionado- enviamos la señal codificada
call Codigo
goto BUCLE
Codigo ; 1 1010
bsf GPIO,2; 1 de inicio
call Demora_30ms
bsf GPIO,2 ;1
call Demora_30ms
bcf GPIO,2 ;0
call Demora_30ms
bsf GPIO,2 ;1
Call Demora_30ms
bcf GPIO,2 ;0
Call suelta
return
suelta
btfss GPIO,1
return
goto suelta
;---------RUTINA DEL RETARDO DE TIEMPO----------
;...............................................
; *** Demora****
Demora_30ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0xC3 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;...............................................
end
RECEPTOR IR
Componentes Importantes
PIC16F628A (http://www.datasheetcatalog.org/datasheet/microchip/40044b.pdf)
LED RECEPTOR(Fototransistor) - L51P3C (http://www.datasheetcatalog.org/datasheets2/59/59198_1.pdf)
(http://beto123456789.webcindario.com/receptor.jpg)
INCLUDE <P16F628A.INC>
__CONFIG _CP_OFF & _WDT_ON & _LVP_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT
cblock 0x20
Contador1
Contador2
ESTADO
Loop
endc
org 0x00
goto INICIO
ORG 0x05
INICIO
bsf STATUS,RP0 ; Banco 1
Movlw b'00010000' ;
Movwf TRISB ; RB5 como entrada los demás como salida
banksel PORTB ;me posiciono en el banco del portb
clrf PORTB ; portb limpio
clrf Contador1 ; limpiamos
clrf Contador2 ; limpiamos
BUCLE
clrwdt ;limpio W
BCF ESTADO,1 ;pongo en 0 el bit1 del registro ESTADO
btfss PORTB,4;si recive un 0 llama a Vercodigo q es el conprueba
call VerCodigo
BTFSC ESTADO,1;Probamos si el código fue correcto si es así titilamos el led
call Alarma
goto BUCLE
;***************** LEER CODIGO ENVIADO POR EL TRANSMISOR *********************
;************* SI EL CODIGO ES CORRECTO ==> ESTADO,1 = 1 **********
;************* SI EL CODIGO ES INCORRECTO ==> ESTADO,1 = 0 **********
;Codigo 1 1010
VerCodigo
BCF ESTADO,1
CALL Demora_30ms
BTFSC PORTB,4 ;****** 0 ******
RETURN
CALL Demora_30ms
BTFSS PORTB,4 ;****** 1 ******
RETURN
CALL Demora_30ms
BTFSC PORTB,4 ;****** 0 ******
RETURN
CALL Demora_30ms
BTFSS PORTB,4 ;****** 1 ******
RETURN
CALL Demora_30ms
CALL Demora_30ms
BSF ESTADO,1 ; ESTADO,1 = 1
RETURN
Alarma
movlw 0x0A ; Hacemos titilar 10 veces el Led.-
movwf Loop
bsf PORTB,5
call Demora_150ms
bcf PORTB,5
call Demora_150ms
decfsz Loop
goto $-5
return
;.................................................
;---------RUTINA DEL RETARDO DE TIEMPO----------
;**** Demora 150MS ****
Demora_150ms
clrf Contador1 ; limpiamos
clrf Contador2 ; limpiamos
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0xC3 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;...............................................
; *** Demora****
Demora_30ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion3
movlw 0xC3 ;
movwf Contador2 ; Iniciamos contador2
Repeticion4
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion4 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion3 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;...............................................
end
end
(http://beto123456789.webcindario.com/IR.jpg)
(http://beto123456789.webcindario.com/IR2.jpg)
Salu2 BETO ROBLEDO SANCHEZ- Estudiante de la UTN - Facultad Regional Resistencia - I.Q
-
Bienvenido al foro beto1234!
(http://img222.imageshack.us/img222/3871/yb641.gif) Muy buen proyecto! Te animo que crees un nuevo tema en el subforo proyectos con PIC para presentarlo :wink:
Saludos!
-
Hola muchas gracias.. A ver si puedo presentar algún proyectivo con MATLAB y un PIC, ahora pronto no creo pero mas adelante seguro. Estoy metido con el matlab en el tema de procesamiento de imágenes y de audio. Estoy tratando de darle uso mas industrial a esto.. pero no tengo drama en presentarlo aqui. :D.
-
Una pregunta gente, me baje el ejemplo en proteus isis del led titilando, mi pregunta es si desde RB0/INT puedo poner mas de un led, o sea que en el proteus funciona perfecto agrego mas led y titilan todos, pero quizas halla problema en la practica, recien estoy empezando agradeceria su ayuda.
-
Pts, colocando una resistencia, un transistor (NPN) y los leds en paralelo en el colector con su respectiva resistencia debería funcionar.
-
Buenas tardes, tratando de compilar un programa muy sencillo en MPLAB me he encontrado con este problema:
Executing: "C:\Archivos de programa\Microchip\MPASM Suite\MPAsmWin.exe" /q /p16F84 "Carrito.asm" /l"Carrito.lst" /e"Carrito.err" /o"Carrito.o"
Warning[205] C:\DOCUMENTS AND SETTINGS\USUARIO\ESCRITORIO\CERCO KEROMUCHI\PROGRAMAS\CARRITO.ASM 1 : Found directive in column 1. (LIST)
Warning[205] C:\DOCUMENTS AND SETTINGS\USUARIO\ESCRITORIO\CERCO KEROMUCHI\PROGRAMAS\CARRITO.ASM 3 : Found directive in column 1. (include)
Skipping link step. The project contains no linker script.
BUILD FAILED: Mon Oct 19 13:38:33 2009
Lo cual no me permite simular el programa, es MPLAB 7.50.
Aca tambien envió el programa que descargue de un tutorial:
include "P16F84.INC"
__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC
Resultado EQU 0x10 ;Define la posición del resultado
org 0x00 ;Vector de Reset
goto Inicio
org 0x05 ;Salva el vector de interrupción
Inicio movlw 0x07 ;Carga 1er. sumando en W
addlw 0x06 ;Suma el 2º sumando
movwf Resultado ;Almacena el resultado
nop ;Poner breakpoint de parada
nop
END ;Fin del programa fuente
De antemano muchas gracias
-
hermanos ya consegui la respuesta disculpen mi ignorancia, me hacia falta agregarle un archivo de link correspondiente al modelo de pic a usar, caramba hace unos 10 años utilice MPLAB pero si mal no recuerdo no habia que agregar ese archivo de link, o estoy errado?
De antemano, muchas gracias nuevamente
-
No, no es necesario. En Project/Select Lenguaje Toolsuite selecciona MPASM Toolsuite y verifica que las "rutas" de los archivos estén correctamente.
Luego al hacer Build All si aparece una ventana preguntando absolute o reloacatable coloca absolute.
Saludos!
-
Nuevamente yo..... espero disculpen ahora superado el primer inconveniente surge otro al tratar de simular, me indica lo siguiente:
CORE-E0002: Stack under flow error occurred from instruction at 0x00000a
Agradeciendo nuevament su ayuda.
Saludos
-
Simular donde? En el mismo MPLab,Proteus u otro?
-
Hola suky , encontre un problema en tu programa de cambio de ciclo de trabajo:
en el bucle de testeo del puerto b 6 y 7 se esta preguntando si esta e BTFSC , pero en tu esquematico estos pines estan a masa
entonces deberia ser BTFSS o me equivoco
otra cosa el retardo no sera muy poco
porque lo estoy probando y todavia no me funciona
saludos desde chile
-
No, fíjate que al pulsar la tecla, el pin del PIC pasa a 1 (5V). Y en el test de estos pines se testea si es cero, salta a consultar por el otro, si este también es cero se salta al bucle nuevamente.
La demora es para que al mantenerlo presionado se note el cambio gradual, y capaz si sea demasiado poco :tongue: Pero si es el caso veras que pasa de 0% a 100% (Ciclo de trabajo) casi sin poder controlarlo.
Saludos!
-
Buenas a todos!!
suki quisiera saber si me podrias enseñar como recivir un caracter o una cadena de caracteres por rs 232 y luego poder tratarla, o sea hacer alguna comparacion, por ejemplo si recibio en el caracter nº 23 una "p" que aga tal cosa. Es pero haber sido lo mas claro posible, ya que enviar desde el pic al pc me sale muy bien pero no se como recibirlo y tratarlo.
Espero me puedas ayudar y si no todo bien igual.
Un saludo desde Mendoza Argentina para todos!
-
Hola kapotik!
Para recibir una cadena puedes usar el direccionamiento indirecto como para guardarlo en un rango de la memoria.
Para comparar datos podes hacerlo de la siguiente:
; Se recibe un carácter y se guarda en RData por ejemplo.
; Se quiere saber si es la 'a'
movlw 'a' ; Cargamos en W en ascii a
subwf RData,0 ; Restamos W-RData y lo guardamos en W.
btfsc STATUS,Z ; Consultamos si la operacion a resultado 0.
goto SiEsA ; Si es A.
goto NoEsA ; No es A...
Saludos!
-
Gracias suky por contestar tan rapídamente!!
disculpa mi ignorancia pero podrias mostrarme como recibir la cadena de caracteres. La comparacion si me quedo bien claro.
Saludos
-
wow amigo suky, que locura, hace tiempo que no toco el assembler, pero igual jamas he llegado a tocar varios temas en assembler, que bien amigo.
muchas gracias por tu esfuerzo, esto es mejor que un libro de assembler
-
USO DE LA LIBRERIA MATEMATICA + - / *
Bueno amigos voy a tratar de explicar como poder multiplicar, dividir, sumar y restar usando una librería matemática muy útil. Para crear esta librería, abrimos el bloc de notas de windows que se encuentra en el menú accesorios. Copiamos el código de la librería que mas abajo la dejo, y lo guardan con el nombre "Matematica" y la extensión "INC".
;****************************************************************************************************************************************
;****************************************************************************************************************************************
;*********************************LIBRERIA DE FUNCIONES MATEMATICAS + - * / *************************************************************
;****************************************************************************************************************************************
;****************************************************************************************************************************************
CBLOCK
NUM1H
NUM1L
NUM2H
NUM2L
RESU1H
RESU1L
ACCdHI
ACCdLO
tempMat
Flags
ENDC
;*******************************************************************************************************************************************
;*******************************************************************************************************************************************
;******************************************************************************************************************************************
; Double Prec*ision Subtraction ( NUM1 - NUM2 -> RESU1 )
;
Restar
movfw NUM1L
movwf RESU1L
movfw NUM1H
movwf RESU1H
movf NUM2L,W
movwf ACCdHI
movf NUM2H,W
movwf ACCdLO
comf ACCdHI,1
incf ACCdHI,1
btfsc STATUS,Z
decf ACCdLO,1
comf ACCdLO,1
movf ACCdHI,w
addwf RESU1L,1
btfsc STATUS,C
incf RESU1H,1
movf ACCdLO,w
addwf RESU1H,1
retlw 0
;******************************************************************************************************************************************
;*******************************************************************************************************************************************
;***********************Double Precision Addition ( NUM1 + NUM2 -> NUM1 )*******************************************************************
;*******************************************************************************************************************************************
Sumar bcf Flags,0 ;Clear temp Carry bit
movf NUM2L,0
addwf NUM1L,1 ;add lsb
btfsc STATUS,C ;add in carry
incf NUM1H,1
btfsc STATUS,C
bsf Flags,0
movf NUM2H,0
addwf NUM1H, 1 ;add msb
btfsc Flags,0
bsf STATUS,C
retlw 0
;*******************************************************************
; Double Precision Multiply ( 16x16 -> 32 )
; ( NUM1*NUM2 -> NUM1,RESU1) : 32 bit output with high word
; in ACCb ( NUM1H,NUM1L ) and low word in ACCc ( RESU1H,RESU1L ).
;*******************************************************************
Multiplicar ;results in ACCb(16 msb's) and ACCc(16 lsb's)
bcf STATUS,RP0 ;banco0
bcf STATUS,RP1
call setup
mloop rrf ACCdHI, 1 ;rotate d right
rrf ACCdLO, 1
btfsc STATUS,C ;need to add?
call Suma
rrf NUM1H, 1
rrf NUM1L, 1
rrf RESU1H, 1
rrf RESU1L, 1
decfsz tempMat, 1 ;loop until all bits checked
goto mloop
retlw 0
setup movlw .16 ; for 16 shifts
movwf tempMat
movf NUM1H,0 ;move ACCb to ACCd
movwf ACCdHI
movf NUM1L,0
movwf ACCdLO
clrf NUM1H
clrf NUM1L
retlw 0
;*******************************************************************
; Double Precision Divide ( 16/16 -> 16 )
;
; ( NUM1/NUM2 -> NUM1 with remainder in RESU1 ) : 16 bit output
; with Quotiont in NUM1 (NUM1H,NUM1L) and Remainder in RESU1 (RESU1H,RESU1L).
;
; NOTE : Before calling this routine, the user should make sure that
; the Numerator(NUM1) is greater than Denominator(NUM2). If
; the case is not true, the user should scale either Numerator
; or Denominator or both such that Numerator is greater than
; the Denominator.
;*******************************************************************
Dividir call setup
clrf RESU1H
clrf RESU1L
dloop bcf STATUS,C
rlf ACCdLO,1
rlf ACCdHI,1
rlf RESU1L,1
rlf RESU1H,1
movf NUM2H,0
subwf RESU1H,0 ;check if a>c
btfss STATUS,2
goto nochk
movf NUM2L,0
subwf RESU1L,0 ;if msb equal then check lsb
nochk btfss STATUS,0 ;carry set if c>a
goto nogo
movf NUM2L,0 ;c-a into c
subwf RESU1L,1
btfss STATUS,0
decf RESU1H,1
movf NUM2H,0
subwf RESU1H,1
bsf STATUS,0 ;shift a 1 into b (result)
nogo rlf NUM1L,1
rlf NUM1H,1
decfsz tempMat,1 ;loop untill all bits checked
goto dloop
retlw 0
MODO DE USO
Para probar solamente abran el MPLAB => File Registers , y van a ver los resultados en el registro TRISA ó TRISB así también como cada registro usado por la librería.
RESTA
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
cblock 0x20 ; registros de uso
ENDC
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio
bsf STATUS,RP0 ;banco1
bcf STATUS,RP1
clrf TRISA
clrf TRISB
CALC ; RESTA 1BYTE - 1BYTE = 1BYTE
;(NUM1H,NUM1L) - (NUM2H,NUM2L) = (RESU1H,RESU1L)
; 10 - 4 = 6
; El resultado lo paso al TrisA
movlw .10
MOVWF NUM1L
CLRF NUM1H
MOVLW .4
MOVWF NUM2L
CLRF NUM2H
CALL Restar
banksel TRISA
MOVF RESU1L,0
MOVWF TRISA
MOVF RESU1H,0
MOVWF TRISB
goto CALC
INCLUDE "C:\....\Matematica.INC"
end
SUMA
#include P16F877A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
cblock 0x20 ; registros de uso
ENDC
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio
bsf STATUS,RP0 ;banco1
bcf STATUS,RP1
clrf TRISA
clrf TRISB
CALC ; SUMA 1BYTE + 1BYTE = 1BYTE
;(NUM1H,NUM1L) + (NUM2H,NUM2L) = (NUM1H,NUM1L)
; 10 - 4 = 6
; El resultado lo paso al TrisA
movlw .10
MOVWF NUM1L
CLRF NUM1H
MOVLW .4
MOVWF NUM2L
CLRF NUM2H
CALL Sumar
banksel TRISA
MOVF NUM1L,0
MOVWF TRISA
MOVF NUM1H,0
MOVWF TRISB
goto CALC
INCLUDE "C:\...\Matematica.INC"
end
MULTIPLICACIÓN
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
cblock 0x20 ; registros de uso
ENDC
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio
bsf STATUS,RP0 ;banco1
bcf STATUS,RP1
clrf TRISA
clrf TRISB
CALC ; MULTIPLICA 1BYTE * 1BYTE = 1BYTE
;(NUM1H,NUM1L) * (NUM2H,NUM2L) = ( RESU1H,RESU1L )
; 2 * 4 = 8
; El resultado lo paso al TrisA
movlw .2
MOVWF NUM1L
CLRF NUM1H
MOVLW .4
MOVWF NUM2L
CLRF NUM2H
CALL Multiplicar
banksel TRISA
MOVF RESU1L,0
MOVWF TRISA
MOVF RESU1H,0
MOVWF TRISB
goto CALC
INCLUDE "C:\...\Matematica.INC"
end
DIVISIÓN
#include P16F877A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
cblock 0x20 ; registros de uso
ENDC
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio
bsf STATUS,RP0 ;banco1
bcf STATUS,RP1
clrf TRISA
clrf TRISB
CALC ; DIVIDE 1BYTE / 1BYTE = 1BYTE
;(NUM1H,NUM1L) / (NUM2H,NUM2L) = (NUM1H,NUM1L) , resto en ( RESU1H,RESU1L )
; 6 / 3 = 2
; El resultado lo paso al TrisA
movlw .6
MOVWF NUM1L
CLRF NUM1H
MOVLW .3
MOVWF NUM2L
CLRF NUM2H
CALL Dividir
banksel TRISA
MOVF NUM1L,0
MOVWF TRISA
MOVF NUM1H,0
MOVWF TRISB
goto CALC
INCLUDE "C:\...\Matematica.INC"
end
-
Excelente aporte Beto! :-/ Una librería muy útil :P
Saludos!
-
Hola Suky y gracias por este tutorial, esta muy bueno.
Yo recien estoy dando mis primeros pasos en este tema de los Pic y queria hacerte una pregunta, como ejemplo te digo que estoy probando con el pic 16f84 al cual conecte 2 leds, 1 en RB0 que enciende cada ves que oprimo el pulsador y el otro led en RB1 el cual quiero que prenda despues de haber oprimido el pulsador una determinada cantidad de veces,
No se si se entiende lo que digo: el led en RB0 enciende siempre que oprima el pulsador y el led en RB1 cuando el pulsador fue oprimido por ejemplo 5 veces.
Como hago para ir contando las veces que se oprimio el pulsador?
Desde ya muchas gracias por tu ayuda
-
Puedes utilizar una variable (Un registro de la RAM) para contar cuantas veces a sido pulsado, esperando que el botón se presione y suelte. Luego comparas este valor con un literal para saber si se ha pulsado N veces.
Saludos!
-
Otro ejemplo:
En este se fija la frecuencia de PWM en 2 kHz y se varía el ciclo de trabajo con 2 pulsadores de control conectados a RB0 y RB1. Solo se modifica en byte alto del CT, ósea el registro CCPR1L con lo que CT se varía de 4 en 4.
Hardware necesario:
(http://img9.imageshack.us/img9/2410/pwm2.png)
; **** Encabezado ****
list p=16f628A ; list directive to define processor
#include <p16f628A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON
;**** Definicion de variables ****
Contador1 equ 0x20 ;
Contador2 equ 0x21 ;
decre equ 0 ; Pulsador para decrementar Ciclo de Trabajo
incre equ 1 ; Pulsador para incrementar Ciclo de Trabajo
;/////////////////////////////////
;**** Inicio del Micro ****
Reset.
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
; **** Programa Principal ****
org 0x05
Inicio
bsf STATUS,RP0 ; Banco 1
bsf TRISB,incre ; Como Entrada.-
bsf TRISB,decre ; Como Entrada.-
bcf TRISB,3 ; RB3 como Salida.
bcf STATUS,RP0 ; Banco 0.-
movlw b'00000110' ; Se selecciona TMR2, preescaler de 1/16.-
movwf T2CON
bsf STATUS,RP0 ; Banco 1
movlw 0x1E ; Señal de 2kHz
movwf PR2
bcf STATUS,RP0 ; Banco 0
clrf CCPR1L ; Ciclo de trabajo 0%
bcf CCP1CON,CCP1X
bcf CCP1CON,CCP1Y
bsf CCP1CON,CCP1M3 ; Configura modulo CCP modo PWM.-
bsf CCP1CON,CCP1M2
Bucle
btfsc PORTB,decre ; Testea si se quiere reducir CT.-
goto Decrementa
btfsc PORTB,incre ; Testea si se quiere aumentar CT.-
goto Incrementa
goto Bucle
Incrementa
incf CCPR1L,1
call Demora_50ms
goto Bucle
Decrementa
decf CCPR1L,1
call Demora_50ms
goto Bucle
;**** Demora ****
Demora_50ms
movlw 0xFF ;
movwf Contador1 ; Iniciamos contador1.-
Repeticion1
movlw 0x40 ;
movwf Contador2 ; Iniciamos contador2
Repeticion2
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
decfsz Contador1,1 ; Decrementa Contador1.-
goto Repeticion1 ; Si no es cero repetimos ciclo.-
return ; Regresa de la subrutina.-
;..............................................
end
hola suky, gracias por todos tus aportes, me interesa este codigo pero lo usare para controlar la velocidad de un motor mediante puente h, etc. tengo entendido que la frecuencia del pwm deberia ser 20khz para que el motor no haga ruidos audibles por el humano, me podrias ayudar???
gracias.
-
Hola SUKY exelente tu aporte !! , me interesaria saber como se programa una eeprom ! , estoy empesando de 0 de nuevo jeje con esto de assembler ! y no encuentro info sobre el tema !
saludos !
-
jaja olvide de escribir la pregunta principal que queria hacer ! :oops: jeje queria preguntarte tambien si conoces mikropascal y si es asi !? que te parece para programar micros ?
gracias por tu tiempo y tu ayuda en otros momentos y espero que estes bien amigo !
saludos !
-
En el contador de 0 - 999 Quiero colocarle dos pulsadores uno INICIO/STOP y otro PAUSE. Como hago para colocar pulsador de INICIO/STOP yo le puse el pulsador para inicio y lo simule en elk proteus y funciono fino pero he tratado de que el mismo pulsador despues de haber iniciado el conteo automatico lo detenga y no he podido, el va a hacer que vuelva a cero y que haga falta volverlo a apretar para que inicie de nuevo.
Para inicio yo coloque btfss perguntado por el estado del pulsador para iniciar y luego volvi a pregunta btfss por el estado de pulsador para el stop, y que va, cuando lo simulo no funciona, a veces hasta se guina el conteo.
-
Comenzando con la creación de nuestro código:
A continuación vamos a desarrollar nuestro primer programa. Considero que se tiene conocimiento del lenguaje Assembler, si no es así se puede leer el tutorial ASM desde cero (http://www.todopic.com.ar/foros/index.php?topic=23623.0) de este mismo foro.
Este activará un led conectado a RB0 siempre que el interruptor conectado a RA0 este cerrado. Para ello vamos a necesitar el siguiente circuito:
(http://img217.imageshack.us/img217/282/hardcontrolledja0.bmp)
En RA0 tenemos conectado un pulsador de forma que cuando lo pulsemos se introduzca un cero lógico en el pin y cuando no lo pulsemos se introduzca un uno lógico. Tenemos un Led con su correspondiente resistencia limitadora de corriente en el pin RB0.
Diagrama de Flujo:
(http://img19.imageshack.us/img19/7125/controlledtz4.jpg)
Primero que nada debemos especificar con que microcontrolador estamos trabajando, esto lo realizamos es las dos primeras líneas:
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
En el archive P16F84A.inc se encuentran las definiciones de las direcciones de los registros específicos, los bits utilizados en cada registro y los fusibles del micro.
Configuración de fusibles. Hay ciertos aspectos del PIC que han de ser activados o desactivados mediante hardware a la hora de programarlo. Esto quiere decir que no se pueden volver a cambiar hasta que el chip no se reprograme de nuevo. El PIC16F84A dispone de 4 fuses (los modelos superiores tienen más). Cada fuse activa o desactiva una opción de funcionamiento.
OSC: Este fuse controla el modo de oscilación que usará el PIC para funcionar. Como ya sabemos, el oscilador se puede configurar de 4 maneras distintas, dependiendo de la velocidad y del tipo de circuito oscilador empleado.
WDT: El famoso "perro guardián" del PIC se configura aquí. Esta es una capacidad del microcontrolador de autorresetearse.
PWRT: Si activamos este fuse, lo que conseguimos es que se genere un retardo en la inicialización del microcontrolador.
CP: Activando este fuse tendremos la garantía de que el código que escribamos en el PIC no pueda ser leído por otra persona, para que no nos lo copien, modifiquen, etc. (Code Protection). Esto no impide que el PIC funcione como siempre, ni que no se pueda sobrescribir su contenido
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
Definición de variables que utilizaremos en nuestro proyecto. En este caso solo definiremos bits, por ejemplo Led y Pulsador.
Para organizar nuestro programa lo estructuraremos de la siguiente manera:
Nivel Directiva Operandos ; Comentarios
;**** Definicion de variables ****
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
Pulsador equ 0 ; Definimos Pulsador como el bit 0, en este caso sera para PORTA
Configuración de puertos.
Para la configuración necesitamos los siguientes registros:
STATUS > 0x03; PORTA > 0x05; PORTB > 0x06; TRISA > 0x86 y TRISB > 0x86.
Por defecto los puertos quedan configurados como entradas de datos y si se quiere cambiar hay que configurarlos. Esto se realiza con los registros TRISA y TRISB, teniendo en cuenta que si se asigna un cero (0) a un pin, quedara como salida y si se asigna un uno (1), quedara como entrada.
En nuestro caso se necesita colocar TRISA igual a 11111 (o se puede dejar por default) y TRISB 11111110. Ahora bien, cuando el PIC arranca se encuentra en el Banco 0, TRISA y TRISB se encuentran en el Banco 1, entonces debemos cambiar de Banco. Esto se realiza con el bit RP0 del registro STATUS. Si este se pone un cero a RP0, estaremos en el Banco 0. Si se coloca un uno, estaremos en el Banco 1.
Registro W: es el registro más importante que tiene el microcontrolador y es denominado ACUMULADOR.
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del código de programa.-
Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111' ; Muevo 11111 a W.-
movwf TRISA ; Cargo en TRISA.-
movlw b'11111110'
movwf TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
bcf PORTB,Led ; Comienza apagado.-
Ya configurado nuestro PIC, vamos a realizar la rutina que ejecutara.
;**** Control de Led ****
Bucle btfsc PORTA,Pulsador ; Preguntamos si esta en 0 logico.-
goto Apagar ; Esta a 1 logico, Apagamos Led.-
bsf PORTB,Led ; Esta a 0 logico, Encendemos Led.-
goto Bucle ; Testeamos nuevamente la condicion del Pulsador.-
Apagar bcf PORTB,Led ;Apagamos Led.-
goto Bucle ; Testeamos nuevamente la condicion del Pulsador.-
end
Aquí solamente en un bucle infinito testeamos continuamente el estado del pulsador, y según su estado se encenderá o apagará el Led.-
:-/
hola buenas , estoy intentando montar este primer circuito y quisiera saber si se puede sustituir el cristal por una red RC y cómo iría ésta colocada.
Saludos.
-
:shock: :shock:
Quiero llorar quiero llorar ... muchas gracias Suky ... con mas personas asi la electronica en sudamerica seria otra cosa :D
me lei de corrido todo hasta los lcd ... en cerca de 2 horas ... tu tuto es una pasta :-/ :-/ :-/
:afro: sos un grosso
-
Muchas gracias por los comentarios! ;-)
jhony85, se puede hacer lo que necesitas, primeramente debes indicarselo al microcontrolador configurando adecuadamente la palabra de configuración (FUSES).
Saludos!
-
Hola suky la verdad que no he podido realizar comunicación serial con pic 16f84a a 115200BPS, lo otro me puedes explicar por favor como recibir RX tramas fbus
Gracias
-
Hola suky la verdad que no he podido realizar comunicación serial con pic 16f84a a 115200BPS, lo otro me puedes explicar por favor como recibir RX tramas fbus
Gracias
Prueba con un microcontrolador que tenga módulo UART, sino muy dificil....
Saludos!
-
buena stardes, soy nuevo en el foro y estoy intentado segir paso a paso este tutorial, peor tengo varias dudas, la primera:
Como simplificas esta fórmula:
Tsub = 2 + 1 + 1 + (0xXX)*[1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 1 + 2] + [1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 2 + 2] ciclos
Lo cual se puede simplificar como sigue
Tsub = [0xXX*((0xYY - 1)*3 + 7) + 5] Tcy
segundo, en el mplab ide y el proteus usando el codigo para hacer titilar el led funciona:
#
Demora_150ms
#
movlw 0xFF ;
#
movwf Contador1 ; Iniciamos contador1.-
#
Repeticion1
#
movlw 0xC3 ;
#
movwf Contador2 ; Iniciamos contador2
#
Repeticion2
#
decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-
#
goto Repeticion2 ; Si no es 0 repetimos ciclo.-
#
decfsz Contador1,1 ; Decrementa Contador1.-
#
goto Repeticion1 ; Si no es cero repetimos ciclo.-
#
return ; Regresa de la subrutina.-
#
#
end
pero si deseo aumentar el tiempo por ejemplo a FF en ambos contadores, el proteus me dice lo siguiente al inicar la emulacion:
PiC16 Load: Program or eeprom data has a invalid adress (2000) hasta el 2003 for this device y luego el wathdog comienza el reseteo del micro cada poco mas de 0.5seg gracias por entenderme :)
-
buena stardes, soy nuevo en el foro y estoy intentado segir paso a paso este tutorial, peor tengo varias dudas, la primera:
Como simplificas esta fórmula:
Tsub = 2 + 1 + 1 + (0xXX)*[1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 1 + 2] + [1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 2 + 2] ciclos
Lo cual se puede simplificar como sigue
Tsub = [0xXX*((0xYY - 1)*3 + 7) + 5] Tcy
Hay que sumar los 1 y los 2. :mrgreen:
Para lo segundo, no debería de haber ningún problema con cambiar solamente el valor de los contadores, revisa con calma para deterninar si no cambiaste otra cosa. :?
Saludos!
-
buena stardes, soy nuevo en el foro y estoy intentado segir paso a paso este tutorial, peor tengo varias dudas, la primera:
Como simplificas esta fórmula:
Tsub = 2 + 1 + 1 + (0xXX)*[1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 1 + 2] + [1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 2 + 2] ciclos
Lo cual se puede simplificar como sigue
Tsub = [0xXX*((0xYY - 1)*3 + 7) + 5] Tcy
Hay que sumar los 1 y los 2. :mrgreen:
Para lo segundo, no debería de haber ningún problema con cambiar solamente el valor de los contadores, revisa con calma para deterninar si no cambiaste otra cosa. :?
Saludos!
Gracias por responder, pero igual sigo con dudas, al sumar los "1 y los 2" obtengo la siguiente fórmula:
4+(0xXX)*[(0xYY-1)*(3)+7]+[(0xYY-1)*(3)+8]
muy diferente ala que tu muestras
[0xXX*((0xYY - 1)*3 + 7) + 5] Tcy
y en cuanto a la rutina de retardo, no no modifico sino el segundo contador, ya que descargue las simlaciones que amablemente compartiste con nosotros y sigo con lo mismo asi cambie al siguiente numero hexadecimal me genera el mismo error, o si le resto a 0xC2 sigue con el problema :S
-
Es cierto :oops: Si simplificamos a esa ecuación, con simple matemática se llega a:
sub = [(0xXX+1)*((0xYY - 1)*3 + 7) + 5] Tcy
El problema es que falta un -1 en la original, debe ser:
Tsub = 2 + 1 + 1 + (0xXX-1)*[1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 1 + 2] + [1 + 1 + (0xYY - 1)*(1 + 2) + 2 + 2 + 2] ciclos
Y eso si da:
sub = [(0xXX)*((0xYY - 1)*3 + 7) + 5] Tcy
Que es lo correcto.
Lo otro, tiene que ser problema del simulador, no veo otro problema.
Saludos!
-
Todo funcionando bien :D
-
(http://img412.imageshack.us/img412/4624/0106.gif)
100.000 visitas! :-/ Este 16F84A sigue rompiendo records!!! Pero con ayuda del 16F628 :mrgreen: (http://img84.imageshack.us/img84/3881/bangef.gif) :D :D
-
suki:
Estoy siguiendo este tema atentamente pero me encuentro que al instalar el ConfigPic me dice que mehace falta el .NET Framework V 1.1.4322 y cuando accede a internet para descargarlo entra en una pàgina donde no está la version mencionada, he instalado versiones superiores de Net, pero el setup sigue con el mismo mensaje.
Alguna idea ?
Saludos
-
suki:
Estoy siguiendo este tema atentamente pero me encuentro que al instalar el ConfigPic me dice que mehace falta el .NET Framework V 1.1.4322 y cuando accede a internet para descargarlo entra en una pàgina donde no está la version mencionada, he instalado versiones superiores de Net, pero el setup sigue con el mismo mensaje.
Alguna idea ?
Saludos
Si ejecutas en .exe (dentro de la carpeta bin) ocurre lo mismo?
Intento compilarlo con VB.NET para probar.
Saludos!
-
Gracias por tu respuesta Suky:
Ejecutando el exe desde la carpeta bin funciona perfectamente.
Gracias de nuevo
-
Saludos Suky
Muchas gracias por tomarte el tiempo de hacer este post.
Quiero felicitarte por tu trabajo y agradecerte por el todo el esfuerzo que has hecho.
Había estado buscando tutoriales para aprender a programar pics y me topé con tu post.
Gracias por comentar tu trabajo tan detalladamente para que los novatos podamos entender el
mundo de los microcontroladores.
Sigue adelante.
Saludos desde México.
:-/
-
hola necesito ayuda en esto!! por favor!!
nesecito resolver esto pero nose como hacerlo sin usar ninguna funcion de division.. solo restas o sumas..
Elaborar un programa (fuente) en lenguaje ensamblador para el PIC16F84A que reciba información binaria de 5 bits en el puerto A y devuelva en un visor de siete segmentos la letra P indicando que el número recibido es primo, caso contrario el visor muestra la letra H indicando que no es primo.
bueno solo necesto la parte de :
Elaborar un programa (fuente) en lenguaje ensamblador para el PIC16F84A que reciba información binaria de 5 bits y determine si es binario o no... por favor!! necesito ayuda urgente!! :(
-
Hola.
Conozco poco del tema, en realidad soy ingeniero agrónomo, disculpen mi ignorancia en el tema.
Pero requiero información sobre el tema ya que estoy diseñando un experimento, con "cangilones" donde debo registrar pulsos en el tiempo, que deben ser guardados por un lapso de tiempo (datalogger), y cargados a la computadora.
Viendo este foro he aprendido algo. y me he enganchado con el tema.
Mi pregunta es: ¿cuando armo el circuito, cuales serian los pasos para configurar el PIC, de forma de generar y registrar los imputs de interes (Pulsos y tiempo entre pulsos)? Tambien quisiera saber como configurar el reset, y el ahorro de energia ya que solo registrara durante las lluvias.
Un millon de gracias. y disculpen mi ignorancia.
-
hola necesito ayuda en esto!! por favor!!
nesecito resolver esto pero nose como hacerlo sin usar ninguna funcion de division.. solo restas o sumas..
Elaborar un programa (fuente) en lenguaje ensamblador para el PIC16F84A que reciba información binaria de 5 bits en el puerto A y devuelva en un visor de siete segmentos la letra P indicando que el número recibido es primo, caso contrario el visor muestra la letra H indicando que no es primo.
bueno solo necesto la parte de :
Elaborar un programa (fuente) en lenguaje ensamblador para el PIC16F84A que reciba información binaria de 5 bits y determine si es binario o no... por favor!! necesito ayuda urgente!! :(
Pues mira si solamente son 5 bits como maximo llegaras al numero 32, como entre entre el 1 y el 32 no hay demasiados numeros primos (seran unos 10 numeros primos) puedes utilizar tablas para guardas los numeros primos comprendidos entre este rango, una vez que tengas tu dato binario de 5 bits simplemente lo comparas con tu tabla y verificas si es primo o no :-/ :-/, bueno esa la forma mas sencilla :D :D ahora si tu dato binario tiene mas de 5 bits eso ya es otra cosa y ahi si ya tienes que usar divisiones sucesivas para hallar si el numero es primo o no :P :P
-
Hola zuky, excelente material, sumamente didáctico, muchas gracias por compartirlo, queria preguntarte ¿Sabes programar en C, basic o algún otro software de alto nivel?
-
Hola! Muchas gracias por los comentarios. Si, se programar en C y algo de C++. En el foro hay un par de tutoriales y librerias, igualmente por aquí puedes encontrar casi todo lo compartido: www.micros-designs.com.ar
Saludos!
-
Saludos
Suky:
He estado haciendo el ejemplo para inicializar el LCD con el 16F84A siguiendo tu tutorial.
Al final del mismo escribiste que no lo pudiste simular en proteus.
Bueno, leyendo otros foros y el datasheet te comento que si pude
Despues de:
movlw LCD_BUS_4_2 ;Vamos a configurar el LCD 4 bits y 5x7 pixeles <D7 D6 D5 D4> = 0x28 con corrimiento
call LCD_COMANDO ;Enviamos el comando al LCD
Escribimos:
movlw LCD_ON ;Encendemos la pantalla
call LCD_COMANDO ;Enviamos el comando al LCD
donde LCD_ON tiene el valor 0x0C que es el comando para encender la pantalla.
Despues de encenderlo utilizo el comando para limpiar el LCD (0x01) y despues el comando para parpadear el cursor(0x0F) y todo perfecto
El LCD en proteus enciende y empieza a parpadear :)
Muchas gracias por tu tutorial
:-/ :-/ :-/
-
Hola a todos soy muy nuevito en esto de los micro controladores PIC hoy estoy trabajando con el 16F84A pero me surgió una duda tengo un código para encender un led con un pulsador y el temporizador lo mantiene encendido 5 seg y después apaga. El tema es que si el pulsador se mantiene presionado los 5 seg corren a partir de que este se suelta y lo que quiero es que el temporizador trabaje independiente sin importar el tiempo que se mantenga presionado el pulsador este es mi código.
MONITOR btfsc PORTA,Pulsador ; Revisa si es 0 si es asi salta una línea
goto Apagar ; Esta a 1 Apagamos Led
bsf PORTB,Led ; Manda un 1 al registro Led y enciende
goto DEMORA ; Salto a Demora
goto MONITOR ; Revisa nuevamente la condición del Pulsador
Apagar bcf PORTB,Led ; Manda un 0 al registro Led y lo apaga
goto MONITOR ; Revisa nuevamente la condición del Pulsador
Según yo la demora debería ser independiente al monitor del pulsador ya que está en una línea de código más abajo pero no me funciona y no doy con el error haber si me pueden ayudar
Gracias de antemano si me pudieran orientar me serviría mucho para entender mejor el funcionamiento de estos bichitos PIC`s
Adjunto el código completo tal vez el error este en otra parte.
-
En teoría si, al pulsar comienza la demora. Pero en hardware real tienes el problema del efecto rebote que puede generarte esos inconvenientes. Puedes esperar 20ms y testear nuevamente como para saber si realmente se ha pulsado o soltado el boton.
Saludos!
-
Saludos a todos,
disculpen una pregunta, pero tengo una duda con este pic16F628, ¿Puedo utlizar un módulo comparador y el módulo PWM al mismo tiempo?. :?
Es que este PIC es nuevo para mi :-/
De antemano gracias por su valiosa ayuda.
-
Hola! Si es el módulo comparador analógico y el módulo CCP en modo PWM, si sin ningún inconveniente. Ahora el módulo CCP en modo comparación y el módulo CCP en modo PWM, no. Éste PIC solo dispone de un módulo CCP, puede cambiar por un PIC16F883, ect.
Saludos!
-
Gracias, este foro es lo máximo.
Encuentro respuestas a casi todo!!
Y quiero mostrarles un dato que encontré en microchip, contiene las directivas _config para cada PIC y como guardar y restaurar registros tras una interrupción incluyendo el PCLATCH.
pero no puedo adjuntar el archivo. :x
Lo subí en otro servidor:
http://depositfiles.com/files/ssadfuyvr
-
hola mi pregunta es la siguiente como y que tengo que usar para empezar a programar pic desde el principio
-
hola mi pregunta es la siguiente como y que tengo que usar para empezar a programar pic desde el principio
Lee con detenimiento el primer mensaje.
Saludos!
-
hola mi pregunta es la siguiente como y que tengo que usar para empezar a programar pic desde el principio
Lee con detenimiento el primer mensaje.
Saludos!
vaya pues is que tienes razon me voy a poner con el tema gracias
-
hola perdonarmi ignorancia llevo casi 3 horas leiendo y ahora queria practicar un poco con el mplab pero ya de entrada me surje una duda cuando voy a empezar el codigo hay que poner lo siguiente
1. ; #### encabezado #### aqui es donda tengo la duda son asyeriscos lo que hay que poner ?
2.
salu2
-
Deberias de empezar asi:
1.; **** Encabezado **** esta es una linea de comentarios. Tdo lo que esta despuesdel ";" el compilador lo trata asi y no genera codigo. Te sirve como ayuda para saber que programas es. Ejemplo: Encabezado puede ser "Mi primer programa
2.list p=16F84A ; Se indica el tipo de micro que vas a utilizar
3.#include P16F84A.inc; Se incluyen los registros de micro utilizado ya predefinidos
4.__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC; Sirve para configurar los fuses del micro como: si vas aproteger la meoria para que no se pueda leer, activar o no el watchdog, el tipo de oscilador,....
A partir va tu programa
F.
-
Deberias de empezar asi:
1.; **** Encabezado **** esta es una linea de comentarios. Tdo lo que esta despuesdel ";" el compilador lo trata asi y no genera codigo. Te sirve como ayuda para saber que programas es. Ejemplo: Encabezado puede ser "Mi primer programa
2.list p=16F84A ; Se indica el tipo de micro que vas a utilizar
3.#include P16F84A.inc; Se incluyen los registros de micro utilizado ya predefinidos
4.__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC; Sirve para configurar los fuses del micro como: si vas aproteger la meoria para que no se pueda leer, activar o no el watchdog, el tipo de oscilador,....
A partir va tu programa
F.
ok gracias seguire particando y leiendo
-
En el primer post tienes un indice de un monton de ejemplos donde puedes ver la estructura de como realizar los programas.
Mirate unos cuantos ejemplos simples y veras que no es complicado
F.
-
Hola
En los primeros posts estan los ejemplos de la interrupciones, hay uos pasos que no ser el porque.
En el momento de guradr los valores de W y STATUS se realizan una serie de cambios de nibbles, que no ser ver el porque, pudiendo salvar directamente el valor de cada registro.
Gracias
-
Es para no modificar el estado del registro STATUS.
Saludos!
-
Amigo Suky lo que me gustaría para agregar a este gran tutorial seria como manejar las memorias del pic, por ejemplo para almacenar información.
-
Amigo Suky lo que me gustaría para agregar a este gran tutorial seria como manejar las memorias del pic, por ejemplo para almacenar información.
Agregue, no hay ningun problema!
Saludos
-
Holaaaa....disculpen he hecho el primer proyecto que esta en el tema...no tuve problema en comprender la logica del ASM, por lo que fue facil pasarlo al simulador, pero a la hora de compilar me marca 3 errores
list p=16F84A
#include p16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
esto menciona en la parte inferior
0004 Error: Unrecognized instruction
quiza tenga que ver donde instale el programa que fue la opcion que esta por default
Podrian ayudarme??? es el segundo que trato de hacer ....comienzo a frustrarme jeje muchas gracias
-
:-/ :-/
Muchas gracias xD
Fontaneros (http://www.repara-madrid.es/fontaneria.html)
Piscinas (http://www.aqualudens.com)
-
buenas noches suky tu tutorial es muy bueno, me gustaria preguntarte algo sobre el PIC16F628A hize la programacion de 4 semaforos de tres colores cada uno como un semaforo ordinario, y una pregunta este fusil _INTOSC_OSC_NOCLKOUT significa que el oscilador interno de 4Mhz que posee el microcontrolador ha sido activado y funcionara con el, asi como el tmr0 si es configurado como temporizador funcionara con el, por lo que a su vez los pines 15 y 16 de 16F628A pueden ser usados como salida digital para prender algun led? me gustaria su respuesta.
-
buenas noches suky tu tutorial es muy bueno, me gustaria preguntarte algo sobre el PIC16F628A hize la programacion de 4 semaforos de tres colores cada uno como un semaforo ordinario, y una pregunta este fusil _INTOSC_OSC_NOCLKOUT significa que el oscilador interno de 4Mhz que posee el microcontrolador ha sido activado y funcionara con el, asi como el tmr0 si es configurado como temporizador funcionara con el, por lo que a su vez los pines 15 y 16 de 16F628A pueden ser usados como salida digital para prender algun led? me gustaria su respuesta.
Exactamente ;-)
-
El Módulo del Timer 0.
Idéntico al del PIC16F84.
El Módulo del Timer 1.
El Timer 1 a diferencia del Timer 0 es un contador / temporizador de 16 bits. El conteo es realizado por dos registros de 8 bits: (TMR1H (0Fh) y TMR1L (0Eh) ), estos dos registros son tanto leíbles como escribibles.
Así, el registro TMR1 se incrementa de 0000h a FFFFh y en la siguiente cuenta se reinicia en 0000h y así sucesivamente, al reciclarse se activa (en alto) la bandera TMR1IF (PIR1<0>), la cual puede ser utilizada para generar una interrupción, o bien, para ser consultada por poleo, teniendo las mismas precauciones que ya se explicaron antes para la bandera T0IF.
En la siguiente figura se muestra un diagrama de bloques de este módulo, en donde se indican los bits que afectan su operación y la manera en que lo hacen.
(http://img8.imageshack.us/img8/9830/timer10.jpg)
Modo temporizador
En este modo el Timer se incrementa (si no se considera preescalador) en cada ciclo de instrucción (a la frecuencia Fosc/4). Este modo se selecciona limpiando el bit TMR1CS (T1CON<1>).
El preescalador que se puede intercalar entre el reloj Fosc/4 y el registro TMR1 puede tener sólo uno de 4 valores: 1/1, 1/2, 1/4 y 1/8.
En este caso la temporización de calcula:
Temporización = Ciclo de instrucción. (65536-TMR1) .Divisor de Frecuencia
Vemos que la máxima temporización posible es con TMR1 = 0, y Divisor de Frecuencia en 8, lográndose unos 524.3 ms aprox.
Modo contador
El Timer 1 también puede operar como contador, en este último caso, la entrada a contar se toma de la patita externa RB6/T1OSO/T1CKI.
Configuraciones:
El Timer 1 posee un bit para habilitación / deshabilitación, este es el bit TMR1ON (T1CON<0>) y habilita en alto.
Además, el Timer 1 posee una entrada interna de RESET, el cual puede ser activado por uno cualquiera de los módulos CCP que.
A continuación se describe el principal registro relacionado con el Timer 1 y todos sus bits, excepto los que tienen que ver con el modo contador:
Registro T1CON (10h)
(http://img9.imageshack.us/img9/1343/timer11.jpg)
bits 5:4
T1CKPS1:T1CKPS0.- Bits de selección del valor del divisor de frecuencia del preescalador:
1 1 = divisor 1/8
1 0 = divisor 1/4
0 1 = divisor 1/2
0 0 = divisor 1/1
bit 1
TMR1CS.- Bit de selección de la fuente de reloj
1 = Modo contador (fuente de reloj: patita RC0/T1OSO/T1CKI)
0 = Modo Temporizador (fuente de reloj Fosc/4)
bit 0
TMR1ON.- Bit de habilitación / deshabilitación del Timer 1:
1 = habilita Timer 1
0 = Deshabilita Timer 1
ConfigPIC traé una herramienta adicional que nos ayuda a seleccionar el preescaler y valor inicial del Timer para obtener una temporización deseada:
(http://img139.imageshack.us/img139/8141/21115051.th.jpg) (http://img139.imageshack.us/my.php?image=21115051.jpg)
hola amigo soy nuevo en programacion de pic, necesito que me den una mano tengo un proyecto que necesito bases de tiempo de 1 seg, 5seg, 1 min, agradeceria ayuda hasta pronto y gracias
-
ACABO DE INGRESAR A ESTE SISTEMA Y MANDO SALUDOS DESDE LA CIUDAD DE MEXICO, ESPERANDO SER PARTE DE SU CLUB DE LECTORES
-
Suky ,
Primero que nada felicitarte por este tutorial!
Estoy comenzando nuevamente en esto de la programacion de PIC16f84 ,mas o menos por el 2001 termine de armar un robot (monty) ,aunque algo llegue hacer luego por distintos motivos largue todo.
Hace algunos meses cansado de verlo ahi en un estante sin hacer nada (jaja) me propuse ver si por fin le encontraba la vuelta a la programacion.
Conclusion hace unas horas este post me hizo a agarrar ganas de registrarme ,oh sorpresa ya me habia registrado hace bastante! ,recupere mi contraseña y usuario y aca estoy!
Queria probar el programa para el LCD en el P16f84 (copie el programa y lo pegue en el Mplab) ,luego al compilarlo me di cuenta despues de un buen rato de buscar que en la linea 51 hay un error de tipeo ,falta una L para la palabra LCD.
Corregido esto pude compilarlo.
Ahora me pongo a armar el circuito para probarlo.
Otra vez ,felicitaciones!
Saludos
-
Gracias por el dato! Éxitos en los proyectos!!
Saludos!
-
Mis primeros programas en ASM. PIC16F84A y PIC16F628A/648A
La idea de este tutorial es ayudar a los que recién están empezando, aquí mostraremos como comenzar. Usaremos en primer lugar el microcontrolador PIC16F84A, porque es el que por lo general se usa en la enseñanza. Comenzaremos explicando como esta constituido, los terminales, manejo de corrientes de los puertos, osciladores externos, circuito de reset, memoria de programa y memoria de datos. Luego iremos a lo interesante, que es la programación, nuestros primeros programitas, de los cuales se tratará de explicarlos detalladamente, el funcionamiento y los registros que se usan en cada caso.-
INDICE
El PIC16F84A
- Introducción (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201393#msg201393)
- Mi Primer Programa, control de un led (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201396#msg201396)
- Creación de Demoras, Led titilando (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201398#msg201398)
- Creación de Tablas, Control Display 7 Segmentos (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201401#msg201401)
- Direccionamiento Indirecto, Control Display 7 Segmentos (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201402#msg201402)
- Control de varios Displays 7 Segmentos con multiplexión (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201403#msg201403)
- Control de varios Displays 7 Segmentos con 74LS164 (http://www.todopic.com.ar/foros/index.php?topic=24720.msg213264#msg213264)
- Interrupciones, Registros y guardado temporario de STATUS y W (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201405#msg201405)
- Interrupción TMR0, modo Temporizador (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201407#msg201407)
- Interrupción TMR0, modo Contador (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201408#msg201408)
- Interrupción RB0, Control de Led (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201409#msg201409)
- Interrupción RB4 a RB7, Control Teclado Matricial (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201410#msg201410)
- Control del LCD, Pantalla de Cristal Liquido (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201411#msg201411)
- Comunicación RS232 (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201413#msg201413)
Todas las simulaciones hechas en proteus, aqui (http://www.mediafire.com/?rxcjmjvl1jm) (Para el PIC16F84A)
El PIC16F628A/648A
- Introducción (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204908#msg204908)
- Timer1 + Ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204910#msg204910)
- Timer2 + Ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204912#msg204912)
- Módulo de comunicación serie (Usart) + Ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204913#msg204913)
- Comparadores analógicos + Ejemplo (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204915#msg204915)
- Módulo CCP. Introducción (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204920#msg204920)
- Modo Captura + Ejemplo: Medir Frecuencia (http://www.todopic.com.ar/foros/index.php?topic=24720.msg204920#msg204920)
- Modo Comparación + Ejemplo: Señal de frecuencia variable (http://www.todopic.com.ar/foros/index.php?topic=24720.msg207734#msg207734)
- Modo PWM + Ejemplo: Señal de 2 Frecuencias distintas (http://www.todopic.com.ar/foros/index.php?topic=24720.msg207737#msg207737)
- 2º Ejemplo PWM. Variando el Ciclo de Trabajo.- (http://www.todopic.com.ar/foros/index.php?topic=24720.msg207739#msg207739)
- Más Información (http://www.todopic.com.ar/foros/index.php?topic=24720.msg207741#msg207741)
- COMUNICACIÓN IR - PIC16F628 Y PIC12F629 (http://www.todopic.com.ar/foros/index.php?topic=24720.msg224696#msg224696) realizado por beto1234 (http://www.todopic.com.ar/foros/index.php?action=profile;u=21383)
Herramientas
Software para escribir nuestro código y compilar: MPLAB (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002)
Software para simular: Proteus (http://www.labcenter.co.uk/download/prodemo_download.cfm)
Una plaquita programadora.
Software para grabar nuestro PIC, se puede usar el WinPic800 (http://www.winpic800.com) o el Icprog (http://www.ic-prog.com/download.html)
:-) Aquí dejo un tutorial de como crear un proyecto en MPLAB, compilar y simular. Un programador de PIC sencillo que pueden armar (Programador JDM – Serial)(circuito, PCB para hacer la plaqueta y una pequeña explicación de cómo grabar con WinPIC800) y un tutorial para crear placas de circuito impreso (PCB) por el método de la plancha ---> Tutoriales (http://www.mediafire.com/file/ak3zio5hl2e/Para Comenzar.rar)
Datasheets
DATASHEET del PIC16F84A (http://ww1.microchip.com/downloads/en/devicedoc/35007b.pdf)
DATASHEET del PIC16F628A/648A (http://host.nigde.edu.tr/muzam/PIC16F648A.pdf)
ConfigPIC (http://www.mediafire.com/file/z2o1jym5zzm/ConfigPIC.rar): Software para realizar el código automáticamente a partir de una interfase de configuración.
(http://img135.imageshack.us/img135/3100/54953366.th.jpg) (http://img135.imageshack.us/my.php?image=54953366.jpg)
-
Hola necesito un poco de ayuda estoy tratando de aprender mediante este tutorial, pero quiero realizar los mismos programas para ql pic12f683 pero no puedo realizar nisiquiera el primeroel de encender un led con un pushbutton si me pueden ayudar se los agradeceria asi es como tengo el codigo:
list p=12F683
#include <p12f683.inc>
__CONFIG _FCMEN_OFF & _IESO_OFF & _MCLRE_OFF & _WDT_OFF & _INTOSCIO
org 0x00
BSF STATUS,RP0 ;PASANDO DE BANCO 0 A BANCO 1
MOVLW b'001010' ;CARGANDO EN W
MOVWF TRISIO ;CONFIGURAR TRISIO COMO W
BCF STATUS,RP0 ;PASANDO DEL BANCO 1 A BANCO 0
MOVLW b'000000' ;GPIO APAGADO
MOVWF GPIO
AQUI:
BTFSC GPIO, 1
GOTO APAGAR
MOVLW b'000001'
MOVWF GPIO
GOTO AQUI
APAGAR:
MOVLW b'000000'
MOVWF GPIO
GOTO AQUI
END
espero y me puedan ayudar gracias de ante mano
estos son los bancos de memoria
(https://www.box.com/s/25no04zuz5pl59nk8kwv)
-
Un saludo Suky:Estoy intentado hacer un receptor para un control remoto de tv,pruebo con el modulo CCP modo captura saco la lectura por el puerto A para visualizar los valores emitidos por cada tecla y no se quedan estables los valores.Quizas este errado con este modulo para esta aplicacion.Att jose
-
Hola que tal, necesito su ayuda si no es mucha molestia, debo hacer un asm en mplab que controle un motor hacia la izquierda, derecja, paro osea 3 pushbuttons con el pic16f84a. Y usando el l293d para inverdir el voltaje del motor, el motor es dc. el problema que tengo es que mi programa no me corre y ya he usado varios programas pero sigo sin obtener ese resultado y pues como apenas estoy iniciando en esto me cuesta un poco de trabajo entenderle.
-
Un saludo:lo puedes hacer con un l298,es uh puente H y segun los pines que utilices puedes hacerlo girar izd o der
-
Como dicen que es de bien nacido ser Agradecido. Muchas gracias por los tutoriales Suky ((:-))
Un Saludo :-/
-
Hola chicos.
Estoy siguiendo este tutorial en el poco tiempo que tengo, pero al empezar con los codigo, al cargarlo en Mplab, me indica un solo error y no se como solucionarlo.
Ante todo, felicitar a Suky por este fantástico tutorial y a continuación os indico el código que es el primero de Suky y el error;
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
Pulsador equ 0 ; Definimos Pulsador como el bit 0, en este caso sera para PORTA
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111' ; Muevo 11111 a W.-
movwf TRISA ; Cargo en TRISA.-
movlw b'11111110'
movwf TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
bcf PORTB,Led ; Comienza apagado.-
;**** Control de Led ****
Bucle btfsc PORTA,Pulsador ; Preguntamos si esta en 0 logico.-
goto Apagar ; Esta a 1 logico, Apagamos Led.-
bsf PORTB,Led ; Esta a 0 logico, Encendemos Led.-
goto Bucle ; Testeamos nuevamente la condicion del Pulsador.-
Apagar bcf PORTB,Led ;Apagamos Led.-
goto Bucle ;Testeamos nuevamente la condicion del Pulsador.-
end
Y esta es la respuesta de Mplab
Building LED.HEX...
Compiling LED.ASM:
Command line: "C:\ARCHIV~1\MPLAB\MPASMWIN.EXE /aINHX8M /e+ /l+ /x- /c+ /rhex /p16F84A /q F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM"
Message[301] C:\ARCHIV~1\MPLAB\P16F84.INC 37 : MESSAGE: (Processor-header file mismatch. Verify selected processor.)
Warning[205] F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM 5 : Found directive in column 1. (__CONFIG)
Error[113] F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM 12 : Symbol not previously defined (inicio)
Message[302] F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM 16 : Register in operand not in bank 0. Ensure that bank bits are correct.
Message[302] F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM 18 : Register in operand not in bank 0. Ensure that bank bits are correct.
MPLAB is unable to find output file "LED.HEX". This may be due to a compile, assemble, or link process failure.
Build failed.
¿Me podríais decir que estoy haciendo mal?
Muchas gracias de antemano.
-
Hola chicos.
Estoy siguiendo este tutorial en el poco tiempo que tengo, pero al empezar con los codigo, al cargarlo en Mplab, me indica un solo error y no se como solucionarlo.
Ante todo, felicitar a Suky por este fantástico tutorial y a continuación os indico el código que es el primero de Suky y el error;
; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
Led equ 0 ; Definimos Led como el bit cero de un registro, en este caso PORTB.-
Pulsador equ 0 ; Definimos Pulsador como el bit 0, en este caso sera para PORTA
;**** Configuracion de puertos ***
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-
movlw b'11111' ; Muevo 11111 a W.-
movwf TRISA ; Cargo en TRISA.-
movlw b'11111110'
movwf TRISB
bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0
bcf PORTB,Led ; Comienza apagado.-
;**** Control de Led ****
Bucle btfsc PORTA,Pulsador ; Preguntamos si esta en 0 logico.-
goto Apagar ; Esta a 1 logico, Apagamos Led.-
bsf PORTB,Led ; Esta a 0 logico, Encendemos Led.-
goto Bucle ; Testeamos nuevamente la condicion del Pulsador.-
Apagar bcf PORTB,Led ;Apagamos Led.-
goto Bucle ;Testeamos nuevamente la condicion del Pulsador.-
end
Y esta es la respuesta de Mplab
Building LED.HEX...
Compiling LED.ASM:
Command line: "C:\ARCHIV~1\MPLAB\MPASMWIN.EXE /aINHX8M /e+ /l+ /x- /c+ /rhex /p16F84A /q F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM"
Message[301] C:\ARCHIV~1\MPLAB\P16F84.INC 37 : MESSAGE: (Processor-header file mismatch. Verify selected processor.)
Warning[205] F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM 5 : Found directive in column 1. (__CONFIG)
Error[113] F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM 12 : Symbol not previously defined (inicio)
Message[302] F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM 16 : Register in operand not in bank 0. Ensure that bank bits are correct.
Message[302] F:\ELECTR~1\MICROC~1\PROJEC~1\LED.ASM 18 : Register in operand not in bank 0. Ensure that bank bits are correct.
MPLAB is unable to find output file "LED.HEX". This may be due to a compile, assemble, or link process failure.
Build failed.
¿Me podríais decir que estoy haciendo mal?
Muchas gracias de antemano.
Hola de nuevo.
Ya resolví el problema y era el siguiente: En la fila diez, (goto inicio, inicio) lo escribo en minúsculas y en la fila 12, (Inicio bsf STATUS,RP0), lo pongo en mayúsculas por lo que no era reconocido por el programa.
Así y todo, muchas gracias.
-
Hola buenas tardes, antes que nada me gustaría decir que el post es muy interesante y me ha enseñado bastantes cosas. Feilicito al autor del post por tratar de ayudar a los que apenas estamos empezando. Dicho esto, me gustaría ver si alguien me alcara una pequeña duda que tengo, verán, decidiendo ir un poco más allá en el programa del contador se me ocurrió que además de que cuente de forma ascendente también lo haga de forma descendente, en un principio no creí que fuera tan difícil y en realidad hacer el conteo regresivo no es el problema.
El programa tiene dos botones, uno que suma y otro que resta una unidad a la variable Contador, después se suma el valor a PCL y retrona el valor del número a mostrar con un RETLW, vamos que es el mismo que está en el post. El problema que tengo es que no logro conseguir que al presionar el botón "restar" cuando contador es 0 se resté 1 y se convierta en 0xFF y el programa deja de funcionar (al menos en proteus). He buscado por la red ejemplos para poder ver en que me equivoco y no he encontrado nada, por eso vengo aquí a ver si alguien me puede ayudar.
Este es el pedazo de código que se encarga de restar una unidad a contador:
[center].[/center]
[center].[/center]
[center].[/center]
INICIO ;Aquí inicia el programa principal
BTFSC PORTC,BOTONME; Como utilizo resistencia pull-up el micro recibe 1s y cuando se presiona boton hay un 0
GOTO MAS ; Si un 1 (no se presiona boton) entonces voy a la "función" MAS
CALL DEMORA_19MS ;retardo anti rebote
BTFSC PORTC,BOTONME
GOTO INICIO
GOTO ESCERO ; Aquí intento saber si en la variable contador hay un cero
MAS
BTFSC PORTC,BOTONMA
GOTO INICIO
CALL DEMORA_19MS
BTFSC PORTC,BOTONMA
GOTO INICIO
GOTO SUMAR
ESCERO
MOVLW CONTADOR ; Aquí cargo contador en W (Ej. 1)
IORWF 0x00,0 ; Aquí hago un OR entre Wy F para saber si hay un 0 en el resultado y que active el BIT Z (en proteus nunca se activa el bit Z, también intenté DECF y nunca me marcó el BIT Z)
BTFSC STATUS,Z ; Si hay un 0 en el bit Z significa que no hay un cero, por lo que puedo restar normalmente; si hay un 1 significa que estoy en 0 y si resto me voy a -1
GOTO INICIO
RESTAR
DECF CONTADOR,1 ;Resto una unidad al contador
MOVF CONTADOR,0 ; La muevo a F
CALL BCD ;LLamo BCD para mostrar numero
MOVWF PORTB
[center].[/center]
[center].[/center]
[center].[/center]
No pongo todo el código porque es el mismo que el publicado así que solo pongo lo que agregué. Un saludo y si me equivoqué en algo tan simple, lo siento pero apenas aprendo xD.
Un saludo!
-
Bienvenido al foro Purevideo.
Deberias abrir un hilo nuevo con tu consulta en vez de seguir aqui.
El problema que tengo es que no logro conseguir que al presionar el botón "restar" cuando contador es 0 se resté 1 y se convierta en 0xFF y el programa deja de funcionar (al menos en proteus).
Seguramente al restar 1 y darte como resultado 0XFF al ir a las tablas se te desbordan y se pierde el programa. Debes de poner como condicion que si es 0 NO reste, pasara a un numero inferior el que este a su izquierda y ese 0 pasara a ser 9.
-
Reset org 0x00 ; Aqui comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
org 0x05 ; Origen del codigo de programa.-
Inicio
Hola Suky.
Cual es la funcionalidad de "org 0x05" si siempre va a estar saltando hasta "goto Inicio ". Veo que nunca va a tener una secuencia que incluya a "org 0x05" (Del ejemplo 1 de este tutorial).
-
Bueno no es necesario suky para responderlo, esta para evitar que si por error se ejecuta una interrupcion, no produsca un comportamiento raro al no tener alguna instruccion.
Suponete
ORG 0x00
GOTO Inicio ;0x00
Inicio
MOVLW 0x0F ; 0x01
MOVWF PORTB ; 0x02
MOVLW 0x10 ; 0x03
MOVWF PORTA ; 0x04
; Resto del programa.
Entonces si por equivocacion del usuario activa la interrupcion, la primer instruccion que va a ejecutar es "MOVWF PORTA" y realmente no tenes idea de lo que hay en W en ese momento.
Por eso mismo yo siempre defino los vectores de interrupcion, por mas que no lo utilize, quedando:
ORG 0x00
GOTO Inicio
ORG 0x04
GOTO Inicio
; Aca Todo mi programa
Y me aseguro que nada incorrecto pueda pasar. Es una costumbre, y no afecta a nadie.
-
Estimados amigos de todopic. Es primera vez que ingreso, he leido bastante en este foro y por lo cuál agradezco el que compartan con los que somos iniciantes en este maravilloso mundo de los PIC. Muchas Gracias.
Permítanme preguntar algo básico, por favor.
Estoy estudiando recien las interrupciones del 16f84, y he creado un rutina pequeña para probar dos de las 4 interrupciones de este PIC. Hay un fenómeno que no he podido dilucidar. Estoy probando la Interrupción RBIE (por activación de RB7:RB4) y cuando se debe, el programa no borra el flag INTCON,0 por programa (bcf intcon,0) cuando lo simulo no hace nada. Luego al pasar por RETFIE, tampoco pone a 1 GIE (intcon,7). He usado MPLAB v7.2 y 7.4 y pasa lo mismo.
He usado la misma rutina para probar la Interr. INTE y funciona ok. ¿¿¿???
Adjunto mi humilde código, a ver si alguien me da una mano. Muchas Gracias
;Prueba dos tipos de interrupciones: cambio en RB7:RB4 ; int.externa RB0/INT
;Se ha puesto un led en A0 para verificar la interr. por in en RB7:RB4 y
;se ha puesto un led en A1 para verificar la interr. por in en RB0/INT
list p=16f84a
#INCLUDE P16F84A.INC
radix hex
radix dec
;line8
porta equ 0x05
portb equ 0x06
trisa equ 0x85
trisb equ 0x86
status equ 0x03
optio equ 0x81
intcon equ 0x0b
tmr0 equ 0x01
saveW equ 0x0c
saveSTATUS equ 0x0d
#DEFINE banco0 bcf status,5
#DEFINE banco1 bsf status,5
;---------------------------------------------------------------------
org 0x000
goto ini
org 0x04 ; Vector de interrupcion
goto inter
; Inicio de programa
; -------------------- Definiciones --------------------------------
ini
banco1 ; banco1
movlw b'11111111' ; Puerta b entradas
movwf trisb
movlw b'00000000' ; Puerta a salidas
movwf trisa
movlw b'01000000'
movwf optio
movlw b'10001000' ; intcon: GIE=1, y RBIE=1 solo interr. gral y la interr. por puertas RB7:RB4
movwf intcon
banco0 ; banco0
; clrf porta
;Programa Principal
;----------------------------------------------------------------------
dormir
nop
nop
goto dormir
;Rutina Servicio Interrupciones
;----------------------------------------------------------------------
inter
movwf saveW ;Guarda W y STATUS, como se recomienda
swapf status,0 ;Guarda W y STATUS, como se recomienda
movwf saveSTATUS ;Guarda W y STATUS, como se recomienda
btfsc intcon,0 ;salta si el flag RBIF de INTCON es 0, si es 1 sigue
goto led0 ;(Se ha provocado un Stimulus sobre RB7. Es un high pulse de 2 cycles)
; btfsc intcon,1 ;salta si el flag INTF (RB0/INT) es 0, si es 1 sigue
; goto led1
; btfsc intcon,2 ;salta si el flag TOIF (TMR0) es 0, si es 1 sigue.
; call led2
bsf porta,0
swapf saveSTATUS,0
movwf status
swapf saveW,1
swapf saveW,0
bcf intcon,0
retfie
;Subrutinas de Interrupción
;----------------------------------------------------------------------
led0
btfsc porta,0 ;se verifica si led en puerta A0 está encendido
goto led0_off ;se apaga si está encendido
bsf porta,0
swapf saveSTATUS,0 ;Se recuperan los registros W y STATUS
movwf status ;Se recuperan los registros W y STATUS
swapf saveW,1 ;Se recuperan los registros W y STATUS
swapf saveW,0 ;Se recuperan los registros W y STATUS
bcf intcon,0 ;SE PIDE BORRAR EL FLAG DE LA INTERR., PERO NO FUNCA EN LA SIMULACIÓN MPLAB V.7.2, V7.4
retfie ;SE SALE DE LA INTERR, Y GIE DE INTCON NO VUELVE A 1, SE QUEDA EN 0.
led0_off
bcf porta,0
swapf saveSTATUS,0
movwf status
swapf saveW,1
swapf saveW,0
; movlw b'10001000'
; movwf intcon
bcf intcon,0
retfie
led1
; btfsc porta,1
; goto led1_off
; bsf porta,1
; bcf intcon,1
; retfie
led1_off
; bcf porta,1
; bcf intcon,1
; retfie
end
-
Bueno varias cosas sobre tu programa, todavia no concernientes a tu problema:
No tiene sentido repetir el radix, el radix hace que lo que tome sea decimal/hexa o lo que sea.
radix hex
MOVLW 10
; W = 32 decimal = 10 hexa
radix dec
MOVLW 10
; W= 10 decima = A hexa
Todo esto:
porta equ 0x05
portb equ 0x06
trisa equ 0x85
trisb equ 0x86
status equ 0x03
optio equ 0x81
intcon equ 0x0b
tmr0 equ 0x01
Es redundante, ya esta definido en el P16F84A.INC. lo unico que esta hecho en mayusculas MOVWF TRISA y tienen los mismos nombres que en el DATASHEET, al igual que los bits ejemplo INTCON,T0IF es mas facil de recordar que un INTCON,2
Algo que tal ves no parece pero si tenes 3 interrupciones como tenes vos, no tiene sentido repetir lo de recuperar el STATUS y W 3 veces.
inter
movwf saveW ;Guarda W y STATUS, como se recomienda
swapf status,0 ;Guarda W y STATUS, como se recomienda
movwf saveSTATUS ;Guarda W y STATUS, como se recomienda
; btfsc intcon,0 ;salta si el flag RBIF de INTCON es 0, si es 1 sigue
; call led0 ;(Se ha provocado un Stimulus sobre RB7. Es un high pulse de 2 cycles)
btfsc intcon,1 ;salta si el flag INTF (RB0/INT) es 0, si es 1 sigue
call led1
btfsc intcon,2 ;salta si el flag TOIF (TMR0) es 0, si es 1 sigue.
goto led2
bsf porta,0
fin_interrupcion
swapf saveSTATUS,0
movwf status
swapf saveW,1
swapf saveW,0
retfie
led1
btfsc porta,1
goto led1_off
bsf porta,1
bcf intcon,1
return
led2
btfsc porta,1
goto led1_off
bsf porta,1
bcf intcon,1
goto fin_interrupcion
Ahi te puse 2 ejemplos, uno con goto y otro con CALL (no esta correcto el codigo pero es para que veas la forma del goto y call, lo de adentro de led1 y led2 fue un copy paste). Observa que hay un solo punto de salida de la interrupcion (un solo retfie y ahi se recuperan los valores de STATUS y W)
El CALL te permite ver todas las interrupciones si es que hay 2 activas y luego salir, mientras que con el GOTO vas a procesar una, y luego cuando intente activar nuevamente las interrupciones ( RETFIE ) va a entrar nuevamente.
En un programa comun donde tenes codigo en el tu loop principal, no podes hacer lo que hiciste, es decir usar el RETFIE sin devolver los valores a STATUS y W. En este ejemplo no afecta en nada por que tu loop principal tiene 2 NOPs y no se modifica ninguna bandera o W. Pero en un programa que si tenga codigo estas obligado. Otra cosa. LO ULTIMO debe ser esas instrucciones, luego de eso no deberia ir nada que afecte a W o a STATUS.
Aunque esto te paresca capricho mio es mas facil de recordar lo que te voy a decir a continuacion
Esto:
swapf saveW,F
swapf saveW,W
es mas facil de recordar que esto:
swapf saveW,1
swapf saveW,0
Donde F indica que el resultado va al registro y W a W obviamente. Creo que esto te va a hacer la vida mas facil a vos y a mi.
-----------------------------------
Por ultimo, ahora si la solucion de tu problema.
Las interrupciones externas del PORTB siempre se comportaron de la misma manera. Yo pienso que esta mal, pero hay que tenerlo en cuenta.
Cuando ocurre una interrupcion por cambio de nivel del pin, se activa el flag de interrupcion. La unica manera de poder borrar ese flag es LEYENDO el puerto, recien ahi te permite borrarlo.
Entonces si vos no lees el PORTB el flag RBIF se mantiene en 1, cuando actua el RETFIE y pone el GIE a 1, hace que vuelva a entrar a la interrupcion. En tu caso estaria siempre entrando a la interrupcion ( es decir GIE = 0 por que esta dentro de la misma siempre, igual que en tu caso)
Siguiendo el ejemplo que di antes:
led0
movf PORTB ; Leo puerto
bcf intcon,0 ; borro flag
; Ahora si el codigo que debe hacer la interrupcion
btfsc porta,0 ;se verifica si led en puerta A0 está encendido
goto led0_off ;se apaga si está encendido
bsf porta,0
return
led0_off
bcf porta,0
return
-
HOLA AMIGO BUENAS NOCHES ESPERO ME PUEDAS AYUDAR , OYE MI PROFESOR ME PIDIO UN PROGRAMA EN EL PIC 16F628 EL CUAL ESTA CONECTADO DIRECTAMENTE A UN DISPLAY DE CATODO COMUN SIN DECODIFICADOR NI NADA ESTA DIRECTO CONECTADO EL DISPLAY POR EJEMPLO EL PIN "A" DEL DISPLAY ESTA CONECTADA AL PUERTO RB0 ,EL PIN "B" ESTA CONECTADO A RB1 Y ASI SUCESIVAMENTE , EL CHISTE ES QUE ME PIDIO UN PROGRAMA CON EL CUAL YO MUESTRE EL NUMERO 4 EN EL DISPLAY ME PODRAS AYUDAR A HACERLO ,GRACIAS AMIGO APENAS ME ADENTRO EN ESTE MUNDO DEL PIC.
-
Hola Christian.
Primero unas cosas, intenta no escribir todo en mayuscula, creo que hasta se dificulta leerlo de esa forma.
Y con respecto al codigo, si te podemos ayudar. Si el profesor te lo dio para que lo hagas es para que aprendas. De nada sirve que te demos el codigo completo. Pero aun asi te podemos indicar algo y si ya tenes un codigo realizado y no te funciona, aun mas facil va a ser orientarte.
Aunque posteaste aca, quiero preguntarte algunas cosas:
- ¿En que lenguaje de programacion te pidieron que lo hagas? ASM? C? Basic?
- El programa que pedis es super facil, asi como lo describiste de solo encender un 4 es muy muy muy muy facil. Me atrevo a decir que solo necesitas unas 10 instrucciones de ASM, 2 mas si es que queres los vectores de reset/interrupcion y tal ves 1 mas por la palabra de configuracion (la cual te lo genera solo el MPLAB).
Asi que ... que deberias saber... Si vas por Assembler que es lo que trata este post, vas a tener algo asi:
#include "p16f628a.inc"
; Bits de configuracion , te lo da el MPLAB X
Principal:
; Aca la configuracion del puerto B como salida, mira el datasheet y seguro que te da el codigo para ponerlo todo como digitales, unas 7 maximo creo
; Aca pongo el valor del puerto, 2 instrucciones
Loop:
GOTO Loop ; Loop infinito que no hace mas nada
En resumen, los bits de configuracion como dije ya 2 veces, te los da el MPLAB X, solo te vas abajo tenes unas pestañas, elegis Configuration Bits, y ahi seleccionas los bits de configuracion.
La parte de la configuracion, andate al datasheet , en I/O Ports tenes el puerto B, buscalo y lee ahi que tiene explicado para que sno cada codigo, sino te vas al final de lo del puerto B y tenes todas los registros y bits que afectan al puerto B. Luego vas a tener que buscar en el PDF registro por registro y activar los bits necesarios. ( Solo tenes que cargar el TRISB, asi que se reduce a 3 instrucciones )
La parte que le das el valor al puerto, le pones un 1 al bit que queres que encienda en tu display. Si por ejemplo queres que se encienda la seccion C del display, pones un 1 en RB2, y directamente para no ir bit a bit poniendo unos y ceros, lo haces todo junto con:
MOVLW 0b11111111 ; Aca numero en binario, hexa, lo que sea.
MOVWF PORTB
Finalemente un loop infinito que se quede ahi para siempre. Ya que va a saltar siempre al GOTO.
Si no haces este proyecto con lo que te di, te deberia dar el codigo completo por que es muy simple y la idea es que aprendas.
Finalmente:
Configuracion : 3 instrucciones
Cargar el puerto: 2 instrucciones
Loop: 1 instruccion
6 instrucciones y completaste tu programa.
-
Hola, disculpe las molestias, soy nuevo en esta pagina y no se como publicar una pregunta, necesito hacer lo siguiente, estoy haciendo un codigo para una maqueta de un ascensor de tres pisos, planta baja, primer y segundo piso, en cada piso hay un sensor conectados a los pines RA1, RA2, Y RA3, ya tengo mi codigo armado, pero quiero simularlo en el mplab, no consigo simular el hecho de que se active el sensor en el pin RA1 con la ventana de estimulos, si puedo realizar una interrupcion por RB0 que se da cuando se abre la puerta de la cabina, alguien sabe como puedo realizar el estimulo por el puerto A? Desde ya, muchas gracias!!
-
Seria bueno que pusieras que PIC estas usando, si es un PIC con conversor analogico digital tenes que recordar que para que el micro sea capas de leer las entradas necesitas pasar las entradas a digitales, ya que en el reset todos los pines que poseen el nombre ANx pasan a ser analogicos, y si los lees, lees un 0, imagino que por eso no podes usar el estimulo para cambiar de valor.
Pero de la misma forma que haces el estimulo del puertoB, lo harias con el puerto A, lo unico que se me ocurre es esa diferencia.
-
Hola, gracias por responder, estoy usando un 16f628a, y tengo deshabilitado los comparadores del puerto a,
;movlw 0x07
;movwf CMCON
con esas instrucciones y con la palabra de configuracion __CONFIG 3F10 que segun mi profe ya indica que deshabilitamos los comparadores.
desde ya muchas gracias!
-
Que buenos tus tutoriales, gracias por compartir tus conocimientos, estoy recién empezando con Microcontroladores se hace muy difícil a veces poder entender ciertos instrucciones.-
Gracias
-
Qué tal soy nuevo en este foro y es muy genial la verdad, quisiera , si es posible, que me den alguna orientación sobre un problema que tengo, es el siguiente:
Se necesita un ventilador extractor para un baño y que cumpla con los siguientes requerimientos:
-cuando se cierre la puerta de dicho baño, se debe de encender el ventilador de 220Vac
-cuando la puerta del baño se abre(después de haber estado cerrado) el ventilador tendrá que permanecer encendido por tiempo de 3 minutos.
si en ese tiempo se cierra y abre la puerta se reiniciará la cuenta de 3 minutos para luego desconectar el ventilador.
-durante dicho tiempo se titilará un led a razón de 1 segundo.
Creo que es necesario usar interrupción externa por RB0, gracias de antemano, saludos!
-
disculpa suki,
si podrias habilitar las imagenes donde esta el hardware necesario y el diagrama para hacer el contador de varios digitos porfavor
-
El link de los programas en Proteus esta caído
-
Hola
Suky por favor resubir el archivo con las simulaciones hechas en Proteus, para el PIC16F84A.
Igualmente está caído el link con las Directivas _CONFIG que colocó emiro99 en la página 9
Muchas gracias.
-
Buenos días, estoy implementado un contador de 2 dígitos con 3 pulsadores ascendente, descendente y reset, funciona casi perfecto, necesito que los display inicien prendidos en cero cero, pero solo se encienden al iniciar el conteo.
Por favor alguien que me ayude a modificar el código y saber si se puede migrar a 16f628a
-
Buenos días, ya lo solucione tan pronto lo tenga listo lo subiré para compartirlo a quien lo necesite.
-
El problema es simple.....
El codigo de mostrar unicamente se ejecuta cuando incrementa, decrementa, etc. Y ahi esta el problema.
Tu loop principal deberia:
- Leer los botones
- Cambiar el contador en caso de que sea necesario
- Mostrar
De esa forma siempre se muestra...
Aunque esto trae unos ciertos problemas, como que la lectura de los botones no deben ser bloqueantes (quedarse encerrados en un loop).
Si vos logras que tanto leer lso botones, como cambiar el contador no demore demasiado sea si tenes presionado el boton por siempre, entonces no vas a tener problemas. y vas a poder visualizar el 000.
La otra forma que libera de estos problemas es usar las interrupciones de un timer, y que en el timer se maneje el tiempo de cada display.
-
Amigo gracias por contestar pero le cuento que me estas hablando en chino :( pues lo que tengo lo he encontrado en una pagina y otra y pues si te das cuenta en el codigo tengo desactivado el __config pues me salen errores al compilar y no tengo la menor idea de como solucionarlo, te agradezco la ayuda que me puedas dar.
-
Amigo gracias por contestar pero le cuento que me estas hablando en chino :( pues lo que tengo lo he encontrado en una pagina y otra y pues si te das cuenta en el codigo tengo desactivado el __config pues me salen errores al compilar y no tengo la menor idea de como solucionarlo, te agradezco la ayuda que me puedas dar.
Considero que darte el codigo (debido que hay que cambiar casi todo) no significa ningun aprendizaje. Deberias intentar entender el codigo y una ves que lo entiendas modificarlo.
Yo no tengo ningun problema que me preguntes cuales son tus dudas respecto al codigo, pero no te va a servir nada si yo lo hago. No es para no hacerlo, es para tu propio bien.
-
Mis primeros programas en ASM. PIC16F84A y PIC16F628A/648A
Buenas, se que el tema es muy antiguo pero, ¿podrías actualizar los link de las simulaciones?
Mil gracias!! :-/