TODOPIC

Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: groundman en 10 de Enero de 2009, 22:47:46

Título: pequeños proyectos
Publicado por: groundman en 10 de Enero de 2009, 22:47:46
hola,queria abrir este tema para publicar pequeños proyectos en asm.muy basicos pero de gran ayuda.
para  hacer funcionar los diferentes modulos integrados en nuestros PICs.sin extendernos en amplios programas que complicarian
el entendimiento de las funciones de estos modulos.

y si hubiera algun error agradeceria me lo indicasen para corregirlo.
Título: Re: pequeños proyectos
Publicado por: groundman en 10 de Enero de 2009, 22:57:33
en este programa,se visualizara por el puerto B. el dato que se reciva por el pin Rx de la usart del pic 16f876.

como practica principal he usado el hiperterminal de windows.que conectando un conversor USB-RS232 con una conexion a 9600 bps.
y culla señal tx.se ha conectado a un adaptador de señales con un MAX232.y de este a la usart del pic(RC7  pin rx)




;****************************************** http://www.ingeniopic.com *******
; PROGRAMA : usart_rx.asm
; Funcion : visualizar datos recividos de la usart por el puerto B.
;           Serial port config: 9600 baudios,8 bits,paridad = none
;   
;  Revision : 1.0        6/1/2009            Programa para : PIC16F876
; CPU Clock : 4 MHz                      Reloj instruccion : 4 MHz = 0.25 us
;       WDT : Deshabilitado                  Tipo de reloj : XT 
; Code Prot : OFF                        velocidad usart: 9.600 Kbps
;****************************************** http://www.ingeniopic.com *******

            LIST   P=16F876         ;Se indica el modo de procesador
     
            RADIX   HEX            ;Sistema de numeracion hexadecimal

            INCLUDE   <P16f876.inc>  ;se incluye la definicion de los registros
               ;registros internos
            __CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF &_WRT_ENABLE_OFF
            ERRORLEVEL      -302     ;para que no se notifiquen los errires por los registros fuera del banco de ram.
                 
BANK0         MACRO               ;macro para la seleccion del banco 0
            BCF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

BANK1         MACRO               ;macro para la seleccion del banco 1
            BSF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
            ORG   0x00            ;Inicio en el Vector de Reset
     
            goto   INICIO            ;Va a la primera instruccion del programa
               
;<<<<<<------------------- VECTOR DE INTERRUPCION -------------------->>>>>>>

            ORG   0x04            ;Vector de interrupcion

           goto   INTER         ;salta a la linea INTER

;<<<<<<----------------- CONFIGURACION DE LOS REGISTROS GENERALES ------------------->>>>>>>
INICIO      BANK1
            clrf   TRISB            ;Puerto B como salida
            bsf    TRISC,7      ;RC7/Rx como entrada 
            movlw   .25            ;valor para seleccionar 9600 baudios
            movwf   SPBRG
            movlw   b'00100100'      ;Configuracion USART modo alta velocidad 9600 baud y activacion de transmision
            movwf   TXSTA            ;carga valor anterior en registro asociado al generador del baud rate
            bsf     PIE1,RCIE      ;Habilitacion interrupcion RX
           BANK0               ;Cambio al banco 0
            movlw   b'10010000'      ;Configuracion de la usart
            movwf   RCSTA            ;para recepcion continua y habilitacion de la usart
            movlw   b'11000000'      ;Habilitacion para las
            movwf   INTCON         ;interrupciones generales
            clrf      PORTB         ;borra las salidas del puerto b
;<<<<<<<<-----------------------------PROGRAMA PRINCIPAL--------------------------->>>>>>>>>>>>>>>>>>>>>>>>     
           
BUCLE         goto      BUCLE            ;espera aqui hasta que salte la interuupcion.




;<<<<<<<<-------------------COMPROVACION DE TIPO DE INTERRUPCION------------>>>>>>>>>>>>>>
   
INTER         BANK0
            btfss   PIR1,RCIF      ;comprueba si el shift register(RSR)esta lleno.y si es asi salta
            retfie               ;retorno de interrupcion si no se ha dado la circunstancia anterior
            
;<<<<<<<<-------------------------VISUALIZACION DE DATO RECIVIDO------------>>>>>>>>>>>>>>
         
LEEDATO     movf      RCREG,W         ;Lectura dato recibido
           movwf   PORTB            ;Visualiza dato recibido
            retfie                  ;retorna de la interrupcion.
     
           END 
Título: Re: pequeños proyectos
Publicado por: groundman en 11 de Enero de 2009, 13:30:03
en este programa se transmite por el pin Tx de la usart del pic 16f876 el dato que metamos en el puerto A.

igual que en el caso anterior he usado el hiperterminal de windows ,el conversor y el adaptador de señales.



;****************************************** http://www.ingeniopic.com *******
; PROGRAMA : usart_tx.asm
; Funcion : transmitir el valor del puerto A.por la usart interna del pic.
;           Serial port config: 9600 baudios,8 bits,paridad = none
;   
;  Revision : 1.0       11/1/2009            Programa para : PIC16F876
; CPU Clock : 4 MHz                      Reloj instruccion : 4 MHz = 0.25 us
;       WDT : Deshabilitado                  Tipo de reloj : XT 
; Code Prot : OFF                        velocidad usart: 9.600 Kbps
;****************************************** http://www.ingeniopic.com *******

            LIST   P=16F876         ;Se indica el modo de procesador
     
            RADIX   HEX            ;Sistema de numeracion hexadecimal

            INCLUDE   <P16f876.inc>  ;se incluye la definicion de los registros
               ;registros internos
            __CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF &_WRT_ENABLE_OFF
            ERRORLEVEL      -302     ;para que no se notifiquen los errires por los registros fuera del banco de ram.

CounterA   EQU   20h            ;registros para retardo
CounterB   EQU   21h
CounterC   EQU   22h
                 
BANK0         MACRO               ;macro para la seleccion del banco 0
            BCF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

BANK1         MACRO               ;macro para la seleccion del banco 1
            BSF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
            ORG   0x00            ;Inicio en el Vector de Reset
     
            goto   INICIO            ;Va a la primera instruccion del programa
               

;<<<<<<----------------- CONFIGURACION DE LOS REGISTROS GENERALES ------------------->>>>>>>
INICIO      BANK0               ;Cambio al banco 0
         clrf   PORTA         ;borra PORTA (para inicializar el puerto)
         movlw   b'10010000'      ;Configuracion de la usart
            movwf   RCSTA            ;para recepcion continua y habilitacion de la usart
         
         BANK1
         movlw   0x06         ;configura PORTA como entradas digitales
         movwf   ADCON1
         movlw   0xff
         movwf   TRISA         ;PORTA como entrada de datos
            bcf      TRISC,6         ;RC6/Tx como salida   
            movlw   .25            ;valor para seleccionar 9600 baudios
            movwf   SPBRG
            movlw   b'00100100'      ;Configuracion USART modo alta velocidad 9600 baud y activacion de transmision
            movwf   TXSTA            ;carga valor anterior en registro asociado al generador del baud rate
            
;<<<<<<<<-----------------------------PROGRAMA PRINCIPAL--------------------------->>>>>>>>>>>>>>>>>>>>>>>>     
           

;<<<<<<<<-------------------------------ENVIO DE DATOS--------------------------->>>>>>>>>>>>>>
ESCRIBEDATO   BANK0
                              movfw   PORTA
         movwf   TXREG
         
COMP_TX     btfsc   TXSTA,TRMT      ;comprueba si el shift register(TSR)esta lleno.y si es asi salta.
            goto      COMP_TX
         call    RETARDO         ;pausa para el envio de datos
         GOTO   ESCRIBEDATO
         
;<<<<<<----------------------- RUTINAS DE RETARDO ------------------------->>>>>>>

RETARDO     
            movlw   D'6'
            movwf   CounterC
            movlw   D'24'
            movwf   CounterB
            movlw   D'168'
            movwf   CounterA
loop         decfsz   CounterA,1
            goto   loop
            decfsz   CounterB,1
            goto   loop
            decfsz   CounterC,1
            goto   loop
            return         
         
     
           END 
Título: Re: pequeños proyectos
Publicado por: pibe en 11 de Enero de 2009, 15:22:12
Gracias por tu aporte pero creo que este tópico iría mejor en la sección ALMACEN DEL ASSEMBLER , donde hay todo tipo de ejemplos en asm.
Título: Re: pequeños proyectos
Publicado por: groundman en 11 de Enero de 2009, 19:30:00
se que en parte deberia estar dode dices.ya lo habia pensado.
lo que pasa es que mi intencion es añadirle a las respuestas enlaces para la descarga de los circuitos con los que van
a funcionar.almenos para algunos de los pequeños proyectos que posteare.y veia que seria engorroso tener los proyectos en distintos hilos.
Título: Re: pequeños proyectos
Publicado por: jfh900 en 11 de Enero de 2009, 20:48:20
Puedes postear todos los proyectos en este hilo y si te parece bien lo movemos al almacén de ASM, que yo también creo que estará mejor allí.

Un saludo
Título: Re: pequeños proyectos
Publicado por: groundman en 11 de Enero de 2009, 21:15:55
de acuerdo,no hay ningun problema.se podria mober al almacen del ensembler.
y los proyectos los pondria en el hilo de pequeños proyectos.

voy a ver que tal queda.y si algo queda mal supongo que se podria arreglar.
Título: Re: pequeños proyectos
Publicado por: Leon Pic en 11 de Enero de 2009, 21:46:13
Muy útil será este tema. Gracias Groudman
Título: Re: pequeños proyectos
Publicado por: groundman en 12 de Enero de 2009, 18:54:46
no hay de que darlas.para mi es muy gratificante el poder contribuir en el foro, para avanzar en el conocimiento de este tipo de microcontroladores.

en el foro hay mucho codigo asm para el desarollo de aplicaciones y me han sido de gran utilidad en mis proyectos.
pero resultaria mas util para los principiantes,tener un programa listo para funcionar.sin instrucciones de mas.
basicamente utilizar el puerto A para enviar datos y el puerto B para recivirlos.

saludos.
Título: Re: pequeños proyectos
Publicado por: jfh900 en 12 de Enero de 2009, 21:43:49
Yo no programo en ASM mas que lo estrictamente necesario, pero creo que tu idea es muy buena y puede ayudar a mucha gente que comience. Animo y gracias por tu esfuerzo hombre masa, digo groundman  :-)

Un saludo
Título: Re: pequeños proyectos
Publicado por: groundman en 13 de Enero de 2009, 12:50:35
jejeje.parece que has descifrado el nick.resulta que hace mucho tiempo buscaba un nick relacionado con la electronica.y vi por ahi el de vccman.
y se me ocurrio poner groundman.para que sepais que lo de hombre masa no va por los musculos. :D
ya que los tecnicos electronicos por norma general no solemos ejercitar mucho los musculos del cuerpo.quizas el unico musculo que solemos ejercitar  el que tenemos dentro de la cabeza.y en estos ultimos años tambien el de los dedos.quien  iva a decir que los ordenadores fueran a ser la herramienta imprescindible.
aun me acuerdo cuando cojia una libreta y un boli.y empezaba a dibujar puertas logicas para crear mis proyectos de electronica.

el primer circuito digital que realize y sin copiarme de ningun circuito ya hecho.fue un dado electronico.con un display y otros cuantos componentes.
y la primera vez que conoci los pic.fue en una revista,donde se explicaba como montar un circuito para recivir la señal meteosat.y visualizar la imagen
de españa desde el satelite.pero lo vi un poco complicado y descarte el montage.aparte de que por aquel tiempo todavia realizaba las placas con rotulador.
por entonces no habia la informacion que hay hoy en dia en internet.

bueno no me enrroyo y haver si pronto empiezo a subir mas ejemplos para experimentar.
Título: Re: pequeños proyectos
Publicado por: pity en 16 de Enero de 2009, 10:07:28
Asi vamos armando esto
este es un programa que toma un valor analogico por el puerto A pin 1 , lo compara con un valor prefijado, que en este caso es 100 en decimal, y si es mayor prende un led y si es menor prende otro. de paso muestra el valor medido en el puerto B

inicialmente esta pensado para un termostato, y de paso, ver el valor
ahora estoy trabajando en esto mismo, pero que me muestre el valor en decimal en un LCD 2 x 16, pero para eso falta todavia q2ue descule como se pasa un numero binario a los 3 valores decimales de unidad decena y centena


list   P=16F877   ;Se indica el modo de procesador
      
include   "P16f877.inc"   ;se incluye la definicion de los
               ;registros internos
PDel0         EQU       0x21      
PDel1          EQU      0x22
PDel2         EQU    0x23
Temp         EQU      0x24      
Seteo         EQU      b'1100100'

;      PORTA COMO ENTRADA ANALOGICA
;
;
;----------------------------------------------------------------------------
INICIO

      org       0x00      ;vector de inicio
      nop      
      nop
      


      

;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>

      bsf      STATUS,RP0   ;Pone en 1 RP0 (para seleccionar banco 1)
      bcf      STATUS,RP1   ;Pone en 0 RP1 (para seleccionar banco 1)
      clrf   Temp      ;cargo todos 0 en Temp

                  ;Configuracion de puertos
      clrf      TRISB      ;PORTB como salida
      clrf      TRISC      ;PORTC como salida
      clrf      TRISD      ;PORTD como salida
      clrf      TRISE      ;PORTE como salida
      movlw      b'11111111'   ;Carga W con b'11111111'
      movwf      TRISA      ;PORTA como entrada

      movlw      b'11000001'   ;Configura ADCON1
      movwf      ADCON1      ;Todo el PORTA como entrada analógica, VDD = VREF+, VSS = VREF-





      bcf         STATUS,RP0   ;Pone en 0 RP0 (para seleccionar banco 0)
      bcf         STATUS,RP1   ;Pone en 0 RP1 (para seleccionar banco 0)
   
      clrf      PORTA      ;Limpia todos los puertos
      clrf      PORTB
      clrf      PORTC
      clrf      PORTD
      clrf      PORTE
   
      movlw      b'10000111'   ;Configura ADCON0
      movwf      ADCON0      ;FOSC/64
                  ;Channel 0 (AN0)
                  ;GO = 1 ADON = 1



LOOP   
      clrf      PORTA
      bsf         ADCON0,GO   ;Set en GO para iniciar la conversion del coversor AD
      call      DEMORA      ;Salta a demora de 50 ms
      movf      ADRESH,W    ;mueve la parte alta de la conversion al PORTB
      movwf      PORTB
      
               
            
      bsf         STATUS,RP0   ;Pone en 1 RP0 (para seleccionar banco 1)
      bcf         STATUS,RP1   ;Pone en 0 RP1 (para seleccionar banco 1)
   
      movf      ADRESL,W    ;mueve la parte baja de la conversion al PORTD
      bcf         STATUS,RP0   ;Pone en 0 RP0 (para seleccionar banco 0)
      bcf         STATUS,RP1   ;Pone en 0 RP1 (para seleccionar banco 0)
      movwf      Temp      ;cargo el valor leido en la posicion de memoria Temp

      movwf      PORTD      ;cargo el valor leido en el puerto D

       movlw      b'1100100'   ;cargo el valor de seteo 100 en W
      subwf      Temp,W      ; resto punto seteado contra lo leido
      movwf      PORTC
      btfss      STATUS,C   ;si el status c es 1 es que el seteo es mayor o igual que el valor medido y la dif es negativa
      goto      ENFRIA      ;si es 0
      bsf         PORTB,7      ;si es 1 es que la resta dio negativa, prende el calefactor y el led
      bcf         PORTB,6      ;apaga el led anterior al que prendi
      goto       LOOP
      



   
ENFRIA
      bcf         PORTC,0      ;la temp es mayor a lo seteado, apaga el led
      bcf         PORTB,7      ;apaga el calefactor
      bsf         PORTB,6      ;funcion inversa al del anterior
      call      DEMORA      ;espera
      goto      LOOP      ;vuelve al loop



;-------------------------demora de 50 ms-----------------
DEMORA  movlw     .197      ; 1 set numero de repeticion  (B)
        movwf     PDel0     ; 1 |
PLoop1  movlw     .253      ; 1 set numero de repeticion  (A)
        movwf     PDel1     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        clrwdt              ; 1 ciclo delay
        decfsz    PDel1, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto PDelL2         ; 2 ciclos delay
PDelL2 
        return              ; 2+2 Fin.



   END
Título: Re: pequeños proyectos
Publicado por: Suky en 16 de Enero de 2009, 10:50:34
Esta muy buena la idea!! Los que estamos empezando siempre nos viene bien un ejemplito que "abra la cabeza"  :-)
En cualquier momento posteo algo...
Título: Re: pequeños proyectos
Publicado por: groundman en 16 de Enero de 2009, 19:08:57
hola pity.me parece muy bueno tu proyecto.lo que pasa es que mi intencion era crear mini proyectos basicos. para que el principiante entienda el funcionamiento basico de los modulos internos de nuestros pic.
hubiera estado muy bien que hubieras puesto el proyecto que describes en dos partes en la que se maneja el modulo analogico.y la funcion de comparacion entre dos valores.
y despues si que estaria muy bien el avanzar con la mezcla de ambos.
queria sugerirte que hay una funcion para comparar valores analogicos en este modulo interno del pic.y tu proyecto quedaria muy bien si utilizaras esta funcion.
se basa en la comparacion de dos valores que estan en AN2(Vref-) o AN3(Vref+) y otro valor que puedes meter con el sensor de temperatura en AN1 o la entrada analogica que te quede libre.pero no puedo decirte mas porque nunca he experimentado con esta funcion.y tampoco se si estoy en lo cierto.
aunque experimentando un poco creo que tiene que ser facil.
y te animo a que contrivuyas con tu experiencia en estos cacharritos.saludos.
Título: Re: pequeños proyectos
Publicado por: Suky en 16 de Enero de 2009, 21:14:29
Este es un programita que se encarga de controlar un LCD, es flexible y se puede modificar el puerto que lo controla.
Es para control a 4 bits.-
Se adjunta esquematico del Hardware
;============================================
;   Compilado en MPLAB IDE v7.42
;   inf.labwindows@live.com.ar
;============================================

   List p=16f84a
   #include <p16f84a.inc>
   __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC


;===============================
;                  Declaración de Registros
;===============================
datoa      equ     0x0C   ;registro para enviar a LCD el nible alto
datob        equ    0x0D   ;registro para enviar a LCD el nible bajo
PDel0       equ    0x0E   ;registro para demoras
PDel1       equ    0x0F   ;registro para demoras
PDel2      equ    0x10   ;registro para demoras
loop      equ    0x11   ;registro para inicializacion del LCD
Digito      equ    0x12   ;Registro para seleccionar digito a visualizar
Contador   equ    0x13   ;Registro para mover mensaje en Display

; Declaracionde bit del LCD
enable      equ    6
rs      equ    5
rw      equ    4
backlight   equ    7
bf      equ    3

; Declaracion de Bytes del LCD
PORT_LCD   equ    0x06 ; PORTB para control del LCD
TRIS_LCD   equ    0x86

; <<    COMANDO  >>
; Borrar Display         0x01
; Ir al Inicio            0x02
;--- Modos de Entrada
; Incrementa Direccion, Display fijo   0x06
; Decrementa Direccion, Display fijo   0x04
; Incrementa Direccion, Cursor fijo   0x07
; Decrementa Direccion, Cursor fijo   0x05
;--- Encendido Display
; Apagar Display         0x08
; Encender Display         0x0C
; Encender Display y Cursor      0x0E
; Encender Display y Cursor Parpadeando   0x0F
; Encender Display con parpadeo      0x0D
;--- Corriemiento Cursor
; Cursor a la Izquierda         0x10
; Cursor a la Derecha         0x14
; Display a la Izquierda      0x18
; Display a la Derecha         0x1C
;--- Fijar Sistema
; Bus 8 bits, 1 línea, 5x7      0x30
; Bus 8 bits, 1 linea, 5x10      0x34
; Bus 8 bits, 2 líneas, 5x7      0x38
; Bus 4 bits, 1 línea, 5x7      0x20   
; Bus 4 bits, 1 linea, 5x10      0x24
; Bus 4 bits, 2 líneas, 5x7       0x28
;---Control de Posicion de Cursor
; Linea 1            0x80 hasta 0x8F
; Linea 2            0xC0 hasta 0xCF



      goto         inicio
;**********************************************

;==============================================
;                           INICIO
;==============================================
;==============================================
;     configuracion de puertos
;==============================================
inicio
      banksel         TRIS_LCD   ;Seleccionamos bank de TRIS_LCD
      clrf         TRIS_LCD   ;Configuramos puerto
;==============================================
;configuracion de LCD
;==============================================
      banksel         PORT_LCD
      call         demora_150ms
      movlw         0x03
      movwf         loop   ; 3 ciclos para inicializacion
Inicializacion
      movlw         0x03
      movwf         PORT_LCD
      bsf            PORT_LCD,enable          
      call         demora_4ms   
      bcf            PORT_LCD,enable
      call         demora_4ms   
      decfsz         loop
      goto         Inicializacion
;Interfase de 4 bits
      movlw         0x02
      movwf         PORT_LCD
      bsf            PORT_LCD,enable   ;enable      
      call         demora_4ms   
      bcf            PORT_LCD,enable
      call         demora_4ms   
         
;Fijar sistema...<< Bus de 4 bits, 2 lineas, 5x7>>
      movlw         0x28
      call         prep_dato_lcd   ;   Prepara los datos para enviar (Nible alto y nible Bajo)
      call         lcd_envia_coman   ;   Envia comando al LCD --> RS=0
   
;Limpia display y retorna al origen
      movlw         0x01
      call         prep_dato_lcd
      call         lcd_envia_coman
;Encendemos el LCD
      movlw         0x0C
      call         prep_dato_lcd
      call         lcd_envia_coman

;==============================================
;Datos al LCD
;==============================================
;Colocamos cursor en Linea 1, Posicion 8.-
      movlw         0x88         
      call         prep_dato_lcd
      call         lcd_envia_coman
;*************************************************
;Escribimos TODO PIC en el diplay
      clrf         Digito
repetir     movf            Digito,w         
                  call            tabla            ;obtiene el caracter
                  iorlw           0                ;Compara
                  btfsc           STATUS,2         ;Es el ultimo?
                  goto            seguir           ;Si
                  call             prep_dato_lcd   ;Se prepara para enviar
      call         lcd_envia_carac   ;Visualiza caracter --> RS=0
                  incf              Digito,f         ;Incrementa numero de Digito
                  goto           repetir          ;Vuelve a escribir
;*************************************************
;Movemos Display de derecha a izquierda y viceverza
                  
      clrf         Contador      ;Para contar las posiciones de movimiento del Display      
seguir         
               
      call         demora_150ms      ; Demora para visualizar el efecto
      movlw         0x1C         ; Comando para mover Display a la Izquierda
      call         prep_dato_lcd
      call         lcd_envia_coman
      incf         Contador,1
      movlw         d'8'
      subwf         Contador,0
      btfss         STATUS,Z      ; Se movio 8 posiciones?
      goto         seguir         ; No
      clrf         Contador      ; Si, comenzamos a mover a la Derecha
re_seguir      
                  
      call         demora_150ms
      movlw         0x18         ; Comando para mover Display a la Derecha
      call         prep_dato_lcd
      call         lcd_envia_coman
      incf         Contador,1
      movlw         d'8'
      subwf         Contador,0
      btfss         STATUS,Z      ; Se movio 8 posiciones?
      goto         re_seguir      ; No
      clrf         Contador      ; Si, Comenzamos a mover a la Izquierda
                 goto              seguir          ; Buclee infinito

;***********************************************
; Caracteres a enviar al LCD
tabla
      addwf          PCL,1
      retlw           'T'
      retlw           'O'
      retlw           'D'
      retlw           'O'
      retlw           ' '
      retlw           'P'
      retlw           'I'
      retlw           'C'
      retlw          0x00


 
;==============================================
;SUBRUTINAS
;==============================================
;**********************************************
;Prepara nible bajo y nible alto para enviar.(Si el nible del LCD es el bajo del puerto (Ver esquematico))
prep_dato_lcd
      movwf         datob      ; 0xXY
      swapf         datob,w      ; 0xYX
      movwf         datoa      ; 0xYX
      movlw         0x0F      
      andwf         datoa,1      ; 0x0X
      andwf         datob,1      ; 0x0Y   
               return
;**********************************************
prender_backlight
      banksel       PORT_LCD
      bsf          PORT_LCD,backlight
      return
;**********************************************
apagar_backlight
      banksel         PORT_LCD
      bcf            PORT_LCD,backlight
      return
;**********************************************
LCD_BANDERA
      bcf         PORT_LCD,0  ; para borrar datos anteriores sin borrar backligth
      bcf         PORT_LCD,1
      bcf         PORT_LCD,2
      bcf         PORT_LCD,3
      bcf         PORT_LCD,rw
      bcf         PORT_LCD,rs
      bcf         PORT_LCD,enable
      nop
      bsf         PORT_LCD,rw   ; R/W =1 Lectura
      banksel       TRIS_LCD
      movlw         0x0F   ;configuramos banco para leer bandera
      movwf         TRIS_LCD
      banksel       PORT_LCD
      bsf         PORT_LCD,enable   ; Enable =1   
      nop
espera      btfsc         PORT_LCD,bf ;testea estado
      goto          espera   ; No esta desocupado, esperamos
      bcf           PORT_LCD,enable   ; Si seguimos, Enable =0
      banksel       TRIS_LCD
      clrf          TRIS_LCD
      banksel         PORT_LCD
      return
;**********************************************
LCD_ENABLE
      bsf          PORT_LCD,enable   ; Enviamos un pulso de Enable
      nop
      nop
      bcf         PORT_LCD,enable
      return
;**********************************************
lcd_envia_coman ;RS=0 Selección registro de control
      ;call         LCD_BANDERA  ;Controla si el LCD esta en condiciones de recibir un nuevo dato
      call         demora_4ms
      btfss          PORT_LCD,backlight ; Preguntamos estado del Backlight >>
      goto          back0_1   ; << para mantener su estado despues de enviar el dato >>
      movlw          0x80   ; << al LCD
      addwf          datoa,W   
      movwf         PORT_LCD   ;Enviamos nible alto al LCD
      call          LCD_ENABLE   
Preg0
      btfss          PORT_LCD,backlight   ; Preguntamos estado del Backlight
      goto          back0_2
      movlw          0x80
      addwf         datob,W   
      movwf            PORT_LCD   ; Enviamos nible bajo al LCD
      call         LCD_ENABLE
      return
back0_1
      movf            datoa,W   ; No esta encendido Backlight
      movwf           PORT_LCD   ; Enviamos nible alto al LCD
      call          LCD_ENABLE
      goto          Preg0
back0_2
      movf          datob,W   ; No esta encendido Backlight
      movwf          PORT_LCD   ; Enviamos nible bajo al LCD
      call         LCD_ENABLE
      return
;**********************************************
lcd_envia_carac ;RS=1 Selección registro de datos
      ;call         LCD_BANDERA ;Controla si el LCD esta en condiciones de recibir un nuevo dato
      call         demora_4ms
      btfss         PORT_LCD,backlight  ; Preguntamos estado del Backlight>>
      goto          back00_1 ; << para mantener su estado despues de enviar el dato>>
      movlw              0xA0    ; << al LCD
      addwf         datoa,w
      movwf         PORT_LCD   ;Enviamos nible alto al LCD
      call          LCD_ENABLE
Preg1   
      btfss          PORT_LCD,backlight
      goto          back00_2
      movlw           0xA0
      addwf         datob,w
      movwf         PORT_LCD   ; Enviamos nible bajo al LCD
      call          LCD_ENABLE
      return
back00_1
      movlw         0x20
      addwf         datoa,w   ; No esta encendido Backlight
      movwf         PORT_LCD   ;Enviamos nible alto al LCD
      call          LCD_ENABLE
      goto          Preg1
back00_2
      movlw         0x20
      addwf         datob,w   ; No esta encendido Backlight
      movwf         PORT_LCD   ; Enviamos nible bajo al LCD
      call         LCD_ENABLE
      return
;**********************************************

;----------------------------------------------------------------------------
;                             DEMORAS
;----------------------------------------------------------------------------
demora_150ms
      movlw           .117     
             movwf           PDel0   
PLoop0_     movlw           .213       
           movwf           PDel1     
PLoop1_     movlw           .1     
           movwf           PDel2     
PLoop2_     nop                 
           decfsz          PDel2, 1 
           goto            PLoop2_   
           decfsz          PDel1,  1
           goto            PLoop1_   
             decfsz          PDel0,  1
           goto            PLoop0_   
PDelL1_     goto          PDelL2_       
PDelL2_     nop                 
           return     
;**********************************************
demora_4ms
      movlw           .5     
      movwf           PDel0     
PLoop3      movlw           .159     
      movwf           PDel1     
PLoop4      NOP             
      decfsz          PDel1,1 
      goto            PLoop4   
      decfsz          PDel0,1 
      goto            PLoop3   
PDelL3      goto            PDelL4         
PDelL4      NOP           
      return   
;*********************************************       

      end

Título: Re: pequeños proyectos
Publicado por: groundman en 17 de Enero de 2009, 12:15:48
y aqui pongo un programa para la recepcion y emision por usart.es una mezcla de los programas de arriva usart_rx.asm y usart_tx.
el dato que entra por el puerto A sale por tx.para visualizarlo por ejem.en el hiperterminal de windows.
y la tecla que se pulsa en el hiperterminal de windows.mete el dato por rx del pic para bisualizarlo por el puerto B.

el programa en si,contiene un bucle para la emision continua de caracteres ascii hacia el hiperterminal.los datos que se emiten son los que introducamos en el
puerto A del pic.
y la visualizacion de los datos recividos se realizara por el purto B.despues de que salte la interrupcion por transferencia completa RCIF.
pero para que esto suceda,no puede haber ningun cable conectado en el pin TX.de lo contrario no se visualizaran los datos en el puerto B.
no se si es culpa del hiperterminal.pero si lo aberiguo ya lo pondre por aqui.




;****************************************** http://www.ingeniopic.com *******
; PROGRAMA : usart_rx_tx.asm
; Funcion : visualizar datos recividos de la usart por el puerto B y transmitir el valor del puerto A.por la usart interna del pic. .
;           (hay que desconectar cualquier cable conectado en TX,para poder recivir por RX)
;           Serial port config: 9600 baudios,8 bits,paridad = none
;   
;  Revision : 1.0        6/1/2009            Programa para : PIC16F876
; CPU Clock : 4 MHz                      Reloj instruccion : 4 MHz = 0.25 us
;       WDT : Deshabilitado                  Tipo de reloj : XT 
; Code Prot : OFF                        velocidad usart: 9.600 Kbps
;****************************************** http://www.ingeniopic.com *******

            LIST   P=16F876         ;Se indica el modo de procesador
     
            RADIX   HEX            ;Sistema de numeracion hexadecimal

            INCLUDE   <P16f876.inc>  ;se incluye la definicion de los registros
               ;registros internos
            __CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF &_WRT_ENABLE_OFF
            ERRORLEVEL      -302     ;para que no se notifiquen los errires por los registros fuera del banco de ram.

CounterA      EQU  20h            ;registros para retardo
CounterB      EQU  21h
CounterC      EQU  22h
W_TEMP         EQU    23h
STATUS_TEMP   EQU    24h
PCLATH_TEMP   EQU    25h   

         #define      GIE_ON   bsf      INTCON,GIE
         #define      GIE_OFF   bcf      INTCON,GIE
   
                 
BANK0       MACRO                  ;macro para la seleccion del banco 0
            BCF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

BANK1       MACRO                  ;macro para la seleccion del banco 1
            BSF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

PUSH      MACRO               ;macro para salvar registros antes de una llamada a interrupcion   
         movwf   W_TEMP               
            swapf   STATUS,W
            movwf   STATUS_TEMP         
            clrf      STATUS               
            movfw   PCLATH               
           movwf   PCLATH_TEMP
            clrf      PCLATH
         ENDM

POP         MACRO               ;macro para restaurar registros   despues de una llamada a interrupcion
         movfw   PCLATH_TEMP         
            movwf   PCLATH
            swapf   STATUS_TEMP,W      
            movwf   STATUS
            swapf   W_TEMP,F         
            swapf   W_TEMP,W
         ENDM

;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
            ORG   0x00               ;Inicio en el Vector de Reset
     
            goto   INICIO           ;Va a la primera instruccion del programa
               
;<<<<<<------------------- VECTOR DE INTERRUPCION -------------------->>>>>>>

            ORG   0x04               ;Vector de interrupcion

           goto   INTER            ;salta a la linea INTER

;<<<<<<----------------- CONFIGURACION DE LOS REGISTROS GENERALES ------------------->>>>>>>
INICIO                     
         BANK0                  ;Cambio al banco 0
         clrf   PORTA         ;borra puerto A
           movlw   b'10010000'     ;Configuracion de la usart
            movwf   RCSTA           ;para recepcion continua y habilitacion de la usart
           
         BANK1
         movlw   0x06            
           movwf   ADCON1         ;configura PORTA como entradas digitales
         movlw   0xff
            movwf   TRISA            ;PORTA como entrada de datos
            clrf   TRISB            ;Puerto B como salida de datos
            bsf      TRISC,7         ;RC7/Rx como entrada
         ;bcf      TRISC,6         ;RC6/Tx como salida     
            movlw   .25               ;valor para seleccionar 9600 baudios
            movwf   SPBRG         ;mete el valor en el registro baud rate generator
            movlw   b'00100100'     ;Configuracion USART modo alta velocidad 9600 baud y activacion de transmision
            movwf   TXSTA           ;carga valor anterior en registro asociado al generador del baud rate
            bsf     PIE1,RCIE       ;Habilitacion interrupcion RX

         BANK0
         clrf      PORTB         ;borra las salidas del puerto b
         movlw   b'11000000'     ;Habilitacion para las
            movwf   INTCON            ;interrupciones generales y perifericas.
   
           
;<<<<<<<<-----------------------------PROGRAMA PRINCIPAL--------------------------->>>>>>>>>>>>>>>>>>>>>>>>     
            nop                  ;aqui se pondra el programa principal y cuando queramos mandar un dato,
         nop                  ;solo tendremos que hacer un salto al programa de envio de datos "ESCRIBEDATO"
PRINCIPAL   call   ESCRIBEDATO      
         GOTO   PRINCIPAL
;<<<<<<<<-------------------------------ENVIO DE DATOS--------------------------->>>>>>>>>>>>>>
ESCRIBEDATO   GIE_OFF               ;deshabilita interrupciones.para que cuando este enviando un dato,no haya errores
         BANK0               ;selecciona banco 0
         movfw   PORTA         ;caraga en w el contenido del puerto A
         movwf   TXREG         ;escribe los datos en el registro de envio de datos
         BANK1               ;selecciona banco1
COMP_TX     btfsc   TXSTA,TRMT      ;comprueba si el shift register(TSR)esta lleno.y si es asi salta.
            goto      COMP_TX         ;en caso contrario bucle infinito.
         BANK0               ;selecciona banco 0
         GIE_ON               ;habilita interrupciones
         call    RETARDO         ;pausa para el envio de datos
         return               ;retorna a PRINCIPAL

;<<<<<<<<-------------------COMPROVACION DE TIPO DE INTERRUPCION------------>>>>>>>>>>>>>>
   
INTER        PUSH                 ;salva el contenido de W,STATUS Y PCLATH
         BANK0
         btfsc   PIR1,RCIF         ;comprueba si el shift register(RSR)esta lleno.y si es asi salta
         goto   LEEDATO         
         POP                  ;restaura el contenido de W,STATUS Y PCLATH
            retfie                  ;retorno de interrupcion si no se ha dado la circunstancia anterior
           
;<<<<<<<<-------------------------VISUALIZACION DE DATO RECIVIDO------------>>>>>>>>>>>>>>
         
LEEDATO     BANK0
         movf    RCREG,W         ;Lectura dato recibido
              movwf   PORTB           ;Visualiza dato recibido en el puerto B
         POP                  ;restaura el contenido de W,STATUS Y PCLATH
            retfie                  ;retorna de la interrupcion.
         
         
;<<<<<<----------------------- RUTINAS DE RETARDO ------------------------->>>>>>>

RETARDO                        ;sub programa para realizar una pausa en el envio de datos
            movlw   D'1'
            movwf   CounterC
            movlw   D'20'
            movwf   CounterB
            movlw   D'50'
            movwf   CounterA
loop         decfsz   CounterA,1
            goto   loop
            decfsz   CounterB,1
            goto   loop
            decfsz   CounterC,1
            goto   loop
            return         
     
           END 
Título: Re: pequeños proyectos
Publicado por: groundman en 17 de Enero de 2009, 17:31:47
este programa transmite un mensage en ascii al iperterminal de windows.la velocidad de transmision de caracteres
podemos graduarla modificando los valores de la rutina de retardo.


;****************************************** http://www.ingeniopic.com *******
; PROGRAMA : usart_mensage.asm
; Funcion : transmitir un mensage por la usart interna del pic hacia el hiperterminal de windows.
;           Serial port config: 9600 baudios,8 bits,paridad = none
;   
;  Revision : 1.0       11/1/2009            Programa para : PIC16F876
; CPU Clock : 4 MHz                      Reloj instruccion : 4 MHz = 0.25 us
;       WDT : Deshabilitado                  Tipo de reloj : XT 
; Code Prot : OFF                        velocidad usart: 9.600 Kbps
;****************************************** http://www.ingeniopic.com *******

            LIST   P=16F876         ;Se indica el modo de procesador
     
            RADIX   HEX            ;Sistema de numeracion hexadecimal

            INCLUDE   <P16f876.inc> ;se incluye la definicion de los registros
                                 ;registros internos
            __CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF &_WRT_ENABLE_OFF
            ERRORLEVEL      -302     ;para que no se notifiquen los errires por los registros fuera del banco de ram.

CounterA      EQU      20h            ;registros para retardo
CounterB      EQU      21h
CounterC      EQU      22h
KEY_1      EQU    23h            ;registro de puntero de tabla
TEMP_DATOS   EQU      24h            ;registro temporal de datos
                 
BANK0         MACRO               ;macro para la seleccion del banco 0
            BCF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

BANK1         MACRO               ;macro para la seleccion del banco 1
            BSF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
            ORG   0x00            ;Inicio en el Vector de Reset
     
            goto   INICIO            ;Va a la primera instruccion del programa
               

;<<<<<<----------------- CONFIGURACION DE LOS REGISTROS GENERALES ------------------->>>>>>>
INICIO      BANK0               ;Cambio al banco 0
         movlw   b'10010000'      ;Configuracion de la usart
            movwf   RCSTA            ;para recepcion continua y habilitacion de la usart
         BANK1
         movlw   0x06         ;configura PORTA como entradas digitales
         movwf   ADCON1
         bcf      TRISC,6         ;RC6/Tx como salida
         clrf   PORTB         ;puerto B como salida
            movlw   .25            ;valor para seleccionar 9600 baudios
            movwf   SPBRG
            movlw   b'00100100'      ;Configuracion USART modo alta velocidad 9600 baud y activacion de transmision
            movwf   TXSTA            ;carga valor anterior en registro asociado al generador del baud rate
            
;<<<<<<<<-----------------------------PROGRAMA PRINCIPAL--------------------------->>>>>>>>>>>>>>>>>>>>>>>>     
PRINCIPAL   BANK0               ;selecciona banco 0
         clrf   KEY_1         ;borra el puntero de tabla
         call   ESCRIBEDATO    ;salta al programa para escribir datos
         goto   PRINCIPAL           

;<<<<<<<<-------------------------------ENVIO DE DATOS--------------------------->>>>>>>>>>>>>>
ESCRIBEDATO   BANK0
         
         call   DATOS         ;busca caracter ascii en la tabla de datos
         movwf   TEMP_DATOS      ;mete el resultado de la busqueda en el registro temporal de datos
         xorlw   0xff         ;valor de fin de tabla
         btfsc   STATUS,Z      ;comprueva si ha leido el valor indicado
         return               ;retorna si ha a llegado al final de la tabla
         movfw   TEMP_DATOS      ;carga en W el valos guardado anteriormante en el registro temporal de datos
         movwf   TXREG         ;mete el valor en el registro de transmision de datos
         movwf   PORTB         ;saca el valor por el puerto B
         incf   KEY_1,F         ;incrementa el puntero de tabla
         BANK1
COMP_TX     btfsc   TXSTA,TRMT      ;comprueba si el shift register(TSR)esta lleno.y si es asi salta.
            goto      COMP_TX         ;si no,espera
         call    RETARDO         ;pausa para el envio de datos
         GOTO   ESCRIBEDATO      ;buelve a escribir el siguiente dato
;<<<<<<--------------------------------DATOS A EMITIR---------------------------->>>>>>>>>>>

DATOS      
         movf      KEY_1,W
            addwf   PCL,F
            ;addwf   PCL,1
         retlw   '"'
         retlw   'W'
            retlw   'W'
            retlw   'W'
            retlw   '.'
            retlw   'I'
            retlw   'N'
            retlw   'G'
            retlw   'E'
            retlw   'N'
            retlw   'I'
            retlw   'O'
            retlw   'P'
         retlw   'I'
            retlw   'C'
         retlw   '.'
         retlw   'C'
            retlw   'O'
            retlw   'M'
         retlw   '"'   
         retlw   ' '
         retlw    0xff

         
;<<<<<<---------------------------- RUTINAS DE RETARDO ------------------------->>>>>>>

RETARDO     
            movlw   D'2'
            movwf   CounterC
            movlw   D'1'
            movwf   CounterB
            movlw   D'1'
            movwf   CounterA
loop         decfsz   CounterA,1
            goto   loop
            decfsz   CounterB,1
            goto   loop
            decfsz   CounterC,1
            goto   loop
            return         
         
     
           END 
Título: Re: pequeños proyectos
Publicado por: jhozate en 31 de Enero de 2009, 23:51:11
muchas gracias por este aporte..justo lo q necesitaba, tengo una inquietudes con respecto al usart_rx_tx.asm
1- estuve simulando(en proteus) y encuentro q el TX siempre esta enviando el dato, a la hora de hacer comunicacion con el pc, seria conflictivo que simpre hayan datos en la linea.?
2- Tambien en la simulacion tan solo se permiten enviar datos de 4 bits, y los datos que presenta el virtual terminal solo corresponden cuando el bit 6 y 7 estan en 1
Título: Re: pequeños proyectos
Publicado por: jhozate en 01 de Febrero de 2009, 00:09:54
creo q estaba algo desinformado, lo de los 4 bit corresponde al codigo baudot?...pero igual para baudot son 5 bits y en simulacion solo se pueden usar 4 bits...adjunto unas capturas de pantalla para ver la simulacion...observa q la primera imagen es correcto el dato que se envia..es el "1"...pero en la segunda imagen..si cambiamos el estado de RA4 a "0" cambia el dato por un "!"....
Título: Re: pequeños proyectos
Publicado por: PACMER en 03 de Febrero de 2009, 09:13:28
codigo ASCII es la respuesta a tu duda

lo que esta leyendo el pic del puerto A es un valor binario
y al transmitirlo se convierte en codigo ascii

DIP         1   2   3   4   5   6   7   8
VALOR    1   2   4   8   16 32 64 128

en la pantalla uno tu dip esta:

|          binario             |dec |ascii |
|0  0    1   1   0   0   0 1|      |       |
|0+0+32+16+0+0+0+1| 49 |   1  |

pantalla 2:
|0  0    1   0  0  0  0  1  |      |      |
|0+0+32+0+0+0+0+1  | 33 |   !  |


esa es la razon :mrgreen:

descarga el adjunto
Título: Re: pequeños proyectos
Publicado por: jhozate en 03 de Febrero de 2009, 16:22:19
hola,,,gracias PACMER por la respuesta, tu programas en assembler? lo q pasa es q he estado tratanto de modificar el programa que esta mas arriba en este post llamado usart_rx_tx.asm,,,quisieras saber si me puedes colaborar...el programa asi como esta en el post siempre se encuentra enviando un dato por el TX y yo lo cambie a que solo se envie el dato cuando reciba "1" por el RX,,,pero el programa simulando presenta  unos errores.
Título: Re: pequeños proyectos
Publicado por: groundman en 03 de Febrero de 2009, 20:48:26
hola jhozate.te he modificado el programa rapidamente.asi que puede que sobren algunas lineas para que estubiera mas depurado.pero a mi me funciona.
solo tienes que pulsar la tecla '1' y reciviras en el hiperterminal el dato introducido en el puerto A.en formato ascii.


;****************************************** http://www.ingeniopic.com *******
; PROGRAMA : usart_rx_tx_v2.asm
; Funcion : visualizar datos ascii entregados por el puerto A.cuando se pulse la tecla '1' mediante el hiperterminal.
;           
;           Serial port config: 9600 baudios,8 bits,paridad = none
;   
;  Revision : 1.0        6/1/2009            Programa para : PIC16F876
; CPU Clock : 4 MHz                      Reloj instruccion : 4 MHz = 0.25 us
;       WDT : Deshabilitado                  Tipo de reloj : XT 
; Code Prot : OFF                        velocidad usart: 9.600 Kbps
;****************************************** http://www.ingeniopic.com *******

            LIST   P=16F876         ;Se indica el modo de procesador
     
            RADIX   HEX            ;Sistema de numeracion hexadecimal

            INCLUDE   <P16f876.inc>  ;se incluye la definicion de los registros
               ;registros internos
            __CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF &_WRT_ENABLE_OFF
            ERRORLEVEL      -302     ;para que no se notifiquen los errires por los registros fuera del banco de ram.

CounterA      EQU  20h            ;registros para retardo
CounterB      EQU  21h
CounterC      EQU  22h
W_TEMP         EQU    23h
STATUS_TEMP   EQU    24h
PCLATH_TEMP   EQU    25h   

         #define      GIE_ON   bsf      INTCON,GIE
         #define      GIE_OFF   bcf      INTCON,GIE
   
                 
BANK0       MACRO                  ;macro para la seleccion del banco 0
            BCF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

BANK1       MACRO                  ;macro para la seleccion del banco 1
            BSF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

PUSH      MACRO               ;macro para salvar registros antes de una llamada a interrupcion   
         movwf   W_TEMP               
            swapf   STATUS,W
            movwf   STATUS_TEMP         
            clrf      STATUS               
            movfw   PCLATH               
           movwf   PCLATH_TEMP
            clrf      PCLATH
         ENDM

POP         MACRO               ;macro para restaurar registros   despues de una llamada a interrupcion
         movfw   PCLATH_TEMP         
            movwf   PCLATH
            swapf   STATUS_TEMP,W      
            movwf   STATUS
            swapf   W_TEMP,F         
            swapf   W_TEMP,W
         ENDM

;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
            ORG   0x00               ;Inicio en el Vector de Reset
     
            goto   INICIO           ;Va a la primera instruccion del programa
               
;<<<<<<------------------- VECTOR DE INTERRUPCION -------------------->>>>>>>

            ORG   0x04               ;Vector de interrupcion

           goto   INTER            ;salta a la linea INTER

;<<<<<<----------------- CONFIGURACION DE LOS REGISTROS GENERALES ------------------->>>>>>>
INICIO                     
         BANK0                  ;Cambio al banco 0
         clrf   PORTA         ;borra puerto A
           movlw   b'10010000'     ;Configuracion de la usart
            movwf   RCSTA           ;para recepcion continua y habilitacion de la usart
           
         BANK1
         movlw   0x06            
           movwf   ADCON1         ;configura PORTA como entradas digitales
         movlw   0xff
            movwf   TRISA            ;PORTA como entrada de datos
            clrf   TRISB            ;Puerto B como salida de datos
            bsf      TRISC,7         ;RC7/Rx como entrada
         ;bcf      TRISC,6         ;RC6/Tx como salida     
            movlw   .25               ;valor para seleccionar 9600 baudios
            movwf   SPBRG         ;mete el valor en el registro baud rate generator
            movlw   b'00100100'     ;Configuracion USART modo alta velocidad 9600 baud y activacion de transmision
            movwf   TXSTA           ;carga valor anterior en registro asociado al generador del baud rate
            bsf     PIE1,RCIE       ;Habilitacion interrupcion RX

         BANK0
         clrf      PORTB         ;borra las salidas del puerto b
         movlw   b'11000000'     ;Habilitacion para las
            movwf   INTCON            ;interrupciones generales y perifericas.
   
           
;<<<<<<<<-----------------------------PROGRAMA PRINCIPAL--------------------------->>>>>>>>>>>>>>>>>>>>>>>>     
            nop                  ;aqui se pondra el programa principal y cuando queramos mandar un dato,
         nop                  ;solo tendremos que hacer un salto al programa de envio de datos "ESCRIBEDATO"
PRINCIPAL   call   PRINCIPAL;ESCRIBEDATO      
         GOTO   PRINCIPAL
;<<<<<<<<-------------------------------ENVIO DE DATOS--------------------------->>>>>>>>>>>>>>
ESCRIBEDATO   GIE_OFF               ;deshabilita interrupciones.para que cuando este enviando un dato,no haya errores
         BANK0               ;selecciona banco 0
         movfw   PORTA         ;caraga en w el contenido del puerto A
         movwf   TXREG         ;escribe los datos en el registro de envio de datos
         BANK1               ;selecciona banco1
COMP_TX     btfsc   TXSTA,TRMT      ;comprueba si el shift register(TSR)esta lleno.y si es asi salta.
            goto      COMP_TX         ;en caso contrario bucle infinito.
         BANK0               ;selecciona banco 0
         GIE_ON               ;habilita interrupciones
         call    RETARDO         ;pausa para el envio de datos
         return               ;retorna a PRINCIPAL

;<<<<<<<<-------------------COMPROVACION DE TIPO DE INTERRUPCION------------>>>>>>>>>>>>>>
   
INTER        PUSH                 ;salva el contenido de W,STATUS Y PCLATH
         BANK0
         btfsc   PIR1,RCIF         ;comprueba si el shift register(RSR)esta lleno.y si es asi salta
         goto   LEEDATO         
         POP                  ;restaura el contenido de W,STATUS Y PCLATH
            retfie                  ;retorno de interrupcion si no se ha dado la circunstancia anterior
           
;<<<<<<<<-------------------------VISUALIZACION DE DATO RECIVIDO------------>>>>>>>>>>>>>>
         
LEEDATO     BANK0
         ;movf    RCREG,W         ;Lectura dato recibido
              ;movwf   PORTB           ;Visualiza dato recibido en el puerto B
         movlw   '1'
         xorwf   RCREG,W
         btfsc   STATUS,Z
         call   ESCRIBEDATO
         POP                  ;restaura el contenido de W,STATUS Y PCLATH
            retfie                  ;retorna de la interrupcion.
         
         
;<<<<<<----------------------- RUTINAS DE RETARDO ------------------------->>>>>>>

RETARDO                        ;sub programa para realizar una pausa en el envio de datos
            movlw   D'1'
            movwf   CounterC
            movlw   D'20'
            movwf   CounterB
            movlw   D'50'
            movwf   CounterA
loop         decfsz   CounterA,1
            goto   loop
            decfsz   CounterB,1
            goto   loop
            decfsz   CounterC,1
            goto   loop
            return         
     
           END 
Título: Re: pequeños proyectos
Publicado por: jhozate en 03 de Febrero de 2009, 22:41:55
cordial saludo groundman...fijate que yo simulo este ultimo codigo en el proteus y desde el inicio de la simulacion me lanza muchos mensajes de advertencia, aunque el programa si realiza la tarea de solo enviar el dato cuando llegue un 1 por RX, te adjunto una captura de pantalla....
Título: Re: pequeños proyectos
Publicado por: jhozate en 03 de Febrero de 2009, 23:12:35
editando el codigo pude minimizar tantos avisos de advertencias,, igual me sigue el mismo error "stack overflow executing CALL instruction" pero este solo pasa cada que presiono 4 veces la tecla 1 en virtual terminal de proteus..adjunté la captura de pantalla
Código: [Seleccionar]
****************************************** HTTP://WWW.INGENIOPIC.COM *******
; PROGRAMA : USART_RX_TX.ASM
; FUNCION : VISUALIZAR DATOS RECIVIDOS DE LA USART POR EL PUERTO B Y TRANSMITIR EL VALOR DEL PUERTO A.POR LA USART INTERNA DEL PIC. .
;           (HAY QUE DESCONECTAR CUALQUIER CABLE CONECTADO EN TX,PARA PODER RECIVIR POR RX)
;           SERIAL PORT CONFIG: 9600 BAUDIOS,8 BITS,PARIDAD = NONE
;   
;  REVISION : 1.0        6/1/2009            PROGRAMA PARA : PIC16F876
; CPU CLOCK : 4 MHZ                      RELOJ INSTRUCCION : 4 MHZ = 0.25 US
;       WDT : DESHABILITADO                  TIPO DE RELOJ : XT
; CODE PROT : OFF                        VELOCIDAD USART: 9.600 KBPS
;****************************************** HTTP://WWW.INGENIOPIC.COM *******

            LIST   P=16F877         ;SE INDICA EL MODO DE PROCESADOR
     
            RADIX   HEX            ;SISTEMA DE NUMERACION HEXADECIMAL

            INCLUDE   <P16F877.INC>  ;SE INCLUYE LA DEFINICION DE LOS REGISTROS
               ;REGISTROS INTERNOS
            __CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF &_WRT_ENABLE_OFF
            ERRORLEVEL      -302     ;PARA QUE NO SE NOTIFIQUEN LOS ERRIRES POR LOS REGISTROS FUERA DEL BANCO DE RAM.

COUNTERA      EQU  20H            ;REGISTROS PARA RETARDO
COUNTERB      EQU  21H
COUNTERC      EQU  22H
W_TEMP          EQU    23H
STATUS_TEMP    EQU    24H
PCLATH_TEMP    EQU    25H   

        #DEFINE      GIE_ON   BSF      INTCON,GIE
          #DEFINE      GIE_OFF   BCF      INTCON,GIE
   
                 
BANK0       MACRO                  ;MACRO PARA LA SELECCION DEL BANCO 0
            BCF    STATUS,RP0
            BCF    STATUS,RP1
            ENDM

BANK1       MACRO                  ;MACRO PARA LA SELECCION DEL BANCO 1
            BSF    STATUS,RP0
            BCF    STATUS,RP1
            ENDM

PUSH      MACRO               ;MACRO PARA SALVAR REGISTROS ANTES DE UNA LLAMADA A INTERRUPCION   
          MOVWF   W_TEMP               
            SWAPF   STATUS,W
            MOVWF   STATUS_TEMP         
            CLRF    STATUS               
            MOVFW   PCLATH               
            MOVWF   PCLATH_TEMP
            CLRF    PCLATH
          ENDM

POP         MACRO               ;MACRO PARA RESTAURAR REGISTROS   DESPUES DE UNA LLAMADA A INTERRUPCION
          MOVFW   PCLATH_TEMP         
            MOVWF   PCLATH
            SWAPF   STATUS_TEMP,W     
            MOVWF   STATUS
            SWAPF   W_TEMP,F         
            SWAPF   W_TEMP,W
          ENDM

;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
            ORG    0X00               ;INICIO EN EL VECTOR DE RESET
     
            GOTO    INICIO           ;VA A LA PRIMERA INSTRUCCION DEL PROGRAMA
               
;<<<<<<------------------- VECTOR DE INTERRUPCION -------------------->>>>>>>

            ORG    0X04               ;VECTOR DE INTERRUPCION

           GOTO    INTER            ;SALTA A LA LINEA INTER

;<<<<<<----------------- CONFIGURACION DE LOS REGISTROS GENERALES ------------------->>>>>>>
INICIO                     
          BANK0                  ;CAMBIO AL BANCO 0
          CLRF    PORTA         ;BORRA PUERTO A
          MOVLW   B'10010000'     ;CONFIGURACION DE LA USART
            MOVWF   RCSTA           ;PARA RECEPCION CONTINUA Y HABILITACION DE LA USART
           
          BANK1
          MOVLW   0X06           
            MOVWF   ADCON1         ;CONFIGURA PORTA COMO ENTRADAS DIGITALES
          MOVLW   0XFF
            MOVWF   TRISA            ;PORTA COMO ENTRADA DE DATOS
            CLRF    TRISB            ;PUERTO B COMO SALIDA DE DATOS
            BSF     TRISC,7         ;RC7/RX COMO ENTRADA
          BCF     TRISC,6         ;RC6/TX COMO SALIDA     
            MOVLW   .25               ;VALOR PARA SELECCIONAR 9600 BAUDIOS
            MOVWF   SPBRG         ;METE EL VALOR EN EL REGISTRO BAUD RATE GENERATOR
            MOVLW   B'00100100'     ;CONFIGURACION USART MODO ALTA VELOCIDAD 9600 BAUD Y ACTIVACION DE TRANSMISION
            MOVWF   TXSTA           ;CARGA VALOR ANTERIOR EN REGISTRO ASOCIADO AL GENERADOR DEL BAUD RATE
            BSF     PIE1,RCIE       ;HABILITACION INTERRUPCION RX

          BANK0
          CLRF    PORTB         ;BORRA LAS SALIDAS DEL PUERTO B
          MOVLW   B'11000000'     ;HABILITACION PARA LAS
            MOVWF   INTCON            ;INTERRUPCIONES GENERALES Y PERIFERICAS.
   
           
;<<<<<<<<-----------------------------PROGRAMA PRINCIPAL--------------------------->>>>>>>>>>>>>>>>>>>>>>>>     
            NOP                  ;AQUI SE PONDRA EL PROGRAMA PRINCIPAL Y CUANDO QUERAMOS MANDAR UN DATO,
          NOP                  ;SOLO TENDREMOS QUE HACER UN SALTO AL PROGRAMA DE ENVIO DE DATOS "ESCRIBEDATO"
PRINCIPAL   GOTO   INTER     
          ;CALL   ESCRIBEDATO
;<<<<<<<<-------------------------------ENVIO DE DATOS--------------------------->>>>>>>>>>>>>>
ESCRIBEDATO GIE_OFF               ;DESHABILITA INTERRUPCIONES.PARA QUE CUANDO ESTE ENVIANDO UN DATO,NO HAYA ERRORES
          BANK0               ;SELECCIONA BANCO 0
BCF PIR1,TXIF
          MOVFW   PORTA         ;CARAGA EN W EL CONTENIDO DEL PUERTO A
          MOVWF   TXREG         ;ESCRIBE LOS DATOS EN EL REGISTRO DE ENVIO DE DATOS
          BANK1               ;SELECCIONA BANCO1
COMP_TX     BTFSS   TXSTA,TRMT      ;COMPRUEBA SI EL SHIFT REGISTER(TSR)ESTA LLENO.Y SI ES ASI SALTA.
            GOTO      COMP_TX         ;EN CASO CONTRARIO BUCLE INFINITO.
          BANK0               ;SELECCIONA BANCO 0
BCF PIR1,TXIF

          GIE_ON 
             ;HABILITA INTERRUPCIONES
          CALL    RETARDO         ;PAUSA PARA EL ENVIO DE DATOS
          ;RETURN               ;RETORNA A PRINCIPAL

;<<<<<<<<-------------------COMPROVACION DE TIPO DE INTERRUPCION------------>>>>>>>>>>>>>>
   
INTER       PUSH                 ;SALVA EL CONTENIDO DE W,STATUS Y PCLATH
          BANK0
VOLVER      BTFSS   PIR1,RCIF         ;COMPRUEBA SI EL SHIFT REGISTER(RSR)ESTA LLENO.Y SI ES ASI SALTA
GOTO VOLVER
BCF  PIR1,RCIF ;REPONER EL FLAG DE INTERRUPCION
;BSF INTCON,PEIE
GOTO    LEEDATO
                 
          POP                  ;RESTAURA EL CONTENIDO DE W,STATUS Y PCLATH
            RETFIE                  ;RETORNO DE INTERRUPCION SI NO SE HA DADO LA CIRCUNSTANCIA ANTERIOR
           
;<<<<<<<<-------------------------VISUALIZACION DE DATO RECIVIDO------------>>>>>>>>>>>>>>
         
LEEDATO     BANK0
          MOVF    RCREG,W         ;LECTURA DATO RECIBIDO
MOVWF   PORTB           ;VISUALIZA DATO RECIBIDO EN EL PUERTO B
XORLW 0X31
BTFSC STATUS,Z
CALL ESCRIBEDATO
POP 
RETFIE   
          GOTO LEEDATO  ;RESTAURA EL CONTENIDO DE W,STATUS Y PCLATH
                      ;RETORNA DE LA INTERRUPCION.           
           
         
         
;<<<<<<----------------------- RUTINAS DE RETARDO ------------------------->>>>>>>

RETARDO                        ;SUB PROGRAMA PARA REALIZAR UNA PAUSA EN EL ENVIO DE DATOS
            MOVLW   D'1'
            MOVWF   COUNTERC
            MOVLW   D'20'
            MOVWF   COUNTERB
            MOVLW   D'50'
            MOVWF   COUNTERA
LOOP        DECFSZ   COUNTERA,1
            GOTO   LOOP
            DECFSZ   COUNTERB,1
            GOTO   LOOP
            DECFSZ   COUNTERC,1
            GOTO   LOOP
            RETURN         
     
            END 
Título: Re: pequeños proyectos
Publicado por: groundman en 04 de Febrero de 2009, 19:59:17
siento no poder ayudarte en la parte del simulador.ya que nunca he usado este.me gustaria mucho aprender y parece que esta chulo.

en cuanto al programa.quizas se te quiten estos fallos.si no se utilizaran las interrupciones para la ejecucion del asm.solo tienes que deshabilitar las interrupciones.y ejecutar directamente la direccion INTER.y eliminar algunas lineas.

yo he usado interrupciones porque de esta forma.puedo estar ejecutando un programa hasta que se utilize la usart.prueva a ver que tal
Título: Re: pequeños proyectos
Publicado por: jhozate en 04 de Febrero de 2009, 22:27:13
gracias en todo caso..voy a seguir depurando el codigo a ver q tal me va....aqui te dejo unos pdf de proteus..te lo recomiendo es un excelente simulador..si lo requieres tambien te facilito el link para descargarlo...
gracias
http://www.4shared.com/file/84491690/8d223d2a/PROTEUS_TE_1.html
http://www.4shared.com/file/84491689/ede5b4cf/PROTEUS_TE_2.html
http://www.4shared.com/file/84491688/9ae28459/PROTEUS_TE_3.html
http://www.4shared.com/file/84491687/a5d99c8/PROTEUS_TE_4.html
http://www.4shared.com/file/84491694/8a4ff933/PROTEUS_TE_5.html
http://www.4shared.com/file/84491693/142b6c90/PROTEUS_TE_6.html
http://www.4shared.com/file/84491692/632c5c06/PROTEUS_TE_7.html
http://www.4shared.com/file/84491691/fa250dbc/PROTEUS_TE_8.html
Título: Re: pequeños proyectos
Publicado por: Nocturno en 05 de Febrero de 2009, 03:10:56
¡Ojo!, que aquí no permitimos software ilegal.
Título: Re: pequeños proyectos
Publicado por: groundman en 05 de Febrero de 2009, 12:34:38
muchisimas gracias jhozate.le he hechado un vistazo por encima.a los manuales y perece que me va a gustar.

en cuanto al programa.no te preocupes seguro que tiene que haber algun shareware o demo.para empezar es suficiente.
ya si me gusta.mirare si el precio es atractivo.y si no ,a seguir como lo hago ahora fisicamente.no hay problema.
Título: Re: pequeños proyectos
Publicado por: sander en 13 de Febrero de 2009, 12:31:48
Bueno este me parece el mejor lugar para colgar pequeño proyecto.

Bueno el proyecto es para la lectura de una memoria i2c usando un micro sin MSSP, en este caso uso el PIC16F690 que tiene el SSP, pero el SSP es bastante limitado para implementar un i2c maestro, asi que hice las rutinas para la comunicacion i2c y estan en el archivo i2cCom.inc y en el archivo I2Cmacro.inc, tambien hice unas rutinas para manejar la memoria estas estan en el archivo EE24AA64.inc.

El programa es:

Código: ASM
  1. ;**********************************************************************
  2. ;                              |¯¯\/¯¯|
  3. ;                                         VDD  --->|1   20|<--- VSS
  4. ;        RA5/T1CKL/OSC1/CLKIN <--->|2   19|<---> RA0/AN0/C1IN+/ICSPDAT/ULPWU
  5. ;RA4/AN3/_T1G/OSC2/CLKOUT <--->|3   18|<---> RA1/AN1/C12IN-/VREF/ICSPCLK
  6. ;                        RA3/_MCLR/VPP --->|4   17|<---> RA2/AN2/T0CLK/INT/C1OUT
  7. ;                        RC5/CPP1/P1A <--->|5   16|<---> RC0/AN4/C2IN+
  8. ;                        RC4/C2OUT/P1B<--->|6   15|<---> RC1/AN5/C2IN-
  9. ;                        RC3/AN7/P1C  <--->|7   14|<---> RC2/AN6/P1D                
  10. ;                    RC6/AN8/_SS  <--->|8   13|<---> RB4/AN10/SD1/SDA
  11. ;                    RC7/AN9/SDO  <--->|9   12|<---> RB5/AN11/RX/DT
  12. ;                        RB7/TX/CK        <--->|10  11|<---> RB6/SCK/SCL
  13. ;                                                      |______|
  14. ;                                                         PIC 16F690
  15. ;                                                                     *
  16. ;**********************************************************************
  17. ;                                                                     *
  18. ;       Nombre:         Test2.asm
  19. ;       Fecha:          28-01-2009
  20. ;       Version:        v1.00
  21. ;                                                                     *
  22. ;       Autor:          Sander
  23. ;       Empresa:
  24. ;                                                                     *
  25. ;                                                                     *
  26. ;**********************************************************************
  27. ;                                                                     *
  28. ;       Archivos Requeridos:
  29. ;
  30. ;       I2Cmacro.inc
  31. ;       i2cCom.inc
  32. ;       EE24AA64.inc
  33. ;**********************************************************************
  34. ;                                                                     *
  35. ;       Notas:
  36. ;       Despues de #include     <P16F690.inc>, debemos incluir las macros para
  37. ;       la comunicacion I2C (I2Cmacro.inc), y despues (al final del programa)
  38. ;       debemos incluir las     rutinas para manejar el bus i2c (i2cCom.inc) y
  39. ;       para manejar la memoria (EE24AA64.inc)
  40. ;
  41. ;       Este programa muestra el uso de una memoria i2c que pueda direccionar
  42. ;       maximo 16 bits, para este ejemplo se usara la AT24C64, que puede
  43. ;       direccionar hasta 8192 bytes.
  44. ;       -------------------------------------------------------------------------
  45. ;       Notas de versiones
  46. ;       v1.00   C-11-02-2009
  47. ;       El programa permite :
  48. ;               1       Escribir un byte en cualquier direccion
  49. ;               2       Leer un byte de cualquier direccion
  50. ;               3       Escribir varios bytes (maximo 32) a partir de cualquier direccion      
  51. ;               4       Leer hasta 80 bytes a partir de cualquier byte.
  52. ;       ------------------------------------------------------------------------
  53. ;**********************************************************************
  54.  
  55.  
  56.         list            p=16f690                ;directiva list para definir procesador
  57.         #include        <P16F690.inc>   ;definicion de variables especificas (SFRs)
  58.         #include        <I2Cmacro.inc>
  59.         __CONFIG    _CP_OFF & _CPD_OFF & _BOR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF
  60.  
  61.  
  62. ;La directiva '__CONFIG' se usa para colocar datos de configuracion
  63. ;dentro del archivo .asm.
  64. ; Las etiquetas que siguen a la directiva se encuentran en el archivo .inc respectivo
  65. ; Buscar en la hoja de datos respectiva para informacion adicional de la
  66. ;palabra de configuracion
  67.  
  68.  
  69. ;***** Definicion de Variables
  70. w_temp          EQU     0x71                    ; variable usada para salvar contexto
  71. status_temp     EQU     0x72                    ; variable usada para salvar contexto
  72. pclath_temp     EQU     0x73                    ; variable usada para salvar contexto
  73.  
  74.         CBLOCK  0x20
  75.         i2cDato
  76.         i2cCont
  77.         i2cFlags                                        ;para la comunicacion i2c
  78.         i2cEEAddr:2,i2cEEDato           ;
  79.         EECont                                          ;para manejar la EEPROM externa
  80.         OffsTabla, AddrTabla:.2         ;para manejar tablas
  81.  
  82.         DatoRx, DatoTx                          ;para guardar datos del EUSART
  83.         I,J                                                     ;puntero para buffers en memoria
  84.         ContBytes                                       ;para controlar cantidad de bytes
  85.  
  86.         DatoAux                                         ;para usar en subrutinas
  87.         ENDC
  88.  
  89.         CBLOCK  0xA0
  90.         BufferRx:.80                            ;buffer para la recepcion
  91.         ENDC
  92.  
  93.         CBLOCK  0x120
  94.         Buffer2:.80                                     ;bufer de proposito general
  95.         ENDC
  96.  
  97.         _9600           EQU             .103    ;0x67 para BRGH=1, BRG16=1, y Fosc=4MHz
  98.  
  99.         EEDir1          EQU             0xA0    ;direccion de la EEPROM externa
  100.  
  101.         #DEFINE         ACK_F           i2cFlags,.0
  102.         #DEFINE         S_NACK_F        i2cFlags,.1
  103. ;**********************************************************************
  104.         ORG             0x000                           ; Vector de Reset
  105.         goto            main                    ; ir al inicio del progra
  106.  
  107.  
  108.         ORG             0x004                           ;posicion del vector de interrupcion
  109.         movwf           w_temp                  ; salvar el contenido actual de W
  110.         movf            STATUS,w                ;
  111.         movwf           status_temp             ; salvar el contenido actual de STATUS
  112.         movf            PCLATH,w                ;
  113.         movwf           pclath_temp             ; salvar el contenido actual de PCLATH
  114.  
  115.  
  116. ;La rutina de interrupcio puede ir a continuacion o se puede realizar una
  117. ;llamada a la rutina usando call
  118.  
  119.         movf            pclath_temp,w   ; recuperar el valor de PCLATH
  120.         movwf           PCLATH                  ; antes de la interrupcion
  121.         movf            status_temp,w   ; recuperar el valor de STATUS
  122.         movwf           STATUS                  ; antes de la interrupcion
  123.         swapf           w_temp,f
  124.         swapf           w_temp,w                ; recuperar el valor de W
  125.         retfie                                          ;retornar de la interrupcion
  126.  
  127.  
  128.  
  129. main
  130. ;el programa principal va a continuacion
  131.  
  132. ;***************        Inicializacion de puertos       *******************
  133.         banksel         ANSEL                   ;banco 2
  134.         clrf            ANSEL
  135.         clrf            ANSELH                  ;todos los pines como I/O digitales
  136.         banksel         PORTA                   ;banco 0
  137. ;******************************************************************
  138.  
  139. ;***************        Inicializacion del EUSART       *******************
  140.  
  141.         banksel         TRISB                   ;banco 1
  142.         movlw           B'11110000'             ;RB5 y RB7 para usar el EUSART
  143.         movwf           TRISB                   ;RB4 y RB6 para hacer i2c
  144.         banksel         BAUDCTL                 ;banco 1
  145.         movlw           B'01001000'             ;Bit 3(BRG16) en 1 para usar generador
  146.         movwf           BAUDCTL                 ;de bauds de 16 bit.
  147.         movlw           B'00000100'             ;Bit 2(BRGH) en 1 para High Baud rate
  148.         movwf           TXSTA                   ;Bit 4(SYNC) = 0 modo asincrono
  149.         movlw           HIGH _9600
  150.         movwf           SPBRGH
  151.         movlw           LOW _9600
  152.         movwf           SPBRG                   ;Ajustamos la velocidad
  153.         banksel         RCSTA                   ;Banco 0
  154.         movlw           B'10010000'             ;Bit 7(SPEN) = 1 Habilita puerto serial
  155.         movwf           RCSTA                   ;Bit 4(CREN) = 1 Habilita recepcion.
  156. ;******************************************************************
  157.  
  158. ;***************        Inicializacion de variables     *******************
  159.         clrf            i2cFlags
  160.         clrf            i2cEEAddr+1
  161.         clrf            i2cEEAddr
  162. ;******************************************************************
  163.         banksel         TXSTA
  164.         bsf                     TXSTA,TXEN              ;Habilitamos el transmisor
  165.         banksel         PORTB
  166.  
  167. mainP0
  168.         clrw           
  169.         call            EnvMsg
  170.         movlw           .1
  171.         call            EnvMsg                  ;Enviamos mensaje de opciones
  172.  
  173.         call            RxEusart                ;recibimos la opcion del menu(solo un byte)
  174.         movf            ContBytes,W             ;
  175.         xorlw           .1                              ;verificamos que solo se reciba un byte
  176.         btfss           STATUS,Z                ;Se recibio solo un byte?
  177.         goto            MainEr1                 ;No => vamos a error
  178.         movlw           BufferRx                ;Si => vemos que opcion se recibio
  179.         movwf           FSR                             ;
  180.         movf            INDF,W                  ;Leemos el byte recibido
  181.         andlw           0x0F                    ;solo tomamos los bits menos significativos
  182.         movwf           INDF           
  183.         sublw           .4
  184.         btfss           STATUS,C                ;El valor recibido es <= 4?
  185.         goto            MainEr1                 ;No => vamos a error
  186.         movlw           HIGH mainP0_0   ;Si => nos preparamos para ir a la rutina de
  187.         movwf           PCLATH                  ;la opcion seleccionada
  188.         movlw           LOW mainP0_0    ;
  189.         addwf           INDF,W
  190.         btfsc           STATUS,C
  191.         incf            PCLATH,F
  192.         movf            INDF,W
  193.         addwf           PCL
  194. mainP0_0
  195.         goto            MainEr1
  196.         goto            MainOpc1
  197.         goto            MainOpc2
  198.         goto            MainOpc3
  199.         goto            MainOpc4
  200. MainEr1
  201.         movlw           .8
  202.         call            EnvMsg                  ;enviamos mensaje de dato erroneo
  203.         goto            mainP0                  ;volvemos a empezar con la rutina
  204.  
  205. ;**************************
  206.  
  207. ;***********************        MainOpc1        *******************************
  208. ;       MainOpc1        Atiende la opcion 1 del menu, permite recibir una
  209. ;                               direccion y un dato a escribir, controla si existen
  210. ;       errores al momento de introducir la direccion o el dato.
  211. ;       Si el dato se ecribio en la memoria envia un mensaje.
  212. ;**********************************************************************
  213. MainOpc1
  214.         movlw           .3
  215.         call            EnvMsg                  ;Enviamos mensaje para la opcion 1
  216.         call            RxEusart                ;para recibir los datos
  217.         call            IntDir                  ;Para procesar la direccion
  218.         xorlw           .0
  219.         btfsc           STATUS,Z                ;IntDir devolvio 0x00
  220.         goto            MainOpc1Er              ;Si => no se recibio una direccion valida
  221. MainOpc1P0
  222.         movlw           .4
  223.         call            EnvMsg                  ;Mensaje para introducir dato
  224.         call            RxEusart               
  225.         call            IntDato                 ;para recibir el dato
  226.         xorlw           .0
  227.         btfsc           STATUS,Z                ;IntDato devolvio 0x00
  228.         goto            MainOpc1Er2             ;Si => no se recibio un dato valido
  229.         call            EEWrByte                ;No => Escribimos el dato en la EEPROM
  230.         movlw           .5
  231.         call            EnvMsg                  ;Mensaje que indica que se escribio correctamente
  232.         movlw           .14
  233.         call            EnvMsg                  ;Para marcar que se termino de leer
  234.         goto            mainP0                  ;Volvemos a las opciones iniciales
  235. MainOpc1Er
  236.         movlw           .8
  237.         call            EnvMsg                  ;enviamos mensaje de dir erronea
  238.         goto            MainOpc1                ;volvemos a empezar con la rutina
  239. MainOpc1Er2
  240.         movlw           .8
  241.         call            EnvMsg                  ;enviamos mensaje de dato erroneo
  242.         goto            MainOpc1P0              ;volvemos a pedir dato
  243. ;**********************************************************************
  244.  
  245. ;***********************        MainOpc2        *******************************
  246. ;       MainOpc2        Atiende la opcion 2 del menu, permite recibir una
  247. ;                               direccion, controla si existen  errores al momento de
  248. ;       introducir la direccion.
  249. ;       Envia el dato leido en forma hexadecimal
  250. ;**********************************************************************
  251. MainOpc2
  252.         movlw           .6
  253.         call            EnvMsg                  ;enviamos mensaje para la opcion 2
  254.         call            RxEusart               
  255.         call            IntDir                  ;recibimos bytes de direccion
  256.         xorlw           .0
  257.         btfsc           STATUS,Z                ;IntDir devolvio 0x00?
  258.         goto            MainOpc2Er              ;Si => no se recibio una direccion valida
  259.         call            EERdByte                ;No => Leemos el byte.
  260.         movlw           .7
  261.         call            EnvMsg                  ;mensaje para mostrar el valor leido
  262.         movf            i2cEEDato,W
  263.         call            EnvEEDato               ;Enviamos el dato leido de la EEPROM en hex
  264.         movlw           .14
  265.         call            EnvMsg                  ;Para marcar que se termino de leer
  266.         goto            mainP0                  ;;Volvemos a las opciones iniciales
  267. MainOpc2Er
  268.         movlw           .8
  269.         call            EnvMsg                  ;enviamos mensaje de dato erroneo
  270.         goto            MainOpc2                ;volvemos a empezar con la rutina
  271. ;**********************************************************************
  272.  
  273. ;***********************        MainOpc3        *******************************
  274. ;       MainOpc3        Atiende la opcion 3 del menu, permite recibir una
  275. ;                               direccion y un dato a escribir, controla si se recibio
  276. ;       una direccion erronea, luego de recibir la direccion permite que se
  277. ;       vayan recibiendo hasta 32 datos y los va guardando en BufferRx tal
  278. ;       cual los va recibiendo (generalmente ASCII).
  279. ;       Cuando los datos se terminaron de escribir en la memoria envia un mensaje.
  280. ;**********************************************************************
  281. MainOpc3
  282.         movlw           .9
  283.         call            EnvMsg                  ;mensaje de inicio para este modo
  284.         call            RxEusart                ;recibimos la direccion donde
  285.         call            IntDir                  ;grabaremos
  286.         xorlw           .0
  287.         btfsc           STATUS,Z                ;IntDir retorno error?
  288.         goto            MainOpc3Er              ;Si => vamos a atender el error
  289.         movlw           .10                            
  290.         call            EnvMsg                  ;mensaje para introducir los datos
  291.         call            RxEusart                ;introducimos datos, en este modo
  292.         movf            ContBytes,W
  293.         movwf           EECont                  ;En EECont se pasa la cantidad de bytes escribir
  294.         call            EEWrPage                ;se guardan los datos en ascii(como se reciben)
  295.         movlw           .5
  296.         call            EnvMsg                  ;mensaje de caracteres grabados
  297.         movlw           .14
  298.         call            EnvMsg                  ;Para marcar que se termino de leer
  299.         goto            mainP0                  ;volvemos al menu principal
  300. MainOpc3Er
  301.         movlw           .8
  302.         call            EnvMsg                  ;enviamos mensaje de dato erroneo
  303.         goto            MainOpc3                ;volvemos a empezar con la rutina
  304. ;**********************************************************************
  305.  
  306. ;***********************        MainOpc4        *******************************
  307. ;       MainOpc4        Atiende la opcion 4 del menu, permite recibir una
  308. ;                               direccion y una cantidad de datos a leer, controla si existen
  309. ;       errores al momento de introducir la direccion y la cantidad de datos.
  310. ;       Envia los datos leidos en forma hexadecimal separados por espacios en
  311. ;       blanco.
  312. ;**********************************************************************
  313. MainOpc4
  314.         movlw           .11
  315.         call            EnvMsg                  ;mensaje de inicio para este modo
  316.         call            RxEusart                ;recibimos la direccion desde donde
  317.         call            IntDir                  ;leeremos
  318.         xorlw           .0
  319.         btfsc           STATUS,Z                ;IntDir retorno error?
  320.         goto            MainOpc4Er              ;Si => vamos a atender el error
  321. MainOpc4P0
  322.         movlw           .12
  323.         call            EnvMsg                  ;mensaje para introducir cantidad de bytes
  324.         call            RxEusart                ;recibimos la cantidad de datos
  325.         movf            ContBytes,W             ;
  326.         xorlw           .2
  327.         btfss           STATUS,Z                ;Se recibio 2 datos(para cantdad datos)?
  328.         goto            MainOpc4Er2             ;No => atendemos error
  329.  
  330.         movlw           BufferRx                ;convertimos los dos datos recibidos en binario
  331.         movwf           FSR                             ;
  332.         movf            INDF,W                  ;Leemos el 1er dato    
  333.         movwf           DatoAux                 ;revisamos que sea numero
  334.         sublw           0x29
  335.         btfsc           STATUS,C                ;DatoAux >= '0'?
  336.         goto            MainOpc4Er2             ;No => atendemos error
  337.         movf            DatoAux,W
  338.         sublw           '9'
  339.         btfss           STATUS,C                ;DatoAux <= '9'?
  340.         goto            MainOpc4Er2             ;No => atendemos error
  341.         movlw           0x0F
  342.         andwf           DatoAux,F               ;aqui tenemos las decenas
  343.         clrf            EECont
  344. MainOpc4P0_0
  345.         movlw           .10
  346.         addwf           EECont,F                ;EECont = EECont + 10
  347.         decfsz          DatoAux,F               ;decenas == 0?
  348.         goto            MainOpc4P0_0    ;No => seguimos sumando
  349.        
  350.         incf            FSR,F                   ;Si => revisamos el otro byte
  351.         movf            INDF,W                  ;Leemos el 2do dato    
  352.         movwf           DatoAux                 ;revisamos que sea numero
  353.         sublw           0x29
  354.         btfsc           STATUS,C                ;DatoAux >= '0'?
  355.         goto            MainOpc4Er2             ;No => atendemos error
  356.         movf            DatoAux,W
  357.         sublw           '9'
  358.         btfss           STATUS,C                ;DatoAux <= '9'?
  359.         goto            MainOpc4Er2             ;No => atendemos error
  360.         movlw           0x0F
  361.         andwf           DatoAux,F               ;aqui tenemos las unidades
  362. MainOpc4P0_1
  363.         movlw           .1
  364.         addwf           EECont,F                ;EECont = EECont + 10
  365.         decfsz          DatoAux,F               ;decenas == 0?
  366.         goto            MainOpc4P0_1    ;No => seguimos sumando
  367.                
  368.         movf            EECont,W                ;Si => revisamos si EECont <= 80
  369.         sublw           .80
  370.         btfss           STATUS,C                ;DatoAux <= 80?
  371.         goto            MainOpc4Er2             ;No => atendemos error
  372.        
  373.         movf            EECont,W
  374.         movwf           ContBytes
  375.         call            EERdPage                ;leemos los datos
  376.  
  377.         movlw           .13
  378.         call            EnvMsg                  ;mensaje para mostrar los datos leidos
  379.  
  380. MainOpc4P1
  381.         movlw           Buffer2
  382.         movwf           FSR
  383.         bsf                     STATUS,IRP              ;para apuntar al banco 2       
  384. MainOpc4P1_0
  385.         movf            INDF,W                  ;leemos el dato que queremos enviar
  386.         movwf           i2cEEDato               ;para enviar el dato en formato hexadecimal
  387.         call            EnvEEDato               ;es decir, como esta escrito en la memoria
  388.         movlw           ' '
  389.         btfss           PIR1,TXIF
  390.         goto            $-1
  391.         movwf           TXREG                   ;Enviamos espacio en blanco
  392.  
  393.         incf            FSR,F                   ;para tomar el siguiente dato
  394.         decfsz          ContBytes,F             ;;Se transmitieron todos los datos?
  395.         goto            MainOpc4P1_0    ;No => seguimos transmitiendo
  396.         bcf                     STATUS,IRP              ;FSR para apuntar al banco 0 o 1
  397.         movlw           .14
  398.         call            EnvMsg                  ;Para marcar que se termino de leer
  399.         goto            mainP0
  400. MainOpc4Er
  401.         movlw           .8
  402.         call            EnvMsg                  ;enviamos mensaje de dir erroneo
  403.         goto            MainOpc4                ;volvemos a empezar con la rutina
  404. MainOpc4Er2
  405.         movlw           .8
  406.         call            EnvMsg                  ;enviamos mensaje de cantidad erroneo
  407.         goto            MainOpc4P0              ;volvemos a recibir cantidad bytes
  408. ;**********************************************************************
  409.  
  410. ;***************************    IntDir  *******************************
  411. ;       IntDir  Lleva  4 bytes recibidos en ASCII mediante la rutina
  412. ;                       RxEusart a i2cEEAddr, para tener asi la direccion con la
  413. ;       que se quiere trabajar en la EEPROM. por ejemplo si se recibe
  414. ;       '0','1','a','B' => i2cEEAddr = 01AB. la rutina retorna error si
  415. ;       se recibieron mas de 4 bytes o si el caracter recibido no
  416. ;       es un numero o una letra de la 'a' a la 'f'.
  417. ;**********************************************************************
  418. IntDir
  419.         movf            ContBytes,W
  420.         xorlw           .4
  421.         btfss           STATUS,Z                ;Se recibio 4 datos(para direccion)?
  422.         retlw           0x00                    ;No => retornamos error
  423.         movlw           BufferRx
  424.         movwf           FSR                             ;
  425.         movf            INDF,W                  ;Leemos el 1er dato
  426.         call            Ascii2Hex               ;Convertimos el dato a hex
  427.         xorlw           .0                             
  428.         btfsc           STATUS,Z                ;Ascii2Hex retorno 0?
  429.         retlw           0x00                    ;No => retornamos error
  430.         swapf           DatoAux,W
  431.         movwf           i2cEEAddr+1             ;nible alto de i2cEEAddr+1
  432.        
  433.         incf            FSR,F                   ;siguiente dato
  434.         movf            INDF,W                  ;Leemos el 2do dato
  435.         call            Ascii2Hex               ;Convertimos el dato a hex
  436.         xorlw           .0                             
  437.         btfsc           STATUS,Z                ;Ascii2Hex retorno 0?
  438.         retlw           0x00                    ;No => retornamos error
  439.         movf            DatoAux,W
  440.         iorwf           i2cEEAddr+1,F   ;nible bajo de i2cEEAddr+1
  441.  
  442.         incf            FSR,F                   ;siguiente dato
  443.         movf            INDF,W                  ;Leemos el 3er dato
  444.         call            Ascii2Hex               ;Convertimos el dato a hex
  445.         xorlw           .0                             
  446.         btfsc           STATUS,Z                ;Ascii2Hex retorno 0?
  447.         retlw           0x00                    ;No => retornamos error
  448.         swapf           DatoAux,W
  449.         movwf           i2cEEAddr               ;nible alto de i2cEEAddr
  450.  
  451.         incf            FSR,F                   ;siguiente dato
  452.         movf            INDF,W                  ;Leemos el 4to dato
  453.         call            Ascii2Hex               ;Convertimos el dato a hex
  454.         xorlw           .0                             
  455.         btfsc           STATUS,Z                ;Ascii2Hex retorno 0?
  456.         retlw           0x00                    ;No => retornamos error
  457.         movf            DatoAux,W
  458.         iorwf           i2cEEAddr,F             ;nible bajo de i2cEEAddr
  459.         retlw           0x01
  460. ;*******************************************************************
  461.  
  462. ;***************************    IntDato *******************************
  463. ;       IntDato         Similar a IntDir pero solo trabaja con dos datos, por
  464. ;                               ejemplo si se recibio 'F','e' => i2cEEDato = FE
  465. ;       Retorna error si se recibieron mas de 2 bytes o si el caracter recibido
  466. ;       no es un numero o una letra de la 'a' a la 'f'.
  467. ;**********************************************************************
  468. IntDato
  469.         movf            ContBytes,W
  470.         xorlw           .2
  471.         btfss           STATUS,Z                ;Se recibio 2 datos(para dato)?
  472.         retlw           0x00                    ;No => retornamos error
  473.         movlw           BufferRx
  474.         movwf           FSR                             ;
  475.         movf            INDF,W                  ;Leemos el 1er dato
  476.         call            Ascii2Hex               ;Convertimos el dato a hex
  477.         xorlw           .0                             
  478.         btfsc           STATUS,Z                ;Ascii2Hex retorno 0?
  479.         retlw           0x00                    ;Si => retornamos error
  480.         swapf           DatoAux,W
  481.         movwf           i2cEEDato               ;nible alto de i2cEEDato
  482.        
  483.         incf            FSR,F                   ;siguiente dato
  484.         movf            INDF,W                  ;Leemos el 2do dato
  485.         call            Ascii2Hex               ;Convertimos el dato a hex
  486.         xorlw           .0                             
  487.         btfsc           STATUS,Z                ;Ascii2Hex retorno 0?
  488.         retlw           0x00                    ;Si => retornamos error
  489.         movf            DatoAux,W
  490.         iorwf           i2cEEDato,F             ;nible bajo de i2cEEDato
  491.         retlw           0x01
  492. ;**********************************************************************
  493.  
  494. ;***************************    EnvEEDato       ***************************
  495. ;       EnvEEDato       Recibe un dato leido de la EEPROM en i2cEEDato y lo
  496. ;                               transmite por el EUSART en ASCII para que pueda
  497. ;       visualizarse correctamente en el terminal , por ejemlo, si
  498. ;       i2cEEDato = 6F, se transmitira '6'y'F'.
  499. ;**********************************************************************
  500. EnvEEDato
  501.         swapf           i2cEEDato,W
  502.         andlw           0x0F                    ;primero trabajamos con el nible alto
  503.         call            Hex2Ascii               ;convertimos el hexadecimal a ASCII
  504.         movf            DatoAux,W
  505.         btfss           PIR1,TXIF
  506.         goto            $-1
  507.         movwf           TXREG                   ;cargamos TXREG si esta vacio
  508.         movf            i2cEEDato,W
  509.         andlw           0x0F                    ;trabajamos con el nible bajo
  510.         call            Hex2Ascii               ;convertimos el hexadecimal a ASCII
  511.         movf            DatoAux,W
  512.         btfss           PIR1,TXIF
  513.         goto            $-1
  514.         movwf           TXREG                   ;cargamos TXREG si esta vacio
  515.         return
  516. ;**********************************************************************
  517.  
  518. ;***************************    Ascii2Hex       ***************************
  519. ;       Ascii2Hex       La rutina recibe en W un  numero o letra de la 'a' a la 'f'
  520. ;                               y devuelve mediante DatoAux un numero en hexadecimal
  521. ;       equivalente, por ejemplo :
  522. ;
  523. ;       si WREG = '5' => DatoAux = 0x05
  524. ;          WREG = 'F' => DatoAux = 0x0F
  525. ;
  526. ;       retorna Error si no se recibio un numero o una letra de la 'a' a 'f'
  527. ;**********************************************************************
  528. Ascii2Hex
  529.         movwf           DatoAux
  530.         sublw           ' '
  531.         btfsc           STATUS,C                ;DatoAux >= '0'?
  532.         retlw           0x00                    ;No => error
  533.         movf            DatoAux,W
  534.         sublw           '9'
  535.         btfss           STATUS,C                ;DatoAux <= '9'?
  536.         goto            Ascii2HexP1             ;No => revisamos si es letra mayuscula
  537.         movlw           0x0F
  538.         andwf           DatoAux,F
  539.         retlw           0x01
  540. Ascii2HexP1
  541.         movf            DatoAux,W
  542.         sublw           '@'
  543.         btfsc           STATUS,C                ;DatoAux >= '@'?
  544.         retlw           0x00                    ;No => error
  545.         movf            DatoAux,W
  546.         sublw           'F'
  547.         btfss           STATUS,C                ;DatoAux <= 'F'?
  548.         goto            Ascii2HexP2             ;No => revisamos si es letra minuscula
  549.         movlw           0x0F
  550.         andwf           DatoAux,F               ;Aqui tenemos un numero del 1 al 6
  551.         movlw           .9
  552.         addwf           DatoAux,F               ;al sumarle 9 tenemos un valor de 0x0A a 0x0F
  553.         retlw           0x01
  554. Ascii2HexP2
  555.         movf            DatoAux,W
  556.         sublw           0x60
  557.         btfsc           STATUS,C                ;DatoAux >= 0x60?
  558.         retlw           0x00                    ;No => error
  559.         movf            DatoAux,W
  560.         sublw           'f'
  561.         btfss           STATUS,C                ;DatoAux <= 'f'?
  562.         retlw           0x00                    ;No => error
  563.         movlw           0x0F
  564.         andwf           DatoAux,F               ;Aqui tenemos un numero del 1 al 6
  565.         movlw           .9
  566.         addwf           DatoAux,F               ;al sumarle 9 tenemos un valor de 0x0A a 0x0F
  567.         retlw           0x01
  568.  
  569. ;***************************    Hex2Ascii       ***************************
  570. ;       Hex2Ascii       Recibe en W un numero de 0x00 a 0x0F y retorna mediante
  571. ;                               DatoAux el equivalente ASCII del numero recibido
  572. ;       Por ejemplo : Si W = 0x05 => DatoAux = '5'(0x35)
  573. ;                                 Si W = 0x0A => DatoAux = 'A'(0x41)
  574. ;**********************************************************************
  575. Hex2Ascii
  576.         movwf           DatoAux
  577.         sublw           0x09
  578.         btfss           STATUS,C                ;DatoAux <= '9'?
  579.         goto            Hex2AsciiP1             ;No => sera letra
  580.         movlw           0x30                    ;Si => lo convertimos a ASCII
  581.         iorwf           DatoAux,F               ;(0x30 a 0x39)
  582.         return
  583. Hex2AsciiP1
  584.         movlw           0x09                    ;al restarle 9 tenemos 1 si era 0x0A
  585.         subwf           DatoAux,F               ;hasta 6 si era 0x0F
  586.         movlw           0x40
  587.         iorwf           DatoAux,F               ;convertimos a ASCII (si 0x0C => 'C')
  588.         return
  589. ;**********************************************************************
  590.  
  591. ;***************************    RxEusart        ***************************
  592. ;       RxEusart        Recibe caracteres y los almacena en BufferRx, sale
  593. ;                               cuando se recibe un enter(0x0D) o cuando se recibieron
  594. ;       32 caracteres. La cuenta de los caracteres recibidos se realiza
  595. ;       mediante ContBytes.
  596. ;**********************************************************************
  597. RxEusart
  598.         clrf            ContBytes
  599.         movlw           BufferRx
  600.         movwf           I
  601. RxEusartP0
  602.         movf            I,W
  603.         movwf           FSR
  604.         btfss           PIR1,RCIF               ;Se recibio un caracter?
  605.         goto            $-1                             ;No => Esperamos
  606.         btfss           RCSTA,OERR              ;Hubo un dsborde?
  607.         goto            RxEusartP1              ;No => vamos a leer el caracter
  608.         bcf                     RCSTA,CREN              ;Si => reiniciamos la recepcion
  609.         bsf                     RCSTA,CREN
  610.         goto            RxEusart
  611. RxEusartP1
  612.         movf            RCREG,W                
  613.         movwf           DatoRx                  ;guardamos el caracter recibido en DatoRx
  614.         xorlw           0x0D                   
  615.         btfsc           STATUS,Z                ;Se recibio enter?
  616.         return                                          ;Si => salimos
  617.         movf            DatoRx,W                ;No => guardamos el dato y hacemos eco
  618.         movwf           INDF                    ;BufferRx[I] = DatoRx
  619.         btfss           PIR1,TXIF               ;TXREG vacio?
  620.         goto            $-1
  621.         movwf           TXREG                   ;Si => hacemos eco
  622.         incf            I,F                             ;I++
  623.         incf            ContBytes,F             ;ContBytes ++
  624.         movf            ContBytes,W
  625.         xorlw           .32
  626.         btfss           STATUS,Z                ;Se recibieron 32 bytes?
  627.         goto            RxEusartP0              ;No => seguimos recibiendo
  628.         movlw           .2                             
  629.         call            EnvMsg                  ;Si => mensaje de buffer lleno
  630.         btfss           PIR1,RCIF               ;Esperamos a que no haya ningun byte mas
  631.         return                                          ;No hay bytes => Salimos
  632.         movf            RCREG,W                 ;si se recibio algun caracter mas
  633.         bcf                     RCSTA,CREN
  634.         bsf                     RCSTA,CREN              ;Reiniciamos el Receptor
  635.         return
  636. ;**********************************************************************
  637.        
  638.  
  639. ;***************************    EnvMsg  *******************************
  640. ;       EnvMsg  Envia un mensaje por el EUSART, recibe el mensaje que se
  641. ;                       quiere enviar en W
  642. ;**********************************************************************
  643.  
  644. EnvMsg
  645.         movwf           OffsTabla               ;guardamos el mensaje que queremos desplegar   
  646.         movlw           HIGH EnvMsgP0   ;Actualizamos PCLATH para hacer un computed
  647.         movwf           PCLATH                  ;goto en EnvMsgP0
  648.         movlw           LOW EnvMsgP0    ;revisamos de no excedernos de la direccion
  649.         addwf           OffsTabla,W             ;en PCLARH
  650.         btfsc           STATUS,C                ;Nos excedemos?
  651.         incf            PCLATH                  ;Si => incrementamos PCLATH
  652.         movf            OffsTabla,W             ;No =>realizamos el salto
  653.         addwf           PCL,F
  654. EnvMsgP0
  655.         goto            EnvMsg_0                ;Vamos a enviar mensaje 0
  656.         goto            EnvMsg_1                ;Vamos a enviar mensaje 1
  657.         goto            EnvMsg_2                ;Vamos a enviar mensaje 2
  658.         goto            EnvMsg_3                ;Vamos a enviar mensaje 3
  659.         goto            EnvMsg_4                ;Vamos a enviar mensaje 4
  660.         goto            EnvMsg_5                ;Vamos a enviar mensaje 5
  661.         goto            EnvMsg_6                ;Vamos a enviar mensaje 6
  662.         goto            EnvMsg_7                ;Vamos a enviar mensaje 7
  663.         goto            EnvMsg_8                ;Vamos a enviar mensaje 8
  664.         goto            EnvMsg_9                ;Vamos a enviar mensaje 9
  665.         goto            EnvMsg_10               ;Vamos a enviar mensaje 10
  666.         goto            EnvMsg_11               ;Vamos a enviar mensaje 11
  667.         goto            EnvMsg_12               ;Vamos a enviar mensaje 12
  668.         goto            EnvMsg_13               ;Vamos a enviar mensaje 13
  669.         goto            EnvMsg_14               ;Vamos a enviar mensaje 14
  670. EnvMsg_0
  671.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  672. EnvMsg_0P0
  673.         movlw           HIGH Msg_0
  674.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  675.         movlw           LOW Msg_0               ;mensaje que queremos desplegar
  676.         movwf           AddrTabla
  677.         call            Mensajes                ;recojemos el carcater que toca
  678.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  679.         xorlw           0x00
  680.         btfsc           STATUS,Z                ;Se tiene 0x00?
  681.         return                                          ;si => se termino el mensaje
  682.                                                                 ;no => continuamos
  683.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  684.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  685.         goto            EnvMsg_0P0
  686.  
  687. EnvMsg_1
  688.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  689. EnvMsg_1P0
  690.         movlw           HIGH Msg_1
  691.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  692.         movlw           LOW Msg_1               ;mensaje que queremos desplegar
  693.         movwf           AddrTabla
  694.         call            Mensajes                ;recojemos el carcater que toca
  695.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  696.         xorlw           0x00
  697.         btfsc           STATUS,Z                ;Se tiene 0x00?
  698.         return                                          ;si => se termino el mensaje
  699.                                                                 ;no => continuamos
  700.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  701.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  702.         goto            EnvMsg_1P0
  703.  
  704. EnvMsg_2
  705.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  706. EnvMsg_2P0
  707.         movlw           HIGH Msg_2
  708.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  709.         movlw           LOW Msg_2               ;mensaje que queremos desplegar
  710.         movwf           AddrTabla
  711.         call            Mensajes                ;recojemos el carcater que toca
  712.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  713.         xorlw           0x00
  714.         btfsc           STATUS,Z                ;Se tiene 0x00?
  715.         return                                          ;si => se termino el mensaje
  716.                                                                 ;no => continuamos
  717.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  718.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  719.         goto            EnvMsg_2P0
  720.  
  721. EnvMsg_3
  722.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  723. EnvMsg_3P0
  724.         movlw           HIGH Msg_3
  725.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  726.         movlw           LOW Msg_3               ;mensaje que queremos desplegar
  727.         movwf           AddrTabla
  728.         call            Mensajes                ;recojemos el carcater que toca
  729.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  730.         xorlw           0x00
  731.         btfsc           STATUS,Z                ;Se tiene 0x00?
  732.         return                                          ;si => se termino el mensaje
  733.                                                                 ;no => continuamos
  734.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  735.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  736.         goto            EnvMsg_3P0
  737.  
  738. EnvMsg_4
  739.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  740. EnvMsg_4P0
  741.         movlw           HIGH Msg_4
  742.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  743.         movlw           LOW Msg_4               ;mensaje que queremos desplegar
  744.         movwf           AddrTabla
  745.         call            Mensajes                ;recojemos el carcater que toca
  746.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  747.         xorlw           0x00
  748.         btfsc           STATUS,Z                ;Se tiene 0x00?
  749.         return                                          ;si => se termino el mensaje
  750.                                                                 ;no => continuamos
  751.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  752.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  753.         goto            EnvMsg_4P0
  754.  
  755. EnvMsg_5
  756.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  757. EnvMsg_5P0
  758.         movlw           HIGH Msg_5
  759.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  760.         movlw           LOW Msg_5               ;mensaje que queremos desplegar
  761.         movwf           AddrTabla
  762.         call            Mensajes                ;recojemos el carcater que toca
  763.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  764.         xorlw           0x00
  765.         btfsc           STATUS,Z                ;Se tiene 0x00?
  766.         return                                          ;si => se termino el mensaje
  767.                                                                 ;no => continuamos
  768.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  769.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  770.         goto            EnvMsg_5P0
  771.  
  772. EnvMsg_6
  773.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  774. EnvMsg_6P0
  775.         movlw           HIGH Msg_6
  776.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  777.         movlw           LOW Msg_6               ;mensaje que queremos desplegar
  778.         movwf           AddrTabla
  779.         call            Mensajes                ;recojemos el carcater que toca
  780.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  781.         xorlw           0x00
  782.         btfsc           STATUS,Z                ;Se tiene 0x00?
  783.         return                                          ;si => se termino el mensaje
  784.                                                                 ;no => continuamos
  785.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  786.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  787.         goto            EnvMsg_6P0
  788.  
  789. EnvMsg_7
  790.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  791. EnvMsg_7P0
  792.         movlw           HIGH Msg_7
  793.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  794.         movlw           LOW Msg_7               ;mensaje que queremos desplegar
  795.         movwf           AddrTabla
  796.         call            Mensajes                ;recojemos el carcater que toca
  797.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  798.         xorlw           0x00
  799.         btfsc           STATUS,Z                ;Se tiene 0x00?
  800.         return                                          ;si => se termino el mensaje
  801.                                                                 ;no => continuamos
  802.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  803.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  804.         goto            EnvMsg_7P0
  805.  
  806. EnvMsg_8
  807.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  808. EnvMsg_8P0
  809.         movlw           HIGH Msg_8
  810.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  811.         movlw           LOW Msg_8               ;mensaje que queremos desplegar
  812.         movwf           AddrTabla
  813.         call            Mensajes                ;recojemos el carcater que toca
  814.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  815.         xorlw           0x00
  816.         btfsc           STATUS,Z                ;Se tiene 0x00?
  817.         return                                          ;si => se termino el mensaje
  818.                                                                 ;no => continuamos
  819.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  820.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  821.         goto            EnvMsg_8P0
  822.  
  823. EnvMsg_9
  824.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  825. EnvMsg_9P0
  826.         movlw           HIGH Msg_9
  827.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  828.         movlw           LOW Msg_9               ;mensaje que queremos desplegar
  829.         movwf           AddrTabla
  830.         call            Mensajes                ;recojemos el carcater que toca
  831.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  832.         xorlw           0x00
  833.         btfsc           STATUS,Z                ;Se tiene 0x00?
  834.         return                                          ;si => se termino el mensaje
  835.                                                                 ;no => continuamos
  836.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  837.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  838.         goto            EnvMsg_9P0
  839.  
  840. EnvMsg_10
  841.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  842. EnvMsg_10P0
  843.         movlw           HIGH Msg_10
  844.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  845.         movlw           LOW Msg_10              ;mensaje que queremos desplegar
  846.         movwf           AddrTabla
  847.         call            Mensajes                ;recojemos el carcater que toca
  848.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  849.         xorlw           0x00
  850.         btfsc           STATUS,Z                ;Se tiene 0x00?
  851.         return                                          ;si => se termino el mensaje
  852.                                                                 ;no => continuamos
  853.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  854.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  855.         goto            EnvMsg_10P0
  856.  
  857. EnvMsg_11
  858.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  859. EnvMsg_11P0
  860.         movlw           HIGH Msg_11
  861.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  862.         movlw           LOW Msg_11              ;mensaje que queremos desplegar
  863.         movwf           AddrTabla
  864.         call            Mensajes                ;recojemos el carcater que toca
  865.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  866.         xorlw           0x00
  867.         btfsc           STATUS,Z                ;Se tiene 0x00?
  868.         return                                          ;si => se termino el mensaje
  869.                                                                 ;no => continuamos
  870.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  871.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  872.         goto            EnvMsg_11P0
  873.  
  874. EnvMsg_12
  875.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  876. EnvMsg_12P0
  877.         movlw           HIGH Msg_12
  878.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  879.         movlw           LOW Msg_12              ;mensaje que queremos desplegar
  880.         movwf           AddrTabla
  881.         call            Mensajes                ;recojemos el carcater que toca
  882.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  883.         xorlw           0x00
  884.         btfsc           STATUS,Z                ;Se tiene 0x00?
  885.         return                                          ;si => se termino el mensaje
  886.                                                                 ;no => continuamos
  887.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  888.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  889.         goto            EnvMsg_12P0
  890.  
  891. EnvMsg_13
  892.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  893. EnvMsg_13P0
  894.         movlw           HIGH Msg_13
  895.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  896.         movlw           LOW Msg_13              ;mensaje que queremos desplegar
  897.         movwf           AddrTabla
  898.         call            Mensajes                ;recojemos el carcater que toca
  899.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  900.         xorlw           0x00
  901.         btfsc           STATUS,Z                ;Se tiene 0x00?
  902.         return                                          ;si => se termino el mensaje
  903.                                                                 ;no => continuamos
  904.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  905.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  906.         goto            EnvMsg_13P0
  907.  
  908. EnvMsg_14
  909.         clrf            OffsTabla               ;Para comenzar desde el primer caracter
  910. EnvMsg_14P0
  911.         movlw           HIGH Msg_14
  912.         movwf           AddrTabla+1             ;Con AddrTabla direccionamos el
  913.         movlw           LOW Msg_14              ;mensaje que queremos desplegar
  914.         movwf           AddrTabla
  915.         call            Mensajes                ;recojemos el carcater que toca
  916.         movwf           DatoTx                  ;y lo guardamos en DatoTx
  917.         xorlw           0x00
  918.         btfsc           STATUS,Z                ;Se tiene 0x00?
  919.         return                                          ;si => se termino el mensaje
  920.                                                                 ;no => continuamos
  921.         call            EUSART_Tx               ;llamamos a la rutina que envia caracteres
  922.         incf            OffsTabla,F             ;Para transmitir el siguiente caracter
  923.         goto            EnvMsg_14P0
  924.        
  925. EUSART_Tx
  926.         btfss           PIR1,TXIF               ;TXREG esta vacio?
  927.         goto            $-1                             ;No  => esperamos
  928.         movf            DatoTx,W
  929.         movwf           TXREG                   ;cargamos TXREG
  930.         return
  931.  
  932.  
  933. Mensajes
  934.         movf            OffsTabla,W
  935.         addwf           AddrTabla,W             ;determinamos si el sato no excede 0xFF
  936.         btfsc           STATUS,C
  937.         incf            AddrTabla+1,F   ;Si excede => incrementamos la parte alta
  938.         movf            AddrTabla+1,W
  939.         movwf           PCLATH                  ;actualizamos PCLATH(parte alta)
  940.         movf            OffsTabla,W
  941.         addwf           AddrTabla,W             ;volvemos a calcular el salto
  942.         movwf           PCL                             ;actualizamos PCL para realizar el salto.
  943.  
  944. Msg_0
  945.         DT      "\n\rEjemplo de lectura y escritura de una memoria i2c\n\r",0
  946. Msg_1
  947.         DT      "\n\rIntroduzca el numero de una de las opciones :\n\r\n\r"
  948.         DT      "1 Escribir un byte\n\r"
  949.         DT      "2 Leer un byte\n\r"
  950.         DT      "3 Escribir varios bytes (maximo 32)\n\r"
  951.         DT      "4 Leer varios bytes (maximo 80)\n\r\n\r",0
  952. Msg_2
  953.         DT      "\n\rBuffer lleno\n\r",0
  954. Msg_3
  955.         DT      "\n\r***** Escribir un byte *****\n\r"
  956.         DT      "Introduzca direccion en hexadecimal (2 bytes): ",0
  957.        
  958. Msg_4
  959.         DT      "\n\rIntroduzca dato en hexadecimal (1 byte): ",0
  960. Msg_5
  961.         DT      "\n\rValor(es) escrito(s)",0
  962. Msg_6
  963.         DT      "\n\r***** Leer un byte *****\n\r"
  964.         DT      "Introduzca direccion en hexadecimal (2 bytes): ",0
  965. Msg_7
  966.         DT      "\n\rEl valor leido es: ",0
  967. Msg_8
  968.         DT      "\n\rValor no valido\n\r",0
  969. Msg_9
  970.         DT      "\n\r***** Escribir varios bytes *****\n\r"
  971.         DT      "Introduzca direccion en hexadecimal (2 bytes): ",0
  972. Msg_10
  973.         DT      "\n\rIntroduzca los datos (maximo 32 caracteres):\n\r",0
  974. Msg_11
  975.         DT      "\n\r***** Leer varios bytes *****\n\r"
  976.         DT      "Introduzca direccion en hexadecimal (2 bytes): ",0
  977. Msg_12
  978.         DT      "\n\rIntroduzca la cantidad de bytes a leer (max 80): ",0
  979. Msg_13
  980.         DT      "\n\rLos valores leidos son:\n\r",0
  981. Msg_14
  982.         DT      "\n\r**********************************************\n\r ",0
  983.  
  984.         #include        <i2cCom.inc>
  985.         #include        <EE24AA64.inc>
  986.  
  987.         ORG     0x2100                          ; Pocision de la EEPROM interna
  988.         DE      1,2,3,4                         ; define las primeras cuatro posiciones de la
  989.                                                         ; EEPROM como 1,2,3 y 4
  990.  
  991.         END                       ; directiva 'fin del programa'

Aqui le dejo unas imagenes de cuando probe el programa.

(http://img132.imageshack.us/img132/7481/pantalla1bp3.jpg)

(http://img145.imageshack.us/img145/924/pantalla2qy8.jpg)

tambien les dejo todos los archivos del proyecto en MPLAB 8.14 y un archivo para simulacion en proteus 7.2

Saludos
Título: Re: pequeños proyectos
Publicado por: groundman en 13 de Febrero de 2009, 20:15:55
valla! muchas gracias por tu aporte.he visto que utilizas algunas funciones que desconocia.como esta linea:
incf   AddrTabla+1,F   ;Si excede => incrementamos la parte alta. supongo que lo que realiza es el incremento de AddrTabla y luego suma 1 al resultado.

y luego veo que has utilizado el hiperterminal para la comunicacion con el pic.nunca se me ocurrio su uso con este fin.
creo que voy a aprender muchas cosas con tu programa. :-)
Título: Re: pequeños proyectos
Publicado por: sander en 13 de Febrero de 2009, 21:50:47
valla! muchas gracias por tu aporte.he visto que utilizas algunas funciones que desconocia.como esta linea:
incf   AddrTabla+1,F   ;Si excede => incrementamos la parte alta. supongo que lo que realiza es el incremento de AddrTabla y luego suma 1 al resultado.

No hace eso que dices, fijate que cuando declaro variables  declaro AddrTabla:.2, esto es porque AddrTabla la uso como variable de 16 bits, y el hacer el AddrTabla+1 simplemente me permite acceder a los 8 bits altos de mi variable, por ejemplo si quisiera borrar la variable AddrTabla lo haria de la siguiente manera:

Código: ASM
  1. clrf      AddrTabla     ;borra la parte baja de la variable AddrTabla
  2. clrf      AddrTabla+1     ;borra la parte alta de la variable AddrTabla

Debes notar que guardo la parte baja de la variable en la direccion mas baja de memoria y la parte alta en la direccion alta, esto si no me equivoco es una convencion de INTEL.

Saludos.
Título: Re: pequeños proyectos
Publicado por: groundman en 14 de Febrero de 2009, 14:54:30
ah! vale ya entiendo.pero abajo pongo otras lineas de tu programa y hay dos diferencias en los .2 o sin punto.



i2cEEAddr:2                 ;en esta instruccion i2cEEAddr:2   
hace lo mismo que en esta?:    OffsTabla, AddrTabla:.2   o es que esta equivocada?   
   
Título: Re: pequeños proyectos
Publicado por: sander en 15 de Febrero de 2009, 01:00:01

i2cEEAddr:2                 ;en esta instruccion i2cEEAddr:2   
hace lo mismo que en esta?:    OffsTabla, AddrTabla:.2   o es que esta equivocada?   

En este caso es lo mismo, el ASM toma el .2 como un valor decimal y el 2 como un valor en hexadecimal, aqui no habria problema , pero una vez defini un buffer de recepcion como Buffer: 40, pesando que era 40 en decimal, pero .... en realidad el buffer termino siendo de 64 bytes (40 en hexadecimal), y eso me costo un par de horas revisando un programa, je jej,  por eso los buffers en este programa estan definidos con .80

Saludos
Título: Re: pequeños proyectos
Publicado por: groundman en 23 de Agosto de 2009, 14:49:07
ahi otro pequeño programa:



;*****************************************
; PROGRAMA : gps_usart.asm
; Funcion : guarda la trama GPS en memoria ram 
;           Serial port config: 38400 baudios,8 bits,paridad = none
;   
;  Revision : 1.0        23/8/2009            Programa para : PIC16F876A
; CPU Clock : 3.6864 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF           
;******************************************
;
;NOTAS:
;        este programa almacena una trama complata de GPS en la direccion 0x20
;        la trama podemos elegirla cambiando los caracteres de C1,C2,C3,C4,C5,C6,C7.
;

      LIST   P=16F876A   ;Se indica el modo de procesador
     
      RADIX   HEX      ;Sistema de numeracion hexadecimal

      INCLUDE   "P16f876A.inc"   ;se incluye la definicion de los
     
               ;registros internos
      __CONFIG    _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF ;&_WRT_ENABLE_OFF
      ERRORLEVEL      -302

         CBLOCK   0X20         ;BLOQUE DEL COMANDO A LEER
         C1         ;'$'
         C2         ;'G'
         C3         ;'P'
            C4         ;'G'
         C5         ;'G'
         C6         ;'A'
         C7         ;'.'
         ENDC

            CBLOCK    0x75           
           W_TEMP         
         STATUS_TEMP   
         PCLATH_TEMP
         ENDC

   
PUSH         MACRO               ;macro para salvar registros antes de una llamada a interrupcion   
            movwf   W_TEMP               
            swapf   STATUS,W
            movwf   STATUS_TEMP         
            clrf    STATUS               
            movfw   PCLATH               
              movwf   PCLATH_TEMP
            clrf    PCLATH
            ENDM

POP         MACRO               ;macro para restaurar registros   despues de una llamada a interrupcion
            movfw   PCLATH_TEMP         
            movwf   PCLATH
            swapf   STATUS_TEMP,W     
            movwf   STATUS
            swapf   W_TEMP,F         
            swapf   W_TEMP,W
            ENDM

BANK0         MACRO
            BCF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM

BANK1         MACRO
            BSF   STATUS,RP0
            BCF   STATUS,RP1
            ENDM
;<<<<<<<<<<<<<SELECCION DE LOS SECTORES DE LA MEMORIA DE PROGRAMA>>>>
;--------IMPORTANTE:
;ANTES DE UBICAR UNA TABLA DEL TIPO (ADDWF   PCL,F)TENEMOS QUE INDICAR EL SECTOR DONDE SE UBICA ESE SUBPROGRAMA
;EJM.SI PONEMOS EL SUBPROGRAMA EN EL SECTOR A PARTIR DE LA DIR:100 .PONDREMOS LA LINEA SECTOR_100 ANTES DE LA TABLA DE DATOS
;
SECTOR_000   MACRO
         BCF   PCLATH,0
         BCF   PCLATH,1
         ENDM
SECTOR_100   MACRO
         BSF   PCLATH,0
         BCF   PCLATH,1
         ENDM
SECTOR_200   MACRO
         BCF   PCLATH,0
         BSF   PCLATH,1
         ENDM
SECTOR_300   MACRO
         BSF   PCLATH,0
         BSF   PCLATH,1
         ENDM


;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
         ORG      0x00      ;Inicio en el Vector de Reset
         goto   INICIO      ;Va a la primera instruccion del programa
;<<<<<<--------------------VECTOR DE INTERRUPCION---------------------->>>>>>>
       ORG      0x04             
       goto     INTER      ;Va al programa de interrupcion   
               
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO      BANK1                  ;selecciona banco 1
            movlw   .5               ;(.5 =38400 baudios crystal 3.6864 MHz)
            movwf   SPBRG
          movlw   b'00000110'
            movwf   ADCON1         ;porta entradas digitales
            movlw   0xFF
            movwf   TRISA
            movlw   b'00000110'       ;Configuracion USART modo alta velocidad 38400 baud
            movwf   TXSTA     
            
            BANK0                  ;selecciona banco 0 -------------
            movlw   b'10010000'      ;Configuracion de la usart
            movwf   RCSTA            ;para recepcion continua y habilitacion de la usart
            movlw   '$'
         movwf   C1            ;registros para la cabezera NMEA
         movlw   'G'
         movwf   C2
         movlw   'P'
         movwf   C3
         movlw   'G'
         movwf   C4
         movlw   'G'
         movwf   C5
         movlw   'A'
         movwf   C6
         movlw   ','
         movwf   C7
         BANK1
         movlw   b'00100000'      ;habilita interrupcion por recepcion de usart
         movwf   PIE1
         movlw   b'11000000'      ;habilita interrupciones generales y perifericas
         movwf   INTCON
         
         
      
PRINCIPAL   GOTO   PRINCIPAL
   
;<<<<<<<<<<--------------METE EN UN BLOQUE DE RAM LOS COMANDOS RECIBIDOS------------>>>>>>>>>>>>>>>   
         
LEEDATO           BANK0               ;Cambio al banco 0
            movlw   0x1f         ;carga en w el valor 0x4F "(0X50) principio de RAM para introducir mensages recividos"
            movwf   FSR            ;cargalo en el puntero de registro de proposito general
LEEDATO2      incf   FSR,F         ;incrementa la siguiente direccion de la ram
            movfw   INDF         ;carga en W el valor direcionado en FSR
            xorwf   RCREG,W         ;comparalo con el caracter recivido de la USART
            btfss   STATUS,Z      ;si es el mismo continua con el programa
            return               ;en caso contrario retorna 
            call   ERR_USART      ;salta a ERR_USART
            
            movlw   ','            ;carga en w el caracter '.' caracter posterior de cabezera
            xorwf   RCREG,W         ;comparalo con el caracter recivido de la USART
            btfss   STATUS,Z      ;si es el mismo salta
            goto   LEEDATO2
SIGUIENTE      incf   FSR            ;incrementa FSR
            movfw   RCREG         ;carga en W el caracter recivido
            movwf   INDF         ;mete el caracter en la posicion de memoria que apunta FSR
            movlw   '$'            ;carga valor '$' en w
            xorwf   RCREG,W         ;comparalo con el valor recivido de la usart(primer caracter de siguiente trama)
            btfsc   STATUS,Z
            return               ;si es igual retorna(fin de captura de trama)
            call   ERR_USART      ;salta a ERR_USART
            goto   SIGUIENTE

;<<<<<<<<<<<<<<<<<<<<------SUBPROGRAMA PARA ESPERA DE CARACTER Y CORRECTOR DE ERRORES----->>>>>>>>>>>>>
ERR_USART      btfss   PIR1,RCIF      ;espera al proximo caracter
            goto    ERR_USART 
            btfsc   RCSTA,OERR   
            call   BORR_ERR      ;Error de Sobreescritura
            btfsc   RCSTA,FERR   
            call   BORR_ERR      ;Error de Trama
            BCF      PIR1,RCIF      ;borra el flag de interrupcion por caracter recivido            
            return
            
BORR_ERR      bcf      RCSTA,CREN   
            movf   RCREG,w   
            movf   RCREG,w   
            movf   RCREG,w            
            bsf      RCSTA,CREN   
            return            
         
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<PROGRAMA DE GESTION DE INTERRUPCIONES>>>>>>>>>>>>>>>>>>>>>>
INTER           PUSH                    ;salva el contenido de W,STATUS Y PCLATH
               BANK0
               btfsc   PIR1,RCIF      ;comprueba si el shift register(RSR)esta lleno.y si es asi salta
               call   LEEDATO   
               POP                    ;restaura el contenido de W,STATUS Y PCLATH
            bcf   PIR1,RCIF         ;borra flag de interrupcion por recepcion de usart
               retfie                 ;retorno de interrupcion

            END

     




Título: Re: pequeños proyectos
Publicado por: groundman en 21 de Septiembre de 2009, 18:02:47
y aqui pongo otro programa relacionado con la usart.aunque en este hay varias funcionalidades.aparte de recivir datos ,tambien tenemos un subprograma que es llamado por una interrupcion por recepcion de usart.la cual es prioritaria.
dentro de este subprograma,se espera recivir un comando NMEA.especificamente el GPGGA.del cual extraeremos la informacion que arrastra y que meteremos
a partir de la direccion 0x20 comando incluido.
aunque tambien podemos especificar otro comando diferente.seguir las instruciones de la nota del asm.
a parte de esto cuando se almacene la informacion.tenemos un programa PRINCIPAL.en el que pondremos el programa para tratar los datos de la trama NMEA.


;*****************************************
; PROGRAMA : gps_usart.asm
; Funcion : guarda la trama GPS en memoria ram  
;           Serial port config: 38400 baudios,8 bits,paridad = none
;  
;  Revision : 1.0        23/8/2009            Programa para : PIC16F876A
; CPU Clock : 3.6864 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF          
;******************************************
;
;NOTAS:
;        este programa almacena una trama complata de GPS en la direccion 0x20
;        la trama podemos elegirla cambiando los caracteres de C1,C2,C3,C4,C5,C6,C7.
;

      LIST   P=16F876A   ;Se indica el modo de procesador
      
      RADIX   HEX      ;Sistema de numeracion hexadecimal

      INCLUDE   "P16f876A.inc"   ;se incluye la definicion de los
      
               ;registros internos
      __CONFIG    _CP_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF ;&_WRT_ENABLE_OFF
      ERRORLEVEL      -302


      

            CBLOCK   0X20         ;BLOQUE DEL COMANDO A LEER
            C1         ;'$'
            C2         ;'G'
            C3         ;'P'
               C4         ;'G'
            C5         ;'G'
            C6         ;'A'
            C7         ;','
            ENDC

               CBLOCK    0x70
              W_TEMP        
            STATUS_TEMP  
            PCLATH_TEMP
            TEMP_FSR
            ;PCL_REG
            ENDC
            
            
   
PUSH            MACRO               ;macro para salvar registros antes de una llamada a interrupcion  
               BANK0
            movwf   W_TEMP              
               swapf   STATUS,W
            movwf   STATUS_TEMP  
               clrf    STATUS              
               movfw   PCLATH              
                 movwf   PCLATH_TEMP
               clrf    PCLATH
            movfw   FSR
            movwf   TEMP_FSR
            ENDM

POP            MACRO               ;macro para restaurar registros   despues de una llamada a interrupcion
               BANK0
            movfw   PCLATH_TEMP        
               movwf   PCLATH
               swapf   STATUS_TEMP,W  
            movwf   STATUS
            swapf   W_TEMP,F        
               swapf   W_TEMP,W
            movfw   TEMP_FSR
            movwf   FSR
            ENDM

BANK0            MACRO                  ;seleccion del banco 0
               BCF   STATUS,RP0         
               BCF   STATUS,RP1
               ENDM

BANK1            MACRO                  ;seleccion del banco 1
               BSF   STATUS,RP0         
               BCF   STATUS,RP1
               ENDM

BANK2            MACRO                  ;seleccion del banco 2
               BCF   STATUS,RP0         
               BSF   STATUS,RP1
               ENDM

BANK3            MACRO                  ;seleccion del banco 3
               BSF   STATUS,RP0
               BSF   STATUS,RP1
               ENDM

         
;<<<<<<<<<<<<<SELECCION DE LOS SECTORES DE LA MEMORIA DE PROGRAMA>>>>
;--------IMPORTANTE:
;ANTES DE UBICAR UNA TABLA DEL TIPO (ADDWF   PCL,F)TENEMOS QUE INDICAR EL SECTOR DONDE SE UBICA ESE SUBPROGRAMA
;EJM.SI PONEMOS EL SUBPROGRAMA EN EL SECTOR A PARTIR DE LA DIR:100 .PONDREMOS LA LINEA SECTOR_100 ANTES DE LA TABLA DE DATOS
;
SECTOR_000     MACRO                  ;seleccion del sector 000
               BCF   PCLATH,0
               BCF   PCLATH,1
               ENDM
SECTOR_100     MACRO                  ;seleccion del sector 100
               BSF   PCLATH,0
               BCF   PCLATH,1
               ENDM
SECTOR_200      MACRO                  ;seleccion del sector 200
               BCF   PCLATH,0
               BSF   PCLATH,1
               ENDM
SECTOR_300      MACRO                  ;seleccion del sector 300
               BSF   PCLATH,0
               BSF   PCLATH,1
               ENDM

            #define      GIE_ON      bsf      INTCON,GIE   ;activa interrupciones
               #define      GIE_OFF      bcf      INTCON,GIE   ;desactiva interrupciones



;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
               ORG      0x00            ;Inicio en el Vector de Reset
               goto   INICIO            ;Va a la primera instruccion del programa
;<<<<<<--------------------VECTOR DE INTERRUPCION---------------------->>>>>>>
             ORG      0x04              
             goto     INTER            ;Va al programa de interrupcion  
              
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO         BANK1                  ;selecciona banco 1
               movlw   .5               ;(.5 =38400 baudios crystal 3.6864 MHz)
               movwf   SPBRG
             movlw   b'00000110'
               movwf   ADCON1         ;PORTA entradas digitales
               movlw   b'00000110'       ;Configuracion USART modo alta velocidad
               movwf   TXSTA      
               movlw   b'11000000'
            movwf   TRISC         ;configura pins TX y RX para la usart
            movlw   b'00100000'      ;habilita interrupcion por recepcion de usart
            movwf   PIE1
            movlw   b'01000000'      ;habilita interrupciones perifericas
            movwf   INTCON
               BANK0                  ;selecciona banco 0 -------------
            movlw   b'10010000'      ;Configuracion de la usart
               movwf   RCSTA            ;para recepcion continua y habilitacion de la usart
            
               movlw   '$'            ;registros para la cabezera NMEA(cambiarlos para otra cabecera)
            movwf   C1            
            movlw   'G'
            movwf   C2
            movlw   'P'
            movwf   C3
            movlw   'G'
            movwf   C4
            movlw   'G'
            movwf   C5
            movlw   'A'
            movwf   C6
            movlw   ','
            movwf   C7
            
            GIE_ON               ;habilita interrupciones generales
            
            
;<<<<<<<------------------------------------------------PROGRAMA PRINCIPAL---------------------------------------->>>>>>>>>>>>>>         
PRINCIPAL      goto   PRINCIPAL      



            
            
;<<<<<<<<<<--------------METE EN UN BLOQUE DE RAM LOS COMANDOS RECIBIDOS------------>>>>>>>>>>>>>>>   
        
LEEDATO           BANK0               ;Cambio al banco 0
            
            movlw   0x1f         ;carga en w el valor 0x1F  principio de RAM para introducir mensages recividos"
            movwf   FSR            ;cargalo en el puntero de registro de proposito general
LEEDATO2      incf   FSR,F         ;incrementa la siguiente direccion de la ram
            movfw   INDF         ;carga en W el valor direcionado en FSR
            xorwf   RCREG,W         ;comparalo con el caracter recivido de la USART
            btfss   STATUS,Z      ;si es el mismo continua con el programa
            return               ;en caso contrario empieza de nuevo
            call   ERR_USART      ;salta a ERR_USART
            movlw   ','            ;carga en w el caracter ',' caracter posterior de cabezera
            xorwf   RCREG,W         ;comparalo con el caracter recivido de la USART
            btfss   STATUS,Z      ;si es el mismo salta
            goto   LEEDATO2

SIGUIENTE      incf   FSR,F         ;incrementa FSR
            movfw   RCREG         ;carga en W el caracter recivido
            movwf   INDF         ;mete el caracter en la posicion de memoria que apunta FSR
            movlw   '*'            ;carga valor '*' en w
            xorwf   RCREG,W         ;comparalo con el valor recivido de la usart(caracter de fin trama)
            btfsc   STATUS,Z
            return               ;si es igual retorna(fin de captura de trama)
            movlw   0x6F         ;valor limite de RAM
            xorwf   FSR,W
            btfsc   STATUS,Z
            return               ;si se excede del valor anterior.retorna
            call   ERR_USART      ;salta a ERR_USART
            goto   SIGUIENTE

;<<<<<<<<<<<<<<<<<<<<------SUBPROGRAMA PARA ESPERA DE CARACTER Y CORRECTOR DE ERRORES----->>>>>>>>>>>>>
ERR_USART      btfss   PIR1,RCIF      ;espera al proximo caracter
            goto    ERR_USART  
            btfsc   RCSTA,OERR   
            call   BORR_ERR      ;Error de Sobreescritura
            btfsc   RCSTA,FERR   
            call   BORR_ERR      ;Error de Trama
            bcf      PIR1,RCIF      ;borra el flag de interrupcion por caracter recivido            
            return
            
BORR_ERR      bcf      RCSTA,CREN      ;deshabilita recepcion usart
            movf   RCREG,w         
            movf   RCREG,w   
            movf   RCREG,w            
            bsf      RCSTA,CREN      ;habilita recepcion usart
            return            
         
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<PROGRAMA DE GESTION DE INTERRUPCIONES>>>>>>>>>>>>>>>>>>>>>>
INTER           PUSH                    ;salva el contenido de W,STATUS Y PCLATH
            BANK0
            call      LEEDATO
            bcf      PIR1,RCIF         ;borra flag de interrupcion por recepcion de usart
            call   BORR_ERR
            POP                    ;restaura el contenido de W,STATUS Y PCLATH
            retfie
            
            END
Título: Re: pequeños proyectos
Publicado por: groundman en 21 de Septiembre de 2009, 19:30:23
este programa de abajo es una ampliacion del anterior.
en este he agregado un subprograma que selecciona los datos de la hora y las coordenadas.y luego pasa por otro que convierte estos datos a decimales para pasarlos a los registros direccionados a partir de la direccion 0xA0.

ademas he puesto en el programa principal unas instrucciones para visualizar los datos de los segundos por el PORTB.



;*****************************************
; PROGRAMA : gps_usart.asm
; Funcion : guarda la trama GPS en memoria ram 
;           Serial port config: 38400 baudios,8 bits,paridad = none
;   
;  Revision : 1.0        23/8/2009            Programa para : PIC16F876A
; CPU Clock : 3.6864 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF           
;******************************************
;
;NOTAS:
;        este programa almacena una trama complata de GPS en la direccion 0x20
;        y pasa los datos de hora y coordenadas a partir de la direccion A0.
;      

      LIST   P=16F876A   ;Se indica el modo de procesador
     
      RADIX   HEX      ;Sistema de numeracion hexadecimal

      INCLUDE   "P16f876A.inc"   ;se incluye la definicion de los
     
               ;registros internos
      __CONFIG    _CP_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF ;&_WRT_ENABLE_OFF
      ERRORLEVEL      -302


      

            CBLOCK   0X20         ;BLOQUE DEL COMANDO A LEER
            C1         ;'$'
            C2         ;'G'
            C3         ;'P'
               C4         ;'G'
            C5         ;'G'
            C6         ;'A'
            C7         ;','
            ENDC

               CBLOCK    0x70
            
              W_TEMP         
            STATUS_TEMP   
            PCLATH_TEMP
            TEMP_FSR
            TEMP_DATO_H
            TEMP_DATO_L
            TEMP_NUMERICO
            PRINCIPIO_RAM
            CARACTER
         
            ENDC
            
            

   
PUSH            MACRO               ;macro para salvar registros antes de una llamada a interrupcion   
               BANK0
            movwf   W_TEMP               
               swapf   STATUS,W
            movwf   STATUS_TEMP 
               clrf    STATUS               
               movfw   PCLATH               
                 movwf   PCLATH_TEMP
               clrf    PCLATH
            movfw   FSR
            movwf   TEMP_FSR
            ENDM

POP            MACRO               ;macro para restaurar registros   despues de una llamada a interrupcion
               BANK0
            movfw   PCLATH_TEMP         
               movwf   PCLATH
               swapf   STATUS_TEMP,W 
            movwf   STATUS
            swapf   W_TEMP,F         
               swapf   W_TEMP,W
            movfw   TEMP_FSR
            movwf   FSR
            ENDM

BANK0            MACRO                  ;seleccion del banco 0
               BCF   STATUS,RP0         
               BCF   STATUS,RP1
               ENDM

BANK1            MACRO                  ;seleccion del banco 1
               BSF   STATUS,RP0         
               BCF   STATUS,RP1
               ENDM

BANK2            MACRO                  ;seleccion del banco 2
               BCF   STATUS,RP0         
               BSF   STATUS,RP1
               ENDM

BANK3            MACRO                  ;seleccion del banco 3
               BSF   STATUS,RP0
               BSF   STATUS,RP1
               ENDM

         
;<<<<<<<<<<<<<SELECCION DE LOS SECTORES DE LA MEMORIA DE PROGRAMA>>>>
;--------IMPORTANTE:
;ANTES DE UBICAR UNA TABLA DEL TIPO (ADDWF   PCL,F)TENEMOS QUE INDICAR EL SECTOR DONDE SE UBICA ESE SUBPROGRAMA
;EJM.SI PONEMOS EL SUBPROGRAMA EN EL SECTOR A PARTIR DE LA DIR:100 .PONDREMOS LA LINEA SECTOR_100 ANTES DE LA TABLA DE DATOS
;
SECTOR_000     MACRO                  ;seleccion del sector 000
               BCF   PCLATH,0
               BCF   PCLATH,1
               ENDM
SECTOR_100     MACRO                  ;seleccion del sector 100
               BSF   PCLATH,0
               BCF   PCLATH,1
               ENDM
SECTOR_200      MACRO                  ;seleccion del sector 200
               BCF   PCLATH,0
               BSF   PCLATH,1
               ENDM
SECTOR_300      MACRO                  ;seleccion del sector 300
               BSF   PCLATH,0
               BSF   PCLATH,1
               ENDM

            #define      GIE_ON      bsf      INTCON,GIE   ;activa interrupciones
               #define      GIE_OFF      bcf      INTCON,GIE   ;desactiva interrupciones



;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
               ORG      0x00            ;Inicio en el Vector de Reset
               goto   INICIO            ;Va a la primera instruccion del programa
;<<<<<<--------------------VECTOR DE INTERRUPCION---------------------->>>>>>>
             ORG      0x04             
             goto     INTER            ;Va al programa de interrupcion   
               
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO         BANK0
            clrf   PORTB         ;borra salidas de PORTB antes de configurarlo como salida.
            BANK1                  ;selecciona banco 1
               movlw   .5               ;(.5 =38400 baudios crystal 3.6864 MHz)
               movwf   SPBRG
             movlw   b'00000110'
               movwf   ADCON1         ;PORTA entradas digitales
               movlw   b'00000110'       ;Configuracion USART modo alta velocidad
               movwf   TXSTA     
               movlw   b'11000000'
            movwf   TRISC         ;configura pins TX y RX para la usart
            movlw   b'00100000'      ;habilita interrupcion por recepcion de usart
            movwf   PIE1
            movlw   b'01000000'      ;habilita interrupciones perifericas
            movwf   INTCON
            clrf   PORTB         ;PORTB como salida
               BANK0                  ;selecciona banco 0 -------------
            movlw   b'10010000'      ;Configuracion de la usart
               movwf   RCSTA            ;para recepcion continua y habilitacion de la usart
            
               movlw   '$'            ;registros para la cabezera NMEA(cambiarlos para otra cabecera)
            movwf   C1            
            movlw   'G'
            movwf   C2
            movlw   'P'
            movwf   C3
            movlw   'G'
            movwf   C4
            movlw   'G'
            movwf   C5
            movlw   'A'
            movwf   C6
            movlw   ','
            movwf   C7
            
            GIE_ON               ;habilita interrupciones generales
            
            
;<<<<<<<------------------------------------------------PROGRAMA PRINCIPAL---------------------------------------->>>>>>>>>>>>>>         
PRINCIPAL      BANK1
            movlw   0xA2         ;direccion segundos decimales.
            movwf   FSR            ;cargala en el registro FSR
            movfw   INDF         ;recoje el dato dicha direccion
            BANK0
            movwf   PORTB         ;visualizalo en el PORTB
            goto   PRINCIPAL      



            
            
;<<<<<<<<<<--------------METE EN UN BLOQUE DE RAM LOS COMANDOS RECIBIDOS------------>>>>>>>>>>>>>>>   
         
LEEDATO           BANK0               ;Cambio al banco 0
            
            movlw   0x1f         ;carga en w el valor 0x1F  principio de RAM para introducir mensages recividos"
            movwf   FSR            ;cargalo en el puntero de registro de proposito general
LEEDATO2      incf   FSR,F         ;incrementa la siguiente direccion de la ram
            movfw   INDF         ;carga en W el valor direcionado en FSR
            xorwf   RCREG,W         ;comparalo con el caracter recivido de la USART
            btfss   STATUS,Z      ;si es el mismo continua con el programa
            return               ;en caso contrario empieza de nuevo
            call   ERR_USART      ;salta a ERR_USART
            movlw   ','            ;carga en w el caracter ',' caracter posterior de cabezera
            xorwf   RCREG,W         ;comparalo con el caracter recivido de la USART
            btfss   STATUS,Z      ;si es el mismo salta
            goto   LEEDATO2

SIGUIENTE      incf   FSR,F         ;incrementa FSR
            movfw   RCREG         ;carga en W el caracter recivido
            movwf   INDF         ;mete el caracter en la posicion de memoria que apunta FSR
            movlw   '*'            ;carga valor '*' en w
            xorwf   RCREG,W         ;comparalo con el valor recivido de la usart(caracter de fin trama)
            btfsc   STATUS,Z
            return               ;si es igual retorna(fin de captura de trama)
            movlw   0x6F         ;valor limite de RAM
            xorwf   FSR,W
            btfsc   STATUS,Z
            return               ;si se excede del valor anterior.retorna
            call   ERR_USART      ;salta a ERR_USART
            goto   SIGUIENTE

;<<<<<<<<<<<<<<<<<<<<------SUBPROGRAMA PARA ESPERA DE CARACTER Y CORRECTOR DE ERRORES----->>>>>>>>>>>>>
ERR_USART      btfss   PIR1,RCIF      ;espera al proximo caracter
            goto    ERR_USART 
            btfsc   RCSTA,OERR   
            call   BORR_ERR      ;Error de Sobreescritura
            btfsc   RCSTA,FERR   
            call   BORR_ERR      ;Error de Trama
            bcf     PIR1,RCIF      ;borra el flag de interrupcion por caracter recivido            
            return
            
BORR_ERR      bcf      RCSTA,CREN      ;deshabilita recepcion usart
            movf   RCREG,w         
            movf   RCREG,w   
            movf   RCREG,w            
            bsf      RCSTA,CREN      ;habilita recepcion usart
            return            

;<<<<<<<--------------------------PROGRAMA PARA ALMACENAR A PARTIR DE LA DIRECION 0XA0 DE LA RAM,LOS DATOS IMPORTANTES DE LA TRAMA NMEA.--------         
      
GRARAM         movlw   0xA0         ;valor del principio de los registros a leer
            movwf   PRINCIPIO_RAM   ;carga el valor en el registro puntero.
            BANK0
            movlw   0x27         ;valor del primer caracter de la ram a traducir
            movwf   TEMP_FSR      ;cargalo en el registro temporal FSR
            
REP3         movfw   TEMP_FSR
            movwf   FSR            ;carga el puntero de ram
   
            movfw   FSR            ;
            xorlw   2D            ;direccion comienzo a ignorar "direccion de comienzo de datos inservibles"
            btfsc   STATUS,Z
            call   SUMA5         ;cinco pociciones de memoria a ignorar

            movfw   FSR            ;
            xorlw   36            ;direccion comienzo a ignorar
            btfsc   STATUS,Z
            call   SUMA1         ;una pocicion de memoria a ignorar

            movfw   FSR            ;
            xorlw   3B            ;direccion centenas de coordenada ecuador
            btfsc   STATUS,Z
            call   CENTENAS

            movfw   FSR            ;
            xorlw   43            ;direccion comienzo a ignorar
            btfsc   STATUS,Z
            call   SUMA1         ;una pocicion de memoria a ignorar

            movfw   FSR            ;
            xorlw   48            ;direccion comienzo a ignorar
            btfsc   STATUS,Z
            return               ;final del subprograma

            movfw   TEMP_FSR
            movwf   FSR            ;carga el puntero de ram
            movfw   INDF         ;recoge valor
            movwf   CARACTER
            
            movfw   CARACTER
            call   TRADUCE         ;traduce el valor ascii a decimal
            movwf   TEMP_NUMERICO   ;temporal de valor traducido.
            
            movfw   PRINCIPIO_RAM
            movwf   FSR
            
            movfw   TEMP_NUMERICO
            movwf   INDF
         
            incf   PRINCIPIO_RAM,F
            BANK0
               
            incf   TEMP_FSR,F
REP4         incf   TEMP_FSR,F
            goto   REP3
            
SUMA5         movlw   0x05         ;salto de 5 direcciones FSR
            addwf   TEMP_FSR,f
            return
SUMA1         movlw   0x01         ;salto de 1 direccion FSR
            addwf   TEMP_FSR,f
            return

SUMA2         movlw   0x02         ;salto de 2 direcciones FSR
            addwf   TEMP_FSR,f
            return

CENTENAS      movlw   0x3E
            movwf   FSR
            
            clrf   TEMP_DATO_H
            movlw   '0'
            xorwf   INDF,W
            btfss   STATUS,Z
            incf   TEMP_DATO_H,F
            movlw   0x3F
            movwf   TEMP_FSR
            BANK1
            incf   PRINCIPIO_RAM,F
            BANK0
            movlw   0xA7
            movwf   FSR
            movfw   TEMP_DATO_H
            movwf   INDF   
            return

            
            
;<<<<<<<<<<<-------------CONVERTIR VALORES HEX EN DECIMALES--------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>

TRADUCE         movwf   TEMP_DATO_H      ;
            movlw   0x30
            
            subwf   TEMP_DATO_H,F
            swapf   TEMP_DATO_H,F
            incf   FSR,F
            movfw   INDF
            movwf   TEMP_DATO_L
            movlw   0x30
            subwf   TEMP_DATO_L,W
            addwf   TEMP_DATO_H,W
            return
         
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<PROGRAMA DE GESTION DE INTERRUPCIONES>>>>>>>>>>>>>>>>>>>>>>
INTER           PUSH                    ;salva el contenido de W,STATUS Y PCLATH
            BANK0
            call      LEEDATO
            call   GRARAM
            bcf      PIR1,RCIF         ;borra flag de interrupcion por recepcion de usart
            call   BORR_ERR
            POP                    ;restaura el contenido de W,STATUS Y PCLATH
            retfie
            
            END

     




Título: Re: pequeños proyectos
Publicado por: groundman en 22 de Noviembre de 2009, 18:54:28
he realizado una usart por software para el pic12f508.
el programa recive un dato por el pin GP1 y lo transmite por el GP0.lo he realizado lo mas simplificado posible y es facil de modificar para separar el programa de recepcion del de transmision.y asi utilizarlo en otros proyectos.
se podria usar un solo pin para la recepcion y la emision.solo hay que cambiar algunas lineas del codigo.pero este no queria complicarlo mas.
podemos utilizar diferentes velocidades de transmision.para 1200,2400,4800,9600 y 19200bps. trabajando con el oscilador interno de este pic a 4Mhz.
no podemos utilizar frecuencias mayores sin que por ello se produzcan errores de transmision.

que lo disfruten.que trabajito me ha costado.
            

;*****************************************
; PROGRAMA : usart_12c508
; Funcion : recepcion y emision de datos mediante comunicacion serie.
;          
;  
;  Revision : 1.0        26/10/2009            Programa para : PIC12F508
; CPU Clock : 4 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : IntRC
; Code Prot : OFF          
;******************************************
;
;este programa recive datos por el pin GP1 y los transmite por el GP0
;podemos configurar la velocidad que deseemos.el valor es introducido en el registro BAUDRATE.
;en el subprograma de ENVIO DE DATOS he puesto una linea deshabilitada por si queremos usar solamente la emision de datos.
;habilitandola solo tendriamos que cargar un valor en W.y hacer una llamada .call ENVIO.y el dato se emitiria
;por el pin GP0 del pic12f508
      LIST   P=12F508   ;Se indica el modo de procesador
      
      RADIX   HEX      ;Sistema de numeracion hexadecimal

      INCLUDE   "P12F508.inc"  
      
               ;registros internos
      __CONFIG   _IntRC_OSC & _CP_OFF & _WDT_OFF & _MCLRE_OFF

      ERRORLEVEL      -302


            CBLOCK    0x08
            CONTADOR
            DATO
            CONFIG_GPIO
            BAUDRATE
            ENDC
         
;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
               ORG      0x00            ;Inicio en el Vector de Reset
              goto   INICIO            ;Va a la primera instruccion del programa

;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO         movlw   b'11000000'      ;configura el divisor de TMR0
            option   
            clrf   CONFIG_GPIO      ;borra el registro configuracion de E/S
            movlw   d'40'
            movwf   BAUDRATE
            ;valores para el vaudrate:
            ;
            ;para divisor TMR0=000
            ;190=2400bps, 90=4800bps, 40=9600bps, 15=19200bps,
            ;
            ;para divisor TMR0=010
            ;97=1200bps,
         
;<<<<<<<------------------------------------------------PROGRAMA PRINCIPAL---------------------------------------->>>>>>>>>>>>>>         
PRINCIPAL      call   RECEPCION
            
            call   ENVIO
            goto   PRINCIPAL
;<<<<<<---------------------------------------------SUBPROGRAMA RECEPCION DE DATOS--------------------------
            
RECEPCION      bsf      CONFIG_GPIO,1   ;pin 1 de GPIO como entrada
            movfw   CONFIG_GPIO      ;carga en w la configuracion de los pines GPIO
            tris    GPIO         ;aplica la configuracion de E/S   
            bsf      GPIO,0         ;pon a 0 el pin de salida de datos
            clrf   CONTADOR      ;borra el contador de bits
            btfsc   GPIO,1         ;comprueva si hay una señal de estado bajo por pin 0 de GPIO
            goto   $-1            ;si no hay señar espera

            clrf   TMR0         ;borra TMR0
            movfw   BAUDRATE      ;carga valor del baudrate en w
            subwf   TMR0,w         ;comprueva si ha llegado al valor o se pasa
            btfss   STATUS,C      ;si es menos sigue comprovando
            goto   $-3
            
COMP1         clrf   TMR0         ;borra TMR0
COMP2         movfw   BAUDRATE      ;carga valor del baudrate en w
            subwf   TMR0,w         ;resta el contenido de TMR0 con el de w(comprovacion => )
            btfss   STATUS,C      ;comprueva si ha llegado al valor o se pasa
            goto   COMP2         ;si es menos sigue comprovando

            btfsc   GPIO,1         ;comprueva el estado del pin de entrada
            call   UNO            ;si es 1 salta a UNO
            btfss   GPIO,1         ;comprueva el estado del pin de entrada
            call   CERO         ;si es 0 salta a CERO

            bsf      GPIO,2
            BCF      GPIO,2

            incf   CONTADOR,F      ;incrementa el contador de bits
            movlw   0x08         ;valor de bit a comprovar
            xorwf   CONTADOR,W      ;hacer xor con CONTADOR
            btfss   STATUS,Z      ;comprueva si es igual
            goto   COMP1         ;si no es igual sigue las comprobaciones
            movfw   DATO         ;carga el dato recivido en w
            retlw   0x00         ;retorno de subprograma

UNO            rrf      DATO,F         ;rota a la derecha una posicion   
            bsf      DATO,7         ;pon a 1 el bit 7 del registro DATO
            retlw   0x00         ;retorna

CERO         rrf      DATO,F         ;rota a la derecha una posicion
            bcf      DATO,7         ;pon a 0 el bit 7 del registro DATO
            retlw   0x00         ;retorna
            
         
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<SUBPROGRAMA DE ENVIO DE DATOS>>>>>>>>>>>>>>>>>      

   
ENVIO         ;movwf   DATO         ;carga el contenido de w al registro DATO
            bcf      CONFIG_GPIO,0   ;pin 0 de GPIO como salida
            movfw   CONFIG_GPIO      ;carga en w la configuracion de los pines GPIO
            tris    GPIO         ;aplica la configuracion de E/S
            bsf      GPIO,0         ;establecer la salida a 1(evitar errores primer caracter)
ENVIO2         clrf   CONTADOR      ;borra el registro CONTADOR de bits
            bcf      GPIO,0         ;bit START   
            call   RETARDO   
            
ENV_1         btfsc   DATO,0         ;comprueva bit 0 del registro DATO(comprovacion de bits a enviar)
            goto   UNOS         ;salta a UNOS si el bit leido es 1
            btfss   DATO,0         ;comprueva bit 0 del registro DATO(comprovacion de bits a enviar)
            goto   CEROS         ;salta a CEROS si el bit leido es 0
ENV_2         rrf      DATO,F         ;rota a la derecha el registro DATO
            incf   CONTADOR,F      ;incrementa CONTADOR (registro contador de bits)
            movlw   0x08         ;valor de bits a leer
            xorwf   CONTADOR,W      ;comprueva si son 8
            btfss   STATUS,Z      ;si no es 8 repite la comprovacion del siguiente bit
            goto   ENV_1         ;comprueva de nuevo
            retlw   0x00         ;retorna del subprograma

UNOS         bsf      GPIO,0         ;saca valor 1 por pin 0 de GPIO
            call   RETARDO         ;tiempo de un bit
            goto   ENV_2         ;siguiente bit
CEROS         bcf      GPIO,0         ;saca valor 0 por pin 0 de GPIO
            call   RETARDO         ;tiempo de un bit
            goto   ENV_2         ;siguiente bit

;**********************************************RETARDO***************************************

RETARDO         clrf   TMR0         ;borra el temporizador
COMP         movfw   BAUDRATE      ;valor del retardo
            subwf   TMR0,w         ;comprueva si ha llegado al valor o se pasa
            btfss   STATUS,C      ;si es menos sigue comprovando
            goto   COMP
            retlw   0x00         ;si ha llegado retorna


            end                  ;fin
Título: Re: pequeños proyectos
Publicado por: Leon Pic en 23 de Noviembre de 2009, 08:08:00
Te re felicito groundman  :-/ :-/
Título: Re: pequeños proyectos
Publicado por: Suky en 23 de Noviembre de 2009, 09:33:44
Muy bien Groundman! Una consulta, ese PIC tiene interrupción por flanco en alguno de sus pines? Si es si, podes utilizarlo para detectar la llegada de algún dato. Por aquí (http://www.todopic.com.ar/foros/index.php?topic=24720.msg201414#msg201414) un ejemplo.

Cuando postees código hazlo entre [ code ] aquí código [ /code ] (Sin los espacios) así queda más ordenado y entendible  ;-)

Saludos!
Título: Re: pequeños proyectos
Publicado por: groundman en 23 de Noviembre de 2009, 19:09:05
gracias por los elogios. :)

suky.este pic no lleva interrupciones.ya pense en eso.lo unico mas parecido a una interrupcion si no me equivoco.es la posibilidad de despertar del modo sleep
por cambio de estado en algunos de sus pins.
es un pic tan pequeño que solo tiene 2 stack pointer. :( con lo que me fastidia usar los goto para llamar a otros subprogramas.
pronto posteare otro codigo para usarlo en un 16f84.y esta vez si que integrare esta posibilidad.de esta forma se aprobechara mejor su velocidad de funcionamiento.

ah.y lo de
Código: [Seleccionar]
no lo sabia.lo hare en el proximo asm que posteo.

saludos.
Título: Re: pequeños proyectos
Publicado por: alogic.on en 23 de Noviembre de 2009, 19:26:47
coach, pues a mi lo que siempre me ha tirado por los suelos de estos pequeñines es que no tienen hard. para comunicarse, si le pusiesen i2c ... o usart, pero mirando esto a lo mejor me animo a hacer alguna cosilla con ellos, gracias Groundman

un saludo
Título: Re: pequeños proyectos
Publicado por: groundman en 23 de Noviembre de 2009, 20:50:10
a mi lo que mas me a gustado de estos pequeñines es el precio   :D sobre los 2€
que si valiese igual que el 16f84 que vale el doble.seguro que ni los hubiera mirado.porque mira que tiene pocos recursos  :(

eso si.en estos pic es donde se nos obliga a la optimizacion del codigo.y se nos hace casi imprencindible realizar el sofware exclusivamente en asm.
y solo de esta forma apreciamos las caracteristicas que integran sus hermanos mayores.y nos damos cuenta de lo preciados que son los bytes.
aunque segun vamos usando chips mas potentes.se nos va olvidando esa optimizacion.
de ahi que no me guste usar otro lenguage que no sea asm.aunque supongo que todo depende del precio del componente y sus recursos.

seguiran los 12F508 a 2€ o por contra.y por no vajar un precio un dia se consideraran obsoletos y cesaran su fabricacion?

mi opinion es que en la gama baja. los precios se aproximaran tanto que no sera efectivo utilizar los chips que tubieran menos recursos.



Título: Re: pequeños proyectos
Publicado por: AKENAFAB en 23 de Noviembre de 2009, 22:15:10
aqui los pics enanos , ese mas enano que nada 12F508 y 509 cuestan -+ US1.00 hasta 1.5

Los pics como el 12f683/675 oscilan entre 2 y 3 dolares. Esto en Mexico Saludos!

Son de mis preferidos! ^^
Título: Re: pequeños proyectos
Publicado por: Suky en 23 de Noviembre de 2009, 23:23:23
Por aquí un 12F508 sale 1.6 U$S, es de 0.5k  :shock: :shock: Si que hay que optimizar código  :?


Saludos!
Título: Re: pequeños proyectos
Publicado por: JOJOJORGE5 en 24 de Noviembre de 2009, 22:11:18
Hola

Felicidades Groundman.

Yo aquí por Bolivia no vi ningún pic de gama baja, ni para comprar ni nadie que se trajera uno.
Si los tuviera por aquí y fueran baratos, ya los estaría exprimiendo hasta el último bit de memoria.

Por el momento lomas barato que puedo conseguir es un 16f628 aunque ya pasa tiempo de la última ves que pregunte y tal ves ya ni lo tienen.
También no esta demás decir que el 16f84 me parece muy mala inversión, pero para aprender yo creo que esta bien porque existen muchos ejemplos para este pic.

Salu2:)
Título: Re: pequeños proyectos
Publicado por: groundman en 27 de Noviembre de 2009, 11:15:47
aqui en españa los pic que mas se han usado son los 12c508,16f84 y 16f876.

el 12c508 era por el pirateo de las PS ONE.
y los 16f84 y los 16f876 por las targetas decodificadoras del C+ o viadigital.

el consumo de microchips esta basado en las necesidades de su utilizacion.y es un negocio muy grande para los fabricantes.
nunca se sabe que chip sera el proximo en hacerse famoso.solo hace falta una aplicacion lo suficientemente atractiva para que un usuario
que ni siquiera tiene idea de lo que son estos chips, dispare la venta de estos.y quizas la venta de estos bajen el precio.
aunque sea para un uso ilegal.   como dice el reflan. no hay mal que por bien no venga. :lol:

cual sera el proximo invento :?:



Título: Re: pequeños proyectos
Publicado por: Nocturno en 27 de Noviembre de 2009, 13:25:45
No tardarán en sacar algo para ver Gol TV  :D
Título: Re: pequeños proyectos
Publicado por: groundman en 27 de Noviembre de 2009, 18:16:33
la verdad es que no me gusta nada el futbol.pero garcias a el descubri el potencial de los PICs. :)
Título: Re: pequeños proyectos
Publicado por: Cryn en 27 de Noviembre de 2009, 19:31:59
Yo aquí por Bolivia no vi ningún pic de gama baja, ni para comprar ni nadie que se trajera uno.
Si los tuviera por aquí y fueran baratos, ya los estaría exprimiendo hasta el último bit de memoria.

Por el momento lomas barato que puedo conseguir es un 16f628 aunque ya pasa tiempo de la última ves que pregunte y tal ves ya ni lo tienen.
También no esta demás decir que el 16f84 me parece muy mala inversión, pero para aprender yo creo que esta bien porque existen muchos ejemplos para este pic.
Hola Jojojorge5, creo que para aprender se puede aprender con casi cualquier micro 16Fxxx, y estoy totalmente de acuerdo contigo en que el 84a es una pésima inversión, el 628 es más barato y mejor.

Pero te cuento que he visto que existe a la venta un micro de 8pines el 12F675, que es un micro muy bueno para ser pequeño, también tengo algunos ejemplares jaja, si no me equivoco está entre 20 y 25 Bs al menos por aquí en Cocha.

saludos.
Título: Re: pequeños proyectos
Publicado por: JOJOJORGE5 en 28 de Noviembre de 2009, 22:40:49
Hola Cryn.

entonces creo que me comprare uno para renegar un poco por la falta de recursos :D

aunque viendo el datasheet no esta del todo mal.

salu2:)
Título: Re: pequeños proyectos
Publicado por: pibe en 01 de Diciembre de 2009, 12:19:15
Os dejo un proyectito que hice donde utilizo el 16f819 para un cuadro eléctrico especial. Es un cuadrito para subir o bajar 2 plataformas elevadoras.
Y para que utilizo un pic? Para evitar que pueda subir y bajar a la vez y me ahorro los contactos NC que impiden que puedas hacer esta maniobra funesta. A su vez y por ser una plataforma hidráulica debo activar un contactor para un motor eléctrico unos segundos antes de activar la electroválvula de subida (la de bajada no lleva motor eléctrico sino solo la electroválvula.)
No me lío mas, seguramente nunca vayais a utilizar mi programa tal cual porque es muy específico pero lo interesante es que para hacer el temporizador ajustable entre 0 y 2-3 segundos he utilizado la entrada ADC con un potenciómetro de 10k.
Tomo la lectura del pote, la guardo en una variable que será la que me indique que cantidad de veces debe repetir el bucle de demora. Facil, no?

; EL MICRO ESCANEA LOS PULSADORES DE SUBIR Y BAJAR PLATAFORMAS Y
; TEMPORIZA LA SALIDA CORRESPONDIENTE . EL TIEMPO PODRA AJUSTARSE
; POR MEDIO DE UN POTENCIOMETRO CONECTADO A LA ENTRADA ADC DEL MICRO.


   list      p=16f819           ; list directive to define processor
   #include <p16F819.inc>        ; processor specific variable definitions
   errorlevel  -302              ; suppress message 302 from list file

   __CONFIG   _CP_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _CCP1_RB2 & _DEBUG_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _WDT_OFF & _PWRTE_ON & _INTRC_IO



   Cblock 0x20
PDel0
PDel1
PDel2
PDel3
FLAG
timer1

   endc

;SALIDAS
#define EV1S   PORTB,0      ; SALIDA ELECTROVÁLVULA #1 SUBIR
#define EV1B   PORTB,1    ; SALIDA ELECTROVÁLVULA #1 BAJAR
#define EV2S   PORTB,2      ; SALIDA ELECTROVÁLVULA #2 SUBIR
#define EV2B   PORTB,3      ; SALIDA ELECTROVÁLVULA #2 BAJAR
#define K1      PORTB,4      ; SALIDA CONTACTOR MOTOR ELECTRICO

;ENTRADAS

#define S1      PORTA,1      ; ENTRADA SUBIR PLATAFORMA 1
#define B1      PORTA,2      ; ENTRADA BAJAR PLATAFORMA 1
#define S2      PORTA,3      ; ENTRADA SUBIR PLATAFORMA 2
#define B2      PORTA,4      ; ENTRADA BAJAR PLATAFORMA 2

;BANDERAS
#define S1F      FLAG,0  
#define S2F      FLAG,1
#define B1F      FLAG,2

      ORG     0x000       ; processor reset vector
      goto    Inicio

Inicio
      clrf    PORTB
      CLRF    PORTA          
      bsf    STATUS,RP0
      movlw    b'00000000'
      movwf    TRISB
      movlw    b'10000000'
      movwf    OPTION_REG   ; prescaler 8 para TMR0
                     ; pullups desactivadas
      movlw     b'01100000'
      movwf    OSCCON
      MOVLW    b'00001110'   ; Configure all pins
      MOVWF    ADCON1       ; as digital inputs
      MOVLW    b'11111111'      ; Value used to
      MOVWF    TRISA       ; Set RA<7:0> as inputs
      bcf    STATUS,RP0
      clrf    PORTB
      CLRF    FLAG
      movlw    b'11000000'
      movwf   ADCON0

MAIN
call delay20
TESTSUBIR1
      BTFSS   S1         ; ESTÁ PULSADO SUBIR PLATAFORMA 1?
      GOTO    JUMP1      ; NO, VAMOS A LIMPIAR Y SEGUIR
call delay20
      BTFSC    S1F         ; FLAG DE S1 ACTIVO ?
      GOTO    AVERS2      ; TESTSUBIR1;TESTSUBIR2   ; SI, SALTEAMOS
      BSF    K1         ; NO, ACTIVAMOS CONTACTOR DE MOTOR
      BSF    S1F         ; ACTIVAMOS FLAG PARA NO REPETIR
      CALL    DELAYADC   ; DEMORA (SUSTITUIR POR TEMPO CON ADC)
      BSF      EV1S      ; AHORA ACTIVAMOS LA ELECTROVALVULA DE SUBIR
      GOTO    MAIN      ; Y VOLVEMOS A EXPLORAR
JUMP1   
      BCF    S1F         ; LIMPIAMOS FLAG
      BCF    EV1S      ; DESACTIVAMOS ELECTROVALVULA DE SUBIR

TESTSUBIR2
      BTFSS   S2         ; ESTÁ PULSADO SUBIR PLATAFORMA 1?
      GOTO    JUMP2      ; NO, VAMOS A LIMPIAR Y SEGUIR
call delay20
      BTFSC    S2F         ; FLAG DE S1 ACTIVO ?
      GOTO    AVERS1      ; SI, SALTEAMOS
      BSF    K1         ; NO, ACTIVAMOS CONTACTOR DE MOTOR
      BSF    S2F         ; ACTIVAMOS FLAG PARA NO REPETIR
      CALL    DELAYADC   ; DEMORA (SUSTITUIR POR TEMPO CON ADC)
      BSF      EV2S      ; AHORA ACTIVAMOS LA ELECTROVALVULA DE SUBIR
      GOTO    MAIN      ; Y VOLVEMOS A EXPLORAR
JUMP2   
      BCF    S2F         ; LIMPIAMOS FLAG
      BCF    EV2S      ; DESACTIVAMOS ELECTROVALVULA DE SUBIR
      BCF      K1         ; DESCONECTAMOS MOTOR
TESTBAJAR1
      BTFSS   B1         ; ESTA PULSADO BAJAR PLATAFORMA 1?
      GOTO    EV1BOFF      ; NO, MIRAMOS SI ESTA PULSADO BAJAR 2
call delay20
      BTFSC   B1F
      GOTO    TESTBAJAR2
      BSF      B1F
      BSF      EV1B      ; SI, ACTIVAMOS ELECTROVALVULA DE BAJAR 1
   
TESTBAJAR2
      BTFSS   B2         ; ESTA PULSADO BAJAR PLATAFORMA 2?
      GOTO    EV2BOFF      ; NO, VOLVEMOS AL PRINCIPAL
call delay20
      BSF      EV2B      ; SI, ACTIVAMOS ELECTROVALVULA DE BAJAR 2
      GOTO   TESTBAJAR1   ; VOLVEMOS AL PRINCIPAL


EV1BOFF
      BCF    EV1B
      BCF    B1F
      GOTO    TESTBAJAR2

EV2BOFF
      BCF    EV2B
      BTFSC   B1F
      GOTO    TESTBAJAR1
      GOTO    MAIN

AVERS1
      BTFSS   S1
      GOTO    LIMPIARS1
call delay20
      BSF      EV1S
      GOTO    TESTSUBIR2
LIMPIARS1
      BCF    EV1S
      GOTO    TESTSUBIR2

AVERS2
      BTFSS   S2
      GOTO    LIMPIARS2
call delay20
      BSF      EV2S
      GOTO    TESTSUBIR1
LIMPIARS2
      BCF    EV2S
      GOTO    TESTSUBIR1

; Aqui comienza la conversión AD
DELAYADC
      clrf    timer1; Limpio la variable
   
      bsf    ADCON0,ADON ; activo el conversor AD
start
      bsf      ADCON0,GO ; Y lo inicio
waiting
      btfsc   ADCON0,GO ; Espero termine la conversión
      goto   waiting
      movf   ADRESH,W   ; Muevo el resultado al acumulador
      btfsc    STATUS,Z    ; Y si es 0 entonces no temporizo
      goto    salida
      movwf   timer1 ; Muevo el acumulador a la variable

start3
      call    DEMORA      ; Llamo una demora
      decfsz   timer1,1  ; Y la repito tantas veces como lo indique la variable donde guardé la lectura del AD
      goto   start3               ; Volvemos al loop hasta terminar
salida
      bcf    ADCON0,ADON  ; Hemos terminado la temporización, desactivamos el ADC para que no consuma
      RETURN
               ; Y volvemos al menu
      


DEMORA  movlw     .5         ; 1 set numero de repeticion  (B)
        movwf     PDel0     ; 1 |
PLoop1  movlw     .181      ; 1 set numero de repeticion  (A)
        movwf     PDel1     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        clrwdt              ; 1 ciclo delay
        decfsz    PDel1,1   ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,1   ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto PDelL2         ; 2 ciclos delay
PDelL2  goto PDelL3         ; 2 ciclos delay
PDelL3  clrwdt              ; 1 ciclo delay
        return              ; 2+2 Fin.

delay20  movlw     .21       ; 1 set numero de repeticion  (B)
        movwf     PDel0     ; 1 |
aPLoop1  movlw     .237      ; 1 set numero de repeticion  (A)
        movwf     PDel1     ; 1 |
aPLoop2  clrwdt              ; 1 clear watchdog
        decfsz    PDel1, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      aPLoop2    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      aPLoop1    ; 2 no, loop
aPDelL1  goto aPDelL2         ; 2 ciclos delay
aPDelL2  clrwdt              ; 1 ciclo delay
        return              ; 2+2 Fin.


END
Título: Re: pequeños proyectos
Publicado por: pibe en 01 de Diciembre de 2009, 12:46:20
Uno de mis proyectos más complejos fué una caja negra para una grúa , donde se grababan los eventos que ocurrían durante el día , meses y durante los años.
Para ello tuve que probarla en laboratorio antes de lanzarla al mercado y claro, no podía estar dias y dias dándole al mando de la grua para que me grabara los datos correspondientes!
Y me dije: Por qué no hacer una placa con un 16f877 y que me genere "pulsaciones" al azar y con una duración de tiempo al azar también? Y por que no una pausa sin pulsaciones al azar tambien?
Tenía 14 pulsadores o entradas, de la cuales 2 de ellas no debían presentarse tan a menudo. Vamos, que esas 2 entradas eran casos extraños.
Y como lo hago?
Busqué generación de nùmeros aleatorios y me encontré con el problema que al cabo de un tiempo estos números se repetían, o sea que eran "seudo azar". No me servía.
Y si utilizo la entrada AD y la conecto a una entrada alterna y muestreo cada X tiempo? Lo hice (tonto de mi) porque claro, el X tiempo era siempre el mismo el muestreo era por lo tanto siempre el mismo.
Vaya...
Desconecto por casualidad la alimentación alterna a la entrada AD , y voilá ! Muestreos al azar!!!
El ruido o simplemente por dejar el pin adc flotante me daba las lecturas que buscaba!

El resto fué coser y cantar.

Al igual que mi programa anterior, es dificil sino imposible que algún dia tengais que utilizar este programa para la misma aplicación. Pero sirve para demostrar que los numeros COMPLETAMENTE al azar son posibles !
Solo debereis utilizar el resultado obtenido de la conversión AD y hacer con ello lo que os plazca!

Os dejo el programa:

; PROBADOR DATALOGGER
; GENERADOR DE SALIDAS Y TIEMPOS AL AZAR POR PUERTOS B Y D

      List   p=16F877A   ;Tipo de procesador
   #include <p16f877a.inc>   ;processor specific definitions
      __config  _CP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_OFF & _LVP_OFF & _BODEN_OFF

   ERRORLEVEL -302      ;suppress "not in bank 0" message
   ERRORLEVEL -203      ;suppress  message
   ERRORLEVEL -305      ;suppress  message
   ERRORLEVEL -205      ;suppress  message

      cblock 0x20
RANDOM
RANDOMINC      ;variable para guardar el numero random para seleccionar la incidencia (anemometro, FS, BT)


PDel0   
PDel1
PDel2

temp


w_temp            ; variable used for context saving
status_temp         ; variable used for context saving
pclath_temp         ; variable used for context saving            
      endc

#define tempoflag  FLAG,0
#define toggle    FLAG,1 ; on/off de temperatura media

#define SUBIR   PORTB,7
#define BAJAR   PORTB,6
#define ELEV2   PORTB,5
#define ELEV3   PORTB,4
#define GD   PORTB,3
#define GI   PORTB,2
#define GIRO2   PORTB,1
#define GIRO3   PORTB,0

#define CAD  PORTD,6
#define CAT  PORTD,5
#define CARRO2  PORTD,4
#define CARRO3  PORTC,7

#define ANE  PORTD,1

#define FS  PORTC,3


      org   0x00      ;Vector de Reset
      goto   Inicio

;Programa principal

Inicio   
      movlw   0x07      ;deshabilitar-
      movwf   CMCON      ;-comparadores
        clrf   PORTB      ;Desconecta salidas
      clrf   PORTA
      clrf    PORTC
      clrf    PORTD
      bsf       STATUS,RP0   ;Selecciona banco 1
      
      movlw   0
      movwf   TRISB      ;
      movlw   b'00000010'
      movwf   TRISC      ;
      movlw   0
      movwf    TRISD
   ;   movwf   TRISE
      movlw   b'11000111'
      movwf   OPTION_REG   ;Preescaler de 128 asociado al WDT
      bcf      STATUS,RP0   ;Selecciona banco 0





;===========================================================================
;      Inicio de conversion de valores analogicos
;===========================================================================


;---------------------Configuracion CONVERTIDOR A/D-------------------------
CFGADC   
      bsf      STATUS,RP0   ;Banco 1
      bcf      STATUS,RP1
      movlw   b'00001110'; b'00000101'   ;seleccion tipo puertos A/D,
      movwf   ADCON1
      movlw   b'00000001'
      movwf   TRISA      ;RA0 in
      movlw    0 ;PORTE como SALIDA
      movwf    TRISE
      bcf      STATUS,RP0   ;Banco 0
      movlw   b'01000001'   ;seleccion Tad, canales para
      movwf   ADCON0      ;conversion y A/D=ON
      bcf      PIR1,ADIF   ;limpia flag de conversion completa



   
MAIN_LOOP
      CLRF PORTB
CLRF PORTD
CLRF PORTC
CLRF PORTE

      
MANIOBRA
;LLAMADA RUTINA GENERACION VALOR AL AZAR ENTRE 0 Y 3
CALL ROL4

;SI DIO 1 ENTONCES ES C+E, C o E
MOVF RANDOM,W
XORLW .1
BTFSC STATUS,Z
GOTO ES_1

;SI DIO 2 ENTONCES ES C+G, C o G
MOVF RANDOM,W
XORLW .2
BTFSC STATUS,Z
GOTO ES_2

;SI DIO 3 ENTONCES ES E+G, E o G
MOVF RANDOM,W
XORLW .3
BTFSC STATUS,Z
GOTO ES_3

;SI DIO 0 ENTONCES NO HACEMOS NADA
GOTO SALIDA



;RUTINA MANIOBRAS ELEV+CARRO, ELEVACION SOLO O CARRO SOLO
ES_1
;ROL 4 PARA VER QUE VELOCIDAD LLEVA
CALL RUTINA_ELEVACION
CALL RUTINA_CARRO
GOTO SALIDA

ES_2
;RUTINA MANIOBRAS GIRO+CARRO, GIRO SOLO O CARRO SOLO
CALL RUTINA_GIRO
CALL RUTINA_CARRO
GOTO SALIDA

ES_3
;RUTINA MANIOBRAS GIRO+ELEV, GIRO SOLO O ELEV SOLO
CALL RUTINA_ELEVACION
CALL RUTINA_GIRO
GOTO SALIDA


SALIDA
CALL ADC_INC
CALL TEMPORIZACION
GOTO MAIN_LOOP

RUTINA_ELEVACION
;MIRAMOS SI ES 3º VELOCIDAD
CALL ROL4
MOVF RANDOM,W
XORLW .3
BTFSS STATUS,Z
GOTO ELEVAC2
BSF ELEV2
BSF ELEV3
GOTO SUBIROBAJAR

;MIRAMOS SI ES 2º VELOCIDAD
ELEVAC2
MOVF RANDOM,W
XORLW .2
BTFSS STATUS,Z
GOTO ELEVAC1
BSF ELEV2
GOTO SUBIROBAJAR

;MIRAMOS SI ES 1º VELOCIDAD
ELEVAC1
MOVF RANDOM,W
XORLW .1
BTFSS STATUS,Z
RETURN

;mIRAMOS SI ES SUBIR O BAJAR
SUBIROBAJAR
CALL ROL2
BTFSS RANDOM,0
GOTO ESBAJAR
BSF SUBIR
RETURN

ESBAJAR
BSF BAJAR
RETURN



RUTINA_CARRO
;ROL 4 PARA VER QUE VELOCIDAD LLEVA
CALL ROL4

;MIRAMOS SI ES 3º VELOCIDAD
CARRO_3
MOVF RANDOM,W
XORLW .3
BTFSS STATUS,Z
GOTO CARRO_2
BSF CARRO2
BSF CARRO3

GOTO CADOCAT

;MIRAMOS SI ES 2º VELOCIDAD
CARRO_2
MOVF RANDOM,W
XORLW .2
BTFSS STATUS,Z
GOTO CARRO_1
BSF CARRO2
GOTO CADOCAT

;MIRAMOS SI ES 1º VELOCIDAD
CARRO_1
MOVF RANDOM,W
XORLW .1
BTFSS STATUS,Z
RETURN

;mIRAMOS SI ES SUBIR O BAJAR
CADOCAT
CALL ROL2
BTFSS RANDOM,0
GOTO ESCAD
BSF CAT
RETURN

ESCAD
BSF CAD
RETURN


RUTINA_GIRO
;MIRAMOS SI ES 3º VELOCIDAD
CALL ROL4
MOVF RANDOM,W
XORLW .3
BTFSS STATUS,Z
GOTO GIRO_2
BSF GIRO2
BSF GIRO3
GOTO GDOGI

;MIRAMOS SI ES 2º VELOCIDAD
GIRO_2
MOVF RANDOM,W
XORLW .2
BTFSS STATUS,Z
GOTO GIRO_1
BSF GIRO2
GOTO GDOGI

;MIRAMOS SI ES 1º VELOCIDAD
GIRO_1
MOVF RANDOM,W
XORLW .1
BTFSS STATUS,Z
RETURN

;mIRAMOS SI ES GD O GI
GDOGI
CALL ROL2
BTFSS RANDOM,0
GOTO ESGD
BSF GI
RETURN

ESGD
BSF GD
RETURN


;ADC PARA INCIDENCIAS
ADC_INC
CALL RUN_ADC
ANDLW 0X0F
MOVWF RANDOMINC

btfsC STATUS,Z ;si las divisiones dio 0 entonces SEGUIMOS
RETURN
movf  RANDOMINC,W
XORLW .6
BTFSC STATUS,Z
BSF ANE
movf  RANDOMINC,W
XORLW .12
BTFSC STATUS,Z
BSF FS
RETURN


TEMPORIZACION
call demora_150ms
RETURN



;---------------------------------------------------------------------------

RUN_ADC   
   
      bcf      STATUS,RP0   ;Banco 0
      bcf      STATUS,RP1   ;Banco 0
      movlw   b'11000001'   ;repone a cero para que iorlw pueda
      movwf   ADCON0
      bcf      PIR1,ADIF   ;limpia flag de conversion completa
      nop
      nop

GO_ADC   
      bsf      ADCON0,GO_DONE   ;Inicio conversion

wait_ADC
      btfsc   ADCON0,GO_DONE   ;espera a que finalice la conversion
      goto   wait_ADC   ;bucle
      movlw   b'11000000'   ;repone a cero para que iorlw pueda
      movwf   ADCON0

READ_OK      ;La conversion esta en ADRESH:ADRESL
      movf   ADRESH,W
      return


      
demora_150ms
CALL RUN_ADC
MOVWF PDel0
btfsC STATUS,Z ;si las divisiones dio 0 entonces repetimos
GOTO demora_150ms
            
PLoop0_     movlw           .255      
           movwf           PDel1    
PLoop1_     movlw           .255  
           movwf           PDel2    
PLoop2_     nop                
           decfsz          PDel2, 1
           goto            PLoop2_  
           decfsz          PDel1,  1
           goto            PLoop1_  
             decfsz          PDel0,  1
           goto            PLoop0_  
PDelL1_     goto          PDelL2_      
PDelL2_     nop                
           return

ROL4
CALL RUN_ADC
ANDLW 0X03
MOVWF RANDOM
RETURN

ROL2
CALL RUN_ADC
ANDLW 0X01
MOVWF RANDOM
RETURN

   end         ;Fin del programa fuente


Título: Re: pequeños proyectos
Publicado por: groundman en 01 de Diciembre de 2009, 18:09:27
todos los programas son bienvenidos.en todos ellos de aprende algo.por ejemlo para este subprograma.por ejemplo has usado las instrucciones decfsz.para hacer un retardo.



DEMORA  movlw     .5         ; 1 set numero de repeticion  (B)
        movwf     PDel0     ; 1 |
PLoop1  movlw     .181      ; 1 set numero de repeticion  (A)
        movwf     PDel1     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        clrwdt              ; 1 ciclo delay
        decfsz    PDel1,1   ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,1   ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto PDelL2         ; 2 ciclos delay
PDelL2  goto PDelL3         ; 2 ciclos delay
PDelL3  clrwdt              ; 1 ciclo delay
        return              ; 2+2 Fin.

/quote]

yo casi siempre uso temporizaciones como esta:

pausa1         clrf   AUX2
pausae3         clrf   AUX1
pausae2         clrf   AUX0
pausae         incf   AUX0,f
            btfss   AUX0,7
            goto   pausae

            incf   AUX1,f
            btfss   AUX1,4
            goto   pausae2      
            incf   AUX2,f;
            btfss   AUX2,0      ;cambiar a 1;      
            goto   pausae3   ;      
            retlw   0x00   

uso mas la instruccion btfsc. no se cual sistema consume menos recursos.no me ha dado tiempo a comprobarlo. :D
perdon por no hacer bien la cita.pero nunca me aclaro con estas herramientas de los foros
Título: Re: pequeños proyectos
Publicado por: pibe en 01 de Diciembre de 2009, 18:38:16
No es ni mas ni menos que una rutinita generada por el clásico programa de demoras. No me pongo a ver si consume 1 o dos ciclos. Generalemente me gusta ir sobrado de micro en los proyectos que hago.
 Mas vale mas que menos y lamentarse luego :P

Lo que tu haces es incrementar un contador, yo en cambio lo decremento y cuando llega a 0 saltea la proxima instrucción. Lo mismo pero con distinto olor :)
Igualmente ambas instrucciones tardan lo mismo, cada vez que comparas y saltas a la proxima instruccion son 2 ciclos.
Título: Re: pequeños proyectos
Publicado por: Suky en 01 de Diciembre de 2009, 19:11:43
Con respecto a cual usa más recursos, las dos ocupan el micro y no se puede hacer nada más. Después respecto al uso de memoria de programa, contando las lineas que usan cada una para una misma temporización se van a dar cuenta  :mrgreen:

Saludos!
Título: Re: pequeños proyectos
Publicado por: groundman en 11 de Diciembre de 2009, 23:21:48
bueno.seguimos implementando usarts por software.
ahora utilizare el 16F84 y usare sus interupciones.he intentado exponerlo con el comando code.pero salen las lineas desordenadas.
no se como hacerlo :(


;*****************************************www.ingeniopic.com***************************+******
; PROGRAMA : usart_16F84
; Funcion : recepcion de datos serie 
;           
;   
;  Revision : 1.0        12/12/2009            Programa para : PIC16F84
; CPU Clock : 4 MHz o 20Mhz                   Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF           
;*****************************************www.ingeniopic.com**********************************
;
;NOTAS:   este programa esta preparado para interrumpir el funcionamiento del programa programa principal para atender
;       una interrupcion por recepcion de datos provenientes de una usart.la velocidad de la usart podemos modificarla
;       cambiando el valor del registro BAUDRATE.que esta un poco mas abajo de la etiqueta INICIO.cuanto mayor sea la velocidad.mayor sera el margen de error.
;       el dato que recivamos por PB0 sera transmitido por PB1.
;      

      LIST   P=16F84   ;Se indica el modo de procesador
     
      RADIX   HEX      ;Sistema de numeracion hexadecimal

      INCLUDE   "P16F84.inc"   
     
               ;registros internos
      __CONFIG   _XT_OSC & _CP_OFF & _WDT_OFF

      ERRORLEVEL      -302


            CBLOCK    0x0C
            CONTADOR
            DATO
            BAUDRATE

            W_TEMP
            STATUS_TEMP
            PCLATH_TEMP
            ENDC


      
PUSH    MACRO               ;macro para salvar registros antes de una llamada a interrupcion   
        movwf   W_TEMP               
        swapf   STATUS,W
        movwf   STATUS_TEMP         
        clrf    STATUS               
        movfw   PCLATH               
        movwf   PCLATH_TEMP
        clrf    PCLATH
        ENDM

POP     MACRO               ;macro para restaurar registros   despues de una llamada a interrupcion
        movfw   PCLATH_TEMP         
        movwf   PCLATH
        swapf   STATUS_TEMP,W     
        movwf   STATUS
        swapf   W_TEMP,F         
        swapf   W_TEMP,W
        ENDM

      
      #define BANK0      bcf   STATUS,RP0
      #define BANK1      bsf STATUS,RP0
;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
               ORG      0x00            ;Inicio en el Vector de Reset
              goto   INICIO            ;Va a la primera instruccion del programa
;<<<<<<---------------------- VECTOR DE INTEUPCIONES ------------------------>>>>>>>
               ORG      0x04            ;Inicio en el Vector de Reset
              goto   INTERRUPCIONES            ;Va a la primera instruccion del programa


;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO         BANK1
            movlw   b'10000000'      ;activar interrupcion por cambio de estado a 0 de RB0
            movwf   OPTION_REG
            movlw   b'10010000'      ;configura interrupcion por desbordaminto de TMR0 y  por cambio de estado a 0 de RB0
            movwf   INTCON
            movlw   b'00010001'      ;habilita interrupcion por cambio de estado en RB0/INT
            movwf   TRISB
            BANK0
            bsf      PORTB,1         ;establecer la salida usart a 1
            movlw   d'15'         ;valor para la velocidad de la usart
            movwf   BAUDRATE
            ;valores para el baudrate:para 4Mhz
            ;
            ;para divisor TMR0=000
            ;190=2400bps, 90=4800bps, 40=9600bps, 15=19200bps,
            ;
            ;para divisor TMR0=010
            ;97=1200bps,
            ;
            ;valores para el baudrate:para 20Mhz
            ;
            ;para divisor TMR0=000
            ;51=38400,31=57600.
         
;<<<<<<<------------------------------------------------PROGRAMA PRINCIPAL---------------------------------------->>>>>>>>>>>>>>         
PRINCIPAL      NOP
            
            goto   PRINCIPAL
            
;<<<<<<---------------------------------------------SUBPROGRAMA RECEPCION DE DATOS--------------------------
            
RECEPCION      clrf   CONTADOR      ;borra el contador de bits
            clrf   TMR0         ;borra TMR0
            movfw   BAUDRATE      ;carga valor del baudrate en w
            subwf   TMR0,w         ;comprueva si ha llegado al valor o se pasa
            btfss   STATUS,C      ;si es menos sigue comprovando
            goto   $-3
            
COMP1         clrf   TMR0         ;borra TMR0
COMP2         movfw   BAUDRATE      ;carga valor del baudrate en w
            subwf   TMR0,w         ;resta el contenido de TMR0 con el de w(comprovacion => )
            btfss   STATUS,C      ;comprueva si ha llegado al valor o se pasa
            goto   COMP2         ;si es menos sigue comprovando

            bcf      PORTB,2
            bsf      PORTB,2
            
            btfsc   PORTB,0         ;comprueva el estado del pin de entrada
            call   UNO            ;si es 1 salta a UNO
            btfss   PORTB,0         ;comprueva el estado del pin de entrada
            call   CERO         ;si es 0 salta a CERO

            incf   CONTADOR,F      ;incrementa el contador de bits
            movlw   0x08         ;valor de bit a comprovar
            xorwf   CONTADOR,W      ;hacer xor con CONTADOR
            btfss   STATUS,Z      ;comprueva si es igual
            goto   COMP1         ;si no es igual sigue las comprobaciones
            movfw   DATO         ;carga el dato recivido en w
            return               ;retorno de subprograma RECEPCION

UNO            rrf      DATO,F         ;rota a la derecha una posicion   
            bsf      DATO,7         ;pon a 1 el bit 7 del registro DATO
            return         ;retorna

CERO         rrf      DATO,F         ;rota a la derecha una posicion
            bcf      DATO,7         ;pon a 0 el bit 7 del registro DATO
            return         ;retorna
            
         
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<SUBPROGRAMA DE ENVIO DE DATOS>>>>>>>>>>>>>>>>>      

   
ENVIO         bsf      PORTB,1         ;establecer la salida a 1(evitar errores primer caracter)
ENVIO2         clrf   CONTADOR      ;borra el registro CONTADOR de bits
            bcf      PORTB,1         ;bit START   
            call   RETARDO   
            
ENV_1         btfsc   DATO,0         ;comprueva bit 0 del registro DATO(comprovacion de bits a enviar)
            call   UNOS         ;salta a UNOS si el bit leido es 1
            btfss   DATO,0         ;comprueva bit 0 del registro DATO(comprovacion de bits a enviar)
            call   CEROS         ;salta a CEROS si el bit leido es 0
ENV_2         rrf      DATO,F         ;rota a la derecha el registro DATO

            incf   CONTADOR,F      ;incrementa CONTADOR (registro contador de bits)
            movlw   0x08         ;valor de bits a leer
            xorwf   CONTADOR,W      ;comprueva si son 8
            btfss   STATUS,Z      ;si no es 8 repite la comprovacion del siguiente bit
            goto   ENV_1         ;comprueva de nuevo
            bsf      PORTB,1         ;establecer a 1 la salida
            return               ;retorna

UNOS         bsf      PORTB,1         ;saca valor 1 por pin 1 de PORTB
            call   RETARDO         ;tiempo de un bit
            return               ;retorna
CEROS         bcf      PORTB,1         ;saca valor 0 por pin 1 de PORTB
            call   RETARDO         ;tiempo de un bit
            return               ;retorna

;**********************************************RETARDO***************************************
;
;
RETARDO         clrf   TMR0         ;borra el temporizador
COMP         movfw   BAUDRATE      ;valor del retardo
            subwf   TMR0,w         ;comprueva si ha llegado al valor o se pasa
            btfss   STATUS,C      ;si es menos sigue comprovando
            goto   COMP
            return               ;si ha llegado retorna
;*********************************************INTERRUPCIONES******************************
INTERRUPCIONES   PUSH               ;guarda valores de registros
            btfss   INTCON,INTF      ;comprueva interrupcion por cambio de PB0/INT
            goto   SALIR         ;salir del programa
            call   RECEPCION      ;programa de recepcion de datos
            call   ENVIO         ;programa de envio de datos
SALIR         bcf      INTCON,INTF      ;borra bandera señalizadora de interrupcion por cambio en PB0/INT
            POP                  ;restaura valores de registros
            retfie               ;retorna y activa interrupciones

            end                  ;fin

Título: Re: pequeños proyectos
Publicado por: poseidon20 en 12 de Diciembre de 2009, 00:47:07
Es cierto que se desordena un poco, pero ya te lo ordene, por lo menos los nemonicos; los comentarios no se desordenan mucho por eso lo deje como esta.


Código: ASM
  1. ;*****************************************www.ingeniopic.com***************************+******
  2. ; PROGRAMA : usart_16F84
  3. ; Funcion : recepcion de datos serie
  4. ;          
  5. ;  
  6. ;  Revision : 1.0        12/12/2009            Programa para : PIC16F84
  7. ; CPU Clock : 4 MHz o 20Mhz                   Reloj instruccion :
  8. ;       WDT : Deshabilitado                  Tipo de reloj : XT
  9. ; Code Prot : OFF          
  10. ;*****************************************www.ingeniopic.com**********************************
  11. ;
  12. ;NOTAS:   este programa esta preparado para interrumpir el funcionamiento del programa programa principal para atender
  13. ;       una interrupcion por recepcion de datos provenientes de una usart.la velocidad de la usart podemos modificarla
  14. ;       cambiando el valor del registro BAUDRATE.que esta un poco mas abajo de la etiqueta INICIO.cuanto mayor sea la velocidad.mayor sera el margen de error.
  15. ;       el dato que recivamos por PB0 sera transmitido por PB1.
  16. ;      
  17.  
  18.       LIST   P=16F84   ;Se indica el modo de procesador
  19.      
  20.       RADIX   HEX      ;Sistema de numeracion hexadecimal
  21.  
  22.       INCLUDE   "P16F84.inc"  
  23.      
  24.                ;registros internos
  25.       __CONFIG   _XT_OSC & _CP_OFF & _WDT_OFF
  26.  
  27.       ERRORLEVEL      -302
  28.  
  29.  
  30.             CBLOCK    0x0C
  31.             CONTADOR
  32.             DATO
  33.             BAUDRATE
  34.  
  35.             W_TEMP
  36.             STATUS_TEMP
  37.             PCLATH_TEMP
  38.             ENDC
  39.  
  40.  
  41.      
  42. PUSH    MACRO               ;macro para salvar registros antes de una llamada a interrupcion  
  43.         movwf   W_TEMP              
  44.         swapf   STATUS,W
  45.         movwf   STATUS_TEMP        
  46.         clrf    STATUS              
  47.         movfw   PCLATH              
  48.         movwf   PCLATH_TEMP
  49.         clrf    PCLATH
  50.         ENDM
  51.  
  52. POP     MACRO               ;macro para restaurar registros   despues de una llamada a interrupcion
  53.         movfw   PCLATH_TEMP        
  54.         movwf   PCLATH
  55.         swapf   STATUS_TEMP,W    
  56.         movwf   STATUS
  57.         swapf   W_TEMP,F        
  58.         swapf   W_TEMP,W
  59.         ENDM
  60.  
  61.      
  62.       #define BANK0      bcf   STATUS,RP0
  63.       #define BANK1      bsf STATUS,RP0
  64. ;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
  65.             ORG     0x00            ;Inicio en el Vector de Reset
  66.             goto    INICIO            ;Va a la primera instruccion del programa
  67. ;<<<<<<---------------------- VECTOR DE INTEUPCIONES ------------------------>>>>>>>
  68.             ORG     0x04            ;Inicio en el Vector de Reset
  69.             goto    INTERRUPCIONES            ;Va a la primera instruccion del programa
  70.  
  71.  
  72. ;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
  73. INICIO      BANK1
  74.             movlw   b'10000000'      ;activar interrupcion por cambio de estado a 0 de RB0
  75.             movwf   OPTION_REG
  76.             movlw   b'10010000'      ;configura interrupcion por desbordaminto de TMR0 y  por cambio de estado a 0 de RB0
  77.             movwf   INTCON
  78.             movlw   b'00010001'      ;habilita interrupcion por cambio de estado en RB0/INT
  79.             movwf   TRISB
  80.             BANK0
  81.             bsf     PORTB,1         ;establecer la salida usart a 1
  82.             movlw   d'15'         ;valor para la velocidad de la usart
  83.             movwf   BAUDRATE
  84.             ;valores para el baudrate:para 4Mhz
  85.             ;
  86.             ;para divisor TMR0=000
  87.             ;190=2400bps, 90=4800bps, 40=9600bps, 15=19200bps,
  88.             ;
  89.             ;para divisor TMR0=010
  90.             ;97=1200bps,
  91.             ;
  92.             ;valores para el baudrate:para 20Mhz
  93.             ;
  94.             ;para divisor TMR0=000
  95.             ;51=38400,31=57600.
  96.          
  97. ;<<<<<<<------------------------------------------------PROGRAMA PRINCIPAL---------------------------------------->>>>>>>>>>>>>>        
  98. PRINCIPAL   NOP
  99.            
  100.             goto   PRINCIPAL
  101.            
  102. ;<<<<<<---------------------------------------------SUBPROGRAMA RECEPCION DE DATOS--------------------------
  103.            
  104. RECEPCION   clrf    CONTADOR      ;borra el contador de bits
  105.             clrf    TMR0         ;borra TMR0
  106.             movfw   BAUDRATE      ;carga valor del baudrate en w
  107.             subwf   TMR0,w         ;comprueva si ha llegado al valor o se pasa
  108.             btfss   STATUS,C      ;si es menos sigue comprovando
  109.             goto    $-3
  110.            
  111. COMP1       clrf    TMR0         ;borra TMR0
  112. COMP2       movfw   BAUDRATE      ;carga valor del baudrate en w
  113.             subwf   TMR0,w         ;resta el contenido de TMR0 con el de w(comprovacion => )
  114.             btfss   STATUS,C      ;comprueva si ha llegado al valor o se pasa
  115.             goto    COMP2         ;si es menos sigue comprovando
  116.  
  117.             bcf     PORTB,2
  118.             bsf     PORTB,2
  119.            
  120.             btfsc   PORTB,0         ;comprueva el estado del pin de entrada
  121.             call    UNO            ;si es 1 salta a UNO
  122.             btfss   PORTB,0         ;comprueva el estado del pin de entrada
  123.             call    CERO         ;si es 0 salta a CERO
  124.  
  125.             incf    CONTADOR,F      ;incrementa el contador de bits
  126.             movlw   0x08         ;valor de bit a comprovar
  127.             xorwf   CONTADOR,W      ;hacer xor con CONTADOR
  128.             btfss   STATUS,Z      ;comprueva si es igual
  129.             goto    COMP1         ;si no es igual sigue las comprobaciones
  130.             movfw   DATO         ;carga el dato recivido en w
  131.             return               ;retorno de subprograma RECEPCION
  132.  
  133. UNO         rrf     DATO,F         ;rota a la derecha una posicion  
  134.             bsf     DATO,7         ;pon a 1 el bit 7 del registro DATO
  135.             return         ;retorna
  136.  
  137. CERO        rrf     DATO,F         ;rota a la derecha una posicion
  138.             bcf     DATO,7         ;pon a 0 el bit 7 del registro DATO
  139.             return         ;retorna
  140.            
  141.          
  142. ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<SUBPROGRAMA DE ENVIO DE DATOS>>>>>>>>>>>>>>>>>      
  143.  
  144.    
  145. ENVIO       bsf     PORTB,1         ;establecer la salida a 1(evitar errores primer caracter)
  146. ENVIO2      clrf    CONTADOR      ;borra el registro CONTADOR de bits
  147.             bcf     PORTB,1         ;bit START  
  148.             call    RETARDO  
  149.            
  150. ENV_1       btfsc   DATO,0         ;comprueva bit 0 del registro DATO(comprovacion de bits a enviar)
  151.             call    UNOS         ;salta a UNOS si el bit leido es 1
  152.             btfss   DATO,0         ;comprueva bit 0 del registro DATO(comprovacion de bits a enviar)
  153.             call    CEROS         ;salta a CEROS si el bit leido es 0
  154. ENV_2       rrf     DATO,F         ;rota a la derecha el registro DATO
  155.  
  156.             incf    CONTADOR,F      ;incrementa CONTADOR (registro contador de bits)
  157.             movlw   0x08         ;valor de bits a leer
  158.             xorwf   CONTADOR,W      ;comprueva si son 8
  159.             btfss   STATUS,Z      ;si no es 8 repite la comprovacion del siguiente bit
  160.             goto    ENV_1         ;comprueva de nuevo
  161.             bsf     PORTB,1         ;establecer a 1 la salida
  162.             return               ;retorna
  163.  
  164. UNOS        bsf     PORTB,1         ;saca valor 1 por pin 1 de PORTB
  165.             call    RETARDO         ;tiempo de un bit
  166.             return               ;retorna
  167. CEROS       bcf     PORTB,1         ;saca valor 0 por pin 1 de PORTB
  168.             call    RETARDO         ;tiempo de un bit
  169.             return               ;retorna
  170.  
  171. ;**********************************************RETARDO***************************************
  172. ;
  173. ;
  174. RETARDO     clrf    TMR0         ;borra el temporizador
  175. COMP        movfw   BAUDRATE      ;valor del retardo
  176.             subwf   TMR0,w         ;comprueva si ha llegado al valor o se pasa
  177.             btfss   STATUS,C      ;si es menos sigue comprovando
  178.             goto    COMP
  179.             return               ;si ha llegado retorna
  180. ;*********************************************INTERRUPCIONES******************************
  181. INTERRUPCIONES
  182.             PUSH                    ;guarda valores de registros
  183.             btfss   INTCON,INTF      ;comprueva interrupcion por cambio de PB0/INT
  184.             goto    SALIR         ;salir del programa
  185.             call    RECEPCION      ;programa de recepcion de datos
  186.             call    ENVIO         ;programa de envio de datos
  187. SALIR       bcf     INTCON,INTF      ;borra bandera señalizadora de interrupcion por cambio en PB0/INT
  188.             POP                  ;restaura valores de registros
  189.             retfie               ;retorna y activa interrupciones
  190.  
  191.             end                  ;fin
Título: Re: pequeños proyectos
Publicado por: groundman en 12 de Diciembre de 2009, 10:57:30
voy a intentar hacerlo yo haber que tal queda.ademas he quitado dos lineas que solo las utilizaba para depurar el codigo.

Código: [Seleccionar]

;*****************************************www.ingeniopic.com***************************+******
; PROGRAMA : usart_16F84
; Funcion : recepcion de datos serie 
;           
;   
;  Revision : 1.0        12/12/2009            Programa para : PIC16F84
; CPU Clock : 4 MHz o 20Mhz                   Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF           
;*****************************************www.ingeniopic.com**********************************
;
;NOTAS:   este programa esta preparado para interrumpir el funcionamiento del programa programa principal para atender
;       una interrupcion por recepcion de datos provenientes de una usart.la velocidad de la usart podemos modificarla
;       cambiando el valor del registro BAUDRATE.que esta un poco mas abajo de la etiqueta INICIO.cuanto mayor sea la velocidad.mayor sera el margen de error.
;       el dato que recivamos por PB0 sera transmitido por PB1.
;     

      LIST   P=16F84   ;Se indica el modo de procesador
     
      RADIX   HEX      ;Sistema de numeracion hexadecimal

      INCLUDE   "P16F84.inc"   
     
               ;registros internos
      __CONFIG   _XT_OSC & _CP_OFF & _WDT_OFF

      ERRORLEVEL      -302


            CBLOCK    0x0C
            CONTADOR
            DATO
            BAUDRATE

            W_TEMP
            STATUS_TEMP
            PCLATH_TEMP
            ENDC


     
PUSH    MACRO               ;macro para salvar registros antes de una llamada a interrupcion   
        movwf   W_TEMP               
        swapf   STATUS,W
        movwf   STATUS_TEMP         
        clrf    STATUS               
        movfw   PCLATH               
        movwf   PCLATH_TEMP
        clrf    PCLATH
        ENDM

POP     MACRO               ;macro para restaurar registros   despues de una llamada a interrupcion
        movfw   PCLATH_TEMP         
        movwf   PCLATH
        swapf   STATUS_TEMP,W     
        movwf   STATUS
        swapf   W_TEMP,F         
        swapf   W_TEMP,W
        ENDM

     
      #define BANK0      bcf   STATUS,RP0
      #define BANK1      bsf STATUS,RP0
;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
               ORG      0x00            ;Inicio en el Vector de Reset
              goto   INICIO            ;Va a la primera instruccion del programa
;<<<<<<---------------------- VECTOR DE INTEUPCIONES ------------------------>>>>>>>
               ORG      0x04            ;Inicio en el Vector de Reset
              goto   INTERRUPCIONES            ;Va a la primera instruccion del programa


;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO         BANK1
            movlw   b'10000000'      ;activar interrupcion por cambio de estado a 0 de RB0
            movwf   OPTION_REG
            movlw   b'10010000'      ;configura interrupcion por desbordaminto de TMR0 y  por cambio de estado a 0 de RB0
            movwf   INTCON
            movlw   b'00010001'      ;habilita interrupcion por cambio de estado en RB0/INT
            movwf   TRISB
            BANK0
            bsf      PORTB,1         ;establecer la salida usart a 1
            movlw   d'15'         ;valor para la velocidad de la usart
            movwf   BAUDRATE
            ;valores para el baudrate:para 4Mhz
            ;
            ;para divisor TMR0=000
            ;190=2400bps, 90=4800bps, 40=9600bps, 15=19200bps,
            ;
            ;para divisor TMR0=010
            ;97=1200bps,
            ;
            ;valores para el baudrate:para 20Mhz
            ;
            ;para divisor TMR0=000
            ;51=38400,31=57600.
         
;<<<<<<<------------------------------------------------PROGRAMA PRINCIPAL---------------------------------------->>>>>>>>>>>>>>         
PRINCIPAL      NOP
           
            goto   PRINCIPAL
           
;<<<<<<---------------------------------------------SUBPROGRAMA RECEPCION DE DATOS--------------------------
           
RECEPCION      clrf   CONTADOR      ;borra el contador de bits
            clrf   TMR0         ;borra TMR0
            movfw   BAUDRATE      ;carga valor del baudrate en w
            subwf   TMR0,w         ;comprueva si ha llegado al valor o se pasa
            btfss   STATUS,C      ;si es menos sigue comprovando
            goto   $-3
           
COMP1         clrf   TMR0         ;borra TMR0
COMP2         movfw   BAUDRATE      ;carga valor del baudrate en w
            subwf   TMR0,w         ;resta el contenido de TMR0 con el de w(comprovacion => )
            btfss   STATUS,C      ;comprueva si ha llegado al valor o se pasa
            goto   COMP2         ;si es menos sigue comprovando

                       
            btfsc   PORTB,0         ;comprueva el estado del pin de entrada
            call   UNO            ;si es 1 salta a UNO
            btfss   PORTB,0         ;comprueva el estado del pin de entrada
            call   CERO         ;si es 0 salta a CERO

            incf   CONTADOR,F      ;incrementa el contador de bits
            movlw   0x08         ;valor de bit a comprovar
            xorwf   CONTADOR,W      ;hacer xor con CONTADOR
            btfss   STATUS,Z      ;comprueva si es igual
            goto   COMP1         ;si no es igual sigue las comprobaciones
            movfw   DATO         ;carga el dato recivido en w
            return               ;retorno de subprograma RECEPCION

UNO            rrf      DATO,F         ;rota a la derecha una posicion   
            bsf      DATO,7         ;pon a 1 el bit 7 del registro DATO
            return         ;retorna

CERO         rrf      DATO,F         ;rota a la derecha una posicion
            bcf      DATO,7         ;pon a 0 el bit 7 del registro DATO
            return         ;retorna
           
         
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<SUBPROGRAMA DE ENVIO DE DATOS>>>>>>>>>>>>>>>>>     

   
ENVIO             bsf      PORTB,1         ;establecer la salida a 1(evitar errores primer caracter)
ENVIO2         clrf   CONTADOR      ;borra el registro CONTADOR de bits
                 bcf      PORTB,1         ;bit START   
                 call   RETARDO   
           
ENV_1             btfsc   DATO,0         ;comprueva bit 0 del registro DATO(comprovacion de bits a enviar)
                 call   UNOS         ;salta a UNOS si el bit leido es 1
                 btfss   DATO,0         ;comprueva bit 0 del registro DATO(comprovacion de bits a enviar)
                 call   CEROS         ;salta a CEROS si el bit leido es 0
ENV_2             rrf      DATO,F         ;rota a la derecha el registro DATO

                 incf   CONTADOR,F      ;incrementa CONTADOR (registro contador de bits)
                 movlw   0x08         ;valor de bits a leer
                 xorwf   CONTADOR,W      ;comprueva si son 8
                 btfss   STATUS,Z      ;si no es 8 repite la comprovacion del siguiente bit
                 goto   ENV_1         ;comprueva de nuevo
                 bsf      PORTB,1         ;establecer a 1 la salida
                 return               ;retorna

UNOS                bsf      PORTB,1         ;saca valor 1 por pin 1 de PORTB
                 call   RETARDO         ;tiempo de un bit
                 return               ;retorna
CEROS              bcf      PORTB,1         ;saca valor 0 por pin 1 de PORTB
                 call   RETARDO         ;tiempo de un bit
                 return               ;retorna

;**********************************************RETARDO***************************************
;
;
RETARDO          clrf   TMR0         ;borra el temporizador
COMP            movfw   BAUDRATE      ;valor del retardo
                 subwf   TMR0,w         ;comprueva si ha llegado al valor o se pasa
                 btfss   STATUS,C      ;si es menos sigue comprovando
                 goto   COMP
                 return               ;si ha llegado retorna
;*********************************************INTERRUPCIONES******************************
INTERRUPCIONES   PUSH               ;guarda valores de registros
                 btfss   INTCON,INTF      ;comprueva interrupcion por cambio de PB0/INT
                 goto   SALIR         ;salir del programa
                 call   RECEPCION      ;programa de recepcion de datos
                 call   ENVIO         ;programa de envio de datos
SALIR              bcf      INTCON,INTF      ;borra bandera señalizadora de interrupcion por cambio en PB0/INT
                  POP                  ;restaura valores de registros
                  retfie               ;retorna y activa interrupciones

                  end                  ;fin


Título: Re: pequeños proyectos
Publicado por: groundman en 12 de Diciembre de 2009, 11:16:41
valla! parece que me ha quedado algo mejor que la primera vez que lo intente.no tanto como a ti poseidon20 pero por algo se empieza  :D
la verdad que como profesor seria bastante malo.no se me da muy bien los mecanismos de presentacion.sera por el poco tiempo de que dispongo.y prefiero
gastarlo en realizar codigo.
por eso tengo mi pagina web tan poquito actualizada. :)
Título: Re: pequeños proyectos
Publicado por: groundman en 14 de Agosto de 2011, 11:04:10
hola de nuevo.acabo de realizar un programa que muestra un mensage por una LCD de 16x2 . la particularidad de este programa es que puede visualizar
un mensage que pasa entre paginas de la flash sin que se corte y tengamos que hacer varios punteros de tabla.
este programa esta diseñado para el 16f876 y las tablas ocupan sus 3 ultimas paginas.asi que podemos visualizar un mensage de algo mas de 6kBytes
el modo de funcionamiento para controlar la LCD es de 8 bit.

Código: [Seleccionar]

;************************************************** www.ingeniopic.com ***************************************************
; PROGRAMA : mensage.asm
; Funcion : control de temperatura
;          
;  
;  Revision : 1.0        7/8/2011            Programa para : PIC16F876A
; CPU Clock : 4 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF          
;************************************************* www.ingeniopic.com **************************************************
LIST P=16F876A ; Se emplea el PIC 16F876A
RADIX HEX ; Sistema de numeraci¢n hexadecimal
INCLUDE  "P16F876A.INC"
__CONFIG    _CP_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF
ERRORLEVEL -302

;ZONA DE ETIQUETAS
CBLOCK 0X20
TEMP_W
OFFSET
RESUL
INDICE
TEMP_PCL
TEMP_PCLATH
AUX0
AUX1
AUX2
CONT_CARACTER
ENDC

BANK0 MACRO ;CONMUTACION DE BANCOS
BCF STATUS,IRP
bcf STATUS,RP0
bcf STATUS,RP1
ENDM
BANK1 MACRO
BCF STATUS,IRP
bsf STATUS,RP0
bcf STATUS,RP1
ENDM
BANK2 MACRO
BSF STATUS,IRP
bcf STATUS,RP0
bsf STATUS,RP1
ENDM
BANK3 MACRO
BSF STATUS,IRP
bsf STATUS,RP0
bsf STATUS,RP1
ENDM



org 5
INICIO
BANK0
CLRF PORTA ; Initialize PORTA by

BANK1
MOVLW 0x06 ; Configure all pins
MOVWF ADCON1 ; as digital inputs
MOVLW 0xCF ; Value used to
MOVWF TRISA ; Set RA<3:0> as inputs

;PROGRAMA PRINCIPAL

movlw b'01000000' ;activado interrupcion por desbordamiento de tmr0
movwf INTCON
movlw b'00000001' ;activado interrupcion por desbordamiento de TMR1
movwf PIE1
movlw 0xff
movwf TRISA ;porta como entradas
movlw 0x00 ;
movwf TRISB ;
movlw b'00011111'
movwf TRISC ;portc como ENTRADAS
movlw b'00000000'
movwf OPTION_REG ;configuracion del WDT(div128)y activa resistencias pull-up
BANK0 ;selecciona el banco 0
clrf PORTB ;borra PORTB
clrf PORTC
movlw b'00000101'
movwf T1CON ;configuracion del TMR1 preescaler sin divisiones

bcf PIR1,TMR2IF ;borra flag de desbordamiento de TMR2

movlw 0XFF ;valor final de sector
movwf TEMP_PCL ;temporal del PCL
;clrf CONT_PCL


movlw 0x08 ;pagina donde esta ubicada la tabla(DIR 0X800 =pagina1)
MOVWF TEMP_PCLATH



;***********************************************PRINCIPIO DEL PROGRAMA********************************************************************
 
  

PRINCIPAL CALL LCD



REP GOTO REP


;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<INICIALIZA LCD>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        
LCD         clrf   INTCON ;deshabilita las interrupciones
         BANK0 ;selecciona el banco 0
         clrf   PORTA ;borra lacht del PORTA
         BANK1 ;selecciona el banco 1
         movlw   0x06
         movwf   ADCON1
         clrf    TRISA         ; Puerta A como salidas digitales


call UP_LCD ;prepara puerta de E/S
call BORRA_Y_HOME ;borra el display y posicion 0 para caracter.
call LCD_DELAY
movlw b'00110000' ;8 bit interfaz,1 linea LCD,5x8 pixel.
call FUNCTION_SET ;envia funcion
call LCD_DELAY
movlw b'00001100' ;display on,cursor off,blinking off.
call DISPLAY_ON_OFF ;envia funcion
call LCD_DELAY
movlw b'00000110' ;Establece la dirección de movimiento del cursor
call ENTRY_MODE_SET
call LCD_DELAY


call BIENVENIDA


        
BUCLE       goto   BUCLE



;********************************************* MENSAGE LCD *********************************************
;La funcion de este programa es visualizar los caracteres de la tabla.en un lcd de 16 caracteres por 2 lineas.
;para ello se almacenan los primeros 40 caracteres de la tabla en la DDRAM.para obtener un mejor efecto visual
;los primeros 16 caracteres de la tabla estaran en blanco.
;Una vez cargados los caracteres en la DDRAM,comenzaremos la rotacion del mensage por la pantalla.hasta que el caracter-
;numero 40,quede en la posicion mas a la izquierda de la pantalla.que serian 24 desplazamientos.
;Posteriormente borraremos la pantalla y colocaremos el cursor en la primera direccion de la DDRAM
;grabaremos los siguientes 40 caracteres de la tabla.pero cogeremos 16 de los ultimos caracteres que utilizamos
;en la primera visualizacion.de esta forma obtendremos un efecto visual de que el mensage no se ha cortado.

;En las lineas de abajo explico como funciona.

;Datos de la tabla:
;................ESTA ES UNA PRUEVA DE ME NSAGES LARGOS QUE CONTIENE UNA CANTIDAD DE CARACTERES LIMITADA POR LA MEMORIA

;1ª grabacion en DDRAM.los puntos son en realidad 16 espacios en blanco.
;................ESTA ES UNA PRUEVA DE ME

;2ª grabacion.
;UNA PRUEVA DE MENSAGES LARGOS QUE CONTIE

;3ª grabacion
;ARGOS QUE CONTIENE UNA CANTIDAD DE CARAC

;4ª grabacion
;ANTIDAD DE CARACTERES LIMITADA POR LA ME

;5ª grabacion
;MITADA POR LA MEMORIA...................

;Despues de cada grabacion se realizara 24 desplazamientos hacia la izquierda.si nos fijamos bien
;notaremos que despues de 24 desplazamientos,los caracteres coinciden con la siguiente grabacion.
;este es el efecto visual que hara que parezca un solo mensage muy largo.aunque en realidad son 5 mensages superpuestos
  

            
BIENVENIDA BANK0 ;selecciona banco 0
clrf CONT_CARACTER ;incrementa registro contador de caracteres
clrf   RESUL ;

retorn      movf   OFFSET,W ;carga en W el puntero de tabla
         addwf   RESUL,W ;suma el contenido de W al registro RESUL
call MENSAGE ;salta a tabla de caraceres
incf RESUL,F ;incrementa resul
incf INDICE,F ;incrementa indice de tabla
movf TEMP_W,W ;restaura W
call   LCD_DATO ;introduce caracter contenido en W a la ddram de la LCD.
movlw d'40' ;numero de caracteres de la ddram(primera fila)
subwf RESUL,W ;resta el valor contenido en W al registro RESUL.
btfss STATUS,C ;comprueva si se llego a meter los 40 caracteres en la ddram de la LCD
goto retorn ;si no ha llegado salta a retorn en caso contrario continua

FDG call ROTA_IZQ ;rota el LCD hacia la izquierda
call pausa1 ;pausa de rotacion de la LCD
incf CONT_CARACTER,F ;incrementa el contador de caracteres
movlw .24 ;carga valor de desplazamientos hacia la izquierda para mostrar el mensage completo del a ddram.40-16=24 =>  40 bytes - 16 caracteres visibles = 24 caracteres no visibles
xorwf CONT_CARACTER,w ;comprueva si se llego al valor anterior
btfss STATUS,Z ;si no ha llegado,sigue rotando
goto FDG
movlw .16 ;numero de bytes visibles de la LCD (LCD 16x2)
subwf INDICE,F ;desplaza el indice para grabar los 16 ultimos caracteres del primer mensage de la ddr,en los 16 primeros caracteres del siguiente mensage

clrf CONT_CARACTER ;borra contador de caracteres
clrf   RESUL ;borra RESUL
call BORRA_Y_HOME ;borra el display y posicion 0 para caracter.
goto retorn ;siguiente mensage


;************************************************ RETARDO **********************************************************
pausa1 clrf AUX2
pausae3 clrf AUX1
pausae2 clrf AUX0
pausae incf AUX0,f
btfss AUX0,7 ;valor de emporizacion
goto pausae
incf AUX1,f
btfss AUX1,7 ;valor de temporizacion
goto pausae2
incf AUX2,f
btfss AUX2,1 ;velor de temporizacion
goto pausae3
return

;************************************************ MENSAGE ******************************************************


MENSAGE movlw 0xfc
xorwf INDICE,W ;compara si es igual al indice
btfsc STATUS,Z ;si es asi.(valor final del sector)
fin_bank incf TEMP_PCLATH,F ;incrementa PCLATH (para leer datos del siguiente sector)
bsf PCLATH,3 ;conmuta pagina 1 antes de la llamada al subprograma MENSAGE que esta hubicado en la misma

movlw d'32' ;valor del final de la memoria de programa
xorwf TEMP_PCLATH,W ;comparalo con temporal de paginacion
btfsc STATUS,Z
return ;si ha llegado termina el programa de visualizacion de mensages en LCD


call TABLA ;localiza caracter a leer en la tabla
movwf TEMP_W ;guarda el valor localizado de la tabla en el temporal del acumulador
clrf PCLATH ;borra PCLATH antes de retornar a la pagina 0
return ;retorna

org 0x800 ;direccion de memoria donde se hubicara la tabla(primer byte de la pagina 1)

TABLA movf TEMP_PCLATH,W ;carga en w el valor de la pagina
movwf PCLATH ;conmuta la pagina
movfw   INDICE ;carga el contenido de INDICE en w
addwf   PCL,f ;direcciona el valor a leer de la tabla.

dt   "                En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua,"
dt " rocín flaco y galgo corredor. Una olla de algo más vaca que carnero, salpicón las más noches, duelos y quebrantos los sábados, lentejas los viernes, algún palomin"
dt   "o de añadidura los domingos, consumían las tres partes de su hacienda. El resto della concluían sayo de velarte, calzas de velludo para las fiestas con sus pantufl"
dt "os de lo mismo, los días de entre semana se honraba con su vellori de lo más fino. Tenía en su casa una ama que pasaba de los cuarenta, y una sobrina que no llegab"
dt   "a a los veinte, y un mozo de campo y plaza, que así ensillaba el rocín como tomaba la podadera. Frisaba la edad de nuestro hidalgo con los cincuenta años, era de c"
dt "omplexión recia, seco de carnes, enjuto de rostro; gran madrugador y amigo de la caza. Quieren decir que tenía el sobrenombre de Quijada o Quesada (que en esto hay"
dt " alguna diferencia en los autores que deste caso escriben), aunque por conjeturas verosímiles se deja entender que se llama Quijana; pero esto importa poco a nuest"
dt "ro cuento; basta que en la narración dél no se salga un punto de la verdad. Es, pues, de saber, que este sobredicho hidalgo, los ratos que estaba ocioso (que eran "
dt "los más del año) se daba a leer libros de caballerías con tanta afición y gusto, que olvidó casi de todo punto el ejercicio de la caza, y aun la administración de "
dt "su hacienda; y llegó a tanto su curiosidad y desatino en esto, que vendió muchas hanegas de tierra de sembradura, para comprar libros de caballerías en que leer; y"
dt " así llevó a su casa todos cuantos pudo haber dellos; y de todos ningunos le parecían tan bien como los que compuso el famoso Feliciano de Silva: porque la clarida"
dt "d de su prosa, y aquellas intrincadas razones suyas, le parecían de perlas; y más cuando llegaba a leer aquellos requiebros y cartas de desafío, donde en muchas pa"
dt "rtes hallaba escrito: la razón de la sinrazón que a mi razón se hace, de tal manera mi razón enflaquece, que con razón me quejo de la vuestra fermosura, y también "
dt "cuando leía: los altos cielos que de vuestra divinidad divinamente con las estrellas se fortifican, y os hacen merecedora del merecimiento que merecela vuestra gra"
   dt   "deza. Con estas y semejantes razones perdía el pobre caballero el juicio, y desvelábase por entenderlas, y desentrañarles el sentido, que no se lo sacara, ni las e"
dt " entendiera el mismo Aristóteles, si resucitara para sólo ello. No estaba muy bien con las heridas que don Belianis daba y recibía, porque se imaginaba quepor gran"
dt   "des maestros que le hubiesen curado, no dejaría de tener el rostro y todo el cuerpo lleno de cicatrices y señales; pero con todo alababa en su autor aquel acabar s"
dt "u libro con la promesa de aquella inacabable aventura, y muchas veces le vino deseo de tomar la pluma, y darle fin al pie de la letra como allí se promete; y sin d"
dt   "uda alguna lo hiciera, y aun saliera con ello, si otros mayores y continuos pensamientos no se lo estorbaran. Tuvo muchas veces competencia con el cura de su lugar"
dt " (que era hombre docto graduado en Sigüenza), sobre cuál había sido mejor caballero, Palmerín de Inglaterra o Amadís de Gaula; mas maese Nicolás, barbero del mismo"
dt " pueblo, decía que ninguno llegaba al caballero del Febo, y que si alguno se le podía comparar, era don Galaor, hermano de Amadís de Gaula, porque tenía muy acomod"
dt "ada condición para todo; que no era caballero melindroso, ni tan llorón como su hermano, y que en lo de la valentía no le iba en zaga. En resolución, él se enenfra"
dt "scó tanto en su lectura, que se le pasaban las noches leyendo de claro en claro, y los días de turbio en turbio, y así, del poco dormir y del mucho leer, se le sec"
dt "ó el cerebro, de manera que vino a perder el juicio. Llenósele la fantasía de todo aquello que leía en los libros, así de encantamientos, como de pendencias, batal"
dt "las, desafíos, heridas, requiebros, amores, tormentas y disparates imposibles, y asentósele de tal modo en la imaginación que era verdad toda aquella máquina de aq"
dt "uellas soñadas invenciones que leía, que para él no había otra historia más cierta en el mundo. Decía él, que el Cid Ruy Díaz había sido muy buen caballero; pero q"
dt "ue ver con el caballero de la ardiente espada, que de sólo un revés había partido por medio dos fieros y descomunales gigantes. Mejor estaba con Bernardo del Carpi"
dt "Carpio, porque en Roncesvalle había muerto a Roldán el encantado, valiéndose de la industria de Hércules, cuando ahogó a Anteo, el hijo de la Tierra, entre los bra"
dt "brazos. Decía mucho bien del gigante Morgante, porque con ser de aquella generación gigantesca, que todos son soberbios y descomedidos, él solo era afable y bien c"
dt "riado; pero sobre todos estaba bien con Reinaldos de Montalbán, y más cuando le veía salir de su castillo y robar cuantos topaba, y cuando en Allende robó aquel íd"
dt "olo de Mahoma, que era todo de oro, según dice su historia. Diera él, por dar una mano de coces al traidor de Galalón, al ama que tenía y aun a su sobrina de añadi"
dt   "dura. En efecto, rematado ya su juicio, vino a dar en el más extraño pensamiento que jamás dio loco en el mundo, y fue que le pareció convenible y necesario, así p"
dt "ara el aumento de su honra, como para el servicio de su república, hacerse caballero andante, e irse por todo el mundo con sus armas y caballo a buscar las aventur"
dt "as, y a ejercitarse en todo aquello que él había leído, que los caballeros andantes se ejercitaban, deshaciendo todo género de agravio, y poniéndose en ocasiones y"
dt " peligros, donde acabándolos, cobrase eterno nombre y fama. Imaginábase el pobre ya coronado por el valor de su brazo por lo menos del imperio de Trapisonda: y así"
dt " con estos tan agradables pensamientos, llevado del estraño gusto que en ellos sentía, se dió priesa a poner en efecto lo que deseaba. Y lo primero que hizo, fue l"
dt "impiar unas arma"

org 0x1f00

dt "s, que habían sido de sus bisabuelos, que, tomadas de orín y llenas de moho, luengos siglos había que estaban puestas y olvidadas en un rincón. Lim"
dt "piólas y aderezólas lo mejor que pudo; pero vió que tenían una gran falta, y era que no tenía celada de encaj"


org 0x500
include "lcd_cxx_V2.inc"

end


y aqui pongo la libreria para la lcd.no esta acabada pero sirve para el funcionamiento de este programa:

Código: [Seleccionar]
;LCD_CXX.ASM
 
 
;El conjunto de rutinas que se presentan a continuaci¢n permiten realizar
;las tareas b sicas de control del m¢dulo de visualizaci¢n LCD. Se emplean
;con los PIC 16c8xx. En el programa principal se deber  reservar memoria
;para el bloque de variables que utiliza el LCD del modo:
LCD_VAR EQU 0x5A ;direccion de inicio del bloque para meter datos en variables

;BLOQUE DE ETIQUETAS
 
 
   #define ENABLE       bsf PORTA,2 ;Activa E
   #define DISABLE    bcf PORTA,2 ;Desactiva
   #define LEER       bsf PORTA,1 ;Pone LCD en Modo RD
   #define ESCRIBIR    bcf PORTA,1 ;Pone LCD en Modo WR
   #define OFF_COMANDO    bcf PORTA,0 ;Desactiva RS (modo comando)
   #define ON_COMANDO    bsf PORTA,0 ;Activa RS (modo datos)
   CBLOCK    LCD_VAR
      LCD_TEMP_2   ;Inicio de las variables. Ser  la primera direcci¢n libre
            ; disponible
      LCD_TEMP_1  
   ENDC      
 
       LIST
;RUTINA UP_LCD: Con esta rutina se configura el PIC para que trabaje con el LCD.
 
 
UP_LCD
      BANK1    ;Banco 1
  
       clrf    TRISB;PORTB       ;RB <0-7> salidas digitales
      clrf    TRISB;PORTA       ;RA <0-4> salidas digitales
       BANK0    ;Banco 0
      OFF_COMANDO       ;RS=0
      DISABLE       ;E=0
      return
 
 
;RUTINA LCD_BUSY: Con esta rutina se chequea el estado del
;flag BUSY del m¢dulo LCD, que indica, cuando est  activado, que el
;m¢dulo a£n no ha terminado el comando anterior. La rutina espera a
;que se complete cualquier comando anterior antes de retornar al
;programa principal, para poder enviar un nuevo comando.
 
 
LCD_BUSY   LEER          ;Pone el LCD en Modo RD
         BANK1
         movlw    H'FF'
         movwf    TRISB       ;Puerta B como entrada
         BANK0    ;Selecciona el banco 0
         ENABLE          ;Activa el LCD
         nop
L_BUSY       btfsc    PORTB,7      ;Chequea bit de Busy
         goto    L_BUSY
      
         DISABLE        ;Desactiva LCD
         BANK1
         clrf    TRISB       ;Puerta B salida
         BANK0
         ESCRIBIR         ;Pone LCD en modo WR
         return
 
 
;RUTINA LCD_E: Se trata de una peque¤a rutina que se encarga de generar
;un impulso de 1æ s (para una frecuencia de funcionamiento de 4 Mhz)
;por la patita de salida de la Puerta A RA2, que se halla conectada
;a la se¤al E (Enable) del m¢dulo LCD. Con esta rutina se pretende activar
;al m¢dulo LCD.
 
 
LCD_E       ENABLE         ;Activa E
         nop
         DISABLE         ;Desactiva E
         return
 
 
;RUTINA LCD_DATO: Es una rutina que pasa el contenido cargado en el
;registro W, el cual contiene un car cter ASCII, a la PUERTA B, para
;visualizarlo por el LCD o escribirlo en la CGRAM.
 
 
LCD_DATO    OFF_COMANDO       ;Desactiva RS (modo comando)
         movwf   PORTB       ;Valor ASCII a sacar por PORTB
         call    LCD_BUSY    ;Espera a que se libere el LCD
         ON_COMANDO       ;Activa RS (modo dato)
         call    LCD_E       ;Genera pulso de E
          return
 
 
;RUTINA LCD_REG: Rutina parecida a la anterior, pero el contenido de W
;ahora es el c¢digo de un comando para el LCD, que es necesario pasar
;tambi‚n a la PUERTA B para su ejecuci¢n.
 
 
LCD_REG    OFF_COMANDO       ;Desactiva RS (modo comando)
         BANK0
         movwf    PORTB       ;C¢digo de comando
      
         call    LCD_BUSY    ;LCD libre?.
        
         call    LCD_E       ;S¡. Genera pulso de E.
          return
 
 
;RUTINA LCD_INI: Esta rutina se encarga de realizar la secuencia de
;inicializaci¢n del m¢dulo LCD de acuerdo con los tiempos dados por
;el fabricante (15 ms). Se especifican los valores de DL, N y F,
;as¡ como la configuraci¢n de un interfaz de 8 l¡neas con el bus
;de datos del PIC, y 2 l¡neas de 16 caracteres de 5 x 7 pixels.
 
 
LCD_INI      
         movlw   b'00111000'
         call   LCD_REG    ;C¢digo de instrucci¢n
        
         call   LCD_DELAY   ;Temporiza
         movlw   b'00111000'
         call   LCD_REG      ;C¢digo de instrucci¢n
         call   LCD_DELAY   ;Temporiza
         movlw    b'00111000'
         call   LCD_REG      ;C¢digo de instrucci¢n
         call    LCD_DELAY   ;Temporiza
         return
 
 
;RUTINA BORRA_Y_HOME: Borra el display y retorna el cursor a la posici¢n 0.
 
 
BORRA_Y_HOME   movlw    b'00000001'    ;Borra LCD y Home.
            call    LCD_REG
            return
 
 
;RUTINA DISPLAY_ON_CUR_OFF: Control del display y cursor.
;Activa el display y desactiva es cursor
 
DISPLAY_ON_OFF   ;movlw b'00001100'    ;LCD on, cursor off.
         call    LCD_REG
         return
;RUTINA LCD_LINEA2

LCD_LINEA2      movlw   0xC0
            call   LCD_REG
            return
;RUTINA LCD_LINEA1

LCD_LINEA1      movlw   0x80
            call   LCD_REG
            return

ROTA_DER movlw b'00011000'

call LCD_REG
 call    LCD_DELAY   ;Temporiza
return

SET_DDRAM ;movlw b'00100000'
call LCD_REG
call LCD_DELAY
return

FUNCTION_SET
call LCD_REG
return
ENTRY_MODE_SET
call LCD_REG
return
ROTA_IZQ
movlw b'00011100'
call LCD_REG
return
 
;RUTINA LCD_DELAY: Se trata de un rutina que implementa un retardo
;o temporizaci¢n de 5 ms. Utiliza dos variables llamadas LCD_TEMP_1
;y LCD_TEMP_2, que se van decrementando hasta alcanzar dicho tiempo.
 
 
LCD_DELAY   clrwdt
         movlw    10
         movwf    LCD_TEMP_1
         clrf    LCD_TEMP_2
LCD_DELAY_1 decfsz   LCD_TEMP_2,F
         goto   LCD_DELAY_1
         decfsz   LCD_TEMP_1,F
         goto   LCD_DELAY_1
         return


  
         LIST
Título: Re: pequeños proyectos
Publicado por: todopic en 14 de Agosto de 2011, 11:51:49
Gracias Groudman!, interesante tecnica la de ir cargando en la ddram!!!  :mrgreen:
Título: Re: pequeños proyectos
Publicado por: groundman en 14 de Agosto de 2011, 12:28:45
pero hay otra?  :D la verdad es que es la primera vez que me lio en serio con las LCD.y no entiendo mucho del tema.se me ocurrio hacerlo asi porque es lo primero que se me bino a la cabeza.
pero ahora que lo dices tambien se podria cargar solo en los primero 16Bytes.sin utilizar el desplazamiento del LCD.haciendo el desplazamiento por
software.
en todo caso. creo que de la forma que lo he hecho consumire menos recursos del pic.al mantenerlo libre durante el desplazamiento de los caracteres.

saludos.
Título: Re: pequeños proyectos
Publicado por: tapi8 en 14 de Agosto de 2011, 15:09:48
Muy bueno grounman, lo has conseguido (no tenia ninguna duda de que lo harias), y con un texto del Quijote, para que luego digan que los de ciencias somos unos incultos.  :lol: :lol:
Título: Re: pequeños proyectos
Publicado por: groundman en 14 de Agosto de 2011, 17:08:33
espero que no se hechen encima los de derechos d e autor. :D :D :D
Título: Re: pequeños proyectos
Publicado por: groundman en 05 de Septiembre de 2011, 18:34:18
bueno.pongo este programa que es una modificacion del anterior para trabajar en el modo 4bit.de esta forma nos ahorraremos 4 pin del microcontrolador.
tambien he inseratado la rutina que comprueva el flag BUSY.aunque en este modo de funcionamiento normalmente lo que se hace es darle mas tiempo
a la LCD a que termine sus ejecuciones internas.
por eso me ha costado mas terminar esta parte.ya que no hay muchos ejemplos en internet en este modo de funcionamiento de 4bit y uso del flag BUSY.

Código: [Seleccionar]

;************************************************** www.ingeniopic.com ***************************************************
; PROGRAMA : mensage_16f876_4bit.asm
; Funcion : visualizacion de un mensage largo en el modo LCD 4bit
;          
;  
;  Revision : 1.0        7/8/2011            Programa para : PIC16F876A
; CPU Clock : 4 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF          
;************************************************* www.ingeniopic.com **************************************************
LIST P=16F876A ; Se emplea el PIC 16F876A
RADIX HEX ; Sistema de numeraci¢n hexadecimal
INCLUDE  "P16F876A.INC"
__CONFIG    _CP_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF
ERRORLEVEL -302

;ZONA DE ETIQUETAS
CBLOCK 0X20
TEMP_W
OFFSET
RESUL
INDICE
TEMP_PCL
TEMP_PCLATH
AUX0
AUX1
AUX2
CONT_CARACTER
TEMPLCD
TEMP_PORTB
PDel0
TEMP_RS
ENDC

BANK0 MACRO ;CONMUTACION DEL BANCO 0
BCF STATUS,IRP
bcf STATUS,RP0
bcf STATUS,RP1
ENDM
BANK1 MACRO ;CONMUTACION DEL BANCO 1
BCF STATUS,IRP
bsf STATUS,RP0
bcf STATUS,RP1
ENDM
BANK2 MACRO ;CONMUTACION DEL BANCO 2
BSF STATUS,IRP
bcf STATUS,RP0
bsf STATUS,RP1
ENDM
BANK3 MACRO ;CONMUTACION DEL BANCO 3
BSF STATUS,IRP
bsf STATUS,RP0
bsf STATUS,RP1
ENDM
PULSO MACRO ;PULSO EN TERMINAL E DE LA LCD
bsf         PORTA,2
            call        RETARDO
            bcf         PORTA,2
ENDM



#define COMANDOS    bcf PORTA,0 ;Desactiva RS (modo comando)
   #define DATOS     bsf PORTA,0 ;Activa RS (modo datos)
#define E EQU 2
#define   RS EQU 0
#define READ bsf PORTA,1
#define WRITE bcf PORTA,1
#define ENABLE bsf PORTA,2 ;habilita LCD
#define DISABLE bcf PORTA,2 ;deshabilita LCD


org 5
INICIO
BANK0
clrf PORTA ; inicializa PORTA
clrf PORTB ; inicializa PORTB
BANK1
movlw 0x06 ; configura los pin
movwf ADCON1 ; como entradas digitales
movlw 0xCF ; Value used to
movwf TRISA ; activa RA<3:0> como entradas

movlw 0x00 ;
movwf TRISB ;PORTB como salidas
BANK0 ;selecciona el banco 0
clrf PORTB ;borra PORTB
movlw 0XFF ;valor final de sector
movwf TEMP_PCL ;temporal del PCL
movlw 0x08 ;pagina donde esta ubicada la tabla(DIR 0X800 =pagina1)
movwf TEMP_PCLATH

;***********************************************PRINCIPIO DEL PROGRAMA********************************************************************
 
PRINCIPAL CALL LCD
REP GOTO REP ;fin del programa.


;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<INICIALIZA LCD>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        
LCD         clrf   INTCON ;deshabilita las interrupciones
         BANK0 ;selecciona el banco 0
         clrf   PORTA ;borra lacht del PORTA
         BANK1 ;selecciona el banco 1
         movlw   0x06
         movwf   ADCON1
         clrf    TRISA         ; Puerta A como salidas digitales

call LCDINI ;inicializa la LCD
call BIENVENIDA ;salta a mensage de bienvenida


         return




;********************************************* MENSAGE LCD *********************************************
;La funcion de este programa es visualizar los caracteres de la tabla.en un lcd de 16 caracteres por 2 lineas.
;para ello se almacenan los primeros 40 caracteres de la tabla en la DDRAM.para obtener un mejor efecto visual
;los primeros 16 caracteres de la tabla estaran en blanco.
;Una vez cargados los caracteres en la DDRAM,comenzaremos la rotacion del mensage por la pantalla.hasta que el caracter-
;numero 40,quede en la posicion mas a la izquierda de la pantalla.que serian 24 desplazamientos.
;Posteriormente borraremos la pantalla y colocaremos el cursor en la primera direccion de la DDRAM
;grabaremos los siguientes 40 caracteres de la tabla.pero cogeremos 16 de los ultimos caracteres que utilizamos
;en la primera visualizacion.de esta forma obtendremos un efecto visual de que el mensage no se ha cortado.

;En las lineas de abajo explico como funciona.

;Datos de la tabla:
;................ESTA ES UNA PRUEVA DE ME NSAGES LARGOS QUE CONTIENE UNA CANTIDAD DE CARACTERES LIMITADA POR LA MEMORIA

;1ª grabacion en DDRAM.los puntos son en realidad 16 espacios en blanco.
;................ESTA ES UNA PRUEVA DE ME

;2ª grabacion.
;UNA PRUEVA DE MENSAGES LARGOS QUE CONTIE

;3ª grabacion
;ARGOS QUE CONTIENE UNA CANTIDAD DE CARAC

;4ª grabacion
;ANTIDAD DE CARACTERES LIMITADA POR LA ME

;5ª grabacion
;MITADA POR LA MEMORIA...................

;Despues de cada grabacion se realizara 24 desplazamientos hacia la izquierda.si nos fijamos bien
;notaremos que despues de 24 desplazamientos,los caracteres coinciden con la siguiente grabacion.
;este es el efecto visual que hara que parezca un solo mensage muy largo.aunque en realidad son 5 mensages superpuestos
  
;**************************************************** FUNCIONAMIENTO DE ALGUNAS RUTINAS ************************************************
;
;Ddebido a que el uso de una libreria para LCD es un desaprobecho de los recursos del pic.ya que ocupariamos una gran
;parte de la memoria de programa.y perdida de tiempo en las llamadas a estas rutinas.
;He decidido insertar los comandos en el programa principal.estos comandos iran precedidos de una instruccion para
;la conmutacion entre datos y comandos.ejamplo:
;
;envio de un comando a la LCD:
;COMANDOS
;MOVLW 0X01 ;envio del comando HOME
;CALL   BYTE
;
;envio de un datos a la LCD:
;DATOS
;MOVLW 'A' ;envio del caracter "A"
;CALL BYTE
;
;************************************************************MENSAGE DE BIENVENIDA******************************************************  
        
BIENVENIDA BANK0 ;selecciona banco 0
clrf CONT_CARACTER ;incrementa registro contador de caracteres
clrf   RESUL ;borra registro RESUL

retorn      DATOS ;selecciona modo de envio de datos
movf   OFFSET,W ;carga en W el puntero de tabla
         addwf   RESUL,W ;suma el contenido de W al registro RESUL
call MENSAGE ;salta a tabla de caraceres
incf RESUL,F ;incrementa resul
incf INDICE,F ;incrementa indice de tabla

movf TEMP_W,W ;restaura W
call   BYTE ;introduce caracter contenido en W a la ddram de la LCD.
movlw d'40' ;numero de caracteres de la ddram(primera fila)
subwf RESUL,W ;resta el valor contenido en W al registro RESUL.
btfss STATUS,C ;comprueva si se llego a meter los 40 caracteres en la ddram de la LCD
goto retorn ;si no ha llegado salta a retorn en caso contrario continua

FDG COMANDOS ;selecciona modo de envio de comandos
movlw b'00011100' ;comando de rotacion a izquierdas
call BYTE ;envia comando
call pausa1 ;pausa de rotacion de la LCD
incf CONT_CARACTER,F ;incrementa el contador de caracteres
movlw .24 ;carga valor de desplazamientos hacia la izquierda para mostrar el mensage completo del a ddram.40-16=24 =>  40 bytes - 16 caracteres visibles = 24 caracteres no visibles
xorwf CONT_CARACTER,w ;comprueva si se llego al valor anterior
btfss STATUS,Z ;si no ha llegado,sigue rotando
goto FDG
movlw .16 ;numero de bytes visibles de la LCD (LCD 16x2)
subwf INDICE,F ;desplaza el indice para grabar los 16 ultimos caracteres del primer mensage de la ddr,en los 16 primeros caracteres del siguiente mensage
clrf CONT_CARACTER ;borra contador de caracteres
clrf   RESUL ;borra RESUL

COMANDOS ;selecciona el modo comando para la LCD
movlw 0X01 ;HOME. posicion 0 de la DD RAM.
           call   BYTE ;envia comando
goto retorn ;siguiente mensage



;************************************************** INICIALIZACION LCD *************************************************************
LCDINI     COMANDOS ;selecciona el modo comando para la LCD
movlw 0X02 ;HOME. posicion 0 de la DD RAM.
           call   BYTE
           movlw   0X28 ;FUNCTION SET. bus 4bit,LCD 1 linea.
           call    BYTE
           movlw   0X0C ;DISPLAY ON/OFF. display on.
           call    BYTE
           movlw   0X06 ;ENTRY MODE.incremento del cursor
           call    BYTE
           movlw   0X01   ;CLEAR DISPLAY. borra display y activa incremento del cursor
           call    BYTE
           return

;********************************************** ENVIO DE NIBLES  A LA LCD ******************************************************

BYTE                 BANK0 ;selcciona el banco 0
movwf   TEMPLCD ;guarda el contenido de W en registro temporal TEMPLCD
call LCD_BUSY ;comprueva si el LCD esta libre
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            movf    TEMPLCD,W ;carga el contenido de TEMPLCD en W
            andlw   0xf0 ;seleccionar el nible alto de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            swapf   TEMPLCD,W ;inbierte los nibles del registro TEMPLCD
            andlw   0xf0 ;seleccionar el alto bajo de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
return ;retorna


LCD_BUSY           call RETARDO ;retardo para evitar que la lectura del flag BUSY se quede bloqueado.
                                               movfw PORTA ;carga en W el contenido de PORTA
andlw 0x01 ;guarda el valor del estado del bit RS
movwf TEMP_RS ;salva el valor de RS en el registro temporal
COMANDOS ;selecciona el modo comandos
BANK1 ;selecciona banco 1
         movlw    H'F0' ;
         movwf    TRISB       ;nible alto de PORT B como entrada
         BANK0     ;Selecciona el banco 0
READ           ;Pone el LCD en Modo RD "lectura"
         ENABLE           ;Activa el LCD (lectura del nible alto)
L_BUSY      btfsc    PORTB,7       ;Chequea bit de Busy
         goto    L_BUSY ;espera a que la LCD este libre
       DISABLE         ;Desactiva LCD

ENABLE ;Activa el LCD (lectura del nible bajo)
call RETARDO ;retardo de 1ms
DISABLE ;Desactiva LCD

         BANK1 ;selecciona banco 1
         clrf    TRISB       ;Puerta B salida
         BANK0 ;Selecciona el banco 0
         WRITE         ;Pone LCD en modo WR

movfw TEMP_RS ;restaura el valor de SR
iorwf PORTA,f ;activa en PORTA el bit RS
         return ;retorna


;************************************************ RETARDO DE VELOCIDAD DE DESPLAZAMIENTO **********************************************************
pausa1 clrf AUX2
pausae3 clrf AUX1
pausae2 clrf AUX0
pausae incf AUX0,f
btfss AUX0,7 ;valor de temporizacion
goto pausae
incf AUX1,f
btfss AUX1,7 ;valor de temporizacion
goto pausae2
incf AUX2,f
btfss AUX2,1 ;velor de temporizacion
goto pausae3
return
;************************************************ RETARDO 1mS **********************************************************

RETARDO   movlw   .248       ; 1 set numero de repeticion
         movwf   PDel0     ; 1 |
PLoop0   clrwdt             ; 1 clear watchdog
         decfsz  PDel0, 1   ; 1 + (1) es el tiempo 0  ?
         goto    PLoop0     ; 2 no, loop
PDelL1   goto PDelL2         ; 2 ciclos delay
PDelL2   clrwdt               ; 1 ciclo delay
         return               ; 2+2 Fin.
;************************************************ MENSAGE ******************************************************


MENSAGE movlw 0xfc
xorwf INDICE,W ;compara si es igual al indice
btfsc STATUS,Z ;si es asi.(valor final del sector)
fin_bank incf TEMP_PCLATH,F ;incrementa PCLATH (para leer datos del siguiente sector)
bsf PCLATH,3 ;conmuta pagina 1 antes de la llamada al subprograma MENSAGE que esta hubicado en la misma
movlw d'32' ;valor del final de la memoria de programa
xorwf TEMP_PCLATH,W ;comparalo con temporal de paginacion
btfsc STATUS,Z
return ;si ha llegado termina el programa de visualizacion de mensages en LCD
call TABLA ;localiza caracter a leer en la tabla
movwf TEMP_W ;guarda el valor localizado de la tabla en el temporal del acumulador
clrf PCLATH ;borra PCLATH antes de retornar a la pagina 0
return ;retorna

org 0x800 ;direccion de memoria donde se hubicara la tabla(primer byte de la pagina 1)

TABLA movf TEMP_PCLATH,W ;carga en w el valor de la pagina
movwf PCLATH ;conmuta la pagina
movfw   INDICE ;carga el contenido de INDICE en w
addwf   PCL,f ;direcciona el valor a leer de la tabla.

dt   "                En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua,"
dt " rocín flaco y galgo corredor. Una olla de algo más vaca que carnero, salpicón las más noches, duelos y quebrantos los sábados, lentejas los viernes, algún palomin"
dt   "o de añadidura los domingos, consumían las tres partes de su hacienda. El resto della concluían sayo de velarte, calzas de velludo para las fiestas con sus pantufl"
dt "os de lo mismo, los días de entre semana se honraba con su vellori de lo más fino. Tenía en su casa una ama que pasaba de los cuarenta, y una sobrina que no llegab"
dt   "a a los veinte, y un mozo de campo y plaza, que así ensillaba el rocín como tomaba la podadera. Frisaba la edad de nuestro hidalgo con los cincuenta años, era de c"
dt "omplexión recia, seco de carnes, enjuto de rostro; gran madrugador y amigo de la caza. Quieren decir que tenía el sobrenombre de Quijada o Quesada (que en esto hay"
dt " alguna diferencia en los autores que deste caso escriben), aunque por conjeturas verosímiles se deja entender que se llama Quijana; pero esto importa poco a nuest"
dt "ro cuento; basta que en la narración dél no se salga un punto de la verdad. Es, pues, de saber, que este sobredicho hidalgo, los ratos que estaba ocioso (que eran "
dt "los más del año) se daba a leer libros de caballerías con tanta afición y gusto, que olvidó casi de todo punto el ejercicio de la caza, y aun la administración de "
dt "su hacienda; y llegó a tanto su curiosidad y desatino en esto, que vendió muchas hanegas de tierra de sembradura, para comprar libros de caballerías en que leer; y"
dt " así llevó a su casa todos cuantos pudo haber dellos; y de todos ningunos le parecían tan bien como los que compuso el famoso Feliciano de Silva: porque la clarida"
dt "d de su prosa, y aquellas intrincadas razones suyas, le parecían de perlas; y más cuando llegaba a leer aquellos requiebros y cartas de desafío, donde en muchas pa"
dt "rtes hallaba escrito: la razón de la sinrazón que a mi razón se hace, de tal manera mi razón enflaquece, que con razón me quejo de la vuestra fermosura, y también "
dt "cuando leía: los altos cielos que de vuestra divinidad divinamente con las estrellas se fortifican, y os hacen merecedora del merecimiento que merecela vuestra gra"
   dt   "deza. Con estas y semejantes razones perdía el pobre caballero el juicio, y desvelábase por entenderlas, y desentrañarles el sentido, que no se lo sacara, ni las e"
dt " entendiera el mismo Aristóteles, si resucitara para sólo ello. No estaba muy bien con las heridas que don Belianis daba y recibía, porque se imaginaba quepor gran"
dt   "des maestros que le hubiesen curado, no dejaría de tener el rostro y todo el cuerpo lleno de cicatrices y señales; pero con todo alababa en su autor aquel acabar s"
dt "u libro con la promesa de aquella inacabable aventura, y muchas veces le vino deseo de tomar la pluma, y darle fin al pie de la letra como allí se promete; y sin d"
dt   "uda alguna lo hiciera, y aun saliera con ello, si otros mayores y continuos pensamientos no se lo estorbaran. Tuvo muchas veces competencia con el cura de su lugar"
dt " (que era hombre docto graduado en Sigüenza), sobre cuál había sido mejor caballero, Palmerín de Inglaterra o Amadís de Gaula; mas maese Nicolás, barbero del mismo"
dt " pueblo, decía que ninguno llegaba al caballero del Febo, y que si alguno se le podía comparar, era don Galaor, hermano de Amadís de Gaula, porque tenía muy acomod"
dt "ada condición para todo; que no era caballero melindroso, ni tan llorón como su hermano, y que en lo de la valentía no le iba en zaga. En resolución, él se enenfra"
dt "scó tanto en su lectura, que se le pasaban las noches leyendo de claro en claro, y los días de turbio en turbio, y así, del poco dormir y del mucho leer, se le sec"
dt "ó el cerebro, de manera que vino a perder el juicio. Llenósele la fantasía de todo aquello que leía en los libros, así de encantamientos, como de pendencias, batal"
dt "las, desafíos, heridas, requiebros, amores, tormentas y disparates imposibles, y asentósele de tal modo en la imaginación que era verdad toda aquella máquina de aq"
dt "uellas soñadas invenciones que leía, que para él no había otra historia más cierta en el mundo. Decía él, que el Cid Ruy Díaz había sido muy buen caballero; pero q"
dt "ue ver con el caballero de la ardiente espada, que de sólo un revés había partido por medio dos fieros y descomunales gigantes. Mejor estaba con Bernardo del Carpi"
dt "Carpio, porque en Roncesvalle había muerto a Roldán el encantado, valiéndose de la industria de Hércules, cuando ahogó a Anteo, el hijo de la Tierra, entre los bra"
dt "brazos. Decía mucho bien del gigante Morgante, porque con ser de aquella generación gigantesca, que todos son soberbios y descomedidos, él solo era afable y bien c"
dt "riado; pero sobre todos estaba bien con Reinaldos de Montalbán, y más cuando le veía salir de su castillo y robar cuantos topaba, y cuando en Allende robó aquel íd"
dt "olo de Mahoma, que era todo de oro, según dice su historia. Diera él, por dar una mano de coces al traidor de Galalón, al ama que tenía y aun a su sobrina de añadi"
dt   "dura. En efecto, rematado ya su juicio, vino a dar en el más extraño pensamiento que jamás dio loco en el mundo, y fue que le pareció convenible y necesario, así p"
dt "ara el aumento de su honra, como para el servicio de su república, hacerse caballero andante, e irse por todo el mundo con sus armas y caballo a buscar las aventur"
dt "as, y a ejercitarse en todo aquello que él había leído, que los caballeros andantes se ejercitaban, deshaciendo todo género de agravio, y poniéndose en ocasiones y"
dt " peligros, donde acabándolos, cobrase eterno nombre y fama. Imaginábase el pobre ya coronado por el valor de su brazo por lo menos del imperio de Trapisonda: y así"
dt " con estos tan agradables pensamientos, llevado del estraño gusto que en ellos sentía, se dió priesa a poner en efecto lo que deseaba. Y lo primero que hizo, fue l"
dt "impiar unas arma"

org 0x1f00

dt "s, que habían sido de sus bisabuelos, que, tomadas de orín y llenas de moho, luengos siglos había que estaban puestas y olvidadas en un rincón. Lim"
dt "piólas y aderezólas lo mejor que pudo; pero vió que tenían una gran falta, y era que no tenía celada de encaj"


org 0x500
include "lcd_cxx_V2.inc"

end

Título: Re: pequeños proyectos
Publicado por: groundman en 08 de Septiembre de 2011, 18:59:54
pongo este programa que realiza pruevas con comandos de la LCD.en el corrijo caracteres y tambien visualizo alguno especial.

Código: [Seleccionar]

;************************************************** www.ingeniopic.com ***************************************************
; PROGRAMA : pruevas_LCD_v1.asm
; Funcion : pruevas con los comandos de una lcd en modo a 4bits
;           
;   
;  Revision : 1.0        8/9/2011            Programa para : PIC16F876A
; CPU Clock : 4 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF           
;************************************************* www.ingeniopic.com **************************************************
LIST P=16F876A ; Se emplea el PIC 16F876A
RADIX HEX ; Sistema de numeraci¢n hexadecimal
INCLUDE  "P16F876A.INC"
__CONFIG    _CP_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF
ERRORLEVEL -302

;ZONA DE ETIQUETAS
CBLOCK 0X20
TEMP_W
OFFSET
RESUL
INDICE
TEMP_PCL
TEMP_PCLATH
AUX0
AUX1
AUX2
CONT_CARACTER
TEMPLCD
TEMP_PORTB
PDel0
TEMP_RS
ENDC

BANK0 MACRO ;CONMUTACION DEL BANCO 0
BCF STATUS,IRP
bcf STATUS,RP0
bcf STATUS,RP1
ENDM
BANK1 MACRO ;CONMUTACION DEL BANCO 1
BCF STATUS,IRP
bsf STATUS,RP0
bcf STATUS,RP1
ENDM
BANK2 MACRO ;CONMUTACION DEL BANCO 2
BSF STATUS,IRP
bcf STATUS,RP0
bsf STATUS,RP1
ENDM
BANK3 MACRO ;CONMUTACION DEL BANCO 3
BSF STATUS,IRP
bsf STATUS,RP0
bsf STATUS,RP1
ENDM
PULSO MACRO ;PULSO EN TERMINAL E DE LA LCD
bsf         PORTA,2
            call        RETARDO
            bcf         PORTA,2
ENDM



#define COMANDOS    bcf PORTA,0 ;Desactiva RS (modo comando)
    #define DATOS    bsf PORTA,0 ;Activa RS (modo datos)
#define E EQU 2
#define     RS EQU 0
#define READ bsf PORTA,1
#define WRITE bcf PORTA,1
#define ENABLE bsf PORTA,2 ;habilita LCD
#define DISABLE bcf PORTA,2 ;deshabilita LCD


org 5
INICIO
BANK0
clrf PORTA ; inicializa PORTA
clrf PORTB ; inicializa PORTB
BANK1
movlw 0x06 ; configura los pin
movwf ADCON1 ; como entradas digitales
movlw 0xCF ; Value used to
movwf TRISA ; activa RA<3:0> como entradas

movlw 0x00 ;
movwf TRISB ;PORTB como salidas
BANK0 ;selecciona el banco 0
clrf PORTB ;borra PORTB
movlw 0XFF ;valor final de sector
movwf TEMP_PCL ;temporal del PCL
movlw 0x08 ;pagina donde esta ubicada la tabla(DIR 0X800 =pagina1)
movwf TEMP_PCLATH

;***********************************************PRINCIPIO DEL PROGRAMA********************************************************************
 
PRINCIPAL CALL LCD
REP GOTO REP ;fin del programa.


;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<INICIALIZA LCD>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
         
LCD         clrf   INTCON ;deshabilita las interrupciones
          BANK0 ;selecciona el banco 0
          clrf   PORTA ;borra lacht del PORTA
          BANK1 ;selecciona el banco 1
          movlw   0x06
          movwf   ADCON1
          clrf    TRISA          ; Puerta A como salidas digitales

call LCDINI ;inicializa la LCD
call PRUEVAS ;salta a mensage de bienvenida
    return

;************************************************************ PRUEVAS ******************************************************   
         
PRUEVAS NOP
DATOS ;activa envio de datos
MOVLW 'E'
CALL BYTE
MOVLW 's'
CALL BYTE
MOVLW 'p'
CALL BYTE
MOVLW 'a'
CALL BYTE
MOVLW 'ñ'
CALL BYTE
MOVLW 'a'
CALL BYTE


COMANDOS ;activa envio de comandos
MOVLW B'00001110' ;activa display,y el cursor
CALL BYTE
MOVLW B'00000100' ;decremento del cursor
CALL BYTE

DATOS ;activa envio de datos
MOVLW ' '
CALL BYTE
MOVLW ' '
CALL BYTE

COMANDOS ;activa envio de comandos
MOVLW B'00000110' ;incremento del cursor
CALL BYTE

DATOS ;activa envio de datos
MOVLW b'11101110' ;letra "ñ"
CALL BYTE
MOVLW 'a'
CALL BYTE
MOVLW ' '
CALL BYTE
MOVLW 'F'
CALL BYTE
MOVLW 'C'
CALL BYTE
MOVLW '.'
CALL BYTE

COMANDOS
MOVLW B'00010100'; mueve el cursor a la derecha
CALL BYTE
MOVLW B'00010000'; mueve el cursor a la izquierda
CALL BYTE
MOVLW B'00010000'; mueve el cursor a la izquierda
CALL BYTE
MOVLW B'00001101'; display on,cursor on.
CALL BYTE
MOVLW B'00001111'; display on,cursor on,parpadeo on.
CALL BYTE
goto $-2
RETURN



;************************************************** INICIALIZACION LCD *************************************************************
LCDINI    COMANDOS ;selecciona el modo comando para la LCD
movlw 0X02 ;HOME. posicion 0 de la DD RAM.
          call    BYTE
          movlw  0X28 ;FUNCTION SET. bus 4bit,LCD 1 linea.
          call    BYTE
          movlw   0X0C ;DISPLAY ON/OFF. display on.
          call    BYTE
          movlw   0X06 ;ENTRY MODE.incremento del cursor
          call    BYTE
          movlw   0X01  ;CLEAR DISPLAY. borra display y activa incremento del cursor
          call    BYTE
          return




;********************************************** ENVIO DE NIBLES  A LA LCD ******************************************************

BYTE        BANK0 ;selcciona el banco 0
movwf   TEMPLCD ;guarda el contenido de W en registro temporal TEMPLCD
call LCD_BUSY ;comprueva si el LCD esta libre
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            movf    TEMPLCD,W ;carga el contenido de TEMPLCD en W
            andlw   0xf0 ;seleccionar el nible alto de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            swapf   TEMPLCD,W ;inbierte los nibles del registro TEMPLCD
            andlw   0xf0 ;seleccionar el alto bajo de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
return ;retorna


LCD_BUSY    call RETARDO ;retardo para evitar que la lectura del flag BUSY se quede bloqueado.
movfw PORTA ;carga en W el contenido de PORTA
andlw 0x01 ;guarda el valor del estado del bit RS
movwf TEMP_RS ;salva el valor de RS en el registro temporal
COMANDOS ;selecciona el modo comandos
BANK1 ;selecciona banco 1
          movlw    H'F0' ;
          movwf    TRISB        ;nible alto de PORT B como entrada
          BANK0    ;Selecciona el banco 0
READ          ;Pone el LCD en Modo RD "lectura"
          ENABLE          ;Activa el LCD (lectura del nible alto)
L_BUSY      btfsc    PORTB,7      ;Chequea bit de Busy
          goto    L_BUSY ;espera a que la LCD este libre
      DISABLE        ;Desactiva LCD

ENABLE ;Activa el LCD (lectura del nible bajo)
call RETARDO ;retardo de 1ms
DISABLE ;Desactiva LCD

          BANK1 ;selecciona banco 1
          clrf    TRISB        ;Puerta B salida
          BANK0 ;Selecciona el banco 0
          WRITE          ;Pone LCD en modo WR

movfw TEMP_RS ;restaura el valor de SR
iorwf PORTA,f ;activa en PORTA el bit RS
          return ;retorna


;************************************************ RETARDO DE VELOCIDAD DE DESPLAZAMIENTO **********************************************************
pausa1 clrf AUX2
pausae3 clrf AUX1
pausae2 clrf AUX0
pausae incf AUX0,f
btfss AUX0,7 ;valor de temporizacion
goto pausae
incf AUX1,f
btfss AUX1,7 ;valor de temporizacion
goto pausae2
incf AUX2,f
btfss AUX2,1 ;velor de temporizacion
goto pausae3
return
;************************************************ RETARDO 1mS **********************************************************

RETARDO  movlw   .248      ; 1 set numero de repeticion
        movwf   PDel0      ; 1 |
PLoop0  clrwdt              ; 1 clear watchdog
        decfsz  PDel0, 1  ; 1 + (1) es el tiempo 0  ?
        goto    PLoop0    ; 2 no, loop
PDelL1  goto PDelL2          ; 2 ciclos delay
PDelL2  clrwdt              ; 1 ciclo delay
        return              ; 2+2 Fin.

end

Título: Re: pequeños proyectos
Publicado por: groundman en 09 de Septiembre de 2011, 19:32:10
y ahora pongo el programa anterior pero para un PIC18F2550.

Código: [Seleccionar]

;************************************************** www.ingeniopic.com ***************************************************
; PROGRAMA : teclado_LCD_v1.asm
; Funcion : pruevas con teclado y lcd
;           
;   
;  Revision : 1.0        9/9/2011            Programa para : PIC18F2550
; CPU Clock : 48 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF           
;************************************************* www.ingeniopic.com **************************************************
;
;NOTA: se han activado las resistencias pull-up de PORTB.debido a que se nproducia un error al leer el bit BUSY de la LCD.
;      ya que las salidas de la lcd se quedan en alta impedancia.y el pic no leia correctamente D7.

LIST P=18F2550 ; Se emplea el PIC 16F876A
RADIX HEX ; Sistema de numeraci¢n hexadecimal
INCLUDE  "P18F2550.INC"
CONFIG FOSC = HS       ;Osc por XTAL 20mhz
      CONFIG DEBUG = OFF
      CONFIG PWRT = OFF
      CONFIG BOR  = OFF
      CONFIG WDT = OFF
      CONFIG MCLRE = ON
      CONFIG PBADEN = OFF
      CONFIG LVP = OFF
      CONFIG CP0 = OFF
      CONFIG CP1 = OFF
      CONFIG CP2 = OFF
      CONFIG CP3 = OFF
      CONFIG CPB = OFF
      CONFIG CPD = OFF
ERRORLEVEL -302

;ZONA DE ETIQUETAS
CBLOCK 0X20

AUX0
AUX1
AUX2
TEMPLCD
PDel0
PDel1
TEMP_RS
            FLAGS
ENDC


PULSO MACRO ;PULSO EN TERMINAL E DE LA LCD
bsf         PORTA,2
            call        RETARDO
            bcf         PORTA,2
ENDM



#define COMANDOS    bcf PORTA,0 ;Desactiva RS (modo comando)
    #define DATOS    bsf PORTA,0 ;Activa RS (modo datos)
#define E EQU 2
#define     RS EQU 0
#define READ bsf PORTA,1
#define WRITE bcf PORTA,1
#define ENABLE bsf PORTA,2 ;habilita LCD
#define DISABLE bcf PORTA,2 ;deshabilita LCD

;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
          ORG    0x00      ;Inicio en el Vector de Reset
  goto   INICIO      ;ir a la primera instruccion del programa


ORG 0X001C
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO    clrf    INTCON,ACCESS    ; deshabilita todas la interrupciones
clrf UCON,1
clrf FLAGS ;borra registro de banderas
movlw b'01110000' ;activa resistencias pull-up (evitar fallo lectura BUSY LCD)
movwf INTCON2




;***********************************************PRINCIPIO DEL PROGRAMA********************************************************************
 
PRINCIPAL CALL LCD
REP GOTO REP ;fin del programa.


;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<INICIALIZA LCD>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
         
LCD         clrf   INTCON ;deshabilita las interrupciones
          clrf   PORTA ;borra lacht del PORTA
clrf LATA
          movlw   0x0F
          movwf   ADCON1
movlw 0x07
movwf CMCON
          clrf    TRISA          ; Puerta A como salidas digitales

CLRF PORTB
CLRF LATB
CLRF TRISB


call LCDINI ;inicializa la LCD
call PRUEVAS ;salta a mensage de bienvenida
    return

;************************************************************ PRUEVAS ******************************************************   
         
PRUEVAS NOP
DATOS ;activa envio de datos
MOVLW 'E'
CALL BYTE
MOVLW 's'
CALL BYTE
MOVLW 'p'
CALL BYTE
MOVLW 'a'
CALL BYTE
MOVLW 'ñ'
CALL BYTE
MOVLW 'a'
CALL BYTE


COMANDOS ;activa envio de comandos
MOVLW B'00001110' ;activa display,y el cursor
CALL BYTE
MOVLW B'00000100' ;decremento del cursor
CALL BYTE

DATOS ;activa envio de datos
MOVLW ' '
CALL BYTE
MOVLW ' '
CALL BYTE

COMANDOS ;activa envio de comandos
MOVLW B'00000110' ;incremento del cursor
CALL BYTE

DATOS ;activa envio de datos
MOVLW b'11101110' ;letra "ñ"
CALL BYTE
MOVLW 'a'
CALL BYTE
MOVLW ' '
CALL BYTE
MOVLW 'F'
CALL BYTE
MOVLW 'C'
CALL BYTE
MOVLW '.'
CALL BYTE

COMANDOS
MOVLW B'00010100'; mueve el cursor a la derecha
CALL BYTE
MOVLW B'00010000'; mueve el cursor a la izquierda
CALL BYTE
MOVLW B'00010000'; mueve el cursor a la izquierda
CALL BYTE
MOVLW B'00001101'; display on,cursor on.
CALL BYTE
MOVLW B'00001111'; display on,cursor on,parpadeo on.
CALL BYTE
goto $-2
RETURN



;************************************************** INICIALIZACION LCD *************************************************************
LCDINI    COMANDOS ;selecciona el modo comando para la LCD
movlw 0X02 ;HOME. posicion 0 de la DD RAM.
          call    BYTE
          movlw  0X28 ;FUNCTION SET. bus 4bit,LCD 1 linea.
          call    BYTE
          movlw   0X0C ;DISPLAY ON/OFF. display on.
          call    BYTE
          movlw   0X06 ;ENTRY MODE.incremento del cursor
          call    BYTE
          movlw   0X01  ;CLEAR DISPLAY. borra display y activa incremento del cursor
          call    BYTE
          return




;********************************************** ENVIO DE NIBLES  A LA LCD ******************************************************

BYTE        movwf   TEMPLCD ;guarda el contenido de W en registro temporal TEMPLCD
call LCD_BUSY ;comprueva si el LCD esta libre
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            movf    TEMPLCD,W ;carga el contenido de TEMPLCD en W
            andlw   0xf0 ;seleccionar el nible alto de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            swapf   TEMPLCD,W ;inbierte los nibles del registro TEMPLCD
            andlw   0xf0 ;seleccionar el alto bajo de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
return ;retorna


LCD_BUSY    call RETARDO ;retardo para evitar que la lectura del flag BUSY se quede bloqueado.
movf PORTA,W ;carga en W el contenido de PORTA
andlw 0x01 ;guarda el valor del estado del bit RS
movwf TEMP_RS ;salva el valor de RS en el registro temporal
COMANDOS ;selecciona el modo comandos
movlw    H'F0' ;
          movwf    TRISB        ;nible alto de PORT B como entrada
READ          ;Pone el LCD en Modo RD "lectura"
ENABLE          ;Activa el LCD (lectura del nible alto)
L_BUSY      btfsc    PORTB,7      ;Chequea bit de Busy
          goto    L_BUSY ;espera a que la LCD este libre
      DISABLE        ;Desactiva LCD
ENABLE ;Activa el LCD (lectura del nible bajo)
call RETARDO ;retardo de 1ms
DISABLE ;Desactiva LCD
clrf    TRISB        ;Puerta B salida
          WRITE          ;Pone LCD en modo WR
movf TEMP_RS,W ;restaura el valor de SR
iorwf PORTA,f ;activa en PORTA el bit RS
          return ;retorna


;************************************************ RETARDO DE VELOCIDAD DE DESPLAZAMIENTO **********************************************************
pausa1 clrf AUX2
pausae3 clrf AUX1
pausae2 clrf AUX0
pausae incf AUX0,f
btfss AUX0,7 ;valor de temporizacion
goto pausae
incf AUX1,f
btfss AUX1,7 ;valor de temporizacion
goto pausae2
incf AUX2,f
btfss AUX2,1 ;velor de temporizacion
goto pausae3
return
;************************************************ RETARDO 1mS **********************************************************

RETARDO  movlw     .67       ; 1 set numero de repeticion  (B)
        movwf     PDel0     ; 1 |
PLoop1  movlw     .35       ; 1 set numero de repeticion  (A)
        movwf     PDel1     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        clrwdt              ; 1 ciclo delay
        decfsz    PDel1, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto   PDelL2         ; 2 ciclos delay
PDelL2 
        return              ; 2+2 Fin.



end

Título: Re: pequeños proyectos
Publicado por: groundman en 11 de Septiembre de 2011, 17:51:32
este programa envia caracteres a la LCD desde un teclado de 4x4.

Código: [Seleccionar]

;************************************************** www.ingeniopic.com ***************************************************
; PROGRAMA : teclado_LCD_v1.asm
; Funcion : pruevas con teclado y lcd
;           
;   
;  Revision : 1.0        9/9/2011            Programa para : PIC18F2550
; CPU Clock : 48 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF           
;************************************************* www.ingeniopic.com **************************************************
;
;NOTA: se han activado las resistencias pull-up de PORTB.debido a que se nproducia un error al leer el bit BUSY de la LCD.
;      ya que las salidas de la lcd se quedan en alta impedancia.y el pic no leia correctamente D7.

LIST P=18F2550 ; Se emplea el PIC 18F2550
RADIX HEX ; Sistema de numeraci¢n hexadecimal
INCLUDE  "P18F2550.INC"
CONFIG FOSC = HS       ;Osc por XTAL 20mhz
      CONFIG DEBUG = OFF
      CONFIG PWRT = OFF
      CONFIG BOR  = OFF
      CONFIG WDT = OFF
      CONFIG MCLRE = ON
      CONFIG PBADEN = OFF
      CONFIG LVP = OFF
      CONFIG CP0 = OFF
      CONFIG CP1 = OFF
      CONFIG CP2 = OFF
      CONFIG CP3 = OFF
      CONFIG CPB = OFF
      CONFIG CPD = OFF
ERRORLEVEL -302

;ZONA DE ETIQUETAS
CBLOCK 0X20

AUX0
AUX1
AUX2
TEMPLCD
PDel0
PDel1
TEMP_RS
            FLAGS
ROTA_KEYB
ENDC


PULSO MACRO ;PULSO EN TERMINAL E DE LA LCD
bsf         PORTA,2
            call        RETARDO
            bcf         PORTA,2
ENDM



#define COMANDOS    bcf PORTA,0 ;Desactiva RS (modo comando)
    #define DATOS    bsf PORTA,0 ;Activa RS (modo datos)
#define E EQU 2
#define     RS EQU 0
#define READ bsf PORTA,1
#define WRITE bcf PORTA,1
#define ENABLE bsf PORTA,2 ;habilita LCD
#define DISABLE bcf PORTA,2 ;deshabilita LCD
#define GIE_ON bsf INTCON,GIE
#define GIE_OFF bcf INTCON,GIE

;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
          ORG    0x00      ;Inicio en el Vector de Reset
  goto   INICIO      ;ir a la primera instruccion del programa
;<<<<<<---------------------- VECTOR DE INTERRUPCIONES ALTA PRIORIDAD ---------------->>>>>>>>>>
ORG 0X08
goto INTERRUPCIONES
;<<<<<<---------------------- VECTOR DE INTERRUPCIONES BAJA PRIORIDAD ---------------->>>>>>>>>>
ORG 0X18
goto INTERRUPCIONES


ORG 0X001C
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO   
movlw b'00001000' ;permiso de la interrupción por cambio de estado del PORTB
movwf INTCON
clrf UCON,1
clrf FLAGS ;borra registro de banderas
movlw b'01110000' ;activa resistencias pull-up (evitar fallo lectura BUSY LCD)
movwf INTCON2

clrf PIE1,1      ; deshabilita interrupciones perifericas
movlw 0x01
movwf ROTA_KEYB




;***********************************************PRINCIPIO DEL PROGRAMA********************************************************************
 
PRINCIPAL CALL LCD
REP CALL REFR_KEYB
GOTO REP ;fin del programa.


;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<INICIALIZA LCD>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
         
LCD         GIE_OFF;clrf   INTCON ;deshabilita las interrupciones
          ;clrf   PORTA ;borra lacht del PORTA
;MOVLW 0XFF
;MOVWF PORTA
;MOVLW 0XFF
CLRF LATA
          movlw   0x0F
          movwf   ADCON1
movlw 0x07
movwf CMCON
          clrf    TRISA          ; Puerta A como salidas digitales
;MOVLW 0XFF
;MOVWF PORTA
;CLRF PORTB
;movlw 0x0f
;movwf TRISB
CLRF LATB
;CLRF TRISB
movlw 0x0f
movwf TRISB
clrf UCON,1


call LCDINI ;inicializa la LCD
call PRUEVAS ;salta a mensage de bienvenida
    return

;************************************************************ PRUEVAS ******************************************************   
         
PRUEVAS NOP
DATOS ;activa envio de datos LCD

MOVLW 'C' ;texto de la primera fila
CALL BYTE
MOVLW 'l'
CALL BYTE
MOVLW 'a'
CALL BYTE
MOVLW 'v'
CALL BYTE
MOVLW 'e'
CALL BYTE
MOVLW ' '
CALL BYTE
MOVLW 'D'
CALL BYTE
MOVLW 'e'
CALL BYTE
MOVLW ' '
CALL BYTE
MOVLW 'A'
CALL BYTE
MOVLW 'c'
CALL BYTE
MOVLW 'c'
CALL BYTE
MOVLW 'e'
CALL BYTE
MOVLW 's'
CALL BYTE
MOVLW 'o'
CALL BYTE


COMANDOS ;activa envio de comandos LCD


MOVLW B'00001111' ;display on,cursor on,parpadeo on.
CALL BYTE
MOVLW 0XC0     ;principio de la segunda linea
CALL BYTE
DATOS ;activa envio de datos LCD

return

REFR_KEYB movlw 0Xf0 ;nible bajo de POTB como salida
movwf TRISB
movf PORTB,W ;leer PORTB para borrar RBIF por una condición de unión mal hecha
bcf INTCON,RBIF ;se evita que salte la interrupcion al ejecutar el programa
rlncf ROTA_KEYB,F ;rota hacia la izquierda
btfsc ROTA_KEYB,4 ;comprueva si el bit se ha salido del nible bajo.
swapf ROTA_KEYB,F ;si es asi,invierte los nibles
movf ROTA_KEYB,W ;guarda el valor del registro de rotacion en W
andlw 0X0F ;tener en cuenta solo el nible bajo
movwf PORTB ;sacalo por PORTB
GIE_ON ;habilita interrupciones generales
return ;retorna

;************************************************** INICIALIZACION LCD *************************************************************
LCDINI    COMANDOS ;selecciona el modo comando para la LCD
movlw 0X02 ;HOME. posicion 0 de la DD RAM.
          call    BYTE
          movlw  0X28 ;FUNCTION SET. bus 4bit,LCD 2 linea.
          call    BYTE
          movlw   0X0C ;DISPLAY ON/OFF. display on.
          call    BYTE
          movlw   0X06 ;ENTRY MODE.incremento del cursor
          call    BYTE
          movlw   0X01  ;CLEAR DISPLAY. borra display y activa incremento del cursor
          call    BYTE
          return




;********************************************** ENVIO DE NIBLES  A LA LCD ******************************************************

BYTE        movwf   TEMPLCD ;guarda el contenido de W en registro temporal TEMPLCD
call LCD_BUSY ;comprueva si el LCD esta libre
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            movf    TEMPLCD,W ;carga el contenido de TEMPLCD en W
            andlw   0xf0 ;seleccionar el nible alto de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            swapf   TEMPLCD,W ;inbierte los nibles del registro TEMPLCD
            andlw   0xf0 ;seleccionar el alto bajo de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
return ;retorna


LCD_BUSY    call RETARDO ;retardo para evitar que la lectura del flag BUSY se quede bloqueado.
movf PORTA,W ;carga en W el contenido de PORTA
andlw 0x01 ;guarda el valor del estado del bit RS
movwf TEMP_RS ;salva el valor de RS en el registro temporal
COMANDOS ;selecciona el modo comandos
movlw    H'FF' ;
          movwf    TRISB        ;PORT B como entrada
;MOVWF LATB
READ          ;Pone el LCD en Modo RD "lectura"
ENABLE          ;Activa el LCD (lectura del nible alto)
L_BUSY      btfsc    PORTB,7      ;Chequea bit de Busy
          goto    L_BUSY ;espera a que la LCD este libre
      DISABLE        ;Desactiva LCD
ENABLE ;Activa el LCD (lectura del nible bajo)
call RETARDO ;retardo de 1ms
DISABLE ;Desactiva LCD

movlw 0X0F ;nible bajo como entradas
movwf TRISB
bsf INTCON2,RBPU ;deshabilita resistencias pull-up de PORTB
;MOVWF LATB
;clrf    PORTB        ;Puerta B salida
          WRITE          ;Pone LCD en modo WR
movf TEMP_RS,W ;restaura el valor de SR
iorwf PORTA,f ;activa en PORTA el bit RS
          return ;retorna


;************************************************ RETARDO DE VELOCIDAD DE DESPLAZAMIENTO **********************************************************
;pausa1 clrf AUX2
pausae3 clrf AUX1
pausae2 clrf AUX0
pausae incf AUX0,f
btfss AUX0,7 ;valor de temporizacion
goto pausae
incf AUX1,f
btfss AUX1,7 ;valor de temporizacion
goto pausae2
incf AUX2,f
btfss AUX2,1 ;velor de temporizacion
goto pausae3
return
;************************************************ RETARDO 1mS **********************************************************

RETARDO  movlw     .67       ; 1 set numero de repeticion  (B)
        movwf     PDel0     ; 1 |
PLoop1  movlw     .35       ; 1 set numero de repeticion  (A)
        movwf     PDel1     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        clrwdt              ; 1 ciclo delay
        decfsz    PDel1, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto   PDelL2         ; 2 ciclos delay
PDelL2  return              ; 2+2 Fin.


INTERRUPCIONES

btfsc INTCON,RBIF
call TECLADO
retfie

TECLADO movf PORTB,W ;leer PORTB para borrar RBIF por una condición de unión mal hecha
bcf INTCON,RBIF ;borra flag de interrupcion por cambio de estado de PORTB

;comparacion de entradas por PORTB desde el teclado
movlw 0x14
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_1
movlw 0x24
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_2
movlw 0x44
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_3
movlw 0x81
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_A
movlw 0x12
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_4
movlw 0x22
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_5
movlw 0x42
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_6
movlw 0x82
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_B
movlw 0x11
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_7
movlw 0x21
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_8
movlw 0x41
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_9
movlw 0x84
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_C
movlw 0x18
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_F
movlw 0x28
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_0
movlw 0x48
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_E
movlw 0x88
xorwf PORTB,W
btfsc STATUS,Z
goto TECLA_D



retfie


TECLA_1 btfsc PORTB,4 ;comprueva si la tecla esta pulsada
goto $-2 ;si esta pulsada,espera
movlw '1' ;dato a enviar por la LCD
call BYTE ;envia dato
return
TECLA_2 btfsc PORTB,5
goto $-2
movlw '2'
call BYTE
return
TECLA_3 btfsc PORTB,6
goto $-2
movlw '3'
call BYTE
return
TECLA_A btfsc PORTB,7
goto $-2
movlw 'A'
call BYTE
return
TECLA_4 btfsc PORTB,4
goto $-2
movlw '4'
call BYTE
return
TECLA_5 btfsc PORTB,5
goto $-2
movlw '5'
call BYTE
return
TECLA_6 btfsc PORTB,6
goto $-2
movlw '6'
call BYTE
return
TECLA_B btfsc PORTB,7
goto $-2
movlw 'B'
call BYTE
return
TECLA_7 btfsc PORTB,4
goto $-2
movlw '7'
call BYTE
return
TECLA_8 btfsc PORTB,5
goto $-2
movlw '8'
call BYTE
return
TECLA_9 btfsc PORTB,6
goto $-2
movlw '9'
call BYTE
return
TECLA_C btfsc PORTB,7
goto $-2
movlw 'C'
call BYTE
return
TECLA_F btfsc PORTB,4
goto $-2
movlw 'F'
call BYTE
return
TECLA_0 btfsc PORTB,5
goto $-2
movlw '0'
call BYTE
return
TECLA_E btfsc PORTB,6
goto $-2
movlw 'E'
call BYTE
return
TECLA_D btfsc PORTB,7
goto $-2
movlw 'D'
call BYTE
return

end

Título: Re: pequeños proyectos
Publicado por: groundman en 23 de Septiembre de 2011, 17:02:30
hola de nuevo.el programa que expongo al igual que alguno de los anteriores.tambien pongo el ejemplo de visualizar el texto del quijote en una LCD de 16
caracteres por 2 lineas.
en este caso estoy usando el PIC18F2550.y en vez de usar el direccionamiento indirecto para leer las tablas de caracteres,uso las instrucciones
especiales que tiene este pic para la lectura de tablas.
solo hay que indicarle en los registros TBLPTRL y TBLPTRH el principio de la direccion eeprom de donde esta la tabla hubicada.
y en TBLPTRL_TOP y TBLPTRH_TOP,la direccion eeprom del ultimo caracter a leer de la tabla.

si modificamos adecuadamente el programa.tambien podriamos enviar trozos de texto en vez de una frase tan larga.

tambien pondre el asm y la simulacion en proteus para provarlo.

Código: [Seleccionar]
;************************************************** www.ingeniopic.com ***************************************************
; PROGRAMA : mensage_18F_tblptr_4bit
; Funcion : visualizacion de un mensage en una LCD de 16caracteres 2 lineas.en el modo a 4bit.sin el sistema de direccionamiento indirecto
;           
;   
;  Revision : 1.0        22/9/2011            Programa para : PIC18F2550
; CPU Clock : 48 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : XT
; Code Prot : OFF           
;************************************************* www.ingeniopic.com **************************************************
;


LIST P=18F2550 ; Se emplea el PIC 18F2550
RADIX HEX ; Sistema de numeraci¢n hexadecimal
INCLUDE  "P18F2550.INC"
CONFIG FOSC = HS       ;Osc por XTAL 20mhz
      CONFIG DEBUG = OFF
      CONFIG PWRT = OFF
      CONFIG BOR  = OFF
      CONFIG WDT = OFF
      CONFIG MCLRE = ON
      CONFIG PBADEN = OFF
      CONFIG LVP = OFF
      CONFIG CP0 = OFF
      CONFIG CP1 = OFF
      CONFIG CP2 = OFF
      CONFIG CP3 = OFF
      CONFIG CPB = OFF
      CONFIG CPD = OFF
ERRORLEVEL -302

;ZONA DE ETIQUETAS
CBLOCK 0X20

AUX0
AUX1
AUX2
TEMPLCD
PDel0
PDel1
TEMP_RS
            FLAGS
DIR_EEPROM
TBLPTRL_TOP
TBLPTRH_TOP
CONT_CARACTER
RESUL

ENDC


PULSO MACRO ;PULSO EN TERMINAL E DE LA LCD
bsf         PORTA,2
            call        RETARDO
            bcf         PORTA,2
ENDM


#define COMANDOS    bcf PORTA,0 ;Desactiva RS (modo comando)
    #define DATOS    bsf PORTA,0 ;Activa RS (modo datos)
#define E EQU 2
#define     RS EQU 0
#define READ bsf PORTA,1
#define WRITE bcf PORTA,1
#define ENABLE bsf PORTA,2 ;habilita LCD
#define DISABLE bcf PORTA,2 ;deshabilita LCD


;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
          ORG    0x00      ;Inicio en el Vector de Reset
  goto   INICIO      ;ir a la primera instruccion del programa
;<<<<<<---------------------- VECTOR DE INTERRUPCIONES ALTA PRIORIDAD ---------------->>>>>>>>>>
;ORG 0X08
;goto INTERRUPCIONES
;<<<<<<---------------------- VECTOR DE INTERRUPCIONES BAJA PRIORIDAD ---------------->>>>>>>>>>
;ORG 0X18
;goto INTERRUPCIONES


ORG 0X001C
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO   
movlw b'00001000' ;permiso de la interrupción por cambio de estado del PORTB
movwf INTCON
clrf UCON,1
clrf FLAGS ;borra registro de banderas
movlw b'01110000' ;activa resistencias pull-up (evitar fallo lectura BUSY LCD)
movwf INTCON2

clrf PIE1,1      ; deshabilita interrupciones perifericas






;***********************************************PRINCIPIO DEL PROGRAMA********************************************************************
 
PRINCIPAL
CALL LCD




;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<INICIALIZA LCD>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
         
LCD         clrf LATA
          movlw   0x0F
          movwf   ADCON1
movlw 0x07
movwf CMCON
          clrf    TRISA          ; Puerta A como salidas digitales
bsf PORTA,3
clrf LATB
          movlw 0x07

          clrf    TRISB   

movlw 0x0f
movwf TRISB
clrf UCON,1
movlw b'10001000'
movwf T0CON
clrf TMR0L
clrf TMR0H
movlw 0XFF
movwf DIR_EEPROM ;carga la direccion


call LCDINI ;inicializa la LCD
call PRUEVAS ;salta a mensage de bienvenida
    return

;************************************************************ PRUEVAS ******************************************************   
         
PRUEVAS call BIENVENIDA
goto PRUEVAS

;************************************************** INICIALIZACION LCD *************************************************************
LCDINI    COMANDOS ;selecciona el modo comando para la LCD
movlw 0X02 ;HOME. posicion 0 de la DD RAM.
          call    BYTE
          movlw  0X28 ;FUNCTION SET. bus 4bit,LCD 2 linea.
          call    BYTE
          movlw   0X0C ;DISPLAY ON/OFF. display on.
          call    BYTE
          movlw   0X06 ;ENTRY MODE.incremento del cursor
          call    BYTE
          movlw   0X01  ;CLEAR DISPLAY. borra display y activa incremento del cursor
          call    BYTE
          return

;********************************************** ENVIO DE NIBLES  A LA LCD ******************************************************

BYTE        movwf   TEMPLCD ;guarda el contenido de W en registro temporal TEMPLCD
call LCD_BUSY ;comprueva si el LCD esta libre
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            movf    TEMPLCD,W ;carga el contenido de TEMPLCD en W
            andlw   0xf0 ;seleccionar el nible alto de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
            movlw   0x0f ;pon a 0 el nible alto de W
            andwf   PORTB,F ;borra el nible alto de portb sin tocar el nible bajo.
            swapf   TEMPLCD,W ;inbierte los nibles del registro TEMPLCD
            andlw   0xf0 ;seleccionar el alto bajo de W
            iorwf   PORTB,F ;manda nible alto de W a PORTB.
PULSO ;pulso de 1ms en terminal E de la LCD
return ;retorna


LCD_BUSY    call RETARDO ;retardo para evitar que la lectura del flag BUSY se quede bloqueado.
movf PORTA,W ;carga en W el contenido de PORTA
andlw 0x01 ;guarda el valor del estado del bit RS
movwf TEMP_RS ;salva el valor de RS en el registro temporal
COMANDOS ;selecciona el modo comandos
movlw    H'FF' ;
          movwf    TRISB        ;PORT B como entrada

READ          ;Pone el LCD en Modo RD "lectura"
ENABLE          ;Activa el LCD (lectura del nible alto)
L_BUSY      btfsc    PORTB,7      ;Chequea bit de Busy
          goto    L_BUSY ;espera a que la LCD este libre
      DISABLE        ;Desactiva LCD
ENABLE ;Activa el LCD (lectura del nible bajo)
call RETARDO ;retardo de 1ms
DISABLE ;Desactiva LCD

movlw 0X0F ;nible bajo como entradas
movwf TRISB
bsf INTCON2,RBPU ;deshabilita resistencias pull-up de PORTB
WRITE          ;Pone LCD en modo WR
movf TEMP_RS,W ;restaura el valor de SR
iorwf PORTA,f ;activa en PORTA el bit RS
          return ;retorna


;************************************************ RETARDO DE VELOCIDAD DE DESPLAZAMIENTO **********************************************************
pausa1 clrf AUX2
pausae3 clrf AUX1
pausae2 clrf AUX0
pausae incf AUX0,f
btfss AUX0,7 ;valor de temporizacion
goto pausae
incf AUX1,f
btfss AUX1,7 ;valor de temporizacion
goto pausae2
incf AUX2,f
btfss AUX2,3 ;velor de temporizacion
goto pausae3
return




;************************************************ RETARDO 1mS **********************************************************

RETARDO  movlw     .5;.67       ; 1 set numero de repeticion  (B)
        movwf     PDel0      ; 1 |
PLoop1  movlw     .5;.35       ; 1 set numero de repeticion  (A)
        movwf     PDel1      ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        clrwdt              ; 1 ciclo delay
        decfsz    PDel1, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto   PDelL2         ; 2 ciclos delay
PDelL2  return              ; 2+2 Fin.


;************************************************************MENSAGE DE BIENVENIDA******************************************************   
         
BIENVENIDA clrf CONT_CARACTER ;incrementa registro contador de caracteres
clrf    RESUL ;borra registro RESUL
movlw 0x00
movwf TBLPTRL ;direccion baja de principio de frase
movlw 0x02
movwf TBLPTRH ;direccion alta de principio de frase

movlw 0xfe
movwf TBLPTRL_TOP ;byte bajo de caracteres a enviar
movlw 0x7f
movwf TBLPTRH_TOP ;byte alto de caracteres a enviar

retorn      DATOS ;selecciona modo de envio de datos
call TABLA ;salta a tabla de caraceres
btfsc FLAGS,0 ;comprueva si se ha llegado al ultimo caracter a leer
return ;si ha llegado.fin del programa
incf RESUL,F ;incrementa resul
movf TABLAT,W ;mete valor leido del byte bajo de tabla en W
call    BYTE ;introduce caracter contenido en W a la ddram de la LCD.
movlw d'40' ;numero de caracteres de la ddram(primera fila)
subwf RESUL,W ;resta el valor contenido en W al registro RESUL.
btfss STATUS,C ;comprueva si se llego a meter los 40 caracteres en la ddram de la LCD
goto retorn ;si no ha llegado salta a retorn en caso contrario continua

REP COMANDOS ;selecciona modo de envio de comandos
movlw b'00011100' ;comando de rotacion a izquierdas
call BYTE ;envia comando
call pausa1 ;pausa de rotacion de la LCD
incf CONT_CARACTER,F ;incrementa el contador de caracteres
movlw .24 ;carga valor de desplazamientos hacia la izquierda para mostrar el mensage completo del a ddram.40-16=24 =>  40 bytes - 16 caracteres visibles = 24 caracteres no visibles
xorwf CONT_CARACTER,w ;comprueva si se llego al valor anterior
btfss STATUS,Z ;si no ha llegado,sigue rotando
goto REP
movlw .32 ;numero de bytes visibles de la LCD (LCD 16x2)
subwf TBLPTRL,F ;desplaza el indice para grabar los 16 ultimos caracteres del primer mensage de la ddr,en los 16 primeros caracteres del siguiente mensage
btfss STATUS,C ;comprueva si al restar ha habido acarreo
decf TBLPTRH,f ;si lo ha habido decrementa TBLPTRH (inprescindible para detectar fin de frase)
clrf CONT_CARACTER ;borra contador de caracteres
clrf    RESUL ;borra RESUL

COMANDOS ;selecciona el modo comando para la LCD
movlw 0X01 ;HOME. posicion 0 de la DD RAM.
          call    BYTE ;envia comando
goto retorn ;siguiente mensage

TABLA tblrd+* ;incrementa puntero de tabla antes de su lectura
tblrd+* ;incrementa puntero de tabla antes de su lectura
movf TBLPTRL,W ;carga en W el contenido de TBLPTRL
xorwf TBLPTRL_TOP,w ;compara el valor con el valor tope del byte bajo
btfss STATUS,Z ;si es diferente
return ;retorna
movf TBLPTRH,W ;carga en W el contenido de TBLPTRH
xorwf TBLPTRH_TOP,w ;compara el valor con el valor tope del byte alto
btfss STATUS,Z ;si es diferente
return ;retorna
bsf FLAGS,0 ;activa bit de fin de mensage
return ;retorna

org 0x200

dt   "                En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga antigua,"
dt " rocín flaco y galgo corredor. Una olla de algo más vaca que carnero, salpicón las más noches, duelos y quebrantos los sábados, lentejas los viernes, algún palomin"
dt   "o de añadidura los domingos, consumían las tres partes de su hacienda. El resto della concluían sayo de velarte, calzas de velludo para las fiestas con sus pantufl"
dt "os de lo mismo, los días de entre semana se honraba con su vellori de lo más fino. Tenía en su casa una ama que pasaba de los cuarenta, y una sobrina que no llegab"
dt   "a a los veinte, y un mozo de campo y plaza, que así ensillaba el rocín como tomaba la podadera. Frisaba la edad de nuestro hidalgo con los cincuenta años, era de c"
dt "omplexión recia, seco de carnes, enjuto de rostro; gran madrugador y amigo de la caza. Quieren decir que tenía el sobrenombre de Quijada o Quesada (que en esto hay"
dt " alguna diferencia en los autores que deste caso escriben), aunque por conjeturas verosímiles se deja entender que se llama Quijana; pero esto importa poco a nuest"
dt "ro cuento; basta que en la narración dél no se salga un punto de la verdad. Es, pues, de saber, que este sobredicho hidalgo, los ratos que estaba ocioso (que eran "
dt "los más del año) se daba a leer libros de caballerías con tanta afición y gusto, que olvidó casi de todo punto el ejercicio de la caza, y aun la administración de "
dt "su hacienda; y llegó a tanto su curiosidad y desatino en esto, que vendió muchas hanegas de tierra de sembradura, para comprar libros de caballerías en que leer; y"
dt " así llevó a su casa todos cuantos pudo haber dellos; y de todos ningunos le parecían tan bien como los que compuso el famoso Feliciano de Silva: porque la clarida"
dt "d de su prosa, y aquellas intrincadas razones suyas, le parecían de perlas; y más cuando llegaba a leer aquellos requiebros y cartas de desafío, donde en muchas pa"
dt "rtes hallaba escrito: la razón de la sinrazón que a mi razón se hace, de tal manera mi razón enflaquece, que con razón me quejo de la vuestra fermosura, y también "
dt "cuando leía: los altos cielos que de vuestra divinidad divinamente con las estrellas se fortifican, y os hacen merecedora del merecimiento que merecela vuestra gra"
    dt   "deza. Con estas y semejantes razones perdía el pobre caballero el juicio, y desvelábase por entenderlas, y desentrañarles el sentido, que no se lo sacara, ni las e"
dt " entendiera el mismo Aristóteles, si resucitara para sólo ello. No estaba muy bien con las heridas que don Belianis daba y recibía, porque se imaginaba quepor gran"
dt   "des maestros que le hubiesen curado, no dejaría de tener el rostro y todo el cuerpo lleno de cicatrices y señales; pero con todo alababa en su autor aquel acabar s"
dt "u libro con la promesa de aquella inacabable aventura, y muchas veces le vino deseo de tomar la pluma, y darle fin al pie de la letra como allí se promete; y sin d"
dt   "uda alguna lo hiciera, y aun saliera con ello, si otros mayores y continuos pensamientos no se lo estorbaran. Tuvo muchas veces competencia con el cura de su lugar"
dt " (que era hombre docto graduado en Sigüenza), sobre cuál había sido mejor caballero, Palmerín de Inglaterra o Amadís de Gaula; mas maese Nicolás, barbero del mismo"
dt " pueblo, decía que ninguno llegaba al caballero del Febo, y que si alguno se le podía comparar, era don Galaor, hermano de Amadís de Gaula, porque tenía muy acomod"
dt "ada condición para todo; que no era caballero melindroso, ni tan llorón como su hermano, y que en lo de la valentía no le iba en zaga. En resolución, él se enenfra"
dt "scó tanto en su lectura, que se le pasaban las noches leyendo de claro en claro, y los días de turbio en turbio, y así, del poco dormir y del mucho leer, se le sec"
dt "ó el cerebro, de manera que vino a perder el juicio. Llenósele la fantasía de todo aquello que leía en los libros, así de encantamientos, como de pendencias, batal"
dt "las, desafíos, heridas, requiebros, amores, tormentas y disparates imposibles, y asentósele de tal modo en la imaginación que era verdad toda aquella máquina de aq"
dt "uellas soñadas invenciones que leía, que para él no había otra historia más cierta en el mundo. Decía él, que el Cid Ruy Díaz había sido muy buen caballero; pero q"
dt "ue ver con el caballero de la ardiente espada, que de sólo un revés había partido por medio dos fieros y descomunales gigantes. Mejor estaba con Bernardo del Carpi"
dt "Carpio, porque en Roncesvalle había muerto a Roldán el encantado, valiéndose de la industria de Hércules, cuando ahogó a Anteo, el hijo de la Tierra, entre los bra"
dt "brazos. Decía mucho bien del gigante Morgante, porque con ser de aquella generación gigantesca, que todos son soberbios y descomedidos, él solo era afable y bien c"
dt "riado; pero sobre todos estaba bien con Reinaldos de Montalbán, y más cuando le veía salir de su castillo y robar cuantos topaba, y cuando en Allende robó aquel íd"
dt "olo de Mahoma, que era todo de oro, según dice su historia. Diera él, por dar una mano de coces al traidor de Galalón, al ama que tenía y aun a su sobrina de añadi"
dt   "dura. En efecto, rematado ya su juicio, vino a dar en el más extraño pensamiento que jamás dio loco en el mundo, y fue que le pareció convenible y necesario, así p"
dt "ara el aumento de su honra, como para el servicio de su república, hacerse caballero andante, e irse por todo el mundo con sus armas y caballo a buscar las aventur"
dt "as, y a ejercitarse en todo aquello que él había leído, que los caballeros andantes se ejercitaban, deshaciendo todo género de agravio, y poniéndose en ocasiones y"
dt " peligros, donde acabándolos, cobrase eterno nombre y fama. Imaginábase el pobre ya coronado por el valor de su brazo por lo menos del imperio de Trapisonda: y así"
dt " con estos tan agradables pensamientos, llevado del estraño gusto que en ellos sentía, se dió priesa a poner en efecto lo que deseaba. Y lo primero que hizo, fue l"
dt "impiar unas arma"

org 0x2ff8

dt "s, que habían sido de sus bisabuelos, que, tomadas de orín y llenas de moho, luengos siglos había que estaban puestas y olvidadas en un rincón. Lim"
dt "piólas y aderezólas lo mejor que pudo; pero vió que tenían una gran falta, y era que no tenía celada de encajencaje, sino morrión simple; mas a esto suplió su indu"
dt "stria, porque de cartones hizo un modo de media celada, que encajada con el morrión, hacía una apariencia de celada entera. Es verdad que para probar si era fuerte"
dt ", y podía estar al riesgo de una cuchillada, sacó su espada, y le dió dos golpes, y con el primero y en un punto deshizo lo que había hecho en una semana: y no dej"
dt "ó de parecerle mal la facilidad con que la había hecho pedazos, y por asegurarse de este peligro, lo tornó a hacer de nuevo, poniéndole unas barras de hierro por d"
dt "e dentro de tal manera, que él quedó satisfecho de su fortaleza; y, sin querer hacer nueva experiencia de ella, la diputó y tuvo por celada finísima de encaje. Fue"
dt " luego a ver a su rocín, y aunque tenía más cuartos que un real, y más tachas que el caballo de Gonela, que tantum pellis, et ossa fuit, le pareció que ni el Bucéf"
dt "alo de Alejandro, ni Babieca el del Cid con él se igualaban. Cuatro días se le pasaron en imaginar qué nombre le podría: porque, según se decía él a sí mismo, no e"
dt "ra razón que caballo de caballero tan famoso, y tan bueno él por sí, estuviese sin nombre conocido; y así procuraba acomodársele, de manera que declarase quien hab"
dt "ía sido, antes que fuese de caballero andante, y lo que era entones: pues estaba muy puesto en razón, que mudando su señor estado, mudase él también el nombre; y l"
dt "e cobrase famoso y de estruendo, como convenía a la nueva orden y al nuevo ejercicio que ya profesaba: y así después de muchos nombres que formó, borró y quitó, añ"
dt "adió, deshizo y tornó a hacer en su memoria e imaginación, al fin le vino a llamar Rocinante, nombre a su parecer alto, sonoro y significativo de lo que había sido"
dt " cuando fue rocín, antes de lo que ahora era, que era antes y primero de todos los rocines del mundo. Puesto nombre y tan a su gusto a su caballo, quiso ponérsele "
dt "a sí mismo, y en este pensamiento, duró otros ocho días, y al cabo se vino a llamar don Quijote, de donde como queda dicho, tomaron ocasión los autores de esta tan"
dt " verdadera historia, que sin duda se debía llamar Quijada, y no Quesada como otros quisieron decir. Pero acordándose que el valeroso Amadís, no sólo se había conte"
dt "ntado con llamarse Amadís a secas, sino que añadió el nombre de su reino y patria, por hacerla famosa, y se llamó Amadís de Gaula, así quiso, como buen caballero, "
dt "añadir al suyo el nombre de la suya, y llamarse don Quijote de la Mancha, con que a su parecer declaraba muy al vivo su linaje y patria, y la honraba con tomar el "
dt "sobrenombre della. Limpias, pues, sus armas, hecho del morrión celada, puesto nombre a su rocín, y confirmándose a sí mismo, se dió a entender que no le faltaba ot"
dt "ra cosa, sino buscar una dama de quien enamorarse, porque el caballero andante sin amores, era árbol sin hojas y sin fruto, y cuerpo sin alma. Decíase él: si yo po"
dt "r malos de mis pecados, por por mi buena suerte, me encuentro por ahí con algún gigante, como de ordinario les acontece a los caballeros andantes, y le derribo de "
dt "un encuentro, o le parto por mitad del cuerpo, o finalmente, le venzo y le rindo, ¿no será bien tener a quién enviarle presentado, y que entre y se hinque de rodil"
dt "las ante mi dulce señora, y diga con voz humilde y rendida: yo señora, soy el gigante Caraculiambro, señor de la ínsula Malindrania, a quien venció en singular bat"
dt "alla el jamás como se debe alabado caballero D. Quijote de la Mancha, el cual me mandó que me presentase ante la vuestra merced, para que la vuestra grandeza dispo"
dt "nga de mí a su talante? ¡Oh, cómo se holgó nuestro buen caballero, cuando hubo hecho este discurso, y más cuando halló a quién dar nombre de su dama! Y fue, a lo q"
dt "ue se cree, que en un lugar cerca del suyo había una moza labradora de muy buen parecer, de quien él un tiempo anduvo enamorado, aunque según se entiende, ellajamá"
dt "s lo supo ni se dió cata de ello. Llamábase Aldonza Lorenzo, y a esta le pareció ser bien darle título de señora de sus pensamientos; y buscándole nombre que no de"
dt "sdijese mucho del suyo, y que tirase y se encaminase al de princesa y gran señora, vino a llamarla Dulcinea del Toboso, porque era natural del Toboso, nombre a su "
dt "parecer músico y peregrino y significativo, como todos los demás que a él y a sus cosas había puesto.Hechas, pues, estas prevenciones, no quiso aguardar más tiempo"
dt " a poner en efecto su pensamiento, apretándole a ello la falta que él pensaba que hacía en el mundo su tardanza, según eran los agravios que pensaba deshacer, tuer"
dt "tos que enderezar, sinrazones que enmendar, y abusos que mejorar, y deudas que satisfacer; y así, sin dar parte a persona alguna de su intención, y sin que nadie l"
dt "e viese, una mañana, antes del día (que era uno de los calurosos del mes de Julio), se armó de todas sus armas, subió sobre Rocinante, puesta su mal compuesta cela"
dt "da, embrazó su adarga, tomó su lanza, y por la puerta falsa de un corral, salió al campo con grandísimo contento y alborozo de ver con cuánta facilidad había dado "
dt "principio a su buen deseo. Mas apenas se vió en el campo, cuando le asaltó un pensamiento terrible, y tal, que por poco le hiciera dejar la comenzada empresa: y fu"
dt "e que le vino a la memoria que no era armado caballero, y que, conforme a la ley de caballería, ni podía ni debía tomar armas con ningún caballero; y puesto qeu lo"
dt " fuera, había de llevar armas blancas, como novel caballero, sin empresa en el escudo, hasta que por su esfuerzo la ganase.Estos pensamientos le hicieron titubear "
dt "en su propósito; mas pudiendo más su locura que otra razón alguna, propuso de hacerse armar caballero del primero que topase, a imitación de otros muchos que así l"
dt "o hicieron, según él había leído en los libros que tal le tenían. En lo de las armas blancas pensaba limpiarlas de manera, en teniendo lugar, que lo fuesen más que"
dt " un armiño: y con esto se quietó y prosiguió su camino, sin llevar otro que el que su caballo quería, creyendo que en aquello consistía la fuerza de las aventuras."
dt " Yendo, pues, caminando nuestro flamante aventurero, iba hablando consigo mismo, y diciendo: ¿Quién duda sino que en los venideros tiempos, ciando salga a luz la v"
dt "erdadera historia de mis famosos hechos, que el sabio que los escribiere, no ponga, cuando llegue a contar esta mi primera salida tan de mañana, de esta manera? Ap"
dt "enas había el rubicundo Apolo tendido por la faz de la ancha y espaciosa tierra las doradas hebras de sus hermosos cabellos, y apenas los pequeños y pintados pajar"
dt "illos con sus arpadas lenguas habían saludado con dulce y meliflua armonía la venida de la rosada aurora que dejando la blanda cama del celoso marido, por las puer"
dt "tas y balcones del manchego horizonte a los mortales se mostraba, cuando el famoso caballero D. Quijote de la Mancha, dejando las ociosas plumas, subió sobre su fa"
dt "moso caballo Rocinante, y comenzó a caminar por el antiguo y conocido campo de Montiel. (Y era la verdad que por él caminaba) y añadió diciendo: dichosa edad, y si"
dt "glodichoso aquel adonde saldrán a luz las famosas hazañas mías, dignas de entallarse en bronce, esculpirse en mármoles y esculpirse en mármoles y pintarse en tabla"
dt "s para memoria en lo futuro. ¡Oh tú, sabio encantador, quienquiera que seas, a quien ha de tocar el ser coronista de esta peregrina historia! Ruégote que no te olv"
dt "ides de mi buen Rocinante compañero eterno mío en todos mis caminos y carreras. Luego volvía diciendo, como si verdaderamente fuera enamorado: ¡Oh, princesa Dulcin"
dt "ea, señora de este cautivo corazón! Mucho agravio me habedes fecho en despedirme y reprocharme con el riguroso afincamiento de mandarme no parecer ante la vuestra "
dt "fermosura. Plégaos, señora, de membraros de este vuestro sujeto corazón, que tantas cuitas por vuestro amor padece. Con estos iba ensartando otros disparates, todo"
dt "s al modo de los que sus libros le habían enseñado, imitando en cuanto podía su lenguaje; y con esto caminaba tan despaico, y el sol entraba tan apriesa y con tant"
dt "o ardor, que fuera bastante a derretirle los sesos, si algunos tuviera. Casi todo aquel día caminó sin acontecerle cosa que de contar fuese, de lo cual se desesper"
dt "aba, poerque quisiera topar luego, con quien hacer experiencia del valor de su fuerte brazo.Autores hay que dicen que la primera aventura que le avino fue la de Pu"
dt "erto Lápice; otros dicen que la de los molinos de viento; pero lo que yo he podido averiguar en este caso, y lo que he hallado escrito en los anales de la Mancha, "
dt "es que él anduvo todo aquel día, y al anochecer, su rocín y él se hallaron cansados y muertos de hambre; y que mirando a todas partes, por ver si descubriría algún"
dt " castillo o alguna majada de pastores donde recogerse, y adonde pudiese remediar su mucha necesidad, vió no lejos del camino por donde iba una venta, que fucomo si"
dt " viera una estrella, que a los portales, si no a los alcázares de su redención, le encaminaba. Dióse priesa a caminar, y llegó a ella a tiempo que anochecía. Estab"
dt "an acaso a la puerta dos mujeres mozas, de estas que llaman del partido, las cuales iban a Sevilla con unos arrieros, que en la venta aquella noche acertaron a hac"
dt "er jornada; y como a nuestro aventurero todo cuanto pensaba, veía o imaginaba, le parecía ser hecho y pasar al modo de lo que había leído, luego que vió la venta s"
dt "e le representó que era un castillo con sus cuatro torres y chapiteles de luciente plata, sin faltarle su puente levadizo y honda cava, con todos aquellos adherent"
dt "es que semejantes castillos se pintan.Fuese llegando a la venta (que a él le parecía castillo), y a poco trecho de ella detuvo las riendas a Rocinante, esperando q"
dt "ue algún enano se pusiese entre las almenas a dar señal con alguna trompeta de que llegaba caballero al castillo; pero como vió que se tardaban, y que Rocinante se"
dt " daba priesa por llegar a la caballeriza, se llegó a la puerta de la venta, y vió a las dos distraídas mozas que allí estaban, que a él le parecieron dos hermosas "
dt "doncellas, o dos graciosas damas, que delante de la puerta del castillo se estaban solazando. En esto sucedió acaso que un porquero, que andaba recogiendo"


end

Título: Re: pequeños proyectos
Publicado por: groundman en 22 de Diciembre de 2013, 13:58:32
esta rutina es para generar el crc del polinomio 0x131 usado tambien para la generacion de crc del DS18B20.

para su funcionamiento solo hay que cargar la zona de memoria donde esta el primer byte de la trama a generar.en este caso(Scratchpad1)
y luego los bytes a gestionar.
posteriormente llamamos a la rutina GEN_CRC.



Código: [Seleccionar]
CBLOCK   0X22

Scratchpad1
Scratchpad2
Scratchpad3
Scratchpad4
Scratchpad5
Scratchpad6
Scratchpad7
Scratchpad8
Scratchpad9
CRC
CONT
CONT2
INDEX
TEMP_CRC
FLAGS_DS18B20
ZONA_MEM

ENDC


#define POLY 0X8C ;polinomio invertido 0x131
#define CRC_OK bsf FLAGS_DS18B20,0
#define CRC_NOK bcf FLAGS_DS18B20,0


PRINCIPAL call GEN_CRC
btfsc FLAGS_DS18B20,0 ;comprueba si la trama tiene un crc correcto
call siguente programa ;si el crc es correcto continua el programa
goto PRINCIPAL





movlw Scratchpad1
movwf ZONA_MEM
movlw 0x08 ;0x08 para leer el Scratchpad y 0x07 para leer la ROM "identidad"
call GEN_CRC

;**************************************************** GEN_CRC **************************************************************

GEN_CRC movwf CONT2 ;carga en CONT2 la cantidad de bytes a generar
CRC_NOK ;borra el flag de coincidencia de crc
movlb 0x00 ;seleccion de banco
movlw 0X00 ;valor de direccion del banco 0 de la flash
movwf FSR1H ;selecciona el banco 0 de la eeprom de programa.
movlw Scratchpad1 ;principio de la zona de datos donde se ubica la trama a convertir
movwf FSR1L ;introduce el valor en la direccion a leer
movff INDF1,TEMP_CRC ;lee el valor
clrf INDEX ;limpia variable INDEX

PROX movf INDF1,W ;carga valor de la trama
xorwf INDEX,W ;operacion xor de W con INDEX
      call CALC_CRC8 ;llamada a la rutina de calclo de CRC del byte leido
      movwf INDEX ;introduce el CRC generado en INDEX
      incf FSR1L,F ;siguiente direccion del byte a leer
      decfsz CONT2,F ;decrementa el contador de bytes analizados
      goto PROX ;siguente byte a leer
 
movf INDEX,W ;carga el crc calculado en W
xorwf Scratchpad9,W ;compara el crc recibido con el crc generado
btfsc STATUS,Z ;comprueba si son iguales
CRC_OK ;si son iguales activa flag
        return ;return
;*************************************************** CALC_CRC8 *************************************************************     
;Generacion del CRC

CALC_CRC8 movwf CRC ;carga en CRC el  byte a generar
      movlw .8 ;numero de bits a desplazar
      movwf CONT ;contador de bits
NEXT_CRC bcf STATUS,C ;limpia el carry
  rrcf CRC,F ;rota el registro hacia la derecha
  movlw POLY ;carga en w el polinomio 0x131 invertido
  btfsc STATUS,C ;comprueba el carry
  xorwf CRC,F ;si ha habido acarreo hacer xor entre el polinomio y el registro CRC
      decfsz CONT,F ;decrementa el contador de bits
      goto NEXT_CRC ;siguente bit
  movf CRC,W ;carga el CRC generado en el registro CRC
  return ;retorna
 

 


         
Título: Re: pequeños proyectos
Publicado por: groundman en 22 de Diciembre de 2013, 17:27:03
y aqui pongo el calculo del crc con el mismo polinomio anterior pero con el sistema con tabla.

sistema sin tabla= 38bytes 717uS
sistema con tabla=288bytes 188uS

Código: [Seleccionar]
;****************************************** GEN_CRC_TBL **************************************************
;Calculo del crc por el sistema de tabla

GEN_CRC_TBL movwf CONT2 ;carga en CONT2 la cantidad de bytes a generar
CRC_NOK ;borra el flag de coincidencia de crc
movlb 0x00 ;seleccion de banco
movlw 0X00 ;valor de direccion del banco 0 de la flash
movwf FSR1H ;selecciona el banco 0 de la eeprom de programa.
movlw Scratchpad1 ;principio de la zona de datos donde se ubica la trama a convertir
movwf FSR1L ;introduce el valor en la direccion a leer
movff INDF1,TEMP_CRC ;lee el valor
clrf INDEX ;limpia variable INDEX

PROX2 movf INDF1,W ;carga valor de la trama
xorwf INDEX,W ;operacion xor de W con INDEX
       call CRC8 ;llamada a la rutina de calclo de CRC del byte leido
       movwf INDEX ;introduce el CRC generado en INDEX
       incf FSR1L,F ;siguiente direccion del byte a leer
       decfsz CONT2,F ;decrementa el contador de bytes analizados
       goto PROX2 ;siguente byte a leer
  
movf INDEX,W ;carga el crc calculado en W
xorwf Scratchpad9,W ;compara el crc recibido con el crc generado
btfsc STATUS,Z ;comprueba si son iguales
CRC_OK ;si son iguales activa flag
       return ;return




;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CRC8 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

CRC8 movwf TBLPTRL ;
movlw 0X50
movwf TBLPTRH
                        bcf STATUS,C ;borra el carry
rlcf TBLPTRL,F ;multiplica por 2
bnc $+4 ;si ha habido acarreo,
incf TBLPTRH ;incrementa puntero alto de tabla

TABLA_CRC8 tblrd+* ;incrementa puntero de tabla despues de su lectura
tblrd+* ;incrementa puntero de tabla despues de su lectura
movf TABLAT,W
return


ORG 0X5002

dt .00, .94, .188, .226, .97, .63, .221, .131, .194, .156, .126, .32, .163, .253, .31, .65
dt .157, .195, .33, .127, .252, .162, .64, .30, .95, .1, .227, .189, .62, .96, .130, .220
dt .35, .125, .159, .193, .66, .28, .254, .160, .225, .191, .93, .3, .128, .222, .60, .98
  dt .190, .224, .2, .92, .223, .129, .99, .61, .124, .34, .192, .158, .29, .67, .161, .255
dt .70, .24, .250, .164, .39, .121, .155, .197, .132, .218, .56, .102, .229, .187, .89,.7
dt .219, .133, .103, .57, .186, .228, .6, .88, .25, .71, .165, .251, .120, .38, .196, .154
dt  .101, .59, .217, .135, .4, .90, .184, .230, .167, .249, .27, .69, .198, .152, .122, .36
   dt .248, .166, .68, .26, .153, .199, .37, .123, .58, .100, .134, .216, .91, .5, .231, .185
   dt .140, .210, .48, .110, .237, .179, .81, .15, .78, .16, .242, .172, .47, .113, .147, .205
   dt .17, .79, .173, .243, .112, .46, .204, .146, .211, .141, .111, .49, .178, .236, .14, .80
   dt .175, .241, .19, .77, .206, .144, .114, .44, .109, .51, .209, .143, .12, .82, .176, .238
   dt .50, .108, .142, .208, .83, .13, .239, .177, .240, .174, .76, .18, .145, .207, .45, .115
   dt .202, .148, .118, .40, .171, .245, .23, .73, .8, .86, .180, .234, .105, .55, .213, .139
   dt .87, .9, .235, .181, .54, .104, .138, .212, .149, .203, .41, .119, .244, .170, .72, .22
   dt .233, .183, .85, .11, .136, .214, .52, .106, .43, .117, .151, .201, .74, .20, .246, .168
   dt .116, .42, .200, .150, .21, .75, .169, .247, .182, .232, .10, .84, .215, .137, .107, .53

Título: Re: pequeños proyectos
Publicado por: tapi8 en 23 de Diciembre de 2013, 07:28:33
Mi mas sincera enhorabuena grounman  :-/ :-/ ((:-)) ((:-))

Y digo a los señores moderadores ¿No seria bueno ponerle chincheta a este hilo?. Hay programas muy interesantes que se pueden usar a modo de libreria y seria buen sitio para mandar a ususarios nuevos que vienen preguntando.
Título: Re: pequeños proyectos
Publicado por: groundman en 23 de Diciembre de 2013, 16:23:51
gracias tapi8.este hilo lo cree para acceder rapidamente a las rutinas que mas uso.y si que es verdad que tambien he dirigido a novatos al hilo.
seguire incorporando rutinas.siempre me acuerdo de este hilo.
Título: Re: pequeños proyectos
Publicado por: groundman en 12 de Enero de 2014, 15:50:03
rutina para el borrado de toda la ram de un 18F2550


Código: [Seleccionar]
;******************************************************** CLEAR_ALL **************************************************************
;borra toda la memoria

CLEAR_ALL movlw 0x0f ;valor limite de borrado FSR0H
lfsr FSR0,700h ;direcciona la ram
clr2 clrf INDF0 ;borra direccion direccionada
incfsz FSR0L ;siguiente direccion a borrar
goto clr2 ;salta a borrado de direccion
decf FSR0H,f ;decrementa direccionamiento alto
cpfseq FSR0H ;comprueba si se ha llegado al final del direccionamiento
goto clr2 ;si no ha llegado,continua borrando
return ;retorna si se a acabado el borrado

Título: Re: pequeños proyectos
Publicado por: groundman en 16 de Enero de 2014, 18:14:54
esta rutina hace lo mismo que la que puse anteriormente para el calculo del CRC para los DS18B20 por el sistema de la tabla.
solo que tenemos un define para indicar donde ubicaremos la tabla.asi facilitamos el uso como libreria.

esto es para un 18F2550


Código: [Seleccionar]
#define TABLA_CRCs 0x5000 ;direccion donde meter la tabla.




;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CRC8 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

CRC8 movwf TBLPTRL ;carga indexado de la tabla
movlw HIGH TABLA_CRCs ;direccion alta de tabla
movwf TBLPTRH ;cargalo en registro
clrf WREG ;dato 0x00
xorwf TBLPTRL,w ;comprueba si el dato indexado es igual a 0x00
btfsc STATUS,Z ;si es asi,
goto TABLA_CRC8 ;salta a tabla para leer el primer valor "0"
bcf STATUS,C ;borra el carry
rlcf TBLPTRL,F ;multiplica por 2
bnc TABLA_CRC8 ;salta a tabla si el valor indexado esta en los primeros 256bytes.en caso contrario,
incf TBLPTRH ,f ;incrementa puntero alto de tabla
goto TABLA_CRC8 ;y salta a tabla en resto de bytes.

TABLA_CRC8 tblrd*+ ;incrementa puntero de tabla antes de su lectura
movf TABLAT,W ;carga el valor leido de la tabla en W
return ;retorna


;la tabla tiene 256 valores.pero en este pic ocupa 512bytes.ya que cada direccion ocupa 2bytes.y solo uno de ellos es valido.
ORG TABLA_CRCs

dt .00, .94, .188, .226, .97, .63, .221, .131, .194, .156, .126, .32, .163, .253, .31, .65
dt .157, .195, .33, .127, .252, .162, .64, .30, .95, .1, .227, .189, .62, .96, .130, .220
dt .35, .125, .159, .193, .66, .28, .254, .160, .225, .191, .93, .3, .128, .222, .60, .98
  dt .190, .224, .2, .92, .223, .129, .99, .61, .124, .34, .192, .158, .29, .67, .161, .255
dt .70, .24, .250, .164, .39, .121, .155, .197, .132, .218, .56, .102, .229, .187, .89,.7
dt .219, .133, .103, .57, .186, .228, .6, .88, .25, .71, .165, .251, .120, .38, .196, .154
dt  .101, .59, .217, .135, .4, .90, .184, .230, .167, .249, .27, .69, .198, .152, .122, .36
  dt .248, .166, .68, .26, .153, .199, .37, .123, .58, .100, .134, .216, .91, .5, .231, .185
  dt .140, .210, .48, .110, .237, .179, .81, .15, .78, .16, .242, .172, .47, .113, .147, .205
  dt .17, .79, .173, .243, .112, .46, .204, .146, .211, .141, .111, .49, .178, .236, .14, .80
  dt .175, .241, .19, .77, .206, .144, .114, .44, .109, .51, .209, .143, .12, .82, .176, .238
  dt .50, .108, .142, .208, .83, .13, .239, .177, .240, .174, .76, .18, .145, .207, .45, .115
  dt .202, .148, .118, .40, .171, .245, .23, .73, .8, .86, .180, .234, .105, .55, .213, .139
  dt .87, .9, .235, .181, .54, .104, .138, .212, .149, .203, .41, .119, .244, .170, .72, .22
  dt .233, .183, .85, .11, .136, .214, .52, .106, .43, .117, .151, .201, .74, .20, .246, .168
  dt .116, .42, .200, .150, .21, .75, .169, .247, .182, .232, .10, .84, .215, .137, .107, .53


Título: Re: pequeños proyectos
Publicado por: groundman en 23 de Enero de 2014, 19:18:43
Hola.me he decicado a crear una libreria para el uso de un teclado resistivo.cuyo valor sera introducido en una entrada analogica del pic.
en este programa la entrada sera por el pin AN0.asi que con solo dos hilos podemos utilizar muchas teclas.

el teclado puede configurarse con un numero determinado de teclas.en el programa esta configurado para el uso de un teclado de 4x4.
que son 16 teclas.pero puede modificarse un valor para un mayor o menor numero de teclas.

tal y como se muestra en la imagen:

(http://imagizer.imageshack.us/v2/800x600q90/513/a6vm.png)

en modo reposo a la entrada AN0 se le aplica un valor positivo de tension 0xff.y cuando se pulsa una tecla el valor varia entre los valores
 0x00 y 0xff ambos no inclusive.

el programa esta preparado para pregrabar en la memoria eeprom las teclas que vallamos pulsando.las teclas adquiriran los valores o,1,2,3,4....
hasta la cantidad de teclas que definemos.por defecto son hasta 16 teclas.

si hemos definido 16 teclas.cuando terminemos de meter la numero 16.el programa saldra del modo de pregrabado.aunque si queremos menos teclas
tambien podemos finalizar el pregrabado pulsando la primera tecla que se pulso.


este programa tiene un metodo "anti rebote" que consiste en la comparacion de 10 valores analogicos capurados desde AN0.y escoger el
valor mas repetido.


Código: [Seleccionar]
;Este programa devuelbe en el registro TEMP_TECLA ,el indice de la tecla pregrabada.

;la peculariedad de que este programa sea tan grande,es que tiene un sistema de comprovacion de errores,que al pulsar
;una tecla.se almazenan en memoria 10 valores de esa tecla y se coje el valor mas repetido.de esa forma se evita el que al
;pulsar un boton resistivo,no cojamos el valor mas aproximado al real de ese boton.y que nos falle la identificacion de esa tecla.

;el programa tarda en ejecutarse

;La memorizacion de teclas esta limitada a 16 para mas teclas modificar: (#define N_BYTES .16)
;pero habra que tener en cuenta un byte en la posicion 17 para el valor de numeros de teclas memorizadas
;La memorizacion se realiza pulsando el numero de teclas definido.en el caso de que las teclas sean inferiores a las definidas
;solo haria falta pulsar la primera tecla que se presiono para la finalizacion del aprendizaje.

;la primera tecla sera asignada con el valor .0 la siguiente .1 .2 .3 - etc y asi hasta que finalizemos.

;Para el borrado de teclas y reaprendizage,poner a masa la entrada analogica.

CBLOCK BOTON_PULS_VAR
TEMP_ANALOG ;registro de tecla pulsada
COMPARADOR
TEMP_KEY
TEMP_KEY2
CONT_REG
CONT_COINC
CONT_ALMAC ;contador de las teclas almacenadas
PRIMR_TECL ;primera tecla plsada en el aprendizaje
FLAGS_KEY
N_KEYS       ;numero de teclas aprendidas
TEMP_TECLA
  ENDC


#define INI_RAM 0XF6 ;zona donde se ubicaran los datos analogicos de tecla pulsada
#define INI_TABLA 0XEC
#define KEY_OK bsf FLAGS_KEY,0
#define KEY_NOK bcf FLAGS_KEY,0
#define KEY_OK2 bsf FLAGS_KEY,1
#define FIND_OFF bsf FLAGS_KEY,2
#define FLASH_OK bsf FLAGS_KEY,3
#define N_BYTES .16 ;numero de teclas a gestionar y direccion de la eeprom donde se metera el dato del numero de bytes guardados


BOTON_PULS setf PRIMR_TECL
setf TEMP_KEY2
btfsc FLAGS_KEY,3 ;comprueba si ha habido pregrabacion en la eeprom de datos
goto SEARCH ;si la ha habido salta a busqueda de tecla pulsada
bt2 clrf DIR_EEPROM
call ALMAC ;salta a almacenamiento de aprendizage de teclas pulsadas en la eeprom

btfss FLAGS_KEY,2 ;comprueba si se termino con el aprendizage del teclado
goto bt3
call EEP_RAM ;si es asi,traspasa los bytes de la eeprom a la ram
return

bt3 setf TEMP_KEY2 ;en caso contrario setea el registro
goto bt2 ;y sigue el aprendizage




;********************************************************** KEYB ***********************************************************************
;adquisicion de valor de tecla pulsada

KEYB call TECLA ;lee valor de tecla pulsada
btfss FLAGS_KEY,0 ;comprueba si se ha pulsado una tecla
return ;si no es si,retorna
movff TEMP_KEY,TEMP_KEY2 ;guarda valor de tecla pulsada
kb1 call TECLA ;lee valor de tecla pulsada
btfsc FLAGS_KEY,0 ;comprueba si se ha soltado la tecla
goto kb1 ;si no es asi,vuelbe a leer valor de tecla pulsada
return ;retorna


;************************************************************ TECLA ********************************************************************
;Lectura de la entrada analogica y transferencia de 10 valores a la ram


TECLA setf TEMP_KEY
movlw INI_RAM
movwf FSR0L
movlw BANCO_GENERAL
movwf FSR0H

REPE call DAT_AN ;lee dato analogico
call BORRA_TECL ;opcion a borrado de teclado

setf WREG ;valor 0xff.tecla sin pulsar
cpfseq TEMP_ANALOG ;compara con el valor analogico de tecla
goto tec1
KEY_NOK
return ;si el valor analogico de la teclaes 0xff repite busqueda analogica(VALOR DE TECLA SIN PULSAR)
tec1 movff TEMP_ANALOG,INDF0
incf FSR0L,F ;incrementa FSR
clrf WREG
cpfseq FSR0L
goto REPE ;si no se ha llegado al tope de la ram repite


; aqui leemos la ram y buscamos el dato mas repetido
; en esta rutina se cogen los valores almacenados entre las direcciones seleccionadas y se coge valor que tenga mas numeros repetidos.

BUSCA_REP movlw BANCO_GENERAL ;banco donde trabajaremos con los registros generales
movwf FSR2H ;selecciona bancos de direccionamiento indirecto
movwf FSR1H
movwf FSR0H

movlw INI_TABLA ;inicio de tabla ram donde estan los valores a comparar
movwf FSR0L ;selecciona indice de tabla
decf FSR0L,F ;decrementa una direccion para luego incrementarla

movlw INI_RAM ;inicio de tabla ram donde se introduciran cantidad de coincidencias
movwf FSR2L ;selecciona indice de tabla
decf FSR2L,F ;decrementa una direccion para luego incrementarla

movlw .11 ;bytes a comparar menos 1
movwf CONT_COINC ;contador de comparaciones
regsig2 dcfsnz CONT_COINC,F ;decrementa el contador de comparaciones
goto discrim ;si se ha terminado de comprobar las coincidencias salta a esta direccion


movlw INI_RAM ;inicio de tabla ram donde se introduciran cantidad de coincidencias
movwf FSR1L ;selecciona indice de tabla
incf FSR2L,F ;incrementa indice de tabla
decf FSR1L,F

movff INDF2,COMPARADOR ;introduce valor de la tabla en registro comparador
movlw .11 ;registros a comparar
movwf CONT_REG ;contador de registros a comparar
incf FSR0L,F ;incrementa  indice de registros

regsig1 incf FSR1L,F ;incrementa indice de comparaciones
movf INDF1,W ;lee el registro indexado
dcfsnz CONT_REG,F ;decrementa contador de registros
goto regsig2 ;si se ha llegado al limite salta a lectura de siguiente registro
cpfseq COMPARADOR ;comprueba si w es igual a COMPARADOR
goto regsig1 ;siguiente comparacion
incf INDF0,F ;incrementa direccion seleccionada si hay coincidencia
goto regsig1 ;siguiente comparacion


;busca el valor mas alto
discrim movlw .9 ;cantidad de registros a comparar
movwf CONT_REG ;registro contador
movlw INI_TABLA ;inicio de tabla
movwf FSR0L ;direcciona tabla ram
movff INDF0,TEMP_KEY ;introduce el valor contenido en ram al registro prevalescente
dis1 incf FSR0L,F ;siguiente direccion
movf INDF0,W ;carga valor direccionado en W
cpfsgt TEMP_KEY ;comprueba si es mayor
movff INDF0,TEMP_KEY ;si es mayor introduce el valor en el registro prevalescente
decfsz CONT_REG,F ;decrementa contador de comprobaciones
goto dis1 ;siguiente comprovacion

;busca el valor mas alto de las coincidencias
movlw INI_TABLA ;carga inicio de tabla
movwf FSR0L
pre1 movf INDF0,W ;carga el valor direccionado en W
xorwf TEMP_KEY,W ;comparalo con el valor mas alto
btfsc STATUS,Z ;si se ha encontrado,
goto pre2 ;salta a pre2
incf FSR0L,F ;incrementa direccion
goto pre1 ;repite comparacion
pre2 movlw .10 ;valor de salto a tabla de valores
addwf FSR0L ;salta al valor
movff INDF0,TEMP_KEY ;introduce valor en W
KEY_OK
KEY_OK2
return ;retorna CON EL VALOR ANALOGICO DE LA TECLA PULSADA

;******************************************************* BORRA_TECL **********************************************************************
;Borrado de teclas para nuevo aprendizage "entrada analogica a masa para el borrado"

BORRA_TECL clrf WREG ;valor 0x00
cpfseq TEMP_ANALOG ;comprueba si la tecla pulsada esta a masa
return ;retorna en caso de que no este a masa
clrf DIR_EEPROM ;direccion 0x00 de la eeprom
setf DATO_EEPROM ;valor 0xff a grabar en la eeprom
call ESCRIBIR_DATO ;graba el dato
pop ;salir de todas las llamadas
pop
pop
pop
return ;retorna



;//////////////////////////////////(conversor A/D)////////////////////////////////////////////////////////////////////////////////////////////////
;///////////////busca el dato analogico introducido por el pin seleccionado/////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;Si queremos que funcionen todas las entradas analogicas.hay que habilitar las lineas deshabilitadas

DAT_AN bsf ADCON0,GO_DONE ;inicia la conversion
AD_GOIN btfsc ADCON0,GO_DONE ;comprueva si la conversion ha finalizado
goto AD_GOIN ;si la conversion ha finalizado continua
movf ADRESH,w ;carga dato analogico en el acumulador
movwf TEMP_ANALOG ;carga el dato de w en TEMP_ANALOG
;movf ADCON0,W
;movwf CANAL ;mete el contenido de ADCON0 en CANAL
;movf CONT_AD,W ;dato que se suma a ADCON0 para que a la siguiente lectura sea en el proximo canal de AD
;addwf ADCON0,F ;incrementa el canal analogico(AN0->AN4)
;movlw b'00100001';valor para usar AN5 -> b'00101001' ;valor del ultimo registro del conversor analogico
;xorwf ADCON0,w
;btfss STATUS,Z ;si llega a este valor
;return
;movlw 0x01 ;selecciona de nuevo el conversor AN0
;movwf ADCON0
return

;******************************************************** ALMAC *******************************************************************
;Aprendizaje del teclado.
ALMAC clrf FLAGS_KEY
call KEYB ;devuelve dato de tecla pulsada

movlw 0x02
cpfseq FLAGS_KEY

goto ALMAC

AL2 clrf WREG ;valor 0x00
cpfsgt DIR_EEPROM ;comprueba si es la primera tecla pulsada
movff TEMP_KEY2,PRIMR_TECL;almacena la primera tecla pulsada en PRIMR_TRCL.
cpfsgt DIR_EEPROM ;comprueba si es la primera tecla pulsada
goto al1

movf PRIMR_TECL,w ;comprueba si se ha vuelto a pulsar la primera tecla.
cpfseq TEMP_KEY2 ;si no se ha pulsado,-
goto al1 ;salta a al1

al3 movff DIR_EEPROM, N_KEYS  ;guardar el numero de teclas aprendidas
movff N_KEYS,DATO_EEPROM ;pasalo a DATO_EEPROM
movlw N_BYTES ;direccion de la eeprom donde se metera el dato del numero de bytes guardados
movwf DIR_EEPROM ;carga direccion de la eeprom
call ESCRIBIR_DATO ;graba el dato
FIND_OFF ;finalizacion de la memorizacion de teclas
return ;retorna.fin del programa

al1 movff TEMP_KEY2,DATO_EEPROM;carga valor analogico de tecla pulsada en registro de dato eeprom
call ESCRIBIR_DATO ;graba el dato en la eeprom
incf DIR_EEPROM,F ;incrementa la direccion

movlw N_BYTES ;carga tope de bytes a grabar
cpfseq DIR_EEPROM ;comprueba si ha llegado al tope
goto ALMAC ;si no ha llegado salta a ALMAC para siguiente tecla
goto al3 ;en caso contrario salta a al3 para ultima grabacion de numero de bytes y finaliza.

;*************************************************** SEARCH *******************************************************************
;Compara entre tecla pulsada y los valores de tecla almacenados en la eeprom
SEARCH setf TEMP_TECLA
call KEYB ;lee valor de tecla
setf WREG ;valor para tecla sin pulsar
cpfseq TEMP_KEY2 ;comprueba si la tecla esta pulsada.
goto sr1 ;si esta pulsada salta a sr1
return ;en caso contrario.retorna

sr1 clrf DIR_EEPROM ;direccion 0 de la eeprom
sr3 call LEER_DATO ;lee el dato
cpfseq TEMP_KEY2 ;comparalo con la tecla pulsada
goto sr2 ;siguiente direccion a comparar
goto SELEC ;si se ha encontrado la tecla pulsada selecciona valor de tecla.

sr2 incf DIR_EEPROM,F ;increenta la direccion a leer de la eeprom
movf DIR_EEPROM,W ;introducela en el acumulador

cpfsgt N_KEYS ;si la tecla pulsada no esta memorizada,
return ;retorna
goto sr3 ;en caso contrario compara siguiente tecla


SELEC movff DIR_EEPROM,TEMP_TECLA ;almacena en TEMP_TECLA el valor de tecla pulsada.
return ;retorna

;******************************************************* COPM_FLASH *************************************************************

COMP_MEMO clrf FLAGS_KEY ;borra flags
clrf WREG ;dato 0x00
movwf DIR_EEPROM ;direccion a leer de la eeprom de datos 0x00
call LEER_DATO ;lee el dato
setf WREG ;valor 0xFF
cpfseq TEMP_EEP ;comprueba si se ha grabado algo en la direccion 0x00


call EEP_RAM;FLASH_OK ;si se ha grabado algo activa flag de aprendizage
return ;retorna
;***************************************************** EEP_RAM  *****************************************************************
;Traspaso de keys de la eeprom de datos a la ram
EEP_RAM btfsc FLAGS_KEY,2 ;comprueba si es primer reinicio del pic
goto eep2 ;si es el primero,salta a eep2.en caso contrario lee de la eeprom el valor de bytes almacenados

movlw N_BYTES ;direccion de numero de bytes a leer
movwf DIR_EEPROM ;carga la direccion
call LEER_DATO ;lee el dato almacenado en la eeprom
movff TEMP_EEP,N_KEYS ;carga el valor en numero de teclas pulsadas

eep2 lfsr 0,0X07EB ;principio de direccion donde se introduciran los datos leidos de la eeprom de datos
clrf WREG ;dato 0x00
movwf DIR_EEPROM ;direccion a leer de la eeprom de datos 0x00
eep1 call LEER_DATO ;lee el dato
movff TEMP_EEP,INDF0 ;traspasa el dato ledo de la eeprom a la ram
decf FSR0L ;direccion anterior de la ram
incf DIR_EEPROM,f ;siguiente dato a leer de la eeprom
movf N_KEYS,w ;numero de bytes previamente almacenados
cpfseq DIR_EEPROM ;comprueba si se ha llegdo al final de la lectura
goto eep1 ;si no ha llegado.tarspasa siguente byte
FLASH_OK ;flag de datos grabados en flash
return ;retorna


aparte de configurar los puertos al programa se le llamara de esta forma:

Código: [Seleccionar]
call COMP_MEMO ;comprueba si hay algun dato guardado en la direccion 0x00 de la eeprom de datos.y restablece valores de teclas pulsadas
;pr call BOTON_PULS ;deteccion de tecla pulsada
; setf WREG
; cpfseq TEMP_TECLA
; NOP
; goto pr

cuando pulsemos una tecla el programa pasara por el NOP

Código: [Seleccionar]
;libreria para manejo de la eeprom

;//////////////////////////////////////////////ESCRIBIR DATO EN EEPROM///////////////////////////////////////////////////
ESCRIBIR_DATO ;clrwdt
GIE_OFF
;BANK0          ;selecciona banco 0
    movf   DIR_EEPROM,W    ;temporal de direccion de la eeprom de datos
;BANK1 ;selecciona banco 1
    movwf   EEADR ;direccion a acceder
;BANK0 ;selecciona banco 0
movf DATO_EEPROM,W ;temporal de dato de la eeprom de datos
;BANK1 ;selecciona banco 1
      movwf   EEDATA ;dato a grabar
bcf EECON1,EEPGD ;Puntero a la memoria de datos
bcf EECON1,CFGS ;Acceso a la EEPROM

      bsf    EECON1,WREN     ;habilita escritura
;GIE0
movlw   0X55 ;valores imprencindibles para la grabacion de datos en eeprom de datos
      movwf   EECON2 ;"
      movlw   0XAA ;"
        movwf   EECON2 ;"
;GIE1
    bsf    EECON1,WR      ;inicia escritura

      btfsc   EECON1,WR ;comprueva si se grabo el dato
    goto  $-2 ;si lo ha grabado continua.en caso contrario repite la comprobacion.
GIE_ON
bcf    EECON1,WREN ;deshabilitar escritura en eeprom
movf EEADR,W;DIR_EEPROM ;carga el valor de DIR_EEPROM en W
call VERIFICA ;salta a subprograma de verificacion de la correcta grabacion en eeprom de datos
;GIE1
return ;retorna

VERIFICA call LEER_DATO ;salta a subprograma de lectura de dato de la eeprom de datos
movf TEMP_EEP,W ;carga el contenido de TEMP_EEP en W
xorwf DATO_EEPROM,W ;comprueva si es el dato se ha grabado correctamente
btfsc STATUS,Z
return ;si es correcto.retorna

call ESCRIBIR_DATO ;en caso contrario,vuelve a grabar el dato
return ;retorna


;///////////////////////////////////////////LEER DATO DE MEMORIA EEPROM ///////////////////////////////////////////////////////

LEER_DATO    ;BANK1
    bcf EECON1,EEPGD ;Puntero a la memoria de datos
bcf EECON1,CFGS ;Acceso a la EEPROM
movf DIR_EEPROM,W      
      movwf   EEADR ;escribir direccion de memoria eeprom
bsf    EECON1,RD    ;ORDEN DE LECTURA

LEE     btfsc   EECON1,RD ;espera a que se realize la lectura del dato
      goto    LEE
movf  EEDATA,W ;carga valor de eeprom en el registro W
;BANK0 ;selecciona banco 0
movwf   TEMP_EEP ;carga el valor leido de eeprom de datos al registro TEMP_EEP
return ;retorna

Título: Re: pequeños proyectos
Publicado por: tapi8 en 24 de Enero de 2014, 14:45:03
Gracias por todos estos programas/librerias groundman.

Algo parecido a esto lo habia hecho tu paisano Redpic basandose en una nota de aplicacion de Microchip ¿No?.

Llevas una temporada que estas de un currante  :lol: :lol:
Título: Re: pequeños proyectos
Publicado por: groundman en 24 de Enero de 2014, 18:40:30
si. :D estoy con un proyecto de termostato y tengo que crear diferentes librerias que me van a serivir para muchos de los proyectos que haga con los 18f.

lo del teclado resistivo ya hize un proyecto para los mandos del volante de mi coche para usar el casette.pero tube muchos problemas a la hora
de la identificacion de las teclas.porque no realizaba la multiple coincidencia.y si pones un margen superior e inferior para cada tecla.se limita mucho la cantidad
de botones a configurar.y fallaban mucho las pulsaciones.

la idea de usar un teclado matricial ha sido de Redpic.y es muy buena idea.yo solo hubiera puesto resistencias a cada boton.como el caso de lso botones
de volante.

en el caso de los botones del coche.se usan mas de una entrada analogica.asi que este programa lo modificare en un futuro para usar mas entradas.



PD:respecto a la temporada que llevo de currante.tengo algo mas preparado. he creado una libreria para el manejo del sensor DS18B20.con el protocolo one wire.
     pronto lo pondre por aqui.tengo que perfeccionarlo algo mas.
Título: Re: pequeños proyectos
Publicado por: groundman en 25 de Enero de 2014, 05:59:17
aqui pongo un pequeño proyecto que visualiza la temperatura en una lcd con el sensor DS18B20.




en este uso la libreria que mas destaca es la del uso del DS18B20.aunque no esta terminada del todo.si lo esta para este proyecto.la libreria es muy extensa
y puede gestionar practicamente todos los comandos del DS18B20.me he tirado semanas para crearla.incluso esta implementado la comprobacion del CRC.

de esta forma nos evitamos errores de visualizacion en la LCD.aunque se puede visualizar la identidad del dispositivo.solo es para que practiquemos en el isis
ya que podemos cambiarla en la simulacion para experimentar.aunque no se hace uso de esta para el uso del DS18B20.he usado los comandos para la lectura de la temperatura sin identidad para facilitar la comprension y para que funcione cualquier sensor que conectemos al proyecto.

hay multitud de combinaciones de uso de esta libreria con el sensor.desde localizar todas las identidades de varios sensores conectados en paralelo como la
deteccion de alarmas para realizar por ejemplo un termostato.eso si con la gestion del CRC en todo momento.

proximamente hare MODs para otros circuitos como el preostato.o el uso de varios sensores a la vez.


PD: para que en el circuito real la pantalla gire correctamnte.cambiar el comando movlw   B'00011100'  por   movlw   B'00011000' ya que hay un problema
      entre lo que es la simulacion y lo que es el circuito real.
Título: Re:pequeños proyectos
Publicado por: groundman en 26 de Octubre de 2016, 11:19:04
hola a todos de nuevo.el tiempo no pasa en valde.ya hace mas de dos años desde la utima respueta.pero aqui estoy y seguire con el posteo de pequeños proyectos.
bien practicar o para coger lo que nos haga falta.


DS1307_18F2550.asm
Código: [Seleccionar]

;************************************************** www.ingeniopic.com ***************************************************
; PROGRAMA : DS1307_18f2550.asm
; Funcion : gestion del reloj DS1307
;           
;   
;  Revision : 1.0        25/10/2016            Programa para : PIC18F2550
; CPU Clock : 48 MHz                     Reloj instruccion :
;       WDT : Deshabilitado                  Tipo de reloj : HSPLL_HS
; Code Prot : OFF     xtal    :4Mhz
;************************************************* www.ingeniopic.com **************************************************
;
LIST P=18F2550 ; Se emplea el PIC 18F2550
RADIX HEX ; Sistema de numeraci¢n hexadecimal
INCLUDE  "P18F2550.INC"

   CONFIG PLLDIV =12
  CONFIG USBDIV = 1
  CONFIG CPUDIV = OSC1_PLL2
  CONFIG FOSC = HSPLL_HS      ;Osc por XTAL 4mhz
 
 
  CONFIG DEBUG = OFF
      CONFIG PWRT = OFF
      CONFIG BOR  = OFF
      CONFIG WDT = OFF;ON
  CONFIG WDTPS = 256
      CONFIG MCLRE = ON
      CONFIG PBADEN = OFF
      CONFIG LVP = OFF
      CONFIG CP0 = OFF
      CONFIG CP1 = OFF
      CONFIG CP2 = OFF
      CONFIG CP3 = OFF
      CONFIG CPB = OFF
      CONFIG CPD = OFF
  CONFIG CCP2MX= OFF
ERRORLEVEL -302

;ZONA DE ETIQUETAS
CBLOCK 0X20
HI_W_TEMP
LO_W_TEMP
HI_STATUS_TEMP
LO_STATUS_TEMP

TEMP_FSR1L
TEMP_FSR2L
TEMP_FSR2L_LO
TEMP_FSR2H_LO
TEMP_FSR1L_LO
TEMP_FSR1H_LO
TEMP_FSR2L_HI
TEMP_FSR2H_HI

HI_TEMP_STATUS
LO_TEMP_STATUS
HI_TEMP_BSR
LO_TEMP_BSR
TEMP_PCL_HI
TEMP_PCL_LO



CONT_BYTE_RTC ;contador de numero de bytes
DIR_I2C ;principio de direccion de dispositivo
DATO_I2C


ENDC



RETARDOS_VAR EQU 0X00A ;variables de la libreria "retardos.inc" hubicados en una zona de memoria accedida desde todos los bancos

EEP_VAR EQU 0X220

HI_POP_REG MACRO ;restaura registros
MOVLB 0X00 ;asegura que este seleccionado el banco0

;MOVFF TEMP_BANK_HI,BSR
movff HI_STATUS_TEMP,STATUS
movff HI_TEMP_BSR,BSR
movf HI_W_TEMP,W


movff TEMP_FSR2H_LO,FSR2H
movff TEMP_FSR2L_LO,FSR2L
movff TEMP_FSR1H_LO,FSR1H
movff TEMP_FSR1L_LO,FSR1L

movff HI_TEMP_STATUS,STATUS

ENDM

HI_PUSH_REG MACRO ;salva registros
MOVLB 0X00 ;asegura que este seleccionado el banco0

movff STATUS,HI_STATUS_TEMP
movff BSR,HI_TEMP_BSR
movwf HI_W_TEMP
movff FSR2H,TEMP_FSR2H_LO
movff FSR2L,TEMP_FSR2L_LO
movff FSR1H,TEMP_FSR1H_LO
movff FSR1L,TEMP_FSR1L_LO

movff STATUS,HI_TEMP_STATUS


ENDM


LO_POP_REG MACRO ;restaura registros
MOVLB 0X07 ;asegura que este seleccionado el banco7

movff LO_STATUS_TEMP,STATUS
movf LO_W_TEMP,W
movff LO_TEMP_BSR,BSR
movff TEMP_FSR2H_HI,FSR2H
movff TEMP_FSR2L_HI,FSR2L

movff LO_TEMP_STATUS,STATUS

ENDM

LO_PUSH_REG MACRO ;salva registros
MOVLB 0X07 ;asegura que este seleccionado el banco7

movff STATUS,LO_STATUS_TEMP
movwf LO_W_TEMP
movff BSR,LO_TEMP_BSR
movff FSR2H,TEMP_FSR2H_HI
movff FSR2L,TEMP_FSR2L_HI

movff STATUS,LO_TEMP_STATUS

ENDM


;***************Bit Definitions****************************************
#define BANK0 movlb 0x00
#define BANK1 movlb 0x01
#define BANK2 movlb 0x02
#define BANK3 movlb 0x03
#define BANK4 movlb 0x04
#define BANK5 movlb 0x05
#define BANK6 movlb 0x06
#define BANK7 movlb 0x07
#define BANK8 movlb 0x08
#define BANK9 movlb 0x09
#define BANK10 movlb 0x0A
#define BANK11 movlb 0x0B
#define BANK12 movlb 0x0C
#define BANK13 movlb 0x0D
#define BANK14 movlb 0x0E
#define BANK15 movlb 0x0F

#define GIE_HI_ON bsf INTCON,7
#define GIE_HI_OFF bcf INTCON,7
#define GIE_LO_ON bsf INTCON,6
#define GIE_LO_OFF bcf INTCON,6


#define I2C_18F 0X0750 ;direccion donde hubicaremos las rutinas de temporizacion
#define retardos 0X0950 ;direccion donde hubicaremos las rutinas de temporizacion

;<<<<<<---------------------- VECTOR DE RESET ------------------------>>>>>>>
ORG    0x00      ;Inicio en el Vector de Reset
  goto   INICIO      ;ir a la primera instruccion del programa
;<<<<<<---------------------- VECTOR DE INTERRUPCIONES ALTA PRIORIDAD ---------------->>>>>>>>>>
ORG 0X08
goto INTERRUP_HI
;<<<<<<---------------------- VECTOR DE INTERRUPCIONES BAJA PRIORIDAD ---------------->>>>>>>>>>
ORG 0X18
goto INTERRUP_LO


ORG 0X001C
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
INICIO    BANK15


clrf UCON,1


movlw b'01110000' ;activa resistencias pull-up (evitar fallo lectura BUSY LCD)
movwf INTCON2

movlw b'11111110'
movwf LATA
movlw b'11111000'
movwf TRISA
movlw   0x0F
movwf   ADCON1
movlw 0x07
movwf CMCON
clrf PORTB
clrf LATB
setf TRISB

movlw b'10000001' ;configura TMR0
movwf T0CON
bsf INTCON2,TMR0IP ;alta prioridad para tmr0
bcf INTCON2,RBIP ;baja prioridad para portb
clrf TMR0

bsf RCON,IPEN ;activa prioridad de interrupciones

movf PORTB,w ;leer puerto para el posterior borrad e flag RBIF
bcf INTCON,RBIF
bsf INTCON,RBIE




GIE_LO_OFF
GIE_HI_OFF
GIE_LO_OFF
GIE_HI_OFF

call DS1307_INI
;***********************************************PRINCIPIO DEL PROGRAMA********************************************************************
;antes de ejecutar la linea ESCRIBE.hay que poner los datos a grabar en la direccion ox100.ejemplo:
;0x30,0x50,0x12,0x02,0x25,0x10,0x16 = segundos,minutos,hora,(martes),dia,mes,año

PRINCIPAL ;call ESCRIBE ;escribir en el DS1307
call LEE ;leer del DS1307
rep goto rep
goto PRINCIPAL
return





;escritura de datos al DS1307.los datos deben de introducirse a partir de la direccion 0x100
ESCRIBE lfsr FSR2,0X100 ;principio de ram donde se introduciran los datos leidos del dispositivo I2C
movlw 0x00 ;principio de direccion a leer
movwf DIR_I2C
movlw .7 ;nuemro de bytes a escribir
call WRITE_RTC
return

;lectura de datos del DS1307.los datos seran hubicados a partir de la direccion 0x100
LEE lfsr FSR2,0X100 ;principio de ram donde se introduciran los datos leidos del dispositivo I2C
movlw 0x00 ;principio de direccion a leer
movwf DIR_I2C
movlw .7 ;nuemro de bytes a leer
call READ_RTC
return

;fin del programa.




;<<<<<<<<-------------------COMPROBACION DE TIPO DE INTERRUPCION DE ALTA PRIORIDAD------------>>>>>>>>>>>>>>
   
INTERRUP_HI HI_POP_REG


HI_PUSH_REG
retfie             ;retorna y habilita interrupciones generales
;<<<<<<<<-------------------COMPROBACION DE TIPO DE INTERRUPCION DE BAJA PRIORIDAD------------>>>>>>>>>>>>>>
;evento de temporizaciones.1s aproximadamente.para la activacion/desactivacion de salidas.

INTERRUP_LO LO_POP_REG


LO_PUSH_REG
retfie ;retorna y habilita interrupciones



DS1307_INI BANK15
bsf PIE1,SSPIE ;habilita interrupciones para la camara
;bsf ODCON1,7 ;habilita open drain para RC4, SDA1
bsf TRISB,0 ;configura pins como entrada
bsf TRISB,1 ;configura pins como entrada

movlw 0x28        ; I2C master, SSPEN enabled
movwf SSPCON1      ;
movlw   0x80 ; 400Khz compat,
movwf   SSPSTAT             
movlw .159 ; configurar I2C a 100kHz (para fosc de 64Mhz) clock=Fosc/(4*(SSPxADD+1))
;movlw .39 ; configurar I2C a 400kHz (para fosc de 64Mhz) clock=Fosc/(4*(SSPxADD+1))
movwf SSPADD

clrf PIR1

return


org retardos
include "retardos.inc"


org I2C_18F
include "I2C_18F.inc"

 

end


I2C_18F.inc

Código: [Seleccionar]
LIST

; CBLOCK I2C_VAR
; CONT_BYTE_RTC ;contador de numero de bytes
; DIR_I2C ;principio de direccion de dispositivo
; DATO_I2C
; ENDC



;-------------------------------------------------------------------------------------------;
;                                  SUBRUTINAS DE I2C                                        ;
;-------------------------------------------------------------------------------------------;

;Lectura de los datos internos del DS1307
READ_RTC movwf CONT_BYTE_RTC     ;numero de bytes a leer
call Start_I2C     ;Llama a la subrutina de START
rcall retardo_5us
movlw 0xd0     ;modo lectura del RTC
movwf SSPBUF     ;Lo carga en el Buffer de salida
call Write_I2C     ;Llama a la subrutina de escritura
rcall retardo_5us
movff DIR_I2C,SSPBUF     ;Lo carga en el Buffer de salida
call Write_I2C     ;Llama a la subrutina de escritura
rcall retardo_5us
call Restart_I2C         ;Llama a la subrutina de RESTART
   
rcall retardo_5us
movlw 0xd1     ;modo escritura del RTC
movwf SSPBUF,0     ;Lo carga en el Buffer de salida
call Write_I2C     ;Llama a la subrutina de escritura
rcall retardo_5us

Bucle_Leer call Read_I2C            ;Llama a la subrutina de lectura
movff SSPBUF,POSTINC2     ;Guarda el dato en la Ram e incrementa el puntero
rcall retardo_5us
   
decfsz CONT_BYTE_RTC,F     ;repite hasta que sea cero
bra ACK     ;envia ACK y continúa leyendo
call Send_I2C_NoAck      ;llama a la subrutina de ACKNOWLEDGE
rcall retardo_5us
call Stop_I2C            ;Llama a la subrutina de STOP
rcall retardo_5us
return     ;Retorna de la subrutina

ACK call Send_I2C_Ack        ;Llama a la subrutina de ACKNOWLEDGE
rcall retardo_5us
goto Bucle_Leer        
   


;Escritura en el DS1307 antes de la llamada a esta rutina.cargar en FSR2 el inicio de la ram donde se leeran los datos a transferir al DS1307
; y en WREG la cantidad de datos a transferir.
   
WRITE_RTC movwf   CONT_BYTE_RTC     ;numero de bytes a escribir
call    Start_I2C     ;Llama a la subrutina de START
rcall retardo_5us
movlw   0xd0     ;modo escritura del RTC
movwf   SSPBUF     ;Lo carga en el Buffer de salida
call    Write_I2C     ;Llama a la subrutina de escritura
rcall retardo_5us
movff   DIR_I2C,SSPBUF     ;Lo carga en el Buffer de salida
call    Write_I2C     ;Llama a la subrutina de escritura
                rcall retardo_5us
Bucle_Escribir1 movff   POSTINC2,SSPBUF     ;Carga el dato de la Ram en SSP1BUF e incrementa el puntero
                call    Write_I2C     ;Llama a la subrutina de escritura
rcall retardo_5us
decfsz  CONT_BYTE_RTC,F     ;repite hasta que sea cero
bra Bucle_Escribir1     ;continúa enviando datos
                call    Stop_I2C     ;Llama a la subrutina de STOP
rcall retardo_5us
                return     ;Retorna de la subrutina

;retardo de 5us
retardo_5us movlw .11
call retardo_us
return



;*********************************************************************************************************    
i2c_idle btfsc   SSPSTAT,R_W
goto    i2c_idle
reps movf    SSPCON2,w
andlw   0x1F
btfss   STATUS,Z
goto    reps
return    
   



Start_I2C       BANK15
bsf SSPCON2,SEN     ;Pone a uno el bit de START
S2              btfsc   SSPCON2,SEN     ;Espera a que se ponga a cero el bit de START
                bra     S2
S3              btfss   PIR1,SSPIF     ;Espera a que la condicion de START haya sido completada
                bra     S3     ;cuando se ponga a 1 la bandera de interrupción
BCF     PIR1,SSPIF     ;Borra la bandera de la interrupción
                return     ;Retorna de la subrutina
                                                     

Write_I2C       btfsc   SSPSTAT,R_W     ;Verifica que se ponga a cero el bit R/W
                bra     Write_I2C     ;Espera a que termine de enviar el dato
W2              btfsc   SSPCON2,ACKSTAT     ;Espera a que reciba el bit de ACKNOWLEDGE
                bra     W2
BCF     PIR1,SSPIF     ;borra la bandera de la interrupción
                return     ;Retorna de la subrutina


Restart_I2C     bsf     SSPCON2,RSEN     ;Pone a uno el bit de RESTART
R2              btfsc   SSPCON2,RSEN     ;Espera a que se ponga a cero el bit de RESTART
                bra     R2
R3              BTFSS   PIR1,SSPIF     ;Espera a que la condicion de RESTART haya sido completada
                bra     R3     ;cuando se ponga a 1 la bandera de interrupción
                bcf     PIR1,SSPIF     ;Borra la bandera de la interrupción
                return     ;Retorna de la subrutina


Read_I2C        bsf     SSPCON2,RCEN     ;Habilita la recepción de datos mediante el bit RCEN
Rea2            btfsc   SSPCON2,RCEN     ;Espera a que se ponga a cero el bit RCEN
                bra     Rea2
Rea3            BTFSS   SSPSTAT,BF     ;Dato disponible en SSPBUF para ser leidos?
                bra     Rea3     ;No, esperar
Rea4            BTFSS   PIR1,SSPIF     ;Espera a que la condicion de Lectura haya sido completada
                bra     Rea4     ;cuando se ponga a 1 la bandera de interrupción
                bcf     PIR1,SSPIF     ;Borra la bandera de la interrupción
                return     ;Retorna de la subrutina


Send_I2C_Ack    bcf     SSPCON2,ACKDT     ;Pone a cero el bit de ACKNOWLEDGE DATA
                bsf     SSPCON2,ACKEN      ;Genera la condición de ACKNOWLEDGE Poniendo a 1 el bit ACKEN
                btfss   PIR1,SSPIF     ;Espera a que la condicion de ACK haya sido completada
                bra     Rea4     ;cuando se ponga a 1 la bandera de interrupción
                bcf     PIR1,SSPIF     ;Borra la bandera de la interrupción
                return     ;Retorna de la subrutina


Send_I2C_NoAck  bsf     SSPCON2,ACKDT     ;Pone a 1 el bit de ACKNOWLEDGE DATA
                bsf     SSPCON2,ACKEN     ;Genera la condición de NO ACKNOWLEDGE Poniendo a 1 el bit ACKEN
                btfss   PIR1,SSPIF     ;Espera a que la condicion de No ACK haya sido completada
                bra     Rea4     ;cuando se ponga a 1 la bandera de interrupción
                bcf     PIR1,SSPIF     ;Borra la bandera de la interrupción
                return     ;Retorna de la subrutina


Stop_I2C bsf     SSPCON2,PEN     ;Genera la condición de STOP poniendo a 1 el bit PEN
P2 btfsc   SSPCON2,PEN     ;Espera a que se ponga a cero el bit PEN
                bra     P2
        btfss   PIR1,SSPIF     ;Espera a que la condicion de Stop haya sido completada
                bra     Rea4     ;cuando se ponga a 1 la bandera de interrupción
                bcf     PIR1,SSPIF     ;Borra la bandera de la interrupción
                return 

LIST


retardos.inc

Código: [Seleccionar]

CBLOCK RETARDOS_VAR

PDel0
PDel1
PDel2
PDel5
PDel6
PDel7


ENDC

;************************************************************** RETARDO DE 1 SEGUNDO *****************************************************

retardo_s movwf     PDel0     ; 1 |11000000 'À'
PLoop0  movlw     .79       ; 1 set numero de repeticion  (B)
        movwf     PDel1     ; 1 |
PLoop1  movlw     .192      ; 1 set numero de repeticion  (A)
        movwf     PDel2     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        clrwdt              ; 1 ciclo delay
        decfsz    PDel2, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel1,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) es el tiempo 0  ? (C)
        goto      PLoop0    ; 2 no, loop
return              ; 2+2 Fin.


retardo_ms movwf     PDel5     ; 1 |
PLoop1a  movlw     .255       ; 1 set numero de repeticion  (A)
        movwf     PDel6     ; 1 |
PLoop2a  clrwdt              ; 1 clear watchdog
        clrwdt              ; 1 ciclo delay
        decfsz    PDel6, 1  ; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2a    ; 2 no, loop
        decfsz    PDel5,  1 ; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1a    ; 2 no, loop
PDelL1a  goto PDelL2a         ; 2 ciclos delay
PDelL2a 
        return              ; 2+2 Fin.
;
;;----------------------------------------------- RETARDOS EN MICROSEGUNDOS -----------------------------------------
retardo_us movwf     PDel7     ; 1 |
PLoop0b  clrwdt              ; 1 clear watchdog
        decfsz    PDel7, 1  ; 1 + (1) es el tiempo 0  ?
        goto      PLoop0b    ; 2 no, loop
PDelL1b  goto PDelL2b         ; 2 ciclos delay
PDelL2b  clrwdt              ; 1 ciclo delay
        return              ; 2+2 Fin.



en este caso he hecho un programa para configurar un circuito reloj como es el DS1307.y que se usara un pic18f2550 que va a trabajar a 48Mhz pero con un cristal de 4Mhz
ya que usamos el pll interno del pic.

en la linea PRINCIPAL.tenemos dos rutinas que  se llaman ESCRIBE y LEE .las llamadas a estas rutinas hacen que el PIC se comunique via I2C con el DS1307.
a una velocidad de 100Khz.

para leer solo tenemos que realizar la llamada a esta rutina.y los datos del DS1307 seran mandados a la direccion 0x100 de la ram de nuestro pic.

para escribir.antes de la llamada a esta rutina hay que introducir los datos apartir de la direccion 0x100 esta inclusive.y realizar la llamada.
algunos DS1307 hay que ponerlos en hora para que empiezen a trabajar.si no lo hizieramos podriamos intentar leerlos y solo leeriamos estos datos:

0x80,0x00,0x00,0x01,0x01,0x01,0x00,0x03

aqui pongo una direccion donde explico mejor esto:  http://www.todopic.com.ar/foros/index.php?topic=46426.0
 - Tienes que ingresar para ver archivos adjuntos -
Título: Re:pequeños proyectos
Publicado por: pibe en 20 de Noviembre de 2016, 00:56:41
Hola groundman y bienvenido de vuelta!
Mira las casualidades, yo vuelvo luego de varios años alejado de los pics. Pero ya sabes... esto es una enfermedad que no tiene cura XD
Título: Re:pequeños proyectos
Publicado por: groundman en 20 de Noviembre de 2016, 14:03:12
si.todo depende de nuestras necesidades.yo tengo varios proyectos en mente y poco tiempo para desarrollarlos.y lo peor es que cada vez necesito mas velocidad para los proyectos.
si embargo los pic que estan fabricando son mas complejos.y ya hay que utilizar librerias avanzadas.asi que el ASM no va a ser una opcion a partir de las versiones superiores a la 18F

en la proxima generacion voy a tener que aprender CCS.ya veremos lo que pasa. un salud.
Título: Re:pequeños proyectos
Publicado por: pibe en 20 de Noviembre de 2016, 22:27:40
Joder groundman, si parecemos mellizos del destino.
Yo tambien, estoy viendo una nueva alternativa economica a mi magro sueldo. Y tambien he dejado el ASM de lado y estoy empezando con el XC8.
Me duele tener que recordar los comandos de C, me los olvido y debo volver a releerlos. Ademas necesito una salida rapida y no puedo perder tiempo aprendiendo, asi que voy aprendiendo sobre la marcha.