Tutorial+Assembler 2

99

Transcript of Tutorial+Assembler 2

Page 1: Tutorial+Assembler 2

Mis primeros programas en assembler PiC16F84A, PIC16F627A/628A/648A La idea de este tutorial es ayudar a los que recién están empezando, aquí mostraremos como comenzar. Usaremos los microcontrolador PIC16F84A, 16F628A 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.-

2009

Page 2: Tutorial+Assembler 2

Contenido

El PIC16F84A ........................................................................................................................................................ 4

Introducción. ................................................................................................................................................... 4

Reset. ........................................................................................................................................................... 5

Estructura interna del Microcontrolador. ....................................................................................................... 6

Memoria del programa. .............................................................................................................................. 6

Comenzando con la creación de nuestro código. ........................................................................................... 7

Configuración de puertos. ........................................................................................................................... 9

Programa completo: .................................................................................................................................. 11

Creación de Demoras: ................................................................................................................................... 12

Ejemplo: ..................................................................................................................................................... 13

Creación de Tablas: Control de un Display de 7 Segmentos. ........................................................................ 15

Diagrama de Flujo: ..................................................................................................................................... 16

Otra forma de crear una tabla. Direccionamiento Indirecto.- ...................................................................... 20

Control de varios Displays ............................................................................................................................. 23

Diagramas de flujo: .................................................................................................................................... 23

Control de conteo: ..................................................................................................................................... 24

Control de Displays con 74LS164................................................................................................................... 27

Decodificador BCD. ........................................................................................................................................ 31

Interrupciones.- ............................................................................................................................................. 32

Interrupcion externa RB0/INT. ...................................................................................................................... 34

Interrupcion por cambio de estado RB4-RB7. ............................................................................................... 36

Módulo temporizador TMR0 ........................................................................................................................ 41

El modo Temporizador .............................................................................................................................. 41

Ejemplo modo temporizador. ................................................................................................................... 42

Ejemplo modo contador. ........................................................................................................................... 45

Diagrama de Flujo: ..................................................................................................................................... 46

Control LCD .................................................................................................................................................... 46

Descripción: ............................................................................................................................................... 46

Rutinas de Control: .................................................................................................................................... 48

Librería LCD mas ejemplo. ......................................................................................................................... 48

Comunicación RS232 ..................................................................................................................................... 52

Ejemplo. ..................................................................................................................................................... 54

Page 3: Tutorial+Assembler 2

El PIC16F628A .................................................................................................................................................... 59

Puertos ...................................................................................................................................................... 60

Organización de la memoria. ..................................................................................................................... 61

Interrupciones: .............................................................................................................................................. 62

Palabra de Configuración .............................................................................................................................. 64

El Módulo del Timer 0. .................................................................................................................................. 65

Modo temporizador .................................................................................................................................. 66

Oscilador del Timer1 .................................................................................................................................. 66

Configuraciones: ........................................................................................................................................ 66

Registro T1CON (10h) ................................................................................................................................ 67

Ejemplo. ..................................................................................................................................................... 67

El Módulo del Timer 2. .................................................................................................................................. 69

El preescalador .......................................................................................................................................... 70

El Registro de comparación o de Periodo ................................................................................................. 70

El Postescalador ......................................................................................................................................... 70

Registro T2CON (12h) ................................................................................................................................ 71

Ejemplo: ..................................................................................................................................................... 71

La USART del PIC16F628A. ............................................................................................................................ 72

Modo Asíncrono. ....................................................................................................................................... 72

Ejemplo: ..................................................................................................................................................... 75

Módulos de comparación analógica y tensión de referencia ....................................................................... 78

Ejemplo: ..................................................................................................................................................... 81

Módulo CCP ................................................................................................................................................... 84

El Modo de Captura ....................................................................................................................................... 85

El preescalador del CCP ............................................................................................................................. 86

Ejemplo: ..................................................................................................................................................... 86

El Modo Comparador .................................................................................................................................... 89

Configuraciones: ........................................................................................................................................ 90

Ejemplo: ..................................................................................................................................................... 90

Modo PWM (Modulación de Ancho de Pulso). ............................................................................................. 92

Secuencia de configuración del PWM ....................................................................................................... 94

Ejemplo 1: .................................................................................................................................................. 94

Ejemplo 2: .................................................................................................................................................. 96

Page 4: Tutorial+Assembler 2

El PIC16F84A

Introducción. 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:

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

Page 5: Tutorial+Assembler 2

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:

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:

Page 6: Tutorial+Assembler 2

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.

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.

Page 7: Tutorial+Assembler 2

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.

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 del foro TodoPIC.

Este activará un led conectado a RB0 siempre que el interruptor conectado a RA0 este cerrado. Para ello

vamos a necesitar el siguiente circuito:

Page 8: Tutorial+Assembler 2

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:

Primero que nada debemos especificar con que microcontrolador estamos trabajando, esto lo realizamos es las

dos primeras líneas:

Page 9: Tutorial+Assembler 2

Código

1. ; **** Encabezado **** 2. list p=16F84A 3. #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.

Código

1. __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

Código

1. ;**** Definicion de variables **** 2. Led equ 0 ; Definimos Led como el bit cero de un

registro, en este caso PORTB.-

3. 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.

Page 10: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

Código

1. ;**** Configuración de puertos *** 2. Reset

3. org 0x00 ; Aquí comienza el micro.-

4. goto inicio ; Salto a inicio de mi programa.-

5. org 0x05 ; Origen del código de programa.-

6. Inicio

7. bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

8. movlw b'11111' ; Muevo 11111 a W.-

9. movwf TRISA ; Cargo en TRISA.-

10. movlw b'11111110'

11. movwf TRISB

12. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

13. bcf PORTB,Led ; Comienza apagado.-

Ya configurado nuestro PIC, vamos a realizar la rutina que ejecutara.

Código

1. ;**** Control de Led **** 2. Bucle

3. btfsc PORTA,Pulsador ; Preguntamos si esta en 0 logico.-

4. goto Apagar ; Esta a 1 logico, Apagamos Led.-

5. bsf PORTB,Led ; Esta a 0 logico, Encendemos Led.-

6. goto Bucle ; Testeamos nuevamente la condicion del

Pulsador.-

7. 8. Apagar

9. bcf PORTB,Led ;Apagamos Led.-

10. goto Bucle ; Testeamos nuevamente la condicion del Pulsador.-

11.

12. end

Aquí solamente en un bucle infinito testeamos continuamente el estado del pulsador, y según su estado se

encenderá o apagará el Led.-

Page 11: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Programa completo:

Código

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;**** Definicion de variables **** 6. Led equ 0 ; Definimos Led como el bit cero de un registro,

en este caso PORTB.-

7. Pulsador equ 0 ; Definimos Pulsador como el bit 0, en este caso

será para PORTA

8. ;**** Configuración de puertos *** 9. Reset

10. org 0x00 ; Aquí comienza el micro.-

11. goto Inicio ; Salto a inicio de mi programa.-

12. org 0x05 ; Origen del código de programa.-

13. Inicio

14. bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

15. movlw b'11111' ; Muevo 11111 a W.-

16. movwf TRISA ; Cargo en TRISA.-

17. movlw b'11111110'

18. movwf TRISB

19. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

20. bcf PORTB,Led ; Comienza apagado.-

21. ;**** Control de Led ****

22. Bucle

23. btfsc PORTA,Pulsador ; Preguntamos si esta en 0 lógico.-

24. goto Apagar ; Esta a 1 lógico, Apagamos Led.-

25. bsf PORTB,Led ; Esta a 0 lógico, Encendemos Led.-

26. goto Bucle ; Testeamos nuevamente la condición del

Pulsador.-

27.

28. Apagar

29. bcf PORTB,Led ;Apagamos Led.-

30. goto Bucle ;Testeamos nuevamente la condición del

Pulsador.-

31.

32. End

Page 12: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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

Código

1. Demora_xxus 2. movlw 0xXX ; Cargamos valor XX que controla duración (1)

3. movwf Contador ; Iniciamos Contador (1)

4. Repeticion 5. Decfsz Contador ; Decrementa contador y si es cero sale (1 si no

sale, 2 si sale)

6. goto Repeticion ; No es 0, repetimos (2)

7. 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.

Código

1. Demora_xx 2. movlw 0xXX ; (1)

3. movwf Contador1 ; (1)

4. Repeticion1 5. movlw 0xYY ; (1)

6. movwf Contador2 ; (1)

7. Repeticion2 8. decfsz Contador2,1 ; (1 si no sale, 2 si sale)

9. goto Repeticion2 ; (2)

10. decfsz Contador1,1 ; (1 si no sale, 2 si sale)

11. goto Repeticion1 ; (2)

12. 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

Page 13: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Tsub = [0xXX*((0xYY - 1)*3 + 7) + 5] Tcy En este caso el máximo que se puede conseguir es de aprox. 196 milisegundos.-

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:

Código

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;**** Definicion de variables **** 6. Contador1 equ 0x0C ; Seleccionamos posición en la memoria RAM (GPR)

para guardar

7. ; registro utilizado para demora.-

8. Contador2 equ 0x0D ; Registro utilizado en demora.-

9. Led equ 0 ; Definimos Led como el bit cero de un registro,

en este caso PORTB.-

10. Pulsador equ 0 ; Definimos Pulsador como el bit 0, en este

caso será para PORTA

11. ;**** Configuración de puertos ***

12. Reset

13. org 0x00 ; Aquí comienza el micro.-

14. goto Inicio ; Salto a inicio de mi programa.-

15. org 0x05 ; Origen del código de programa.-

16. Inicio

17. bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

18. movlw b'11111' ; Muevo 11111 a W.-

19. movwf TRISA ; Cargo en TRISA.-

20. movlw b'11111110'

Page 14: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

21. movwf TRISB

22. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

23. bcf PORTB,Led ; Comienza apagado.-

24. ;**** Control de Led ****

25. Bucle btfsc PORTA,Pulsador ; Preguntamos si esta en 0 lógico.-

26. goto Apagar ; Esta a 1 lógico, Apagamos Led.-

27. bsf PORTB,Led ; Esta a 0 lógico, Encendemos Led.-

28. call Demora_150ms ; Mantenemos prendido 150 milisegundos

29. bcf PORTB,Led ; Apagamos Led

30. call Demora_150ms ; Apagamos durante 150 ms, Ya realizamos un

titilo.-

31. goto Bucle ; Testeamos nuevamente la condición

del Pulsador

32.

33. Apagar bcf PORTB,Led ;Apagamos Led.-

34. goto Bucle ; Testeamos nuevamente la condición

del Pulsador.-

35. ;**** Demora ****

36. Demora_150ms

37. movlw 0xFF ;

38. movwf Contador1 ; Iniciamos contador1.-

39. Repeticion1

40. movlw 0xC3 ;

41. movwf Contador2 ; Iniciamos contador2

42. Repeticion2

43. decfsz Contador2,1 ; Decrementa Contador2 y si es 0

sale.-

44. goto Repeticion2 ; Si no es 0 repetimos ciclo.-

45. decfsz Contador1,1 ; Decrementa Contador1.-

46. goto Repeticion1 ; Si no es cero repetimos ciclo.-

47. return ; Regresa de la subrutina.-

48.

49. end

Page 15: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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:

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.

Es obvio que con un solo display solamente podremos contar de 0 a 9.

Page 16: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Diagrama de Flujo:

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.

Page 17: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

• El tamaño de la tabla, si nuestra tabla tiene mas de 255 posiciones, si o si debemos manejar los bits mas

