;**********************************************************************
; |¯¯\/¯¯|
; VDD --->|1 20|<--- VSS
; RA5/T1CKL/OSC1/CLKIN <--->|2 19|<---> RA0/AN0/C1IN+/ICSPDAT/ULPWU
;RA4/AN3/_T1G/OSC2/CLKOUT <--->|3 18|<---> RA1/AN1/C12IN-/VREF/ICSPCLK
; RA3/_MCLR/VPP --->|4 17|<---> RA2/AN2/T0CLK/INT/C1OUT
; RC5/CPP1/P1A <--->|5 16|<---> RC0/AN4/C2IN+
; RC4/C2OUT/P1B<--->|6 15|<---> RC1/AN5/C2IN-
; RC3/AN7/P1C <--->|7 14|<---> RC2/AN6/P1D
; RC6/AN8/_SS <--->|8 13|<---> RB4/AN10/SD1/SDA
; RC7/AN9/SDO <--->|9 12|<---> RB5/AN11/RX/DT
; RB7/TX/CK <--->|10 11|<---> RB6/SCK/SCL
; |______|
; PIC 16F690
; *
;**********************************************************************
; *
; Nombre: Test2.asm
; Fecha: 28-01-2009
; Version: v1.00
; *
; Autor: Sander
; Empresa:
; *
; *
;**********************************************************************
; *
; Archivos Requeridos:
;
; I2Cmacro.inc
; i2cCom.inc
; EE24AA64.inc
;**********************************************************************
; *
; Notas:
; Despues de #include <P16F690.inc>, debemos incluir las macros para
; la comunicacion I2C (I2Cmacro.inc), y despues (al final del programa)
; debemos incluir las rutinas para manejar el bus i2c (i2cCom.inc) y
; para manejar la memoria (EE24AA64.inc)
;
; Este programa muestra el uso de una memoria i2c que pueda direccionar
; maximo 16 bits, para este ejemplo se usara la AT24C64, que puede
; direccionar hasta 8192 bytes.
; -------------------------------------------------------------------------
; Notas de versiones
; v1.00 C-11-02-2009
; El programa permite :
; 1 Escribir un byte en cualquier direccion
; 2 Leer un byte de cualquier direccion
; 3 Escribir varios bytes (maximo 32) a partir de cualquier direccion
; 4 Leer hasta 80 bytes a partir de cualquier byte.
; ------------------------------------------------------------------------
;**********************************************************************
list p=16f690 ;directiva list para definir procesador
#include <P16F690.inc> ;definicion de variables especificas (SFRs)
#include <I2Cmacro.inc>
__CONFIG _CP_OFF & _CPD_OFF & _BOR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF
;La directiva '__CONFIG' se usa para colocar datos de configuracion
;dentro del archivo .asm.
; Las etiquetas que siguen a la directiva se encuentran en el archivo .inc respectivo
; Buscar en la hoja de datos respectiva para informacion adicional de la
;palabra de configuracion
;***** Definicion de Variables
w_temp EQU 0x71 ; variable usada para salvar contexto
status_temp EQU 0x72 ; variable usada para salvar contexto
pclath_temp EQU 0x73 ; variable usada para salvar contexto
CBLOCK 0x20
i2cDato
i2cCont
i2cFlags ;para la comunicacion i2c
i2cEEAddr:2,i2cEEDato ;
EECont ;para manejar la EEPROM externa
OffsTabla, AddrTabla:.2 ;para manejar tablas
DatoRx, DatoTx ;para guardar datos del EUSART
I,J ;puntero para buffers en memoria
ContBytes ;para controlar cantidad de bytes
DatoAux ;para usar en subrutinas
ENDC
CBLOCK 0xA0
BufferRx:.80 ;buffer para la recepcion
ENDC
CBLOCK 0x120
Buffer2:.80 ;bufer de proposito general
ENDC
_9600 EQU .103 ;0x67 para BRGH=1, BRG16=1, y Fosc=4MHz
EEDir1 EQU 0xA0 ;direccion de la EEPROM externa
#DEFINE ACK_F i2cFlags,.0
#DEFINE S_NACK_F i2cFlags,.1
;**********************************************************************
ORG 0x000 ; Vector de Reset
goto main ; ir al inicio del progra
ORG 0x004 ;posicion del vector de interrupcion
movwf w_temp ; salvar el contenido actual de W
movf STATUS,w ;
movwf status_temp ; salvar el contenido actual de STATUS
movf PCLATH,w ;
movwf pclath_temp ; salvar el contenido actual de PCLATH
;La rutina de interrupcio puede ir a continuacion o se puede realizar una
;llamada a la rutina usando call
movf pclath_temp,w ; recuperar el valor de PCLATH
movwf PCLATH ; antes de la interrupcion
movf status_temp,w ; recuperar el valor de STATUS
movwf STATUS ; antes de la interrupcion
swapf w_temp,f
swapf w_temp,w ; recuperar el valor de W
retfie ;retornar de la interrupcion
main
;el programa principal va a continuacion
;*************** Inicializacion de puertos *******************
banksel ANSEL ;banco 2
clrf ANSEL
clrf ANSELH ;todos los pines como I/O digitales
banksel PORTA ;banco 0
;******************************************************************
;*************** Inicializacion del EUSART *******************
banksel TRISB ;banco 1
movlw B'11110000' ;RB5 y RB7 para usar el EUSART
movwf TRISB ;RB4 y RB6 para hacer i2c
banksel BAUDCTL ;banco 1
movlw B'01001000' ;Bit 3(BRG16) en 1 para usar generador
movwf BAUDCTL ;de bauds de 16 bit.
movlw B'00000100' ;Bit 2(BRGH) en 1 para High Baud rate
movwf TXSTA ;Bit 4(SYNC) = 0 modo asincrono
movlw HIGH _9600
movwf SPBRGH
movlw LOW _9600
movwf SPBRG ;Ajustamos la velocidad
banksel RCSTA ;Banco 0
movlw B'10010000' ;Bit 7(SPEN) = 1 Habilita puerto serial
movwf RCSTA ;Bit 4(CREN) = 1 Habilita recepcion.
;******************************************************************
;*************** Inicializacion de variables *******************
clrf i2cFlags
clrf i2cEEAddr+1
clrf i2cEEAddr
;******************************************************************
banksel TXSTA
bsf TXSTA,TXEN ;Habilitamos el transmisor
banksel PORTB
mainP0
clrw
call EnvMsg
movlw .1
call EnvMsg ;Enviamos mensaje de opciones
call RxEusart ;recibimos la opcion del menu(solo un byte)
movf ContBytes,W ;
xorlw .1 ;verificamos que solo se reciba un byte
btfss STATUS,Z ;Se recibio solo un byte?
goto MainEr1 ;No => vamos a error
movlw BufferRx ;Si => vemos que opcion se recibio
movwf FSR ;
movf INDF,W ;Leemos el byte recibido
andlw 0x0F ;solo tomamos los bits menos significativos
movwf INDF
sublw .4
btfss STATUS,C ;El valor recibido es <= 4?
goto MainEr1 ;No => vamos a error
movlw HIGH mainP0_0 ;Si => nos preparamos para ir a la rutina de
movwf PCLATH ;la opcion seleccionada
movlw LOW mainP0_0 ;
addwf INDF,W
btfsc STATUS,C
incf PCLATH,F
movf INDF,W
addwf PCL
mainP0_0
goto MainEr1
goto MainOpc1
goto MainOpc2
goto MainOpc3
goto MainOpc4
MainEr1
movlw .8
call EnvMsg ;enviamos mensaje de dato erroneo
goto mainP0 ;volvemos a empezar con la rutina
;**************************
;*********************** MainOpc1 *******************************
; MainOpc1 Atiende la opcion 1 del menu, permite recibir una
; direccion y un dato a escribir, controla si existen
; errores al momento de introducir la direccion o el dato.
; Si el dato se ecribio en la memoria envia un mensaje.
;**********************************************************************
MainOpc1
movlw .3
call EnvMsg ;Enviamos mensaje para la opcion 1
call RxEusart ;para recibir los datos
call IntDir ;Para procesar la direccion
xorlw .0
btfsc STATUS,Z ;IntDir devolvio 0x00
goto MainOpc1Er ;Si => no se recibio una direccion valida
MainOpc1P0
movlw .4
call EnvMsg ;Mensaje para introducir dato
call RxEusart
call IntDato ;para recibir el dato
xorlw .0
btfsc STATUS,Z ;IntDato devolvio 0x00
goto MainOpc1Er2 ;Si => no se recibio un dato valido
call EEWrByte ;No => Escribimos el dato en la EEPROM
movlw .5
call EnvMsg ;Mensaje que indica que se escribio correctamente
movlw .14
call EnvMsg ;Para marcar que se termino de leer
goto mainP0 ;Volvemos a las opciones iniciales
MainOpc1Er
movlw .8
call EnvMsg ;enviamos mensaje de dir erronea
goto MainOpc1 ;volvemos a empezar con la rutina
MainOpc1Er2
movlw .8
call EnvMsg ;enviamos mensaje de dato erroneo
goto MainOpc1P0 ;volvemos a pedir dato
;**********************************************************************
;*********************** MainOpc2 *******************************
; MainOpc2 Atiende la opcion 2 del menu, permite recibir una
; direccion, controla si existen errores al momento de
; introducir la direccion.
; Envia el dato leido en forma hexadecimal
;**********************************************************************
MainOpc2
movlw .6
call EnvMsg ;enviamos mensaje para la opcion 2
call RxEusart
call IntDir ;recibimos bytes de direccion
xorlw .0
btfsc STATUS,Z ;IntDir devolvio 0x00?
goto MainOpc2Er ;Si => no se recibio una direccion valida
call EERdByte ;No => Leemos el byte.
movlw .7
call EnvMsg ;mensaje para mostrar el valor leido
movf i2cEEDato,W
call EnvEEDato ;Enviamos el dato leido de la EEPROM en hex
movlw .14
call EnvMsg ;Para marcar que se termino de leer
goto mainP0 ;;Volvemos a las opciones iniciales
MainOpc2Er
movlw .8
call EnvMsg ;enviamos mensaje de dato erroneo
goto MainOpc2 ;volvemos a empezar con la rutina
;**********************************************************************
;*********************** MainOpc3 *******************************
; MainOpc3 Atiende la opcion 3 del menu, permite recibir una
; direccion y un dato a escribir, controla si se recibio
; una direccion erronea, luego de recibir la direccion permite que se
; vayan recibiendo hasta 32 datos y los va guardando en BufferRx tal
; cual los va recibiendo (generalmente ASCII).
; Cuando los datos se terminaron de escribir en la memoria envia un mensaje.
;**********************************************************************
MainOpc3
movlw .9
call EnvMsg ;mensaje de inicio para este modo
call RxEusart ;recibimos la direccion donde
call IntDir ;grabaremos
xorlw .0
btfsc STATUS,Z ;IntDir retorno error?
goto MainOpc3Er ;Si => vamos a atender el error
movlw .10
call EnvMsg ;mensaje para introducir los datos
call RxEusart ;introducimos datos, en este modo
movf ContBytes,W
movwf EECont ;En EECont se pasa la cantidad de bytes escribir
call EEWrPage ;se guardan los datos en ascii(como se reciben)
movlw .5
call EnvMsg ;mensaje de caracteres grabados
movlw .14
call EnvMsg ;Para marcar que se termino de leer
goto mainP0 ;volvemos al menu principal
MainOpc3Er
movlw .8
call EnvMsg ;enviamos mensaje de dato erroneo
goto MainOpc3 ;volvemos a empezar con la rutina
;**********************************************************************
;*********************** MainOpc4 *******************************
; MainOpc4 Atiende la opcion 4 del menu, permite recibir una
; direccion y una cantidad de datos a leer, controla si existen
; errores al momento de introducir la direccion y la cantidad de datos.
; Envia los datos leidos en forma hexadecimal separados por espacios en
; blanco.
;**********************************************************************
MainOpc4
movlw .11
call EnvMsg ;mensaje de inicio para este modo
call RxEusart ;recibimos la direccion desde donde
call IntDir ;leeremos
xorlw .0
btfsc STATUS,Z ;IntDir retorno error?
goto MainOpc4Er ;Si => vamos a atender el error
MainOpc4P0
movlw .12
call EnvMsg ;mensaje para introducir cantidad de bytes
call RxEusart ;recibimos la cantidad de datos
movf ContBytes,W ;
xorlw .2
btfss STATUS,Z ;Se recibio 2 datos(para cantdad datos)?
goto MainOpc4Er2 ;No => atendemos error
movlw BufferRx ;convertimos los dos datos recibidos en binario
movwf FSR ;
movf INDF,W ;Leemos el 1er dato
movwf DatoAux ;revisamos que sea numero
sublw 0x29
btfsc STATUS,C ;DatoAux >= '0'?
goto MainOpc4Er2 ;No => atendemos error
movf DatoAux,W
sublw '9'
btfss STATUS,C ;DatoAux <= '9'?
goto MainOpc4Er2 ;No => atendemos error
movlw 0x0F
andwf DatoAux,F ;aqui tenemos las decenas
clrf EECont
MainOpc4P0_0
movlw .10
addwf EECont,F ;EECont = EECont + 10
decfsz DatoAux,F ;decenas == 0?
goto MainOpc4P0_0 ;No => seguimos sumando
incf FSR,F ;Si => revisamos el otro byte
movf INDF,W ;Leemos el 2do dato
movwf DatoAux ;revisamos que sea numero
sublw 0x29
btfsc STATUS,C ;DatoAux >= '0'?
goto MainOpc4Er2 ;No => atendemos error
movf DatoAux,W
sublw '9'
btfss STATUS,C ;DatoAux <= '9'?
goto MainOpc4Er2 ;No => atendemos error
movlw 0x0F
andwf DatoAux,F ;aqui tenemos las unidades
MainOpc4P0_1
movlw .1
addwf EECont,F ;EECont = EECont + 10
decfsz DatoAux,F ;decenas == 0?
goto MainOpc4P0_1 ;No => seguimos sumando
movf EECont,W ;Si => revisamos si EECont <= 80
sublw .80
btfss STATUS,C ;DatoAux <= 80?
goto MainOpc4Er2 ;No => atendemos error
movf EECont,W
movwf ContBytes
call EERdPage ;leemos los datos
movlw .13
call EnvMsg ;mensaje para mostrar los datos leidos
MainOpc4P1
movlw Buffer2
movwf FSR
bsf STATUS,IRP ;para apuntar al banco 2
MainOpc4P1_0
movf INDF,W ;leemos el dato que queremos enviar
movwf i2cEEDato ;para enviar el dato en formato hexadecimal
call EnvEEDato ;es decir, como esta escrito en la memoria
movlw ' '
btfss PIR1,TXIF
goto $-1
movwf TXREG ;Enviamos espacio en blanco
incf FSR,F ;para tomar el siguiente dato
decfsz ContBytes,F ;;Se transmitieron todos los datos?
goto MainOpc4P1_0 ;No => seguimos transmitiendo
bcf STATUS,IRP ;FSR para apuntar al banco 0 o 1
movlw .14
call EnvMsg ;Para marcar que se termino de leer
goto mainP0
MainOpc4Er
movlw .8
call EnvMsg ;enviamos mensaje de dir erroneo
goto MainOpc4 ;volvemos a empezar con la rutina
MainOpc4Er2
movlw .8
call EnvMsg ;enviamos mensaje de cantidad erroneo
goto MainOpc4P0 ;volvemos a recibir cantidad bytes
;**********************************************************************
;*************************** IntDir *******************************
; IntDir Lleva 4 bytes recibidos en ASCII mediante la rutina
; RxEusart a i2cEEAddr, para tener asi la direccion con la
; que se quiere trabajar en la EEPROM. por ejemplo si se recibe
; '0','1','a','B' => i2cEEAddr = 01AB. la rutina retorna error si
; se recibieron mas de 4 bytes o si el caracter recibido no
; es un numero o una letra de la 'a' a la 'f'.
;**********************************************************************
IntDir
movf ContBytes,W
xorlw .4
btfss STATUS,Z ;Se recibio 4 datos(para direccion)?
retlw 0x00 ;No => retornamos error
movlw BufferRx
movwf FSR ;
movf INDF,W ;Leemos el 1er dato
call Ascii2Hex ;Convertimos el dato a hex
xorlw .0
btfsc STATUS,Z ;Ascii2Hex retorno 0?
retlw 0x00 ;No => retornamos error
swapf DatoAux,W
movwf i2cEEAddr+1 ;nible alto de i2cEEAddr+1
incf FSR,F ;siguiente dato
movf INDF,W ;Leemos el 2do dato
call Ascii2Hex ;Convertimos el dato a hex
xorlw .0
btfsc STATUS,Z ;Ascii2Hex retorno 0?
retlw 0x00 ;No => retornamos error
movf DatoAux,W
iorwf i2cEEAddr+1,F ;nible bajo de i2cEEAddr+1
incf FSR,F ;siguiente dato
movf INDF,W ;Leemos el 3er dato
call Ascii2Hex ;Convertimos el dato a hex
xorlw .0
btfsc STATUS,Z ;Ascii2Hex retorno 0?
retlw 0x00 ;No => retornamos error
swapf DatoAux,W
movwf i2cEEAddr ;nible alto de i2cEEAddr
incf FSR,F ;siguiente dato
movf INDF,W ;Leemos el 4to dato
call Ascii2Hex ;Convertimos el dato a hex
xorlw .0
btfsc STATUS,Z ;Ascii2Hex retorno 0?
retlw 0x00 ;No => retornamos error
movf DatoAux,W
iorwf i2cEEAddr,F ;nible bajo de i2cEEAddr
retlw 0x01
;*******************************************************************
;*************************** IntDato *******************************
; IntDato Similar a IntDir pero solo trabaja con dos datos, por
; ejemplo si se recibio 'F','e' => i2cEEDato = FE
; Retorna error si se recibieron mas de 2 bytes o si el caracter recibido
; no es un numero o una letra de la 'a' a la 'f'.
;**********************************************************************
IntDato
movf ContBytes,W
xorlw .2
btfss STATUS,Z ;Se recibio 2 datos(para dato)?
retlw 0x00 ;No => retornamos error
movlw BufferRx
movwf FSR ;
movf INDF,W ;Leemos el 1er dato
call Ascii2Hex ;Convertimos el dato a hex
xorlw .0
btfsc STATUS,Z ;Ascii2Hex retorno 0?
retlw 0x00 ;Si => retornamos error
swapf DatoAux,W
movwf i2cEEDato ;nible alto de i2cEEDato
incf FSR,F ;siguiente dato
movf INDF,W ;Leemos el 2do dato
call Ascii2Hex ;Convertimos el dato a hex
xorlw .0
btfsc STATUS,Z ;Ascii2Hex retorno 0?
retlw 0x00 ;Si => retornamos error
movf DatoAux,W
iorwf i2cEEDato,F ;nible bajo de i2cEEDato
retlw 0x01
;**********************************************************************
;*************************** EnvEEDato ***************************
; EnvEEDato Recibe un dato leido de la EEPROM en i2cEEDato y lo
; transmite por el EUSART en ASCII para que pueda
; visualizarse correctamente en el terminal , por ejemlo, si
; i2cEEDato = 6F, se transmitira '6'y'F'.
;**********************************************************************
EnvEEDato
swapf i2cEEDato,W
andlw 0x0F ;primero trabajamos con el nible alto
call Hex2Ascii ;convertimos el hexadecimal a ASCII
movf DatoAux,W
btfss PIR1,TXIF
goto $-1
movwf TXREG ;cargamos TXREG si esta vacio
movf i2cEEDato,W
andlw 0x0F ;trabajamos con el nible bajo
call Hex2Ascii ;convertimos el hexadecimal a ASCII
movf DatoAux,W
btfss PIR1,TXIF
goto $-1
movwf TXREG ;cargamos TXREG si esta vacio
return
;**********************************************************************
;*************************** Ascii2Hex ***************************
; Ascii2Hex La rutina recibe en W un numero o letra de la 'a' a la 'f'
; y devuelve mediante DatoAux un numero en hexadecimal
; equivalente, por ejemplo :
;
; si WREG = '5' => DatoAux = 0x05
; WREG = 'F' => DatoAux = 0x0F
;
; retorna Error si no se recibio un numero o una letra de la 'a' a 'f'
;**********************************************************************
Ascii2Hex
movwf DatoAux
sublw ' '
btfsc STATUS,C ;DatoAux >= '0'?
retlw 0x00 ;No => error
movf DatoAux,W
sublw '9'
btfss STATUS,C ;DatoAux <= '9'?
goto Ascii2HexP1 ;No => revisamos si es letra mayuscula
movlw 0x0F
andwf DatoAux,F
retlw 0x01
Ascii2HexP1
movf DatoAux,W
sublw '@'
btfsc STATUS,C ;DatoAux >= '@'?
retlw 0x00 ;No => error
movf DatoAux,W
sublw 'F'
btfss STATUS,C ;DatoAux <= 'F'?
goto Ascii2HexP2 ;No => revisamos si es letra minuscula
movlw 0x0F
andwf DatoAux,F ;Aqui tenemos un numero del 1 al 6
movlw .9
addwf DatoAux,F ;al sumarle 9 tenemos un valor de 0x0A a 0x0F
retlw 0x01
Ascii2HexP2
movf DatoAux,W
sublw 0x60
btfsc STATUS,C ;DatoAux >= 0x60?
retlw 0x00 ;No => error
movf DatoAux,W
sublw 'f'
btfss STATUS,C ;DatoAux <= 'f'?
retlw 0x00 ;No => error
movlw 0x0F
andwf DatoAux,F ;Aqui tenemos un numero del 1 al 6
movlw .9
addwf DatoAux,F ;al sumarle 9 tenemos un valor de 0x0A a 0x0F
retlw 0x01
;*************************** Hex2Ascii ***************************
; Hex2Ascii Recibe en W un numero de 0x00 a 0x0F y retorna mediante
; DatoAux el equivalente ASCII del numero recibido
; Por ejemplo : Si W = 0x05 => DatoAux = '5'(0x35)
; Si W = 0x0A => DatoAux = 'A'(0x41)
;**********************************************************************
Hex2Ascii
movwf DatoAux
sublw 0x09
btfss STATUS,C ;DatoAux <= '9'?
goto Hex2AsciiP1 ;No => sera letra
movlw 0x30 ;Si => lo convertimos a ASCII
iorwf DatoAux,F ;(0x30 a 0x39)
return
Hex2AsciiP1
movlw 0x09 ;al restarle 9 tenemos 1 si era 0x0A
subwf DatoAux,F ;hasta 6 si era 0x0F
movlw 0x40
iorwf DatoAux,F ;convertimos a ASCII (si 0x0C => 'C')
return
;**********************************************************************
;*************************** RxEusart ***************************
; RxEusart Recibe caracteres y los almacena en BufferRx, sale
; cuando se recibe un enter(0x0D) o cuando se recibieron
; 32 caracteres. La cuenta de los caracteres recibidos se realiza
; mediante ContBytes.
;**********************************************************************
RxEusart
clrf ContBytes
movlw BufferRx
movwf I
RxEusartP0
movf I,W
movwf FSR
btfss PIR1,RCIF ;Se recibio un caracter?
goto $-1 ;No => Esperamos
btfss RCSTA,OERR ;Hubo un dsborde?
goto RxEusartP1 ;No => vamos a leer el caracter
bcf RCSTA,CREN ;Si => reiniciamos la recepcion
bsf RCSTA,CREN
goto RxEusart
RxEusartP1
movf RCREG,W
movwf DatoRx ;guardamos el caracter recibido en DatoRx
xorlw 0x0D
btfsc STATUS,Z ;Se recibio enter?
return ;Si => salimos
movf DatoRx,W ;No => guardamos el dato y hacemos eco
movwf INDF ;BufferRx[I] = DatoRx
btfss PIR1,TXIF ;TXREG vacio?
goto $-1
movwf TXREG ;Si => hacemos eco
incf I,F ;I++
incf ContBytes,F ;ContBytes ++
movf ContBytes,W
xorlw .32
btfss STATUS,Z ;Se recibieron 32 bytes?
goto RxEusartP0 ;No => seguimos recibiendo
movlw .2
call EnvMsg ;Si => mensaje de buffer lleno
btfss PIR1,RCIF ;Esperamos a que no haya ningun byte mas
return ;No hay bytes => Salimos
movf RCREG,W ;si se recibio algun caracter mas
bcf RCSTA,CREN
bsf RCSTA,CREN ;Reiniciamos el Receptor
return
;**********************************************************************
;*************************** EnvMsg *******************************
; EnvMsg Envia un mensaje por el EUSART, recibe el mensaje que se
; quiere enviar en W
;**********************************************************************
EnvMsg
movwf OffsTabla ;guardamos el mensaje que queremos desplegar
movlw HIGH EnvMsgP0 ;Actualizamos PCLATH para hacer un computed
movwf PCLATH ;goto en EnvMsgP0
movlw LOW EnvMsgP0 ;revisamos de no excedernos de la direccion
addwf OffsTabla,W ;en PCLARH
btfsc STATUS,C ;Nos excedemos?
incf PCLATH ;Si => incrementamos PCLATH
movf OffsTabla,W ;No =>realizamos el salto
addwf PCL,F
EnvMsgP0
goto EnvMsg_0 ;Vamos a enviar mensaje 0
goto EnvMsg_1 ;Vamos a enviar mensaje 1
goto EnvMsg_2 ;Vamos a enviar mensaje 2
goto EnvMsg_3 ;Vamos a enviar mensaje 3
goto EnvMsg_4 ;Vamos a enviar mensaje 4
goto EnvMsg_5 ;Vamos a enviar mensaje 5
goto EnvMsg_6 ;Vamos a enviar mensaje 6
goto EnvMsg_7 ;Vamos a enviar mensaje 7
goto EnvMsg_8 ;Vamos a enviar mensaje 8
goto EnvMsg_9 ;Vamos a enviar mensaje 9
goto EnvMsg_10 ;Vamos a enviar mensaje 10
goto EnvMsg_11 ;Vamos a enviar mensaje 11
goto EnvMsg_12 ;Vamos a enviar mensaje 12
goto EnvMsg_13 ;Vamos a enviar mensaje 13
goto EnvMsg_14 ;Vamos a enviar mensaje 14
EnvMsg_0
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_0P0
movlw HIGH Msg_0
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_0 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_0P0
EnvMsg_1
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_1P0
movlw HIGH Msg_1
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_1 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_1P0
EnvMsg_2
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_2P0
movlw HIGH Msg_2
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_2 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_2P0
EnvMsg_3
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_3P0
movlw HIGH Msg_3
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_3 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_3P0
EnvMsg_4
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_4P0
movlw HIGH Msg_4
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_4 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_4P0
EnvMsg_5
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_5P0
movlw HIGH Msg_5
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_5 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_5P0
EnvMsg_6
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_6P0
movlw HIGH Msg_6
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_6 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_6P0
EnvMsg_7
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_7P0
movlw HIGH Msg_7
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_7 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_7P0
EnvMsg_8
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_8P0
movlw HIGH Msg_8
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_8 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_8P0
EnvMsg_9
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_9P0
movlw HIGH Msg_9
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_9 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_9P0
EnvMsg_10
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_10P0
movlw HIGH Msg_10
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_10 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_10P0
EnvMsg_11
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_11P0
movlw HIGH Msg_11
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_11 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_11P0
EnvMsg_12
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_12P0
movlw HIGH Msg_12
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_12 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_12P0
EnvMsg_13
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_13P0
movlw HIGH Msg_13
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_13 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_13P0
EnvMsg_14
clrf OffsTabla ;Para comenzar desde el primer caracter
EnvMsg_14P0
movlw HIGH Msg_14
movwf AddrTabla+1 ;Con AddrTabla direccionamos el
movlw LOW Msg_14 ;mensaje que queremos desplegar
movwf AddrTabla
call Mensajes ;recojemos el carcater que toca
movwf DatoTx ;y lo guardamos en DatoTx
xorlw 0x00
btfsc STATUS,Z ;Se tiene 0x00?
return ;si => se termino el mensaje
;no => continuamos
call EUSART_Tx ;llamamos a la rutina que envia caracteres
incf OffsTabla,F ;Para transmitir el siguiente caracter
goto EnvMsg_14P0
EUSART_Tx
btfss PIR1,TXIF ;TXREG esta vacio?
goto $-1 ;No => esperamos
movf DatoTx,W
movwf TXREG ;cargamos TXREG
return
Mensajes
movf OffsTabla,W
addwf AddrTabla,W ;determinamos si el sato no excede 0xFF
btfsc STATUS,C
incf AddrTabla+1,F ;Si excede => incrementamos la parte alta
movf AddrTabla+1,W
movwf PCLATH ;actualizamos PCLATH(parte alta)
movf OffsTabla,W
addwf AddrTabla,W ;volvemos a calcular el salto
movwf PCL ;actualizamos PCL para realizar el salto.
Msg_0
DT "\n\rEjemplo de lectura y escritura de una memoria i2c\n\r",0
Msg_1
DT "\n\rIntroduzca el numero de una de las opciones :\n\r\n\r"
DT "1 Escribir un byte\n\r"
DT "2 Leer un byte\n\r"
DT "3 Escribir varios bytes (maximo 32)\n\r"
DT "4 Leer varios bytes (maximo 80)\n\r\n\r",0
Msg_2
DT "\n\rBuffer lleno\n\r",0
Msg_3
DT "\n\r***** Escribir un byte *****\n\r"
DT "Introduzca direccion en hexadecimal (2 bytes): ",0
Msg_4
DT "\n\rIntroduzca dato en hexadecimal (1 byte): ",0
Msg_5
DT "\n\rValor(es) escrito(s)",0
Msg_6
DT "\n\r***** Leer un byte *****\n\r"
DT "Introduzca direccion en hexadecimal (2 bytes): ",0
Msg_7
DT "\n\rEl valor leido es: ",0
Msg_8
DT "\n\rValor no valido\n\r",0
Msg_9
DT "\n\r***** Escribir varios bytes *****\n\r"
DT "Introduzca direccion en hexadecimal (2 bytes): ",0
Msg_10
DT "\n\rIntroduzca los datos (maximo 32 caracteres):\n\r",0
Msg_11
DT "\n\r***** Leer varios bytes *****\n\r"
DT "Introduzca direccion en hexadecimal (2 bytes): ",0
Msg_12
DT "\n\rIntroduzca la cantidad de bytes a leer (max 80): ",0
Msg_13
DT "\n\rLos valores leidos son:\n\r",0
Msg_14
DT "\n\r**********************************************\n\r ",0
#include <i2cCom.inc>
#include <EE24AA64.inc>
ORG 0x2100 ; Pocision de la EEPROM interna
DE 1,2,3,4 ; define las primeras cuatro posiciones de la
; EEPROM como 1,2,3 y 4
END ; directiva 'fin del programa'