3
« en: Martes 11 de Diciembre de 2007, 00:28 »
Hola a todos.. tengo un gran problema con un montaje que estoy haciendo. No logro poner a funcionar un reloj Ds 1307 con un pic 16f877. Abajo escribo el codigo que utilizo para ello. Está basado en una nota de aplicacion para uso de protocolo i2c de microchip.
Solo hago algunas variaciones para el baud rate pues el pic usa un cristal de 4 Mhz y no de 10 como en la nota de aplicacion (AN976: I2c y EEprom).
Al final de todo solo veo en el display (lcd 2x16) ????????
Si alguien me puede ayudar les agradeceria en el alma!!
a continuacion el codigo
Nota: los registros y pines que se incluyen corresponden a
una aplicacion que si me funciona y un fichero con las subrutinas del LCD
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
;
; RELOJ DS 1307, CRISTAL 32.768 KHz
;
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LIST P=16F877
__CONFIG _XT_OSC & _WDT_OFF & _LVP_OFF
;---------------------------------------------------
; Port C pin descriptions
; SCL bit = 3 ;SALIDA RELOJ I2C
; SDA bit = 4 ;SALIDA DATOS I2C
; Tx bit = 6 ;SALIDA DATOS RS232
; Rx bit = 7 ;ENTRADA DATOS RS232
;----------------------------------------------------
; 4MHz crystal is being used
;
;*******************RAM register definitions**********************
datai equ 20h ; Data input byte buffer
datao equ 21h ; Data output byte buffer
bytecount equ 22h ; Counter for byte loops
pollcnt equ 23h ; Counter for polling loops
loops equ 24h ; Delay loop counter
loops2 equ 25h ; Delay loop counter
LCD_TEMP equ 26h ; Posiciones auxiliares en el banco 0
DELAY equ 27h ; para temporizar
X_DELAY equ 28h ; para temporizar
AUX equ 29h ; para guardar temporalmente
DIRH equ 2ah
DIRL equ 2bh
CounterA equ 2ch
CounterB equ 2dh
CounterC equ 2eh
XmtReg equ 2fh
I2C_Banderas equ 30h
Segundo equ 31h
Minuto equ 32h
Hora equ 33h
DiaSemana equ 34h
Dia equ 35h
Mes equ 36h
Anho equ 37h
W_TEMP equ 38h ;almacén temporal para el registro W
ST_TEMP equ 39h ;almacén temporal para el registro STATUS
PCLATH_TEMP equ 3ah ;almacén temporal del registro PCLATH
BCD0 equ 3bh ;(DECENAS:UNIDADES)
BCD1 equ 3ch ;(MILLARES:CENTENAS)
BCD2 equ 3dh ;(0:DECENAS DE MIL)
FACTOR1 equ 3eh ;Uno de los factores del producto
FACTOR2 equ 3fh ;Otro de los factores del subprograma producto
SUMA_ALTO equ 40h ;Posición que almacena la parte alta de FACTOR1 desplazado a la izq.
SUMA_BAJO equ 41h ;almacenará la parte baja de FACTOR1 desplazado a la izquierda
CONTADOR equ 42h ;Para el subprograma de multiplicación, cuenta sumas parciales
BIN_ALTO equ 43h ;Parte alta del valor medido en binario
BIN_BAJO equ 44h ;Parte baja del periodo en binario
TMP equ 45h ;otra variable auxiliar
;*******************Macro definitions*****************************
WRITE_ds equ b'11010000' ; Control byte for write operations
READ_ds equ b'11010001' ; Control byte for read operations
;*******************Include file**********************************
include "p16f877.inc" ; Include file for a PIC16F877
errorlevel -302 ; Suppress message 302 from list file
;**********************************************************
LCD_DATA EQU PORTD ;DATOS se conecta a PORTD
LCD_DATA_TRIS EQU TRISD ;
LCD_CTRL EQU PORTE ;CONTROL se conecta a PORTE
LCD_CTRL_TRIS EQU TRISE ;
LCD_LINE0 EQU 0x000 ;dirección comienzo línea superior DDRAM del LCD
LCD_LINE1 EQU 0x040 ;dirección comienzo línea inferior DDRAM del LCD
; También se deben definir los Bits de control:
LCD_E EQU 2 ; Enable será el bit 1 del PORTE
LCD_RW EQU 1 ; Read/Write bit 2 del PORTE
LCD_RS EQU 0 ; RS será el bit 3 del PORTE
; En STATUS
CARRY equ 0
CERO equ 2
;*****************************************************************
org 0x000 ; Set the reset vector
goto start ; Go to the beginning of main
include "volt2.ASM" ; Solo contiene subrutinas para el LCD
;*******************Begin Main Program****************************
;---------------------------------------------------------------
start
call Init ; Initialize device
;- CARGA INICIAL DEL DS1307------;
movlw 00h ;
movwf Segundo ;Segundos inician en 00
movlw 42h ;
movwf Minuto ;Minutos inician
movlw 08h
movwf Hora ;Hora inicia en 08
movlw 02h ;
movwf DiaSemana ;Dia 2 equivale a lunes
movlw 03h ;
movwf Dia ;Dia 03
movlw 12h
movwf Mes ; Mes 12 equivale a dic.
movlw 07h
movwf Anho ; Año 2007
clrf PORTC
; goto display
;-----------------------------------------------------------------------
call BSTART ;
movlw WRITE_ds ; Pbra control modo Escritura
movwf datao
call TX
movlw 0 ; Se indica la direcc. 0h.
movwf datao
call TX
movlw b'00000000' ; activa bit7 del reg 00 (enable reloj).
movwf datao
call TX
call BSTOP ; Termina de enviar datos.
bsf PORTC,5
call PDelay
call BSTART ;
movlw WRITE_ds ; Pbra control modo Escritura
movwf datao
call TX
movlw b'00000111' ; direccc. 07h.
movwf datao
call TX ; ctl de la señal cuadrada
movlw b'00010000' ; output pin 7. señal cuadrada de 1 Hz
movwf datao
call TX
call BSTOP ; Termina de enviar datos.
;------------------------------------------------------
;-inicializando el reloj ds1307-------------------------;
call BSTART ;
movlw WRITE_ds ; Pbra control modo Escritura
movwf datao
call TX ;
movlw 0x00 ; direccion inicial 00
movwf datao
call TX
movf Segundo,0 ; Pasa los segundos de la memoria del PIC16 al DS1307.
movwf datao
call TX
movf Minuto,0 ;
movwf datao
call TX
movf Hora,0
movwf datao
call TX
movf DiaSemana,0
movwf datao
call TX
movf Dia,0
movwf datao
call TX
movf Mes,0
movwf datao
call TX
movf Anho,0
movwf datao
call TX
call BSTOP ; Termina de enviar datos.
call PDelay
;--------------------------------------------------------------------------------
;----------------------------------------------------------
; lee y actualiza el reloj
;----------------------------------------------------------
RTC_LEE
call BSTART ;
movlw WRITE_ds ; modo escritura
call TX
movlw 0x00 ; a los segundos.
movwf datao
call TX
call BRESTART
movlw READ_ds ; Pbra control modo Lectura
movwf datao
call TX
call RX ; Lee los segundos.
movf datai,0
movwf Segundo ; Lo carga en el registro correspondiente.
call RX ;
movf datai,0 ;
movwf Minuto ;
call RX ;
movf datai,0
movwf Hora
call RX
movf datai,0
movwf DiaSemana
call RX
movf datai,0
movwf Dia
call RX
movf datai,0
movwf Mes
;------------------------------------------------------------
; GENERA UN NO ACK INDICANDO QUE ES EL ULTIMO BYTE A LEER
;------------------------------------------------------------
bsf STATUS,RP0 ; Select Bank 01
bsf SSPCON2,ACKDT ; Select to send NO ACK bit genera un NO ACK(Generate NO ACK)
bcf STATUS,RP0 ; Select Bank 00
call RX ;Recibe el ultimo byte
movf datai,0
movwf Anho
call BSTOP ; Termina de leer datos.
bsf PORTC,5
;**********************************************************
display
movlw LCD_LINE1+1 ;Cargo en W la dirección de la línea 0
call LCDSDDA ;y coloco el puntero de la DDRAM del LCD ahí
movlw Segundo
movwf FSR
movlw 7
movwf CONTADOR
show
movf INDF,0 ;
andlw 0xF0
movwf AUX ;
swapf AUX,0 ;
addlw A'0' ;
call LCDPUTCHAR_4_2 ;
movf INDF,0 ;
andlw 0x0F
addlw A'0' ;
call LCDPUTCHAR_4_2 ;
incf FSR,1
decfsz CONTADOR,1
goto show
bcf PORTC,5
goto RTC_LEE
nop
goto $-1 ; Loop here forever
;_----------------------------------------------
;*******************Initialization subroutine*********************
; This routine initializes the MSSP module
; for I2C Master mode, with a 100 kHz clock.
;*****************************************************************
Init
bcf STATUS,RP1 ; Select Bank 01
bsf STATUS,RP0
movlw b'00001110' ;PORTA con RA0 analógica, resto como digitales
movwf ADCON1 ;referencia de 5V y resultado justificado
;a la izquierda: ADRESH_ADRESL
clrf LCD_DATA_TRIS ;Defino PORTD de salidas
movlw 0 ; b'11110001' En el PORTA las 3 salidas
movwf LCD_CTRL_TRIS ;para E, RS y R/W
movlw 0xCF ; Predivisor de 128 asociado al Watchdog ;///////// ;
movwf OPTION_REG
movlw b'10011111'
movwf TRISC ; Set PORTC to all inputs
clrf SSPSTAT ; Disable SMBus inputs
bsf SSPSTAT,SMP ; Disable slew rate control
movlw 9 ; Load 9 into WREG ((fosc/100khz)/4)-1 = 9
movwf SSPADD ; Setup 100 kHz I2C clock
clrf SSPCON2 ; Clear control bits
movlw b'00100100' ;Configuracion USART
movwf TXSTA ;y activacion de transmision
movlw .25 ;9600 baudios
movwf SPBRG
bcf STATUS,RP0 ; Select Bank 00
movlw b'11000001' ;Configuramos entrada por canal analógico 0 (RA0)
movwf ADCON0 ;y reloj RC interno de conversión TAD=4us típico
movlw b'00101000'
movwf SSPCON ; Enable SSP, select I2C Master mode
bcf PIR1,SSPIF ; Clear SSP interrupt flag
bcf PIR2,BCLIF ; Clear Bit Collision flag
bsf RCSTA,SPEN ;se activa la USART
bcf PIR1,ADIF ;Pongo a 0 el flag de fin de conversión
call LCD_RST_P2P ;Reset software del módulo LCD
call LCDINIT_4 ;Inicializamos el LCD para definir funcionamiento
;interface de 4 bits y 2 líneas visibles
call LCDCLEAR ;Limpiamos pantalla al principio
retlw 0
;*******************Start bit subroutine**************************
; This routine generates a Start condition
; (high-to-low transition of SDA while SCL
; is still high.
;*****************************************************************
BSTART
bcf STATUS,RP1
bcf STATUS,RP0 ; Select Bank 00
bcf PIR1,SSPIF ; Clear SSP interrupt flag
bsf STATUS,RP0 ; Select Bank 01
bsf SSPCON2,SEN ; Generate Start condition
bcf STATUS,RP0 ; Select Bank 00
bstart_wait
btfss PIR1,SSPIF ; Check if operation completed
goto bstart_wait ; If not, keep checking
retlw 0
;*******************Restart bit subroutine**************************
; This routine generates a Repeated Start
; condition (high-to-low transition of SDA
; while SCL is still high.
;*****************************************************************
BRESTART
bcf STATUS,RP1
bcf STATUS,RP0 ; Select Bank 00
bcf PIR1,SSPIF ; Clear SSP interrupt flag
bsf STATUS,RP0 ; Select Bank 01
bsf SSPCON2,RSEN ; Generate Restart condition
bcf STATUS,RP0 ; Select Bank 00
brestart_wait
btfss PIR1,SSPIF ; Check if operation completed
goto brestart_wait ; If not, keep checking
retlw 0
;*******************Stop bit subroutine***************************
; This routine generates a Stop condition
; (low-to-high transition of SDA while SCL
; is still high.
;*****************************************************************
BSTOP
bcf STATUS,RP1
bcf STATUS,RP0 ; Select Bank 00
bcf PIR1,SSPIF ; Clear SSP interrupt flag
bsf STATUS,RP0 ; Select Bank 01
bsf SSPCON2,PEN ; Generate Stop condition
bcf STATUS,RP0 ; Select Bank 00
bstop_wait
btfss PIR1,SSPIF ; Check if operation completed
goto bstop_wait ; If not, keep checking
retlw 0
;*******************Data transmit subroutine**********************
; This routine transmits the byte of data
; stored in 'datao' to the serial EEPROM
; device. Instructions are also in place
; to check for an ACK bit, if desired.
; Just replace the 'goto' instruction,
; or create an 'ackfailed' label, to provide
; the functionality.
;*****************************************************************
TX
bcf STATUS,RP1
bcf STATUS,RP0 ; Select Bank 00
bcf PIR1,SSPIF ; Clear SSP interrupt flag
movf datao,W ; Copy datao to WREG
movwf SSPBUF ; Write byte out to device
tx_wait
btfss PIR1,SSPIF ; Check if operation completed
goto tx_wait ; If not, keep checking
; bsf STATUS,RP0 ; Select Bank 01
; btfsc SSPCON2,ACKSTAT ; Check if ACK bit was received
; goto ackfailed ; This executes if no ACK received
retlw 0
;*******************Data receive subroutine***********************
; This routine reads in one byte of data from
; the serial EEPROM device, and stores it in
; 'datai'. It then responds with either an
; ACK or a NO ACK bit, depending on the value
; of 'ACKDT' in 'SSPCON2'.
;*****************************************************************
RX
bcf STATUS,RP1
bcf STATUS,RP0 ; Select Bank 00
bcf PIR1,SSPIF ; Clear SSP interrupt flag
bsf STATUS,RP0 ; Select Bank 01
bsf SSPCON2,RCEN ; Initiate reception of byte
bcf STATUS,RP0 ; Select Bank 00
rx_wait
btfss PIR1,SSPIF ; Check if operation completed
goto rx_wait ; If not, keep checking
movf SSPBUF,W ; Copy byte to WREG
movwf datai ; Copy WREG to datai
bcf PIR1,SSPIF ; Clear SSP interrupt flag
bsf STATUS,RP0 ; Select Bank 01
bsf SSPCON2,ACKEN ; Generate ACK/NO ACK bit
bcf STATUS,RP0 ; Select Bank 00
rx_wait2
btfss PIR1,SSPIF ; Check if operation completed
goto rx_wait2 ; If not, keep checking
retlw 0
;PIC Time Delay = 1,0000020 s with Osc = 4 MHz
PDelay
;return
movlw D'6' ;"6"
movwf CounterC
movlw D'24' ;D'24'
movwf CounterB
movlw D'168' ;D'168'
movwf CounterA
loop
decfsz CounterA,1
goto loop
decfsz CounterB,1
goto loop
decfsz CounterC,1
goto loop
return
END