significativos de PC [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:

Código

1. Tabla

2. addwf PCL,f

3. retlw Valor0

4. retlw Valor1

5. retlw Valor2

6. retlw Valor3

7. ; ....

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:

Código

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;**** Definicion de variables **** 6. Contador equ 0x0C ; Registro para almacenar conteo

7. Contador1 equ 0x0D ; Registro utilizado en demora.-

8. Contador2 equ 0x0E ; Registro utilizado en demora.-

9. Pulsador equ 7 ; Definimos Pulsador como el bit 7, en este

caso sera para PORTB

10. ;**** Inicio del Micro ****

11. Reset org 0x00 ; Aqui comienza el micro.-

12. goto Inicio ; Salto a inicio de mi programa.-

13.

14.

15. ;**** Tabla de conversión BCD a 7 Segmentos ****

16. ; Se coloca al inicio para asegurar ubicación en Pagina.-

17. org 0x05 ; Origen del código de tabla.-

18. BCD7SEG: ; retlw b'gfedcba' para display cátodo

comun

19. addwf PCL,1 ; Se incrementa el contador del programa.-

20. retlw b'0111111' ; 0

21. retlw b'0000110' ; 1

Page 18: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

22. retlw b'1011011' ; 2

23. retlw b'1001111' ; 3

24. retlw b'1100110' ; 4

25. retlw b'1101101' ; 5

26. retlw b'1111101' ; 6

27. retlw b'0000111' ; 7

28. retlw b'1111111' ; 8

29. retlw b'1101111' ; 9

30. clrf Contador ; Si llega 10, se resetea contador

31. retlw b'0111111' ; 0

32.

33. ;**** Programa principal ****

34. ;**** Configuración de puertos ****

35. Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

36. movlw b'10000000' ; RB7 como entrada y los demás como

salida.-

37. movwf TRISB

38. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

39. movlw b'0111111' ; Comienza en cero.-

40. movwf PORTB

41. clrf Contador

42. ;**** Testeo de Pulsador ****

43. Testeo

44. btfss PORTB,Pulsador ; Testeamos si esta a 1 lógico.-

45. goto Testeo ; No, seguimos testeando.-

46. call Demora_20ms ; Eliminamos Efecto rebote

47. btfss PORTB,Pulsador ; Testeamos nuevamente.-

48. goto Testeo ; Falsa Alarma, seguimos

testeando.-

49. incf Contador,1 ; Se ha pulsado, incrementamos

contador.-

50. movfw Contador ; pasamos contador a W

51. call BCD7SEG ; Llamamos tabla.-

52. movwf PORTB ; Cargamos valor recibido por Tabla

en PORTB

53. btfsc PORTB,Pulsador ; Esperamos a que se suelte el pulsador -

**-

54. goto $-1 ; No, PCL - 1, --> btfss

PORTA,Pulsador.-

55. call Demora_20ms ; Eliminamos efecto rebote.-

56. btfsc PORTB,Pulsador ; Testeamos nuevamente.-

57. goto $-4 ; No, Falsa alarma, volvemos a

testear a que se suelte (**).-

58. goto Testeo ; Si, Testeamos nuevamente.-

59.

60. ;**** Demora ****

61. Demora_20ms

62. movlw 0xFF ;

63. movwf Contador1 ; Iniciamos contador1.-

64. Repeticion1

65. movlw 0x19 ;

66. movwf Contador2 ; Iniciamos contador2

67. Repeticion2

68. decfsz Contador2,1 ; Decrementa Contador2 y si es 0

sale.-

69. goto Repeticion2 ; Si no es 0 repetimos ciclo.-

70. decfsz Contador1,1 ; Decrementa Contador1.-

71. goto Repeticion1 ; Si no es cero repetimos ciclo.-

72. return ; Regresa de la subrutina.-

73.

74. end

Page 19: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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:

Código

1. BCD7SEG: ; retlw b'gfedcba' para display cátodo común

2. addwf PCL,1 ; Se incrementa el contador del programa.-

3. DT 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0xFF, 0x6F

4. clrf Contador

5. retlw 0x3F

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.

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.

Page 20: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

Código

1. ; DIRECTO: 2. ; Definimos registro en la memoria de datos.- 3. MyRegistro equ 0x10 ; Ubicado en 0x10.-

4. 5. ; Cargamos dato en el registro.- 6. movlw 0x8A ;

7. movwf MyRegistro ; MyRegistro = 0x8a.-

8. ; Leemos dato del registro.- 9. movfw MyRegistro ; Movemos el valor que tenga MyRegistro a

W.-

10. movwf PORTB ; Por ejemplo, lo cargamos en PORTB.-

11.

12. ; INDIRECTO:

13. ; Cargamos dato en el registro.-

14. movlw 0x10 ;

15. movwf FSR ; Direccionamos Registro de datos ubicado en

0x10.-

16. movlw 0x8A ;

17. movwf INDF ; Cargamos registro direccionado con el valor

0x8A.-

18.

19. ; Leemos dato en el registro.-

20. movlw 0x10 ;

21. movwf FSR ; Direccionamos Registro de datos ubicado en

0x10.-

22. movfw INDF ; Movemos el valor que tenga el registro

seleccionado a W.-

23. 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

Page 21: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

aritméticas se activa si ocurre acarreo entre el bit 3 y bit 4.-

Código completo:

Código

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;**** Definición de variables **** 6. Contador equ 0x0C ; Seleccionamos posición en la memoria RAM

(GPR) para guardar

7. ; registro utilizado para demora.-

8. Contador1 equ 0x0D ; Registro utilizado en demora.-

9. Contador2 equ 0x0E

10. Pulsador equ 7 ; Definimos Pulsador como el bit 0, en este

caso será para PORTA

11.

12.

13. Reset

14. org 0x00 ; Aquí comienza el micro.-

15. goto Inicio ; Salto a inicio de mi programa.-

16. ;**** Programa principal ****

17. ;**** Configuración de puertos ****

18. Inicio

19. bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

20. clrf TRISB ; PORTB como salida.-

21. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

22. call Config_Tabla ; Cargamos registros con Código de 7

segmentos.-

23. movfw INDF ; Leemos código de 7 Segmentos para el

CERO.-

24. movwf PORTB ; Mostramos el CERO.-

25. ;**** Testeo de Pulsador ****

26. Bucle

27. call Demora_190ms ; Demora para visualizar Display

28. incf FSR,1 ; Incrementamos Puntero.-

29. movlw 0x1A ; Consultamos si se pide código

para mostrar "10",

30. subwf FSR,0 ; si es así reseteamos FSR, apunta

a 0x10--> "0".-

31. btfss STATUS,Z ; Si Z=1 --> 0x1A - FSR = 0.-

32. goto Muestro_Display ; No, muestro display.-

33. movlw 0x10 ; Si reseteo puntero.-

34. movwf FSR ;

35. Muestro_Display

36. movfw INDF ; Leo Registro que apunta FSR.-

37. movwf PORTB ; Lo cargo en PORTB.-

38. goto Bucle ; Continuo conteo.-

39.

40.

41. ;**** Demora ****

42. Demora_190ms

43. movlw 0xFF ;

44. movwf Contador1 ; Iniciamos contador1.-

45. Repeticion1

46. movlw 0xFF ;

47. movwf Contador2 ; Iniciamos contador2

48. Repeticion2

49. decfsz Contador2,1 ; Decrementa Contador2 y si es 0

sale.-

Page 22: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

50. goto Repeticion2 ; Si no es 0 repetimos ciclo.-

51. decfsz Contador1,1 ; Decrementa Contador1.-

52. goto Repeticion1 ; Si no es cero repetimos ciclo.-

53. return ; Regresa de la subrutina.-

54. ;**** Cargamos tabla en memoria ****

55. Config_Tabla

56. movlw 0x10 ;

57. movwf FSR ; Direccionamos el registro 0x10 de la

memoria RAM (GPR).-

58. movlw 0x3F ; Cargamos el codigo para mostrar el CERO.-

59. movwf INDF ; Lo guardamos donde apunta FSR --> 0x10.-

60. ;....................

61. incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x11.-

62. movlw 0x06 ; Cargamos codigo para UNO.-

63. movwf INDF ; Lo guardamos donde apunta FSR.-

64. ;....................

65. incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x12.-

66. movlw 0x5B ; Cargamos codigo para DOS.-

67. movwf INDF ; Lo guardamos donde apunta FSR.-

68. ;....................

69. incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x13.-

70. movlw 0x4F ; Cargamos codigo para TRES.-

71. movwf INDF ; Lo guardamos donde apunta FSR.-

72. ;....................

73. incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x14.-

74. movlw 0x66 ; Cargamos codigo para CUATRO.-

75. movwf INDF ; Lo guardamos donde apunta FSR.-

76. ;....................

77. incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x15.-

78. movlw 0x6D ; Cargamos codigo para CINCO.-

79. movwf INDF ; Lo guardamos donde apunta FSR.-

80. ;....................

81. incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x16.-

82. movlw 0x7D ; Cargamos codigo para SEIS.-

83. movwf INDF ; Lo guardamos donde apunta FSR.-

84. ;....................

85. incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x17.-

86. movlw 0x07 ; Cargamos codigo para SIETE.-

87. movwf INDF ; Lo guardamos donde apunta FSR.-

88. ;....................

89. incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x18.-

90. movlw 0xFF ; Cargamos codigo para OCHO.-

91. movwf INDF ; Lo guardamos donde apunta FSR.-

92. ;....................

93. incf FSR,1 ; Incrementamos FSR, ahora apunta a 0x19.-

94. movlw 0x6F ; Cargamos codigo para NUEVE.-

95. movwf INDF ; Lo guardamos donde apunta FSR.-

96. ;....................

97. movlw 0x10 ;

98. movwf FSR ; Direccionamos Registro del CERO.-

99. return ; Cargado los valores, retornamos.-

100. ;.................................................................. 101. End

Page 23: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Control de varios Displays

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:

Diagramas de flujo:

Page 24: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

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.-

Page 25: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Código

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;**** Definicion de variables **** 6. Unidad equ 0x0C ; Guardamos conteo unidad

7. Decena equ 0x0D ;

8. Centena equ 0x0E ;

9. Contador1 equ 0x0F ; Registro utilizado en demora.-

10. Contador2 equ 0x10 ; Registro utilizado en demora.-

11. Contador equ 0x11 ; Control de Refresco de Display.-

12.

13. MuestroU equ 2 ; Para control del 1º

Display

14. MuestroD equ 1 ; Para control del 2º

Display

15. MuestroC equ 0 ; Para control del 3º

Display

16.

17. ;**** Inicio del Micro ****

18. Reset

19. org 0x00 ; Aquí comienza el micro.-

20. goto Inicio ; Salto a inicio de mi programa.-

21.

22.

23. ;**** Tabla de conversion BCD a 7 Segmentos ****

24. ; Se coloca al inicio para asegurar ubicacion en Pagina.-

25. org 0x05 ; Origen del código de tabla.-

26. BCD7SEG ; retlw b'gfedcba' para display catodo comun

27. addwf PCL,1 ; Se incrementa el contador del programa.-

28. DT 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0xFF, 0x6F

29.

30. ;**** Programa principal ****

31. ;**** Configuracion de puertos ****

32. Inicio

33. bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

34. clrf TRISA ; PORTA como salida

35. clrf TRISB ; PORTB como salida.-

36. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

37. clrf PORTA ; Desactivo todos los Displays

38. clrf Unidad ; Comienza en cero --> 0 0 0.-

39. clrf Decena

40. clrf Centena

41. goto Actualizo_Display ; Esta rutina multiplexa los

displays.-

42. ;**** Testeo de Pulsador ****

43. Bucle

44. incf Unidad,1 ; Incremeto Unidad.

45. movlw d'10' ; Si es 10 reseteo e incremento Decena

46. subwf Unidad,0 ;

47. btfss STATUS,Z ;

48. goto Actualizo_Display ; no es 10

49. clrf Unidad ; Si, reseteo.-

50. incf Decena,1 ; Incremento Decena.-

51. movlw d'10' ; Si Decena = 10, reseteo e incremento

Centena

52. subwf Decena,0 ;

53. btfss STATUS,Z ;

54. goto Actualizo_Display ; No es 10.-

Page 26: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

55. clrf Decena ; Si, reseteo.-

56. incf Centena,1 ; Incremento Centena.-

57. movlw d'10' ; Si es 10 Reseteo.-

58. subwf Centena,0

59. btfss STATUS,Z

60. goto Actualizo_Display ; No es 10.-

61. clrf Centena ; Si, reseto

62. ;**** Se multiplexan los Display ****

63. Actualizo_Display

64. movlw d'20' ; Cargo Contador = 20

65. movwf Contador ; Para repeticiones de

visualizacion del mismo valor

66. ; durante 150 ms.-

67. Refresco

68. movfw Unidad ; Obtengo código de 7 Segmentos

para Unidad.-

69. call BCD7SEG ;

70. bcf PORTA,MuestroC ; Apago Display de Centena, Se entiende al

mirar rutina.-

71. movwf PORTB ; Cargo unidad en PORTB.-

72. bsf PORTA,MuestroU ; Enciendo Display de Unidad.-

73. call Demora_5ms

74. movfw Decena ; Obtengo código 7 Segmentos para

Decena.-

75. call BCD7SEG

76. bcf PORTA,MuestroU ; Apago Display de Unidad.-

77. movwf PORTB ; Cargo PORTB con Decena.-

78. bsf PORTA,MuestroD ; Enciendo Display de Decena.-

79. call Demora_5ms

80. movfw Centena ; Obtengo codigo de 7 Segmentos para

Centena.-

81. call BCD7SEG

82. bcf PORTA,MuestroD ; Apago Display de Decena.-

83. movwf PORTB ; Cargo PORTB con Centena.-

84. bsf PORTA,MuestroC ; Enciendo Display Centena.-

85. call Demora_5ms

86. decfsz Contador,1 ; Pregunto si ya se ha repetido 10

veces el ciclo?

87. goto Refresco ; No, repito.-

88. goto Bucle ; Si, actualizo cuenta.-

89. ;**** Demora ****

90. Demora_5ms

91. movlw 0xFF ;

92. movwf Contador1 ; Iniciamos contador1.-

93. Repeticion1

94. movlw 0x05 ;

95. movwf Contador2 ; Iniciamos contador2

96. Repeticion2

97. decfsz Contador2,1 ; Decrementa Contador2 y si es 0

sale.-

98. goto Repeticion2 ; Si no es 0 repetimos ciclo.-

99. decfsz Contador1,1 ; Decrementa Contador1.-

100. goto Repeticion1 ; Si no es cero repetimos ciclo.-

101. return ; Regresa de la subrutina.-

102. 103. end

En este ejemplo se mantiene la visualización del mismo valor durante aprox. 300 ms, se puede determinar ya

Page 27: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.-

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)

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:

Page 28: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Código

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;**** Definicion de variables **** 6. Display1 equ 0x0C ; Valor que luego de convertido se enviara al

Display 1

7. Display2 equ 0x0D ; Valor que luego de convertido se enviara al

Display 2

8. Display3 equ 0x0E ; Valor que luego de convertido se enviara al

Display 3

9. DataEnviar equ 0x0F ; Dato convertido a codigo 7 Segmentos a enviar

10. ContBits equ 0x10 ; Para controlar el envio de bits

11.

12. Desc equ 0 ; Definimos Pulsador descendente.-

13. Asc equ 1 ; Definimos Pulsador ascendente.-

14. BClock equ 0 ; Pin reloj del 74LS164

15. BData equ 1 ; Pin data del 74LS164

16. BReset equ 2 ; Pin Reset del 74LS164

17. Pto equ 0 ; Bit punto, Con este indicamos si se

muestra punto.-

18.

19. Resett org 0x00 ; Aquí comienza el micro.-

20. goto Inicio ; Salto a inicio de mi programa.-

21.

22. ;**** Tabla de conversion BCD a 7 Segmentos ****

23. ; Se coloca al inicio para asegurar ubicacion en Pagina.-

24. org 0x05 ; Origen del código de tabla.-

25. BCD7SEG: ; retlw b'abcdefg0'

para display catodo comun

26. addwf PCL,1 ; Se incrementa el contador del programa.-

27. DT 0xFC , 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6

28.

29. ;**** Programa principal ****

30. ;**** Configuracion de puertos ****

31. Inicio bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

32. movlw b'11111000' ; RB7 como entrada y los demas como

salida.-

33. movwf TRISB

34. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

35. clrf Display1

36. clrf Display2

37. clrf Display3

38. bsf PORTB,BReset ; Habilitamos 74LS164.-

39. bcf PORTB,BData

40. bsf PORTB,BClock ; Seteamos Clock.-

41. goto ActualizoDisplays

42.

43. ;**** Testeo de Pulsador ****

44. Testeo

45. btfss PORTA,Desc ; Testeamos si esta a 1 logico.-

46. goto Descender ; No

47. btfss PORTA,Asc ; Testeamos si esta a 1 logico.-

48. goto Ascender

49. goto Testeo ; Si, Testeamos nuevamente.-

50.

51.

Page 29: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

52.

53. ;**** Rutinas ****

54. Descender

55. btfss PORTA,Desc ;

56. goto $-1 ; Esperamos hasta que se suelte.-

57. decf Display1,1 ; Decremento Display1.

58. movlw d'255' ; Si paso de 0 a 255...

59. subwf Display1,0 ; decremento Display2

60. btfss STATUS,Z ;

61. goto ActualizoDisplays ; no es 255

62. movlw d'9'

63. movwf Display1 ; Si, cargo 9.-

64. decf Display2,1 ; Decremento Display2.-

65. movlw d'255' ; Si paso de 0 a 255...

66. subwf Display2,0 ; decremento display3

67. btfss STATUS,Z ;

68. goto ActualizoDisplays ; No es 10.-

69. movlw d'9'

70. movwf Display2 ; Si, cargo 9.-

71. decf Display3,1 ; Decremento Display3.-

72. movlw d'255' ; Si paso de 0 a 255...

73. subwf Display3,0

74. btfss STATUS,Z

75. goto ActualizoDisplays ; No es 10.-

76. movlw d'9'

77. movwf Display3 ; Si, cargo 9.-

78. goto ActualizoDisplays

79. ;.........................................................

80. Ascender

81. btfss PORTA,Asc ;

82. goto $-1 ; Esperamos hasta que se suelte.-

83. incf Display1,1 ; Incremeto Display1.

84. movlw d'10' ; Si es 10 reseteo e incremento Display2

85. subwf Display1,0 ;

86. btfss STATUS,Z ;

87. goto ActualizoDisplays ; no es 10

88. clrf Display1 ; Si, reseteo.-

89. incf Display2,1 ; Incremento Display2.-

90. movlw d'10' ; Si Decena = 10, reseteo e incremento

Display3

91. subwf Display2,0 ;

92. btfss STATUS,Z ;

93. goto ActualizoDisplays ; No es 10.-

94. clrf Display2 ; Si, reseteo.-

95. incf Display3,1 ; Incremento Display3.-

96. movlw d'10' ; Si es 10 Reseteo.-

97. subwf Display3,0

98. btfss STATUS,Z

99. goto ActualizoDisplays ; No es 10.-

100. clrf Display3 ; Si, reseto

101. goto ActualizoDisplays

102. ;................................................... 103. ActualizoDisplays 104. movfw Display1

105. call BCD7SEG ; Convertimos BCD a codigo 7

Segmentos-

106. movwf DataEnviar ; Cargamos dato a enviar devuelto x

BCD7SEG.-

107. call EnviaDato

108. movfw Display2

Page 30: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

109. call BCD7SEG ; Convertimos BCD a código 7

Segmentos.-

110. movwf DataEnviar ; Cargamos dato a enviar devuelto x

BCD7SEG.-

111. bsf DataEnviar,Pto ; A ejemplo cargamos punto a

enviar.-

112. call EnviaDato

113. movfw Display3

114. call BCD7SEG ; Convertimos BCD a código 7

Segmentos.-

115. movwf DataEnviar ; Cargamos dato a enviar devuelto x

BCD7SEG.-

116. call EnviaDato

117. goto Testeo

118. ;**** Se envía Dato a los registros de desplazamiento **** 119. ;------------------------------------------------------------------------

-----------------

120. ; 1º se envía el LSB, luego se va rotando a la derecha y se envían los bits de mayor peso.-

121. ;-----------------------------------------------------------------------------------------

122. EnviaDato 123. movlw d'8' ; Número de bits a transmitir.

124. movwf ContBits

125. EnviaBit ; Comienza a

enviar datos.

126. btfss DataEnviar,0 ; ¿Es un "1" el bit a transmitir?

127. bcf PORTB,BData ; No, pues envía un "0".

128. btfsc DataEnviar,0 ; ¿Es un "1" el bit a transmitir?

129. bsf PORTB,BData ; Si, Transmite un "1".

130. bcf PORTB,BClock ; Clock=0.-

131. nop

132. bsf PORTB,BClock ; Clock=1.-

133. rrf DataEnviar,1 ; Rota para envia siguiente bit.-

134. decfsz ContBits,1 ; Comprueba si es el último bit.

135. goto EnviaBit ; No es el último bit repite la

operación.

136. return ; Retornamos.-

137. ;.................................................................................

138. End

Page 31: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

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

Page 32: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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:

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

Page 33: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

Código

1. ;**** Rutina de servicio de Interrupcion **** 2. ; Guardado de registro W y STATUS.- 3. Inicio_ISR 4. movwf W_Temp ; Copiamos W a un registro Temporario.-

5. swapf STATUS, W ;Invertimos los nibles del registro STATUS.-

6. movwf STATUS_Temp ; Guardamos STATUS en un registro temporal.-

Page 34: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

7. ISR 8. ; Atendemos la interrupción.-

9. ; Restauramos los valores de W y STATUS.- 10. Fin_ISR

11. Swapf STATUS_Temp,W ; Invertimos lo nibles de STATUS_Temp.-

12. Movwf STATUS

13. Swapf W_Temp, f ; Invertimos los nibles y lo guardamos en el mismo

registro.-

14. swapf W_Temp,W ; Invertimos los nibles nuevamente y lo guardamos

en W.-

15. retfie ; Salimos de interrupción.-

Los registros W_Temp y STATUS_Temp son registros alternativos para guardar temporariamente sus valores

correspondientes.-

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:

Page 35: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Diagrama de Flujo:

Código:

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;**** Definicion de variables **** 6. Contador1 equ 0x0C

7. Contador2 equ 0x0D

8. 9. Pulsador equ 0 ; pin RB0

10. Led equ 1 ; pin RB1

11.

12. ;**** Inicio del Micro ****

13. Reset

14. org 0x00 ; Aqui comienza el micro.-

15. goto Inicio ; Salto a inicio de mi programa.-

16. ;**** Vector de Interrupcion ****

17. org 0x04 ; Atiendo Interrupcion.-

18. goto ISR

19.

20. ; **** Programa Principal ****

21. ;**** Configuracion de puertos ***

22. org 0x05 ; Origen del codigo de programa.-

23. Inicio

24. bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

25. movlw b'11111101' ; RB0 como entrada y RB1 como salida.-

26. movwf TRISB

27. movlw b'01000000' ; Config. Por flanco Ascendente.-

28. movwf OPTION_REG

29. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

30. bcf PORTB,Led ; El Led comienza apagado.-

Page 36: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

31. movlw b'10010000' ; Habilitamos GIE y INTE (interrupción por

RB0)

32. movwf INTCON

33. ;**** Bucle infinito ****

34. Bucle

35. nop ;

36. goto Bucle ;

37.

38. ;.............................................

39. ;**** Rutina de servicio de Interrupcion ****

40. ;**** Interrupcion por RB0 ****

41. ISR

42. btfss INTCON,INTF ; Consultamos si es por RB0.-

43. retfie ; No, Salimos de

interrupción.-

44. call Demora_20ms ; Comprueba si es rebote.-

45. btfss PORTB,Pulsador

46. goto Fin_ISR ; Es rebote, entonces salimos.-

47. btfss PORTB,Led ; Si esta prendido, lo apagamos.-

48. goto Prender_Led

49. bcf PORTB,Led ; Apagamos Led

50. goto Fin_ISR

51. Prender_Led

52. bsf PORTB,Led ; Encendemos Led

53. Fin_ISR

54. bcf INTCON,INTF ; Limpiamos bandera.-

55. retfie ; Salimos de interrupción.-

56. ;..........................................

57. ;**** Demora ****

58. Demora_20ms

59. movlw 0xFF ;

60. movwf Contador1 ; Iniciamos contador1.-

61. Repeticion1

62. movlw 0x19 ;

63. movwf Contador2 ; Iniciamos contador2

64. Repeticion2

65. decfsz Contador2,1 ; Decrementa Contador2 y si es 0

sale.-

66. goto Repeticion2 ; Si no es 0 repetimos ciclo.-

67. decfsz Contador1,1 ; Decrementa Contador1.-

68. goto Repeticion1 ; Si no es cero repetimos ciclo.-

69. return ; Regresa de la subrutina.-

70.

71. end

Interrupcion por cambio de estado RB4-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.

Page 37: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Para detectar la tecla presionada se utilizara el siguiente hardware:

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.

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.

Page 38: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

En nuestro ejemplo representaremos la tecla presionada en forma binaria con leds conectados al puerto A.

Diagrama de Flujo:

Código:

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;**** Definicion de variables **** 6. NTecla equ 0x0C ; Seleccionamos posición en la memoria RAM

(GPR) para guardar

7. W_Temp equ 0x0D ; Registro para guardar temporalmente W.-

8. STATUS_Temp equ 0x0E ; Registro para guardar temporalmete STATUS

9. 10.

11.

12. ;**** Inicio del Micro ****

13. Reset

14. org 0x00 ; Aquí comienza el micro.-

Page 39: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

15. goto Inicio ; Salto a inicio de mi programa.-

16. ;**** Vector de Interrupcion ****

17. org 0x04 ; Atiendo Interrupcion.-

18. goto Inicio_ISR

19. ;**** Programa principal ****

20. ;**** Configuracion de puertos ****

21. Inicio

22. bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

23. clrf TRISA ; PORTA como Salida.-

24. movlw b'11110000' ; Nible bajo como Salida y Nible alto como

Entrada.-

25. movwf TRISB

26. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

27. clrf PORTB

28. bcf INTCON,RBIF ; Borramos bandera de

Interrupcion.-

29. movlw b'10001000' ; Habilitamos GIE y RBIE (interrupción RB4

a RB7)

30. movwf INTCON

31. clrf NTecla

32. ;**** Bucle ****

33. Bucle

34. nop

35. goto Bucle

36. ;**** Rutina de servicio de Interrupcion ****

37.

38. ;---> Aqui haremos copia de respaldo para mostrar como se hace aunque no

es

39. ; necesario ya que el micro no hace otra tarea mientras tanto <---

40.

41. ; Guardado de registro W y STATUS.-

42. Inicio_ISR

43. movwf W_Temp ; Copiamos W a un registro Temporario.-

44. swapf STATUS, W ;Invertimos los nibles del registro

STATUS.-

45. movwf STATUS_Temp ; Guardamos STATUS en un registro

temporal.-

46. ;**** Interrupcion por TMR0 ****

47. ISR

48. btfss INTCON,RBIF ; Consultamos si es por RB4 a RB7.-

49. goto Fin_ISR ; No, entonces restauramos valores.-

50. call Tecla_Presionada ; Se detecta que tecla fue

presionada

51. movfw NTecla

52. movwf PORTA ; Mostarmos en diplay tecla Presionada.-

53. ; Restauramos los valores de W y STATUS.-

54. Fin_ISR

55. swapf STATUS_Temp,W ; Invertimos lo nibles de STATUS_Temp.-

56. movwf STATUS

57. swapf W_Temp, f ; Invertimos los nibles y lo guardamos en

el mismo registro.-

58. swapf W_Temp,W ; Invertimos los nibles nuevamente y lo

guardamos en W.-

59. retfie ; Salimos de interrupción.-

60.

61.

62. ;**** Rutinas *****

63. ; Rastreamos Tecla presionada.-

64. Tecla_Presionada

65. clrf NTecla ; Borra Numero de Tecla y

66. incf NTecla,1 ; prepara NTecla para primer codigo.

Page 40: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

67. movlw b'00001110' ; Saca 0 a la primera fila

68. movwf PORTB ; de la Puerta B

69. nop ; Para estabilizacion de señal.

70. Test_Columnas

71. btfss PORTB,4 ; Primera columna = 0

72. goto Suelta_tecla ; Sale si se ha pulsado tecla.

73. incf NTecla,1 ; Si no tecla pulsada, incrementa nº

tecla.

74. btfss PORTB,5 ; Segunda columna = 0

75. goto Suelta_tecla ; Sale si se ha pulsado tecla.

76. incf NTecla,1 ; Si no tecla pulsada, incrementa nº

tecla.

77. btfss PORTB,6 ; Tercera columna = 0

78. goto Suelta_tecla ; Sale si se ha pulsado tecla.

79. incf NTecla,1 ; Si no tecla pulsada, incrementa nº

tecla.

80. ; En este caso no se Usa teclado 3x4.-

81. ; btfss PORTB,7 ; Cuarta columna = 0

82. ; goto Suelta_tecla ; Sale si se ha pulsado tecla.

83. ; incf NTecla,1 ; Si no tecla pulsada,incrementa nº Tecla.

84.

85. Ultima_tecla

86. btfss PORTB,3 ; Ya se revisaron todas las filas?

87. goto Null_tecla ; Si, Falsa alarma, no se ha

presionado ninguna.-

88. bsf STATUS,C ; No, seguimos con la siguiente.Pone a 1

Bit C

89. rlf PORTB,1 ; asi la Fila 1 pasa a 1 con la rotaci¢n a

izqda.

90. goto Test_Columnas

91.

92. Null_tecla

93. clrf NTecla ; Coloca variable Tecla a 0 (Ninguna)

94. bcf INTCON,RBIF ; Borramos bandera de

Interrupcion.-

95. clrf PORTB ; Dejamos Puerto para recibir otra

tecla.-

96. return ; y regresa.

97.

98. Suelta_tecla

99. ; Ahora se espera a que la tecla sea soltada para evitar rebotes

100. ; y reactivaciones de tecla 101. Espera1 102. btfss PORTB,4 ; Si no se suelta la tecla FILA 1

103. goto Espera1 ; vuelve a esperar.

104. Espera2 105. btfss PORTB,5 ; Si no se suelta la tecla FILA 2

106. goto Espera2 ; vuelve a esperar.

107. Espera3 108. btfss PORTB,6 ; Si no se suelta la tecla FILA 3

109. goto Espera3 ; vuelve a esperar.

110. Espera4 111. btfss PORTB,7 ; Si no se suelta la tecla FILA 4

112. goto Espera4 ; vuelve a esperar.

113. 114. bcf INTCON,RBIF ; Borramos bandera de

Interrupcion.-

115. clrf PORTB ; Dejamos Puerto para recibir otra

tecla.-

Page 41: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

116. return ; vuelve al programa principal que

hizo la llamada.

117. ;.......................................... 118. 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:

Código GeSHi (asm):

1. movfw NTecla

2. call Tabla_TMatricial

3.

4. ;Codificacion de Tecla presionada: 5. Tabla_TMatricial 6. addwf PCL,1

7. DT "1","2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"

Módulo temporizador 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.

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. Este modo es seleccionado al limpiar

Page 42: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

el bit T0CS (OPTION_REG<5>). En este modo si se realiza una escritura al registro TMR0, su incremento

es inhibido por los siguientes dos ciclos de instrucción (Tcy) y si el preescalador está asignado se pierde la

cuenta pero no su asignación.

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 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 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

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:

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.

Page 43: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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:

Codigo:

1. . ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;**** Definicion de variables **** 6. Contador equ 0x0C ; Contador para detectar 4 desbordes de TMR0.-

7. W_Temp equ 0x0D ; Registro para guardar temporalmente W.-

8. STATUS_Temp equ 0x0E ; Registro para guardar temporalmente

STATUS

9. 10. Led equ 0 ; Definimos Led como el bit cero de

un registro, en este caso PORTB.-

11.

12. ;**** Inicio del Micro ****

Page 44: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

13. Reset

14. org 0x00 ; Aquí comienza el micro.-

15. goto Inicio ; Salto a inicio de mi programa.-

16. ;**** Vector de Interrupcion ****

17. org 0x04 ; Atiendo Interrupcion.-

18. goto Inicio_ISR

19.

20. ; **** Programa Principal ****

21. ;**** Configuracion de puertos ***

22. org 0x05 ; Origen del código de programa.-

23. Inicio

24. bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

25. movlw b'11111110' ; RB0 como salida.-

26. movwf TRISB

27. movlw b'00000111' ; Se selecciona TMR0 modo temporizador y

preescaler de 1/256.-

28. movwf OPTION_REG

29. bcf STATUS,RP0 ; Paso del Banco 1 al Banco 0

30. bcf PORTB,Led ; El Led comienza apagado.-

31. movlw 0x3D ; Cargamos 61 en TMR0 para lograr aprox.

50ms.-

32. movwf TMR0

33. clrf Contador ; Iniciamos contador.-

34. movlw b'10100000' ; Habilitamos GIE y T0IE (interrupción del

TMR0)

35. movwf INTCON

36. ;**** Bucle ****

37. Bucle

38. nop ; Aqui el micro puede ejecutar cualquier

otra tarea

39. goto Bucle ; sin necesidad de utilizar tiempo en un

bucle de demora.-

40.

41.

42. ;**** Rutina de servicio de Interrupcion ****

43.

44. ;---> Aqui haremos copia de respaldo para mostrar como se hace aunque no

es

45. ; necesario ya que el micro no hace otra tarea mientras tanto <---

46.

47. ; Guardado de registro W y STATUS.-

48. Inicio_ISR

49. movwf W_Temp ; Copiamos W a un registro Temporario.-

50. swapf STATUS, W ;Invertimos los nibles del registro

STATUS.-

51. movwf STATUS_Temp ; Guardamos STATUS en un registro

temporal.-

52. ;**** Interrupcion por TMR0 ****

53. ISR

54. btfss INTCON,T0IF ; Consultamos si es por TMR0.-

55. goto Fin_ISR ; No, entonces restauramos valores.-

56. incf Contador ; Si, Incrementamos contador

57. movlw 0x04 ; Consultamos si se han producido 4

desbordes

58. subwf Contador,0 ; para obtener 200 ms.-

59. btfss STATUS,Z ;

60. goto Actualizo_TMR0 ; No, cargo TMR0 si salgo.-

61. clrf Contador ; Si, reseteo Contador y controlo Led.-

62. btfss PORTB,Led ; Si esta apagado, prendo y viseversa.-

63. goto Prendo_led

64. bcf PORTB,Led ; Apago Led.-

Page 45: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

65. Actualizo_TMR0 ; Actualizo TMR0 para obtener una

temporizacion de 50 ms.-

66. movlw 0x3D ; d'61'

67. movwf TMR0

68. bcf INTCON,T0IF ; Borro bandera de control de

Interrupcion.-

69. goto Fin_ISR ; Restauro valores.-

70. Prendo_led

71. bsf PORTB,Led ; prendo Led.-

72. goto Actualizo_TMR0

73. ; Restauramos los valores de W y STATUS.-

74. Fin_ISR

75. swapf STATUS_Temp,W ; Invertimos lo nibles de STATUS_Temp.-

76. movwf STATUS

77. swapf W_Temp, f ; Invertimos los nibles y lo guardamos en

el mismo registro.-

78. swapf W_Temp,W ; Invertimos los nibles nuevamente y lo guardamos

en W.-

79. retfie ; Salimos de interrupción.-

80. ;..........................................

81.

82. end

83.

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.

Page 46: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Diagrama de Flujo:

Control 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.

Page 47: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

Código GeSHi (asm):

1. #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:

Page 48: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Código GeSHi (asm):

1. LCD_Putc macro Carac

2. movlw Carac

3. call LCD_Caracter

4. endm 5. LCD_Putd macro Coman

6. movlw Coman

7. call LCD_Comando

8. 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.

Librería LCD mas ejemplo.

Como ejemplo de aplicación se muestra un ejemplo donde se visualiza un mensaje (“InfoPic”):

Código GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. ;/////////////////////////////////////////////////////////////////// 6. ;**** Declaración de Registros **** 7. LCD_Dato equ 0x0C ;registro para guardar dato

a enviar al LCD

8. Loop equ 0x0D ;registro para

inicializacion del LCD

9. Contador1 equ 0x0E ;registro para demoras

10. Contador2 equ 0x0F ;registro para demoras

11. ;**** Declaracion de bits para control LCD ****

12. RS equ 0

13. RW equ 1

14. E equ 2

15. BACK equ 3

Page 49: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

16.

17. D4 equ 4

18. D5 equ 5

19. D6 equ 6

20. D7_BF equ 7

21. ;**** Declaracion de Bytes del LCD ****

22. LCD_PORT_Control equ 0x05 ; PORTA para control del

LCD

23. LCD_PORT_Data equ 0x06 ; PORTB para envio de Datos al LCD

24. LCD_TRIS_Control equ 0x85 ; TRISA

25. LCD_TRIS_Data equ 0x86 ; TRISB

26. ; **** Comandos de Software para la LCD ****

27. LCDLinea1 equ 0x80 ; Dirección comienzo línea1

28. LCDLinea2 equ 0xC0 ; Dirección comienzo línea2

29. LCDClr equ 0x01 ; Borra pantalla, cursor a Inicio

30. LCDInicio equ 0x02 ; Cursor a Inicio, DDRAM sin

cambios

31. LCDInc equ 0x06 ; Modo incrementa cursor

32. LCDDec equ 0x04 ; Modo decrementa cursor

33. LCDOn equ 0x0C ; Pantalla On

34. LCDOff equ 0x08 ; Pantalla Off

35. CursOn equ 0x0E ; Pantalla On, cursor On

36. CursOff equ 0x0C ; Pantalla On, cursor Off

37. CursBlink equ 0x0F ; Pantalla On, Cursor parpadeante

38. CurIzda equ 0x10 ; Mueve cursor a la izquierda

39. CurDecha equ 0x14 ; Mueve cursor a la derecha

40. DisIzda equ 0x18 ; Mueve Display a la izquierda

41. DisDecha equ 0x1C ; Mueve Display a la Derecha

42. LCDBus_4_2 equ 0x28 ; Bus 4 bits, 2 líneas, 5x7

43. ;**** Definiciones para el ensamblador ****

44. #DEFINE LCD_E LCD_PORT_Control,E

45. #DEFINE LCD_RS LCD_PORT_Control,RS

46. #DEFINE LCD_RW LCD_PORT_Control,RW

47. #DEFINE LCD_D4 LCD_PORT_Data,D4

48. #DEFINE LCD_D5 LCD_PORT_Data,D5

49. #DEFINE LCD_D6 LCD_PORT_Data,D6

50. #DEFINE LCD_D7_BF LCD_PORT_Data,D7_BF

51. #DEFINE CD_backlight LCD_PORT_Control,BACK ; Control

Backligth.-

52. ;**** Definición de macros ****

53. LCD_Putc macro Carac

54. movlw Carac

55. call LCD_Caracter

56. endm

57. LCD_Putd macro Coman

58. movlw Coman

59. call LCD_Comando

60. endm

61. ;//////////////////////////////////////////////////////////

62. ;**** Inicio del Micro ****

63. org 0x00

64. goto Inicio

65. ;**** Programa principal ****

66. org 0x05

67. Inicio

68. call LCD_Config_puertos ; Configuramos Puertos a utilizar

por LCD.-

69. call LCD_Init ; Inicializamos LCD.-

70. bsf LCD_backlight ; Prendemos Backlight.-

71. LCD_Putd CursBlink ; Cursor Parpadeante.-

72. LCD_Putc 'I' ; Escribimos en LCD.-

Page 50: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

73. LCD_Putc 'n'

74. LCD_Putc 'f'

75. LCD_Putc 'o'

76. LCD_Putc 'P'

77. LCD_Putc 'I'

78. LCD_Putc 'C'

79. Bucle

80. nop

81. goto Bucle ; Bucle Infinito.-

82.

83. ;**** Subrutinas de Control ****

84.

85. ;**** Configuracion de puertos ****

86. LCD_Config_puertos

87. bsf STATUS,RP0 ; Seleccionamos Banco 1.-

88. bcf LCD_RS ; Colocamos todas las lineas de

control y bus como Salidas.-

89. bcf LCD_RW

90. bcf LCD_E

91. bcf LCD_D4

92. bcf LCD_D5

93. bcf LCD_D6

94. bcf LCD_D7_BF

95. bcf LCD_backlight

96. bcf STATUS,RP0 ; Volvemos an Banco 0.-

97. bcf LCD_RS

98. bcf LCD_RW

99. bcf LCD_E

100. bcf LCD_D4

101. bcf LCD_D5

102. bcf LCD_D6

103. bcf LCD_D7_BF

104. bcf LCD_backlight

105. return

106. ;................................... 107. ;**** Inicializacion de LCD **** 108. LCD_Init 109. bcf STATUS,RP0 ; Aseguramos Banco 0.-

110. movlw 0x03

111. movwf Loop

112. bsf LCD_D4 ;<D7 D6 D5 D4> = 0011.-

113. bsf LCD_D5

114. ;.... se ejecuta 3 veces el siguiente bloque .... 115. bsf LCD_E

116. call Demora_5ms

117. bcf LCD_E

118. call Demora_5ms

119. decfsz Loop

120. goto $-5

121. ;.... Interfase de 4 bits .... 122. bcf LCD_D4 ;<D7 D6 D5 D4> = 0010.-

123. bsf LCD_E

124. call Demora_5ms

125. bcf LCD_E

126. call Demora_5ms

127. ;.... Sistema -> << Bus de 4 bits, 2 lineas, 5x7>>.- 128. movlw LCDBus_4_2

129. call LCD_Comando

130. ;....Limpia display y retorna al origen .... 131. movlw LCDClr

132. call LCD_Comando

Page 51: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

133. return

134. ;......................................... 135. ;**** Lee Estado del LCD **** 136. LCD_Bandera 137. bcf LCD_RW

138. bcf LCD_RS

139. bcf LCD_E

140. bcf LCD_D4

141. bcf LCD_D5

142. bcf LCD_D6

143. bcf LCD_D7_BF

144. nop

145. bsf LCD_RW ; Modo Lectura.-

146. bsf STATUS,RP0 ; Banco 1.-

147. bsf LCD_D7_BF ; Configura TRIS para recibir estado del

LCD.-

148. bcf STATUS,RP0 ; Banco 1.-

149. bsf LCD_E

150. nop

151. btfsc LCD_D7_BF ; Lee estado del LCD, 1-> Ocupado.-

152. goto $-1 ; Esperamos a que se desocupe.-

153. bcf LCD_E ; LCD_D7/BF->0, seguimos adelante.-

154. bsf STATUS,RP0 ; Banco 1.-

155. bcf LCD_D7_BF ; Reconfigura TRIS para envio de Data.-

156. bcf STATUS,RP0 ; Banco 1.-

157. return

158. ;............................. 159. ;**** Envia pulso Enable **** 160. LCD_Enable 161. bsf LCD_E

162. nop

163. nop

164. bcf LCD_E

165. return

166. ;............................. 167. ;**** Envia Dato al LCD **** 168. ;*** Previamente configurado como Comando o como Caracter.- 169. LCD_Envio_Data 170. movwf LCD_Dato ; Guardamos Dato a enviar.-

171. ; CARGAMOS NIBLE ALTO EN PUERTO.-

172. bcf LCD_D4 ; Cargamos un cero.-

173. btfsc LCD_Dato,4 ; Si es 1, modificamos a uno, sino

seguimos.-

174. bsf LCD_D4

175. bcf LCD_D5 ;

176. btfsc LCD_Dato,5

177. bsf LCD_D5

178. bcf LCD_D6 ;

179. btfsc LCD_Dato,6

180. bsf LCD_D6

181. bcf LCD_D7_BF ;

182. btfsc LCD_Dato,7

183. bsf LCD_D7_BF

184. call LCD_Enable ; Habilitamos LCD para recepcion de Data.-

185. ; CARGAMOS NIBLE BAJO EN PUERTO.-

186. bcf LCD_D4 ; Cargamos un cero.-

187. btfsc LCD_Dato,0 ; Si es 1, modificamos a uno, sino

seguimos.-

188. bsf LCD_D4

189. bcf LCD_D5 ;

190. btfsc LCD_Dato,1

Page 52: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

191. bsf LCD_D5

192. bcf LCD_D6 ;

193. btfsc LCD_Dato,2

194. bsf LCD_D6

195. bcf LCD_D7_BF ;

196. btfsc LCD_Dato,3

197. bsf LCD_D7_BF

198. call LCD_Enable ; Habilitamos LCD para recepcion de Data.-

199. return

200. ;............................. 201. ;**** Envia Comando al LCD **** 202. LCD_Comando 203. call LCD_Bandera ;Controla si el LCD esta en

condiciones de recibir un nuevo dato.-

204. bcf LCD_RW ; Modo escritura.-

205. bcf LCD_RS ; Se enviara Comando.-

206. call LCD_Envio_Data ; Envio Comando.-

207. return

208. ;............................. 209. ;**** Envia Caracter al LCD **** 210. LCD_Caracter 211. call LCD_Bandera ;Controla si el LCD esta en

condiciones de recibir un nuevo dato.-

212. bcf LCD_RW ; Modo escritura.-

213. bsf LCD_RS ; Se enviara Caracter.-

214. call LCD_Envio_Data ; Envio Caracter.-

215. return

216. ;.............................. 217. ;**** Demora **** 218. Demora_5ms 219. movlw 0xC8 ; 200

220. movwf Contador1 ; Iniciamos contador1.-

221. Repeticion1 222. movlw 0x07 ;

223. movwf Contador2 ; Iniciamos contador2

224. Repeticion2 225. decfsz Contador2,1 ; Decrementa Contador2 y si es 0

sale.-

226. goto Repeticion2 ; Si no es 0 repetimos ciclo.-

227. decfsz Contador1,1 ; Decrementa Contador1.-

228. goto Repeticion1 ; Si no es cero repetimos ciclo.-

229. return ; Regresa de la subrutina.-

230. 231. ;............................... 232. end

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

Page 53: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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:

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:

Page 54: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

Ejemplo.

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.

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

Page 55: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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, 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)

Código

GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16F84A 3. #include P16F84A.inc 4. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 5. 6. ;**** Declaración de Registros **** 7. RS232_ContBits equ 0x0C

8. RS232_Dato equ 0x0D

9. Flags equ 0x0E

10. Contador equ 0x0F

11.

12. ;**** Definiciones para el ensamblador ****

13. #DEFINE RS232_RX PORTB,0 ; Línea por la que se reciben los

datos.

Page 56: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

14. #DEFINE RS232_TX PORTB,1 ; Línea por la que se envían los

datos.

15. #DEFINE Kbhit Flags,0 ; Indica si se ha recibido algun

dato.-

16. ;**** Definición de macros ****

17. ; Se envia la data de un registro a PC.-

18. Putreg macro Registro

19. movfw Registro

20. call RS232_EnviaDato

21. endm

22. ; Se envia un literal a PC.-

23. Putc macro ACKII

24. movlw ACKII

25. call RS232_EnviaDato

26. endm

27.

28. ;//////////////////////////////////////////

29. ;**** Inicio del Micro ****

30. Reset

31. org 0x00 ; Aqui comienza el micro.-

32. goto Inicio ; Salto a inicio de mi programa.-

33. ;**** Vector de Interrupcion ****

34. org 0x04 ; Atiendo Interrupcion.-

35. goto ISR

36.

37. ; **** Programa Principal ****

38. ;**** Configuracion de puertos ***

39. org 0x05 ; Origen del codigo de programa.-

40. Inicio

41. call RS232_Puerto ; Se inicializa el puerto e interrupcion

para enviar y recibir datos RS232.-

42. ;**** Espera a recibir Dato ****

43. Bucle

44. btfss Kbhit ; ¿Se recibio Dato?

45. goto $-1 ; No, seguimos esperando.-

46. bcf Kbhit ; Si, borramos bandera.-

47. Putreg RS232_Dato ; Enviamos lo guardado en RS232_Dato.-

48. goto Bucle ;

49. ;.............................................

50. ;**** Rutina de servicio de Interrupcion ****

51. ;**** Interrupcion por RB0 ****

52. ; Se lee dato enviado por PC.-

53. ; En este caso no es necesario hacer copias de respaldo de W y STATUS.-

54. ;------------------------------------------------------------------------

----------------------

55. ; El 1º bit recibido se guarda en RS232_Dato,7; al rotarse 7 veces (Se

recibe el byte completo)

56. ; este queda en RS232_Dato,0.-

57. ;------------------------------------------------------------------------

----------------------

58. ISR

59. btfss INTCON,INTF ; Consultamos si es por RB0.-

60. retfie ; No, Salimos de interrupción.-

61. RS232_LeerDato

62. movlw d'7' ; Número de rotaciones.

63. movwf RS232_ContBits

64. call Demora_150us ; El primer bit debe leerlo un tiempo igual

a una

65. ; vez y media el periodo de

transmisión.

66. LeeBit

Page 57: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

67. bcf RS232_Dato,7 ; Ahora lee el pin. En principio supone que

es 0.

68. btfsc RS232_RX ; ¿Realmente es cero?

69. bsf RS232_Dato,7 ; No, pues cambia a "1".

70. rrf RS232_Dato,1 ; Rotamos para recibir el siguiente bit.-

71. call Demora_100us ; Los siguientes bits los lee un periodo

más tarde.

72. decfsz RS232_ContBits,1 ; Comprueba que es el último bit.

73. goto LeeBit ; No es el último, pasa a leer el

siguiente.

74. bcf RS232_Dato,7 ; Ahora lee ultimo bit enviado.Supone que

es 0.

75. btfsc RS232_RX ; ¿Realmente es cero?

76. bsf RS232_Dato,7 ; No, pues cambia a "1".

77. call Demora_100us ; Espera un tiempo igual al bit de Stop.

78. bsf Kbhit ; Se indica que ha llegado dato.-

79. Fin_ISR ; El dato recibido se

guarda en <<RS232_Dato>>

80. bcf INTCON,INTF ; Limpiamos bandera.-

81. retfie ; Salimos de interrupción.-

82. ;.................................................

83. ;**** Rutinas ****

84. ;*** Configura las líneas de salida y entrada ****

85. RS232_Puerto

86. bsf STATUS,RP0

87. bsf RS232_RX ; Esta línea se configura como

entrada.

88. bcf RS232_TX ; Esta línea se configura como

salida.

89. clrf OPTION_REG ; Config. Por flanco Descendente

Interrupcion RB0.-

90. bcf STATUS,RP0

91. bsf RS232_TX ; Condicion de no transmision de

datos.-

92. movlw b'10010000' ; Habilitamos GIE y INTE

(interrupción por RB0)

93. movwf INTCON

94. bcf Kbhit ; Borramos bandera.-

95. return

96.

97. ;**** Se envia Dato ****+

98. ;------------------------------------------------------------------------

-----------------

99. ; 1º se envia el LSB, luego se va rotando a la derecha y se envian los

bits de mayor peso.-

100. ;-----------------------------------------------------------------------------------------

101. RS232_EnviaDato 102. movwf RS232_Dato ; Guarda el contenido del byte a

transmitir.

103. movlw d'8' ; Número de bits a transmitir.

104. movwf RS232_ContBits

105. bcf RS232_TX ; Se genera bit de Start.

106. call Demora_100us

107. EnviaBit ; Comienza a enviar datos.

108. btfss RS232_Dato,0 ; ¿Es un "1" el bit a transmitir?

109. bcf RS232_TX ; No, pues envía un "0".

110. btfsc RS232_Dato,0 ; ¿Es un "1" el bit a transmitir?

111. bsf RS232_TX ; Si, Transmite un "1".

112. rrf RS232_Dato,1 ; Rota para envia siguiente bit.-

Page 58: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

113. call Demora_100us ; Este es el tiempo que estará en

alto o bajo.

114. decfsz RS232_ContBits,1 ; Comprueba si es el último bit.

115. goto EnviaBit ; No es el último bit repite la

operación.

116. bsf RS232_TX ; Envía bit de Stop.

117. call Demora_100us

118. return

119. ;**** Demoras ****

120. Demora_100us 121. movlw d'31'

122. movwf Contador

123. decfsz Contador

124. goto $-1

125. return

126. Demora_150us 127. movlw d'48'

128. movwf Contador

129. decfsz Contador

130. goto $-1

131. return

132. ;..................................... 133. end

Page 59: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

El PIC16F628A 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:

Código GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16f648A ; list directive to define processor

3. #include <p16f648A.inc> ; processor specific variable definitions

Page 60: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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

Page 61: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

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.

Page 62: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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

Page 63: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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:

Page 64: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

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

Page 65: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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 temporizador/contador de 16 bits. El conteo es realizado por dos

registros de 8 bits: (TMR1H (0Fh) y TMR1L (0Eh) ) que 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.

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.

Page 66: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Modo temporizador

Este modo se selecciona limpiando el bit TMR1CS (T1CON<1>) y el Timer se incrementa (si no se

considera preescalador) en cada ciclo de instrucción (a la frecuencia Fosc/4). 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. para cristal de 4MHz.

Modo contador

El Timer 1 también puede operar como contador asíncrono o síncrono contando los flancos ascendentes que

ocurren en pin RB6/T1OSO/T1CKI poniendo a 1 el bit TMR1CS. Después de que el Timer1 se programe en

modo contador, el módulo esperará un flanco de bajada antes de comenzar los incrementos con los flancos de

subida.

Contador sincronizado: Si SYNC T1 se borra, la entrada externa de reloj se sincroniza con la fase interna

de reloj. La sincronización se produce después de la etapa del Predivisor. Este bloque es un contador cíclico

asíncrono.

Contador asincrónico: Si el bit de control SYNC T1 se activa, la entrada de reloj externa no queda

sincronizada con el reloj interno. El temporizador continuará funcionando durante el estado de SLEEP, y

puede provocar una interrupción en su desbordamiento que saque de su “siesta” a la CPU.

Oscilador del Timer1

Se debe conectar un cristal de cuarzo entre las patillas T1OSI (entrada) y T1OSO (salida del amplificador

oscilador). El oscilador se habilita con el bit T1OSCEN (T1CON<3>), y funcionará en bajo consumo a partir

de 200 KHz. Este oscilador continúa funcionando aunque la CPU entre en modo SLEEP, y está diseñado

especialmente para trabajar a 32.768 Hz.

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 el módulo CCP

Page 67: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

(Más adelante se explicará en detalle).

A continuación se describe el principal registro relacionado con el Timer 1 y todos sus bits:

Registro T1CON (10h)

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 3 T1OSCEN: Bit de control de habilitación de oscilador para TMR1.

1 = Oscilador habilitado.

0 = Oscilador anulado.

Bit 2 T1SYNC: Bit de control de sincronización de la entrada de reloj externo de Timer1.

TMR1CS = 1

1 = Entrada de reloj externo no sincronizada.

0 = Entrada de reloj externo sincronizada

TMR1CS = 0

En esta circunstancia, Timer1 usa el reloj interno.

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

Ejemplo.

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.

Page 68: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Hardware:

Código GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16f628A ; list directive to define processor

3. #include <p16f628A.inc> ; processor specific variable definitions

4. __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON &

_INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON

5. 6. ;**** Definiciones para el ensamblador **** 7. #DEFINE Led PORTB,0 ; Led ubicado en Puerto B, bit 0.-

8. 9. ;////////////////////////////////////////// 10. ;**** Inicio del Micro ****

11. Reset

12. org 0x00 ; Aquí comienza el micro.-

13. goto Inicio ; Salto a inicio de mi programa.-

14. ;**** Vector de Interrupcion ****

15. org 0x04 ; Atiendo Interrupcion.-

16. goto ISR

17.

18. ; **** Programa Principal ****

19. ;**** Configuracion de puertos ***

20. org 0x05 ; Origen del código de programa.-

21. Inicio

22. bsf STATUS,RP0 ; Pasamos de Banco 0 a Banco 1.-

23. movlw b'11111110' ; RB0 como salida.-

24. movwf TRISB

25. bcf STATUS,RP0 ; Banco 0.-

26. movlw b'00110001' ; Se selecciona TMR1, preescaler de 1/8,

modo temporizador.-

27. movwf T1CON

28. bcf Led ; El Led comienza apagado.-

29. movlw 0x6D ; Cargamos 28036 en TMR1 para lograr

300ms.-

30. movwf TMR1H ; Byte alto de TMR1.-

31. movlw 0x84

32. movwf TMR1L ; Byte bajo de TMR1.-

33. bsf STATUS,RP0 ; Banco 1.-

34. bsf PIE1,TMR1IE ; Activar interrupción por TMR1.

35. bsf INTCON,GIE ; Habilitacion general de interrupciones.-

Page 69: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

36. bsf INTCON,PEIE ; Habilitacion de Interrupcion por

perifericos.-

37. bcf STATUS,RP0 ; Banco 0.-

38. ;**** Control de Led ****

39. Bucle

40. nop ; Aqui el micro puede ejecutar cualquier

otra tarea

41. goto Bucle ; sin necesidad de utilizar tiempo en un

bucle de demora.-

42.

43.

44. ;**** Rutina de servicio de Interrupcion ****

45. ;**** Interrupcion por TMR1 ****

46. ISR

47. btfss PIR1,TMR1IF ; Consultamos si es por TMR1.-

48. retfie ; No, salimos de interrupcion.-

49. btfss Led ; Si, Controlamos Led. Si esta apagado,

prendo y viseversa.-

50. goto Prendo_led

51. bcf Led ; Apago Led.-

52. Actualizo_TMR1 ; Actualizo TMR1 para obtener una

temporizacion de 300 ms.-

53. movlw 0x6D ; Cargamos 28036 en TMR1.-

54. movwf TMR1H ; Byte alto de TMR1.-

55. movlw 0x84

56. movwf TMR1L ; Byte bajo de TMR1.-

57. goto Fin_ISR ; Restauro valores.-

58. Prendo_led

59. bsf Led ; Prendo Led.-

60. goto Actualizo_TMR1

61. Fin_ISR

62. bcf PIR1,TMR1IF ; Borro bandera de control de

Interrupcion.-

63. retfie ; Salimos de interrupción.-

64. ;..........................................

65.

66. end

67.

El Módulo del Timer 2. El Timer es un temporizador (sin opción de trabajar como contador) de 8 bits con preescalador y

postescalador. 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.

Page 70: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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>).

Nota: Los contadores preescaladores y postescaladores se borran con cualquiera de estos acontecimientos:

Una escritura en el registro TMR2.

Una escritura en el registro T2CON.

Cualquier reset del dispositivo.

El registro TMR2 no se borra cuando se escribe en T2CON.

En este caso la temporización de calcula de la siguiente manera:

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, Divisor de Frecuencia Prescalador en 16,

Page 71: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Divisor de frecuencia Postescalador en 16, lográndose unos 65.5 ms aprox. para un cristal de 4MHz.

A continuación se describe el principal registro relacionado con el Timer 2 y todos sus bits.

Registro T2CON (12h)

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:

Ejemplo de configuración para lograr una temporización de 20 ms:

Código GeSHi (asm):

1. bcf STATUS,RP0 ; Banco 0.-

2. movlw b'01000110' ; Se selecciona TMR2, preescaler de 1/16,

postescaler 1/8.-

3. movwf T2CON

4. bsf STATUS,RP0 ; Banco 1.-

5. movlw 0x9D ; Cargamos 157 en PR2 para lograr 20ms.-

6. movwf PR2

7. bsf PIE1,TMR2IE ; Activar interrupci&#243;n por TMR2.

8. bsf INTCON,GIE ; Habilitacion general de interrupciones.-

9. bsf INTCON,PEIE ; Habilitacion de Interrupcion por perifericos.-

10. bcf STATUS,RP0 ; Banco 0.-

Control de interrupción:

Código GeSHi (asm):

1. ISR 2. btfss PIR1,TMR2IF ; Consultamos si es por TMR2.-

3. retfie ; No, salimos de interrupcion.-

Page 72: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

4. . ; Si, rutina de interrupcion.

5. .

6. .

7. Fin_ISR 8. bcf PIR1,TMR2IF ; Borro bandera de control de Interrupcion.-

9. retfie ; Salimos de interrupcion.-

La USART del PIC16F628A. 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 tabla 1:

Page 73: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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

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:

Page 74: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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

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

Page 75: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

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:

Page 76: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Código GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16f628A ; list directive to define processor

3. #include <p16f628A.inc> ; processor specific variable definitions

4. __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON &

_INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON

5. 6. ;**** Definicion de variables **** 7. DATA_RS232 equ 0x20 ; Dato recibido desde PC.-

8. Flags equ 0x21 ;

9. ;**** Definiciones para el ensamblador **** 10. #DEFINE Kbhit Flags,0 ; Indica si se ha recibido algun

dato.-

11. ;**** Definición de macros ****

12. ; Se envia la data de un registro a PC.-

13. Putreg macro Registro

14. movfw Registro

15. call RS232_EnviaDato

16. endm

17. ; Se envia un literal a PC.-

18. Putc macro ACKII

19. movlw ACKII

20. call RS232_EnviaDato

21. endm

22.

23.

24. ;/////////////////////////////////

25. ;**** Inicio del Micro ****

26. Reset.

27. org 0x00 ; Aquí comienza el micro.-

28. goto Inicio ; Salto a inicio de mi programa.-

29.

30. ;**** Vector de Interrupcion ****

31. org 0x04 ; Atiendo Interrupcion.-

32. goto ISR

33.

34. ; **** Programa Principal ****

35. org 0x05

Page 77: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

36. Inicio

37. bsf STATUS,RP0 ; Banco 1

38. movlw 0x02

39. movwf TRISB ; Configuo pines para Usart.-

40. movlw 0x04

41. movwf TXSTA ; Configura modo asincrono, baud rate de

alta velocidad

42. movlw 0x19 ; Configura velocidad a 9600 baudios con

cristal de 4 Mhz

43. movwf SPBRG

44. bsf PIE1,RCIE ; Habilita interrupcion de puerto serie

para recepcion

45. bsf INTCON,GIE ; Habilitacion general interrupciones

46. bsf INTCON,PEIE ; Habilitacion de interrupciones por

perifericos

47. ; Activar recepcion, transmision.-

48. bsf TXSTA,TXEN ; Habilita transmision

49. bcf STATUS,RP0 ; Banco 0

50. bsf RCSTA,SPEN ; Habilitacion puerto serie

51. bsf RCSTA,CREN ; Habilita recepcion

52. bcf Kbhit ; Limpiamos bandera.

53.

54. Bucle

55. btfss Kbhit ; ¿Se recibio Dato?

56. goto $-1 ; No, seguimos esperando.-

57. bcf Kbhit ; Si, borramos bandera.-

58. Putreg DATA_RS232 ; Enviamos lo guardado en DATA_RS232.-

59. goto Bucle ;

60. ;.............................................

61. ;**** Rutina de servicio de Interrupcion ****

62. ;**** Interrupcion por Usart (Recepcion de Dato)****

63. ISR

64. btfss PIR1,RCIF ; Consultamos si es Usart.-

65. retfie ; No, Salimos de interrupción.-

66. movfw RCREG ; Llego dato, lo guardamos en un registro.

67. movwf DATA_RS232

68. bsf Kbhit ; Indicamos que ha llegado Dato.-

69. Fin_ISR

70. bcf PIR1,RCIF ; Limpiamos bandera.

71. retfie ; Salimos de interrupción.-

72. ;..............................................

73. ;**** Rutinas ****

74. ;**** Se envia Dato ****

75. RS232_EnviaDato

76. bsf STATUS,RP0 ; Banco 1

77. btfss TXSTA,TRMT ; chequea si esta listo

78. goto $-1 ; Esperamos a que se desocupe.-

79. bcf STATUS,RP0 ; Banco 0

80. movwf TXREG ; envia Dato.-

81. return

82. ;...............................................

83. end

84.

Page 78: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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

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.

Page 79: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

Page 80: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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

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)

Page 81: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

VR<3:0> Selección de la tensión de referencia:

Si VRR = 1:

Si VRR = 0:

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.

Ejemplo:

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.

Page 82: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Hardware necesario

Diagrama de Flujo:

Page 83: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Código GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16f628A ; list directive to define processor

3. #include <p16f628A.inc> ; processor specific variable definitions

4. __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON &

_INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON

5. 6. ;**** Definicion de variables **** 7. Contador1 equ 0x20 ; Registro utilizado para demora.-

8. Contador2 equ 0x21 ; Registro utilizado para demora.-

9. Loop equ 0x22 ;

10. ;**** Definiciones para el ensamblador ****

11. #DEFINE Led PORTB,0 ; Led ubicado en Puerto B, bit 0.-

12. ;/////////////////////////////////

13. ;**** Inicio del Micro ****

14. Reset.

15. org 0x00 ; Aquí comienza el micro.-

16. goto Inicio ; Salto a inicio de mi programa.-

17.

18. ;**** Vector de Interrupcion ****

19. org 0x04 ; Atiendo Interrupcion.-

20. goto ISR

21.

22. ; **** Programa Principal ****

23. org 0x05

24. Inicio

25. movlw 0x12 ; Seleccionamos 2 comparadores con Vref

interna.

26. ; C1Vin- -> RA0, C2Vin- ->

RA1.

27. ; Salida de comparador 1

invertida.

28. movwf CMCON

29. bsf STATUS,RP0 ; Banco 1

30. movlw 0x03 ; RA0 y RA1 como entrada.-

31. movwf TRISA

32. clrf TRISB ; PORTB como salida.-

33. movlw 0xAF ; Vref activado, Low, VR<3:0>=15 (Vref=3.59

Volt).-

34. movwf VRCON

35.

36. bcf STATUS,RP0 ; Banco 0.-

37. clrf PORTB

38. movf CMCON,f ; Operacion de lectura.-

39. bcf PIR1,CMIF ; Limpiamos bandera.-

40.

41. bsf STATUS,RP0 ; Banco 1.-

42. bsf PIE1,CMIE ; Habilitamos interrupcion por

comparador analogico.

43. bsf INTCON,PEIE ; Habilitacion de Interrupcion por

perifericos.-

44. bsf INTCON,GIE ; Habilitacion general de interrupciones.-

45. bcf STATUS,RP0 ; Banco 0.-

46. Bucle

47. nop

48. goto Bucle

49. ;.............................................

Page 84: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

50. ;**** Rutina de servicio de Interrupcion ****

51. ;**** Interrupcion por Comparador Analogico****

52. ISR

53. btfss PIR1,CMIF ; Interrupcion por Comparador?

54. retfie ; No, salimos de interrupcion.-

55. btfss CMCON,C1OUT ; Consultamos estado del comparador.-

56. goto Fin_ISR ; Si es 0 salimos de interrupcion.-

57. call Alarma ; Si es 1, indicamos una alarma.-

58. Fin_ISR

59. movf CMCON,f ; Operacion de lectura.-

60. bcf PIR1,CMIF ; Limpiamos bandera.-

61. retfie

62. ;..............................................

63. ;**** Rutinas ****

64. Alarma

65. movlw 0x0A ; Hacemos titilar 10 veces el Led.-

66. movwf Loop

67. bsf Led

68. call Demora_150ms

69. bcf Led

70. call Demora_150ms

71. decfsz Loop

72. goto $-5

73. return

74. ;**** Demora ****

75. Demora_150ms

76. movlw 0xFF ;

77. movwf Contador1 ; Iniciamos contador1.-

78. Repeticion1

79. movlw 0xC3 ;

80. movwf Contador2 ; Iniciamos contador2

81. Repeticion2

82. decfsz Contador2,1 ; Decrementa Contador2 y si es 0 sale.-

83. goto Repeticion2 ; Si no es 0 repetimos ciclo.-

84. decfsz Contador1,1 ; Decrementa Contador1.-

85. goto Repeticion1 ; Si no es cero repetimos ciclo.-

86. return ; Regresa de la subrutina.-

87. ;.................................................

88. 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

Page 85: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Modo PWM: Permite generar señales digitales moduladas en ancho de pulso

El registro principal de este módulo se compone de dos registros de 8 bits, denominados CCPR1H (16h) y

CCPR1L (15h). 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 que reseteará el

Timer 1, ósea que el módulo CCP en modo comparación en evento especial junto al timer1 trabajá como el

timer2 junto a PR2.

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 pin RB3/CCP1. El evento en cuestión puede especificarse previamente como

alguno de los siguientes que se configura mediante los bits de control CCP1M3:CCP1M0

(CCP1CON<3:0>):

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.

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:

Page 86: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

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.

Page 87: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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.

Hardware necesario:

Código GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16f628A ; list directive to define processor

3. #include <p16f628A.inc> ; processor specific variable definitions

4. __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC &

_DATA_CP_OFF & _LVP_OFF & _MCLRE_ON

5. 6. ;**** Definicion de variables **** 7. Msb equ 0x20 ; Guarda Byte alto de

Captura para enviar por RS232

8. Lsb equ 0x21 ; Guarda byte bajo de

Captura para enviar por RS232

9. Contador1 equ 0x22 ; Para demora

10. Contador2 equ 0x23 ; Para demora

Page 88: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

11. ;**** Definiciones para el ensamblador ****

12.

13. ;**** Definición de macros ****

14. ; Se envia la data de un registro a PC.-

15. Putreg macro Registro

16. movfw Registro

17. call RS232_EnviaDato

18. endm

19.

20. ;/////////////////////////////////

21. ;**** Inicio del Micro ****

22. Reset.

23. org 0x00 ; Aquí comienza el micro.-

24. goto Inicio ; Salto a inicio de mi programa.-

25.

26. ; **** Programa Principal ****

27. org 0x05

28. Inicio

29. bsf STATUS,RP0 ; Banco 1

30. movlw b'00001010' ; RB1 entrada, RB2 salida, RB3 entrada.

31. movwf TRISB

32. movlw 0x04

33. movwf TXSTA ; Configura modo asincrono, baud rate de

alta velocidad

34. movlw 0x81 ; Configura velocidad a 9600 baudios con

cristal de 20 Mhz

35. movwf SPBRG

36. bsf TXSTA,TXEN ; Habilita transmision

37. bcf STATUS,RP0 ; Banco 0.-

38. bsf RCSTA,SPEN ; Habilitacion puerto serie

39.

40. movlw b'00000001' ; Se selecciona TMR1, preescaler de 1/1,

modo temporizador.-

41. movwf T1CON

42. movlw b'00000101' ; Se configura CCP modo captura cada flanco

de subida.-

43. movwf CCP1CON

44. Bucle

45. bcf PIR1,CCP1IF ; Borramos bandera

46. btfss PIR1,CCP1IF ; Testeamos bandera.-

47. goto $-1 ; Si no se activo seguimos

esperando

48. bcf PIR1,CCP1IF ; Se activo, la borramos.-

49. clrf TMR1H ; Borramos Timer1.-

50. clrf TMR1L ;

51. btfss PIR1,CCP1IF ; Volvemos a testear bandera.-

52. goto $-1 ; No se activo, seguimos

esperando.-

53. movfw CCPR1L ; Copiamos el valor capturado.-

54. movwf Lsb

55. movfw CCPR1H

56. movwf Msb

57. Putreg Msb ; Enviamos lo guardado en el

registro Msb.-

58. Putreg Lsb ; Enviamos lo guardado en el

registro Lsb.-

59. call Demora_30ms

60. goto Bucle ;

61. ;..............................................

62. ;**** Rutinas ****

63. ;**** Se envia Dato ****

Page 89: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

64. RS232_EnviaDato

65. bsf STATUS,RP0 ; Banco 1

66. btfss TXSTA,TRMT ; chequea si esta listo

67. goto $-1 ; Esperamos a que se desocupe.-

68. bcf STATUS,RP0 ; Banco 0

69. movwf TXREG ; envia Dato.-

70. return

71. ;...............................................

72. ; *** Demora****

73. Demora_30ms

74. movlw 0xFF ;

75. movwf Contador1 ; Iniciamos contador1.-

76. Repeticion1

77. movlw 0xC3 ;

78. movwf Contador2 ; Iniciamos contador2

79. Repeticion2

80. decfsz Contador2,1 ; Decrementa Contador2 y si es 0

sale.-

81. goto Repeticion2 ; Si no es 0 repetimos ciclo.-

82. decfsz Contador1,1 ; Decrementa Contador1.-

83. goto Repeticion1 ; Si no es cero repetimos ciclo.-

84. return ; Regresa de la subrutina.-

85. ;...............................................

86. 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

Page 90: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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:

Código GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16f628A ; list directive to define processor

3. #include <p16f628A.inc> ; processor specific variable definitions

4. __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC &

_DATA_CP_OFF & _LVP_OFF & _MCLRE_ON

5. 6. ;**** Definicion de variables **** 7. decre equ 0 ; Pulsador para decrementar periodo

8. incre equ 1 ; Pulsador para incrementar periodo

9.

Page 91: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

10. ;/////////////////////////////////

11. ;**** Inicio del Micro ****

12. Reset.

13. org 0x00 ; Aquí comienza el micro.-

14. goto Inicio ; Salto a inicio de mi programa.-

15.

16. ; **** Programa Principal ****

17. org 0x05

18. Inicio

19. movlw 0x07 ; Para deshabilitar comparadores

analogicos.-

20. movwf CMCON

21. bsf STATUS,RP0 ; Banco 1

22. bsf TRISA,decre ; Como entrada.-

23. bsf TRISA,incre ; Como entrada.-

24. bcf TRISB,3 ; RB3 como Salida.

25. bcf STATUS,RP0 ; Banco 0.-

26. movlw b'00000001' ; Se selecciona TMR1, preescaler de 1/1,

modo temporizador.-

27. movwf T1CON

28. movlw 0x80 ; Inicia periodo de comparacion a mitad de

rango.-

29. movwf CCPR1H

30. movlw 0x00

31. movwf CCPR1L

32. movlw b'00001000' ; Se configura CCP modo comparación, setea

salida con coincidencia.-

33. movwf CCP1CON

34. clrf TMR1H ; Comenzamos generacion de señal.-

35. clrf TMR1L

36. Bucle

37. bcf PIR1,CCP1IF ; Borramos bandera

38. btfss PIR1,CCP1IF ; Testeamos bandera.

39. goto $-1 ; Si no se activo seguimos

esperando

40. bcf PIR1,CCP1IF ; Se activo, la borramos.

41. movlw b'00000001' ; Invertimos ultimo bit, para pasar de

setear a resetear...

42. xorwf CCP1CON,1 ; o viceversa.-

43. clrf TMR1H ; Reseteamos cuenta Timer1.

44. clrf TMR1L ;

45. btfsc PORTA,decre ; Testea pulsador para decrementar

periodo.-

46. call Decrementa

47. btfsc PORTA,incre ; Testea pulsador para incrementar

periodo.-

48. call Incrementa

49. goto Bucle ;

50. ;..............................................

51. ;**** Rutinas ****

52. Decrementa

53. decf CCPR1L,1 ; Decrementa parte baja.-

54. comf CCPR1L,w ; Carga el negado a W, si CCPR1L=0xFF ->

W=0x00.-

55. btfss STATUS,Z ; Si W=0x00 decrementamos parte alta.-

56. return ; No.-

57. decf CCPR1H,1 ; Decrementa parte alta.-

58. return

59. ;..............................................

60. Incrementa

61. incf CCPR1L,1 ; Incrementa parte baja.-

Page 92: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

62. btfss STATUS,Z ; CCPR1L=0x00?

63. return ; No.-

64. incf CCPR1H,1 ; Si, incrementa parte alta

65. return

66.

67. ;...............................................

68. 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:

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)

Page 93: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

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

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>.

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.

Page 94: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

El número de divisiones que se pueden tener en un Ciclo de Trabajo será , donde n es el número de bits

usados, por lo tanto su duración máxima será:

Sin embargo, dependiendo del valor de Ciclo de trabajo máximo (CT_PWM) deseado, no será posible realizar

las 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:

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).

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 1: 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

Page 95: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Señal de 2kHz PR2=30 (0x1E) CCPR1L&2bits=62 (0x3E) CCPR1L=0x0F & 2bits=10

Hardware necesario:

Código GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16f628A ; list directive to define processor

3. #include <p16f628A.inc> ; processor specific variable definitions

4. __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON &

_INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON

5. 6. ;**** Definicion de variables **** 7. Flags equ 0x20 ; Registro para guardar banderas.-

8. 9. Selec equ 0 ; Bit para indicar

seleccion(Selec=1->500Hz; Selec=0->2kHz).-

10. ;**** Definiciones para el ensamblador ****

11. #define Signal Flags,Selec

12.

13.

14. ;/////////////////////////////////

15. ;**** Inicio del Micro ****

16. Reset.

17. org 0x00 ; Aquí comienza el micro.-

18. goto Inicio ; Salto a inicio de mi programa.-

19.

20. ; **** Programa Principal ****

21. org 0x05

22. Inicio

23. bsf STATUS,RP0 ; Banco 1

24. bsf TRISB,0 ; Como Entrada.-

25. bcf TRISB,3 ; RB3 como Salida.

26. bcf STATUS,RP0 ; Banco 0.-

27. movlw b'00000110' ; Se selecciona TMR2, preescaler de 1/16.-

28. movwf T2CON

Page 96: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

29. bsf STATUS,RP0 ; Banco 1

30. movlw 0x7C ; Inicia periodo de 500Hz.-

31. movwf PR2

32. bcf STATUS,RP0 ; Banco 0.-

33. bsf Signal

34. movlw 0x3E ; Ciclo de trabajo 50%

35. movwf CCPR1L

36. bsf CCP1CON,CCP1X

37. bcf CCP1CON,CCP1Y

38. bsf CCP1CON,CCP1M3 ; Configura modulo CCP modo PWM.-

39. bsf CCP1CON,CCP1M2

40. Bucle

41. btfss PORTB,0 ; Testea si se quiere cambiar de

Frecuencia.-

42. goto $-1 ; No se quiere cambiar.-

43. btfss Signal ; A cual cambiar?

44. goto Cambiar500Hz

45. Cambiar2kHz

46. bsf STATUS,RP0 ; Banco 1

47. movlw 0x1E

48. movwf PR2

49. bcf STATUS,RP0 ; Banco 0

50. bcf Signal ; Señal de 2kHz

51. movlw 0x0F ; Ciclo de trabajo 50%

52. movwf CCPR1L

53. goto Bucle ;

54.

55. Cambiar500Hz

56. bsf STATUS,RP0 ; Banco 1

57. movlw 0x7C ; Inicia periodo de 500Hz.-

58. movwf PR2 ; Señal de 500 Hz.-

59. bcf STATUS,RP0 ; Banco 0.-

60. bsf Signal

61. movlw 0x3E ; Ciclo de trabajo 50%

62. movwf CCPR1L

63. goto Bucle

64. ;...............................................

65. end

Ejemplo 2: 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:

Page 97: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

Código GeSHi (asm):

1. ; **** Encabezado **** 2. list p=16f628A ; list directive to define processor

3. #include <p16f628A.inc> ; processor specific variable definitions

4. __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON &

_INTOSC_OSC_NOCLKOUT & _DATA_CP_OFF & _LVP_OFF & _MCLRE_ON

5. 6. ;**** Definicion de variables **** 7. Contador1 equ 0x20 ;

8. Contador2 equ 0x21 ;

9.

10. decre equ 0 ; Pulsador para decrementar Ciclo

de Trabajo

11. incre equ 1 ; Pulsador para incrementar Ciclo

de Trabajo

12.

13.

14. ;/////////////////////////////////

15. ;**** Inicio del Micro ****

16. Reset.

17. org 0x00 ; Aquí comienza el micro.-

18. goto Inicio ; Salto a inicio de mi programa.-

19.

20. ; **** Programa Principal ****

21. org 0x05

22. Inicio

23. bsf STATUS,RP0 ; Banco 1

24. bsf TRISB,incre ; Como Entrada.-

25. bsf TRISB,decre ; Como Entrada.-

26. bcf TRISB,3 ; RB3 como Salida.

27. bcf STATUS,RP0 ; Banco 0.-

28. movlw b'00000110' ; Se selecciona TMR2, preescaler de 1/16.-

29. movwf T2CON

30. bsf STATUS,RP0 ; Banco 1

Page 98: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com

31. movlw 0x1E ; Señal de 2kHz

32. movwf PR2

33. bcf STATUS,RP0 ; Banco 0

34. clrf CCPR1L ; Ciclo de trabajo 0%

35. bcf CCP1CON,CCP1X

36. bcf CCP1CON,CCP1Y

37. bsf CCP1CON,CCP1M3 ; Configura modulo CCP modo PWM.-

38. bsf CCP1CON,CCP1M2

39. Bucle

40. btfsc PORTB,decre ; Testea si se quiere reducir CT.-

41. goto Decrementa

42. btfsc PORTB,incre ; Testea si se quiere aumentar CT.-

43. goto Incrementa

44. goto Bucle

45. Incrementa

46. incf CCPR1L,1

47. call Demora_50ms

48. goto Bucle

49. Decrementa

50. decf CCPR1L,1

51. call Demora_50ms

52. goto Bucle

53.

54.

55. ;**** Demora ****

56. Demora_50ms

57. movlw 0xFF ;

58. movwf Contador1 ; Iniciamos contador1.-

59. Repeticion1

60. movlw 0x40 ;

61. movwf Contador2 ; Iniciamos contador2

62. Repeticion2

63. decfsz Contador2,1 ; Decrementa Contador2 y si es 0

sale.-

64. goto Repeticion2 ; Si no es 0 repetimos ciclo.-

65. decfsz Contador1,1 ; Decrementa Contador1.-

66. goto Repeticion1 ; Si no es cero repetimos ciclo.-

67. return ; Regresa de la subrutina.-

68. ;..............................................

69. end

Page 99: Tutorial+Assembler 2

Autor: Suky Mail:[email protected] Web:www.infopic.comlu.com