Subrutina de envio de 1 byte por RS232 a 4800 baudios

Buenas noches a todos. Aca estaba revisando un programa que tengo mas o menos armado que es un datalogger (usando el PIC 12F675).
El programa adquiere datos del puerto analogico GP3, y usa el conversor A/D. Luego los 8 bits mas significativos los almacena en una variable que luego es guardada en una posicion de la EEPROM interna.
30 segundos despues hace lo mismo con otro dato. Y asi sucesivamente..

Ahora, tengo un problema cuando quiero bajar los datos de la EEPROM a mi pc usando el hyperterminal de windows xp.

En el programa esta todo calculado para que haya una transmision a 4800 baudios. Pero al conectar el pic al puerto serie de la pc a veces no marca nada la pc y hay veces que recibe datos pero recibe cualquier cosa.

El hyperterminal esta configurado como:
- datos de 8 bits
- 1 bit de parada
- ningun control de flujo
- 4800 baudios

En fin, adjunto la subrutina de transmision a ver si alguno lo revisa a ver que le parece...

Código:
;-------------------------------------------------------------
; SUBRUTINA DE TRANSMISION DE UN BYTE POR EL PUERTO SERIE 
;-------------------------------------------------------------
; la transmision se realiza a 4800 baudios

TRANSMITIR_BYTE	bsf			GPIO,1			;transmite el bit de inicio del byte
				call		demora195
				nop
				nop							;estos 3 nop estan para compensar y que todos los bit midan lo mismo
				nop
				clrf		contador
				goto		analizar_bit

analizar_bit	incf		contador		;para el primer bit, contador se pone en 1.
				movlw		b'00000001'
				andwf		datoleido,w		;me quedo con el ultimo bit
				movwf		aux
				decf		aux,w			;y le resto uno
				btfsc		STATUS,C		
				goto		transmitir_cero	;si la resta da negativa, era un cero
				goto		transmitir_uno	;si la resta no me da negativa, era un uno
				
transmitir_cero	bcf			GPIO,1
				call		demora195
				rrf			datoleido		;deja preparado datoleido para el proximo bit
				movlw		d'8'
				subwf		contador,w		;se fija si ya se transmitieron los 8 bits
				btfss		STATUS,Z
				goto		analizar_bit	;si contador < 8 sigue transmitiendo
				goto		fintransmision	;sino termina la transmision

transmitir_uno	bsf			GPIO,1
				call		demora195
				rrf			datoleido		;deja preparado datoleido para el proximo bit
				movlw		d'8'
				subwf		contador,w		;se fija si ya se transmitieron los 8 bits
				btfss		STATUS,Z
				goto		analizar_bit	;si contador < 8 sigue transmitiendo
				goto		fintransmision	;sino termina la transmision

fintransmision	nop
				nop							;estos 4 nop estan para que todos los bit midan lo mismo
				nop
				nop
				bcf			GPIO,1
				call		demora195
				nop
				nop
				nop
				retlw		0

Muchas gracias por adelantado por su tiempo.
 
Si adjuntaras el proyecto completo sería más fácil poderte ayudar.

Normas del Foro 03: Cuando preguntes, danos la máxima información posible. ¡ No somos adivinos !
 
Bueno, entonces aca adjunto el programa completo. Lo que pasa es que pense que si ponía todo nadie lo iba a leer el mensaje por ser muy largo el programa...

Código:
;-------------------------------------------------------------
; Define el PIC
;-------------------------------------------------------------
				list 		p=12f675
				#include 	P12F675.INC
				__CONFIG    _MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _PWRTE_ON

resetear		org			0				;indica empezar el programa
				goto		normal
				org			4				;indica a donde ir si hay una interrupcion
				goto		interrupcion
				org			5

;-------------------------------------------------------------
; Calibración del RC interno
;-------------------------------------------------------------
normal			bsf 		STATUS,RP0    					;Bank 1
				call 		3FFh          					;Get the cal value
				movwf 		OSCCAL       					;Calibrate
				bcf			STATUS,RP0
;-------------------------------------------------------------
; Declaracion de variables
;-------------------------------------------------------------
conversion		equ			d'00041'
direccion		equ			d'00042'
CounterA		equ			d'00043'
CounterB		equ			d'00044'
CounterC		equ			d'00045'
reiniciar		equ			d'00046'
doblev			equ			d'00047'
dirleida		equ			d'00048'
datoleido		equ			d'00049'
contador		equ			d'00050'
aux				equ			d'00051'

;-------------------------------------------------------------
; Configuración entradas y salidas (GP3 entrada analogica y GP2 entrada INT exterior)
;-------------------------------------------------------------
				bcf			STATUS,RP0      ;se pasa al banco 0
				movlw		b'00001101'     ;[configura 1)"justificado a la izquierda" (todos los bit comprimidos hacia la izquierda del restultado), 2)Vref en Vdd ]
				movwf		ADCON0          ;[3)entrada analogica en GP1. 4)no empieza la conversion y esta operable (ultimos 2 bits)                        ]
				clrf 		GPIO 			;limpia las salidas
				movlw 		b'00000111'		;[desactiva el comparador de tension y quedan libres GP1,GP2 y GP0]
				movwf 		CMCON 			;
				bsf 		STATUS,RP0 		;se pasa al banco 1
				movlw		b'00011000'		;configura 1)toma el divisor de tiempo fosc/8. 2)configura GP3 como entrada analogica y las otras como digitales I/O
				movwf 		ANSEL 			;
				movlw 		b'001101'       ;Configura GP3, GP2 y GP0 como entradas
				movwf 		TRISIO
				bsf			OPTION_REG,INTEDG ; se genera la interrupcion con flanco ascendente de GP2
				bcf			STATUS,RP0		;se pasa al banco 0
				movlw		b'10010000'
				movwf		INTCON			;configura habilitadas las interrupciones y GP2/INT externa
				movlw		b'00000100'		;habilita ioc en GP2
				movwf		IOC
								
;-------------------------------------------------------------
; Programa principal
;-------------------------------------------------------------
				
principal		movlw		d'0'
				movwf		GPIO			;apaga todos los leds			
				movwf		direccion		;comienza a grabar datos desde la posición d'0' de la EEPROM
				movwf		reiniciar		;apaga la bandera que indica si hay que reiniciar el programa por una interrupcion de menos de 0.5sg

inicio			btfss		GPIO,0			;pregunta para empezar conversion cada 30 segundos
				goto		nada
				goto		continuar
nada			bcf			reiniciar,0		;mientras no esta activo el programa se borra la bandera de reiniciar
				goto		inicio

continuar		btfsc		reiniciar,0		;si detecta que hay que reiniciar, reinicia
				goto		resetear
convertir		call		CONVERSORAD
				bsf			STATUS,RP0		;pasa al banco 1 (donde se maneja la EEPROM)
				movf		conversion,w
				movwf		EEDATA			;y lo deja listo para grabar									CONFIGURACION DE DATOS A GRABAR EN EEPROM
				movf		direccion,w		;tambien carga la direccion donde se va a grabar el dato
				movwf		EEADR
				incf		direccion,1		;deja seteado donde se va a grabar el proximo dato				
				call		ESCRIBIR_EEPROM
				bsf			GPIO,5			;avisa que se grabo un dato
				call		demora0.1
				bcf			GPIO,5
				call		demora30
				goto		continuar		;vuelve a preguntar si hay que reiniciar y sigue juntando datos

;-------------------------------------------------------------
; SUBRUTINA QUE OBTIENE EL VALOR DEL CONVERSOR A/D (GP3)
;-------------------------------------------------------------
CONVERSORAD		bsf			ADCON0,1    	;comienza la conversion A/D				
convierte		btfsc		ADCON0,1		;espera a que convierta el dato
				goto		convierte
				movf		ADRESH,w        ;pasa el resultado de la conversion a w
				movwf		conversion		;y luego a la variable conversion
				retlw		0

;-------------------------------------------------------------
; SUBRUTINA DE ESCRITURA DE DATOS EN EEPROM (se deben haber cargado EEDATA y EEADR)
;-------------------------------------------------------------
ESCRIBIR_EEPROM	bsf 		STATUS,RP0 		;Bank 1                                						
				bsf 		EECON1,WREN 	;Enable write
				bcf			INTCON,GIE
				movlw		0x55 			;Inicio de las intrucciones para EECON2
				movwf		EECON2
				movlw		0xAA 		
				movwf		EECON2			;Fin de las intrucciones para EECON2
				bsf 		EECON1,WR 		;Start the write											
				bcf        	EECON1,WREN     ; disable Write
				bsf 		INTCON,GIE 		;habilita las interrupciones
				bcf       	STATUS,RP0      ; Banco 0 
				retlw		0

;-------------------------------------------------------------
; SUBRUTINA DE RETARDO DE 30 SEGUNDOS
;-------------------------------------------------------------
demora30		movlw		D'153'
				movwf		CounterC
				movlw		D'49'
				movwf		CounterB
				movlw		D'161'
				movwf		CounterA
loop1			decfsz		CounterA,1
				goto		loop1
				decfsz		CounterB,1
				goto		loop1
				decfsz		CounterC,1
				goto		loop1
				retlw		0	

;-------------------------------------------------------------
; SUBRUTINA DE RETARDO DE 0.1 SEGUNDOS
;-------------------------------------------------------------
demora0.1		movlw		D'130'
				movwf		CounterB
				movlw		D'221'
				movwf		CounterA
loop2			decfsz		CounterA,1
				goto		loop2
				decfsz		CounterB,1
				goto		loop2
				retlw		0	

;-------------------------------------------------------------
; SUBRUTINA DE RETARDO DE 195 MICROSEGUNDOS  (1/(195+13)) = 4808 baudios
;-------------------------------------------------------------
demora195		movlw	D'63'
				movwf	CounterA
loop3			decfsz	CounterA,1
				goto	loop3
				nop
				retlw	0
				
;-------------------------------------------------------------
; SUBRUTINA DE INTERRUPCION
;-------------------------------------------------------------
;NOTA: cuando se pone a 1 GP2, se produce una interrupcion. Si la misma dura mas de 0.5 sg, se transfieren los datos por RS232 a una pc. Si dura menos, se reinicia el programa.

interrupcion	movwf		doblev			;guarda el dato de w antes de la iterrupcion
				bsf			GPIO,4			;indica que se acepto una interrupcion
				call		demora0.1
				btfss		GPIO,2			
				goto		volver
				call		demora0.1
				btfss		GPIO,2
				goto		volver
				call		demora0.1
				btfss		GPIO,2
				goto		volver
				call		demora0.1
				btfss		GPIO,2
				goto		volver
				bcf			GPIO,4			;indica que comienza la tansferencia de datos por RS232
				call		BAJAR_DATOS		
				goto		volver		

volver			bcf			GPIO,4
				bsf			reiniciar,0		;marca que hay que reiniciar
				bcf			INTCON,INTF		;y borra la bandera de que ocurrio una interrupcion
				movf		doblev,w		;reestablece el valor de w antes de volver
				RETFIE

;-------------------------------------------------------------
; SUBRUTINA DE TRANSFERENCIA DE DATOS A PC POR RS232
;-------------------------------------------------------------
BAJAR_DATOS		movlw		d'0'			;empieza a leer los datos de la EEPROM desde la direccion 0.
				movwf		dirleida
leerotro		call		LEER_DATO
				call		TRANSMITIR_BYTE
				incf		dirleida
				movf		direccion,w		;carga la direccion hasta la que se grabo, y la resta de la direccion actual transmitida. Cuando sean iguales se detiene el proceso.
				subwf		dirleida,w
				btfsc		STATUS,C		;corrobora si la resta dio resultado "negativo"
				goto		leerotro		;si dio negativo hay que seguir transmitiendo		
				retlw		0				;si ya se llego al numero de datos tomados se detiene el proceso

;-------------------------------------------------------------
; SUBRUTINA DE LECTURA DE DATOS DE LA EEPROM (cargar en "dirleida" la direccion del dato a leer)
;-------------------------------------------------------------
LEER_DATO		bsf 		STATUS,RP0 		;Bank 1
				movf 		dirleida,w		;carga la direccion a leer
				movwf 		EEADR 			;Address to read
				bsf 		EECON1,RD 		;EE Read
				movf 		EEDATA,W		;Move data to W
				movwf		datoleido
				retlw		0

;-------------------------------------------------------------
; SUBRUTINA DE TRANSMISION DE UN BYTE POR EL PUERTO SERIE 
;-------------------------------------------------------------
; la transmision se realiza a 4800 baudios

TRANSMITIR_BYTE	bsf			GPIO,1			;transmite el bit de inicio del byte
				call		demora195
				nop
				nop							;estos 3 nop estan para compensar y que todos los bit midan lo mismo
				nop
				clrf		contador
				goto		analizar_bit

analizar_bit	incf		contador		;para el primer bit, contador se pone en 1.
				movlw		b'00000001'
				andwf		datoleido,w		;me quedo con el ultimo bit
				movwf		aux
				decf		aux,w			;y le resto uno
				btfsc		STATUS,C		
				goto		transmitir_cero	;si la resta da negativa, era un cero
				goto		transmitir_uno	;si la resta no me da negativa, era un uno
				
transmitir_cero	bcf			GPIO,1
				call		demora195
				rrf			datoleido		;deja preparado datoleido para el proximo bit
				movlw		d'8'
				subwf		contador,w		;se fija si ya se transmitieron los 8 bits
				btfss		STATUS,Z
				goto		analizar_bit	;si contador < 8 sigue transmitiendo
				goto		fintransmision	;sino termina la transmision

transmitir_uno	bsf			GPIO,1
				call		demora195
				rrf			datoleido		;deja preparado datoleido para el proximo bit
				movlw		d'8'
				subwf		contador,w		;se fija si ya se transmitieron los 8 bits
				btfss		STATUS,Z
				goto		analizar_bit	;si contador < 8 sigue transmitiendo
				goto		fintransmision	;sino termina la transmision

fintransmision	nop
				nop							;estos 4 nop estan para que todos los bit midan lo mismo
				nop
				nop
				bcf			GPIO,1
				call		demora195
				nop
				nop
				nop
				retlw		0
				
				END

Gracias por la respuesta
 
En tu post #1 dices que usas GP3 como entrada analógica, y en el código también, pero GP3 es el pin MCLR
Ahora sería bueno que colocaras el esquema del proyecto para saber como tienes las conexiones.
En el código solo se puede determinar que usas GP4 y GP5 como salidas de aviso, y GP1 como Tx.
Pero algo no concuerda cuando configuras el registro ANSEL y TRISIO

Saludos.
 
En GP0 hay conectado un interruptor, el boton para iniciar el muestreo.
En GP1 esta conectado un transistor PNP como conversor de señal para manejar con pulsos TTL el puerto serie usando la misma alimentacion del puerto serie (este esquema de conexion lo busque un google y me previene de usar el MAX232 que no lo logro conseguir), agrego la direccion de donde se puede ver:

http://www.google.com.ar/imgres?q=t...0&ndsp=20&ved=1t:429,r:3,s:0,i:94&tx=83&ty=22

Es la conexion superior la que estoy usando.

En GP2 hay conectado un interruptor, el de interrupcion, que al ser presionado mas de 0,5 segundos activa la transferencia por RS232 a la pc.
En GP3 esta la entrada analogica entre 0 y 5 volts.
En GP4 y GP5 hay leds para avisar que esta pasando.
 
En GP3 esta la entrada analogica entre 0 y 5 volts.
OK. Pero insisto, GP3 es el pin MCLR/Vpp. No funciona como conversor AD
Puede ser configurado como entrada, pero no análoga.

2AD5x900y900.jpg


Así que tendrás que realizar algunos cambios al programa.
Ya que tengas resuelto esto, te podré decir como hacer el volcado de información a la PC.

Suerte.
 
Mil disculpas. No había notado el detalle de que AN3 era en realidad GP4...
Muchas gracias por la corrección!
Cuando tenga algo más de tiempo voy a cambiar los puertos en el programa a ver si así funciona mejor..

Igualmente me resulta extraño, porque por mas de que este tiempo se hubiesen estado grabando datos de cualquier valor en la eeprom, al querer pasarlos por el puerto serie a la pc tenía un problema, que era que la pc a veces no leía nada y a veces leía cualquier cosa...
Tengo serias dudas de si el "hardware" (con el transistor PNP que utilicé) es correcto o si funciona mal. No se si tendrás experiencias con este tipo de interfaz "barata", pero me sería útil si pudieses confirmarme si alguna vez probaste usando transistores para la interfaz y si funciona realmente...

Gracias por tu tiempo !
 
Tengo serias dudas de si el "hardware" (con el transistor PNP que utilicé) es correcto o si funciona mal. No se si tendrás experiencias con este tipo de interfaz "barata", pero me sería útil si pudieses confirmarme si alguna vez probaste usando transistores para la interfaz y si funciona realmente.
Claro que tengo experiencia con ese tipo de interfaz a transistores, incluso probé varias. :)
Pero definitivamente la que mejor funciono en mis experimentos fue con transistores NPN.

Esta es la interfaz.
SCH NPN.gif
Como veras, tiene las etapas Rx y Tx separadas, y funciona perfectamente.

Suerte.
 
Bueno, hice varias correcciones en el proyecto.
Tome en cuenta tus recomendaciones sobre reasignar los pines, y lo agregué en el código fuente.

El nuevo código con la distribución de pines y todo es el siguiente:

Código:
;-------------------------------------------------------------
; Asignación de pines
;-------------------------------------------------------------
;
;													+5V	-|---U---|- GND
; LED y buzzer que indican escritura de datos en EEPROM -|5		0|- LED indicador de estado de GP2 (util en interrupciones)
;										Datos conv A/D  -|4		1|- Al puerto serie
;	 									 Int. Inicio	-|3-----2|- Int. parada/transferir

;-------------------------------------------------------------
; Define el PIC
;-------------------------------------------------------------
				list 		p=12f675
				#include 	P12F675.INC
				__CONFIG    _MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _PWRTE_ON

resetear		org			0				;indica empezar el programa
				goto		normal
				org			4				;indica a donde ir si hay una interrupcion
				goto		interrupcion
				org			5

;-------------------------------------------------------------
; Calibración del RC interno
;-------------------------------------------------------------
normal			bsf 		STATUS,RP0    					;Bank 1
				call 		3FFh          					;Get the cal value
				movwf 		OSCCAL       					;Calibrate
				bcf			STATUS,RP0
;-------------------------------------------------------------
; Declaracion de variables
;-------------------------------------------------------------
conversion		equ			d'00041'
direccion		equ			d'00042'
CounterA		equ			d'00043'
CounterB		equ			d'00044'
CounterC		equ			d'00045'
reiniciar		equ			d'00046'
doblev			equ			d'00047'
dirleida		equ			d'00048'
datoleido		equ			d'00049'
contador		equ			d'00050'
aux				equ			d'00051'

;-------------------------------------------------------------
; Configuración entradas y salidas (GP3 entrada analogica y GP2 entrada INT exterior)
;-------------------------------------------------------------
				bcf			STATUS,RP0      ;se pasa al banco 0
				movlw		b'00001101'     ;[configura 1)"justificado a la izquierda" (todos los bit comprimidos hacia la izquierda del restultado), 2)Vref en Vdd ]
				movwf		ADCON0          ;[3)entrada analogica en GP3. 4)no empieza la conversion y esta operable (ultimos 2 bits)                        ]
				clrf 		GPIO 			;limpia las salidas
				movlw 		b'00000111'		;[desactiva el comparador de tension y quedan libres GP1,GP2 y GP0]
				movwf 		CMCON 			;
				bsf 		STATUS,RP0 		;se pasa al banco 1
				movlw		b'00011000'		;configura 1)toma el divisor de tiempo fosc/8. 2)configura GP4 como entrada analogica y las otras como digitales I/O
				movwf 		ANSEL 			;
				movlw 		b'011100'       ;Configura GP2, GP3, GP4 como entradas y GP0, GP1, GP5 como salidas.
				movwf 		TRISIO
				bsf			OPTION_REG,INTEDG ; se genera la interrupcion con flanco ascendente de GP2
				bcf			STATUS,RP0		;se pasa al banco 0
				movlw		b'10010000'
				movwf		INTCON			;configura habilitadas las interrupciones y GP2/INT externa
				movlw		b'00000100'		;habilita ioc en GP2
				movwf		IOC
								
;-------------------------------------------------------------
; Programa principal
;-------------------------------------------------------------
				
principal		movlw		d'0'
				movwf		GPIO			;apaga todos los leds			
				movwf		direccion		;comienza a grabar datos desde la posición d'0' de la EEPROM
				movwf		reiniciar		;apaga la bandera que indica si hay que reiniciar el programa por una interrupcion de menos de 0.5sg

inicio			btfss		GPIO,3			;pregunta para empezar conversion cada 30 segundos
				goto		nada
				goto		continuar
nada			bcf			reiniciar,0		;mientras no esta activo el programa se borra la bandera de reiniciar
				goto		inicio

continuar		btfsc		reiniciar,0		;si detecta que hay que reiniciar, reinicia
				goto		resetear
convertir		call		CONVERSORAD
				bsf			STATUS,RP0		;pasa al banco 1 (donde se maneja la EEPROM)
				movf		conversion,w
				movwf		EEDATA			;y lo deja listo para grabar									CONFIGURACION DE DATOS A GRABAR EN EEPROM
				movf		direccion,w		;tambien carga la direccion donde se va a grabar el dato
				movwf		EEADR
				incf		direccion,1		;deja seteado donde se va a grabar el proximo dato				
				call		ESCRIBIR_EEPROM
				bsf			GPIO,5			;avisa que se grabo un dato
				call		demora0.1
				bcf			GPIO,5
				call		demora30
				goto		continuar		;vuelve a preguntar si hay que reiniciar y sigue juntando datos

;-------------------------------------------------------------
; SUBRUTINA QUE OBTIENE EL VALOR DEL CONVERSOR A/D (GP4)
;-------------------------------------------------------------
CONVERSORAD		bsf			ADCON0,1    	;comienza la conversion A/D				
convierte		btfsc		ADCON0,1		;espera a que convierta el dato
				goto		convierte
				movf		ADRESH,w        ;pasa el resultado de la conversion a w
				movwf		conversion		;y luego a la variable conversion
				retlw		0

;-------------------------------------------------------------
; SUBRUTINA DE ESCRITURA DE DATOS EN EEPROM (se deben haber cargado EEDATA y EEADR)
;-------------------------------------------------------------
ESCRIBIR_EEPROM	bsf 		STATUS,RP0 		;Bank 1                                						
				bsf 		EECON1,WREN 	;Enable write
				bcf			INTCON,GIE
				movlw		0x55 			;Inicio de las intrucciones para EECON2
				movwf		EECON2
				movlw		0xAA 		
				movwf		EECON2			;Fin de las intrucciones para EECON2
				bsf 		EECON1,WR 		;Start the write											
				bcf        	EECON1,WREN     ; disable Write
				bsf 		INTCON,GIE 		;habilita las interrupciones
				bcf       	STATUS,RP0      ; Banco 0 
				retlw		0

;-------------------------------------------------------------
; SUBRUTINA DE RETARDO DE 30 SEGUNDOS
;-------------------------------------------------------------
demora30		movlw		D'153'
				movwf		CounterC
				movlw		D'49'
				movwf		CounterB
				movlw		D'161'
				movwf		CounterA
loop1			decfsz		CounterA,1
				goto		loop1
				decfsz		CounterB,1
				goto		loop1
				decfsz		CounterC,1
				goto		loop1
				retlw		0	

;-------------------------------------------------------------
; SUBRUTINA DE RETARDO DE 0.1 SEGUNDOS
;-------------------------------------------------------------
demora0.1		movlw		D'130'
				movwf		CounterB
				movlw		D'221'
				movwf		CounterA
loop2			decfsz		CounterA,1
				goto		loop2
				decfsz		CounterB,1
				goto		loop2
				retlw		0	

;-------------------------------------------------------------
; SUBRUTINA DE RETARDO DE 195 MICROSEGUNDOS  (1/(195+13)) = 4808 baudios
;-------------------------------------------------------------
demora195		movlw	D'63'
				movwf	CounterA
loop3			decfsz	CounterA,1
				goto	loop3
				nop
				retlw	0
				
;-------------------------------------------------------------
; SUBRUTINA DE INTERRUPCION
;-------------------------------------------------------------
;NOTA: cuando se pone a 1 GP2, se produce una interrupcion. Si la misma dura mas de 0.5 sg, se transfieren los datos por RS232 a una pc. Si dura menos, se reinicia el programa.

interrupcion	movwf		doblev			;guarda el dato de w antes de la iterrupcion
				bsf			GPIO,0			;indica que se acepto una interrupcion
				call		demora0.1
				btfss		GPIO,2			
				goto		volver
				call		demora0.1
				btfss		GPIO,2
				goto		volver
				call		demora0.1
				btfss		GPIO,2
				goto		volver
				call		demora0.1
				btfss		GPIO,2
				goto		volver
				bcf			GPIO,0			;indica que comienza la tansferencia de datos por RS232
				call		BAJAR_DATOS		
				goto		volver		

volver			bcf			GPIO,0
				bsf			reiniciar,0		;marca que hay que reiniciar
				bcf			INTCON,INTF		;y borra la bandera de que ocurrio una interrupcion
				movf		doblev,w		;reestablece el valor de w antes de volver
				RETFIE

;-------------------------------------------------------------
; SUBRUTINA DE TRANSFERENCIA DE DATOS A PC POR RS232
;-------------------------------------------------------------
BAJAR_DATOS		movlw		d'0'			;empieza a leer los datos de la EEPROM desde la direccion 0.
				movwf		dirleida
leerotro		call		LEER_DATO
				call		TRANSMITIR_BYTE
				incf		dirleida
				movf		direccion,w		;carga la direccion hasta la que se grabo, y la resta de la direccion actual transmitida. Cuando sean iguales se detiene el proceso.
				subwf		dirleida,w
				btfsc		STATUS,C		;corrobora si la resta dio resultado "negativo"
				goto		leerotro		;si dio negativo hay que seguir transmitiendo		
				retlw		0				;si ya se llego al numero de datos tomados se detiene el proceso

;-------------------------------------------------------------
; SUBRUTINA DE LECTURA DE DATOS DE LA EEPROM (cargar en "dirleida" la direccion del dato a leer)
;-------------------------------------------------------------
LEER_DATO		bsf 		STATUS,RP0 		;Bank 1
				movf 		dirleida,w		;carga la direccion a leer
				movwf 		EEADR 			;Address to read
				bsf 		EECON1,RD 		;EE Read
				movf 		EEDATA,W		;Move data to W
				movwf		datoleido
				retlw		0

;-------------------------------------------------------------
; SUBRUTINA DE TRANSMISION DE UN BYTE POR EL PUERTO SERIE 
;-------------------------------------------------------------
; la transmision se realiza a 4800 baudios

TRANSMITIR_BYTE	bsf			GPIO,1			;transmite el bit de inicio del byte
				call		demora195
				nop
				nop							;estos 3 nop estan para compensar y que todos los bit midan lo mismo
				nop
				clrf		contador
				goto		analizar_bit

analizar_bit	incf		contador		;para el primer bit, contador se pone en 1.
				movlw		b'00000001'
				andwf		datoleido,w		;me quedo con el ultimo bit
				movwf		aux
				decf		aux,w			;y le resto uno
				btfsc		STATUS,C		
				goto		transmitir_cero	;si la resta da negativa, era un cero
				goto		transmitir_uno	;si la resta no me da negativa, era un uno
				
transmitir_cero	bcf			GPIO,1
				call		demora195
				rrf			datoleido,1		;deja preparado datoleido para el proximo bit
				movlw		d'8'
				subwf		contador,w		;se fija si ya se transmitieron los 8 bits
				btfss		STATUS,Z
				goto		analizar_bit	;si contador < 8 sigue transmitiendo
				goto		fintransmision	;sino termina la transmision

transmitir_uno	bsf			GPIO,1
				call		demora195
				rrf			datoleido,1		;deja preparado datoleido para el proximo bit
				movlw		d'8'
				subwf		contador,w		;se fija si ya se transmitieron los 8 bits
				btfss		STATUS,Z
				goto		analizar_bit	;si contador < 8 sigue transmitiendo
				goto		fintransmision	;sino termina la transmision

fintransmision	nop
				nop							;estos 4 nop estan para que todos los bit midan lo mismo
				nop
				nop
				bcf			GPIO,1
				call		demora195
				nop
				nop
				nop
				retlw		0
				
				END

Por otro lado, también cambie el circuito para transmitir los datos por RS232 y utilicé el que me recomendaste.

Así y todo lo probé y no logro que la computadora lea absolutamente nada cuando mantengo apretada la tecla que envía los datos por GP1.
 
Así y todo lo probé y no logro que la computadora lea absolutamente nada cuando mantengo apretada la tecla que envía los datos por GP1.
Primero realiza una prueba de transmisión y recepción de datos con este programa que adjunto.
De hecho te puede servir para que tengas una idea de como realizar una transmisión por software.
Ya que tengas funcionando la rutina de transmisión, entonces podrás continuar con el resto del programa.

Suerte.
 

Adjuntos

  • 12F675 RS232.rar
    15.3 KB · Visitas: 17
Bueno aca estoy de nuevo probando la transmisión serie con el programita que me adjuntaste. Lo leo y me mareo un poco, no entiendo bien que hace el programa...

Yo necesito probar transmitir solamente desde el pic hacia la pc. Pienso hacerlo con el circuito de la parte superior de la imagen que adjuntaste previamente.

Me dirías en que patita del pic12f675 se transmite? y ademas si hay que habilitar algun puerto con un interruptor o algo asi para comenzar la transferencia.

El programa en definitiva que hace?
Lo que necesito es probar una transferencia de cualquier cosa a ver si llega.

La configuracion por lo que lei parece ser:
Velocidad : 9600 baudios
bits de parada: 1
bits de inicio: 1
control de flujo: nulo
paridad: nula

Gracias !
 
Bueno aca estoy de nuevo probando la transmisión serie con el programita que me adjuntaste. Lo leo y me mareo un poco, no entiendo bien que hace el programa...
Lo que hace el programa es realizar una comunicación serial RS232 por software.
Esto lo hace por medio de la comprobación de interrupciones usando el TMR0.
Yo necesito probar transmitir solamente desde el pic hacia la pc. Pienso hacerlo con el circuito de la parte superior de la imagen que adjuntaste previamente.
OK. Con el programa que adjunte, lo puedes lograr sin ningún problema.
El programa esta creado para recibir y transmitir.
Me dirías en que patita del pic12f675 se transmite? y ademas si hay que habilitar algun puerto con un interruptor o algo asi para comenzar la transferencia.
En el código está la declaración de los pines de Tx y Rx
Tx_Pin equ 0x05 ; Tx_Pin = GP5 (pin 2
Rx_Pin equ 0x03 ; Rx_Pin = GP3 (pin 4)
Y no se necesita ningún interruptor para habilitar el sistema y comenzar la transferencia.
El programa en definitiva que hace?
Lo que necesito es probar una transferencia de cualquier cosa a ver si llega.
Lo que hace el programa al inicio, es enviar una cadena de caracteres. "Digamos, la bienvenida"
Esto aparte de estabilizar el bus, sirve para saber que el sistema está listo y funcionando.
Y si podrás enviar, "números y letras".
Luego permanece en espera de datos, y si llega uno, lo reenvía como un eco.
La configuración por lo que leí parece ser:
Velocidad : 9600 baudios
bits de parada: 1
bits de inicio: 1
control de flujo: nulo
paridad: nula
Si, la configuración es... 9600,N,8,1 Handshaking: None

Adjunto el diagrama de conexiones y otros gráficos durante la simulación.
Una prueba fue realizada con el Hyper Terminal, pero yo no uso ese programa.
Para eso realice un programa que lo sustituye, y es con el que trabajo en estos proyectos.

Saludos.
 

Adjuntos

  • HT.jpg
    HT.jpg
    99.3 KB · Visitas: 9
  • Interfaz_Config.jpg
    Interfaz_Config.jpg
    56.5 KB · Visitas: 10
  • Simulación_Inicio_Rx.jpg
    Simulación_Inicio_Rx.jpg
    277.7 KB · Visitas: 10
  • Eco_Hola_Mundo.jpg
    Eco_Hola_Mundo.jpg
    266 KB · Visitas: 11
  • Soft_RS232_SCH.jpg
    Soft_RS232_SCH.jpg
    41.7 KB · Visitas: 12
Última edición:
Acabo de probar el programa y transmite el mensaje, pero de algun modo llega como "distorsionado" (adjunto una imagen).
Ademas, lo transmite una y otra vez hasta que le quito la alimentación. Esto de que se repite calculo que debe ser así porque debe estar programado así.

Mi idea era, una vez que funcione perfecto, acoplar este pedazo de código en mi programa y luego llamarlo con un "call" para transmitir los bytes necesarios, algo asi:

movwf VARIABLE_A_TRANSMITIR
call TRANSMITIR_RS232

En el caso de que quiera hacer eso, ¿En que registro se carga el dato de 8 bits a transmitir (o sea VARIABLE_A_TRANSMITIR)? y ¿con que etiqueta llamo en el call? (TRANSMITIR_RS232 como se llamaria en tu programa).

Disculpa tantas preguntas, pero no soy experto programando y usas muchos términos al programar que yo no conozco, entonces se me dificulta mucho entender.
 

Adjuntos

  • Dibujo.JPG
    Dibujo.JPG
    65.4 KB · Visitas: 12
El porque te llegue el mensaje varias veces, no lo sé.
El programa lo probé antes de subirlo y funciona tanto en la simulación como físicamente, sin repetir.
Ahora, si lo que unicamente requieres saber, es como enviar un dato, aquí adjunto algunos ejemplos.

Realicé los programas en varios lenguajes, para que determines cual se adapta mejor a tus conocimientos.

Notas:
En la carpeta Ensamblador realice el ejemplo de lo que requieres saber.
Todos los programas incluidos, han sido probados físicamente.
También adjunto dentro del archivo, la interfaz RS232.

Suerte.
 

Adjuntos

  • Pack_Soft_RSR232.rar
    217.5 KB · Visitas: 14
Última edición:
Amigo, no te das una idea de la mano que me diste...
Voy a usar este ultimo programa en assembler como una libreria .INC para adjuntarlo en mi programa principal.

Estoy armando un datalogger con la entrada que es un puerto analogico del 12F675. Primero adquiere 128 datos y los guarda en la EEPROM interna, luego se descargan por RS232 a la pc (usando hyperterminal) para graficar en excel o tratarlos.

Una vez que tenga todo el proyecto hecho capaz hago algun tutorial o algo...

Muchas gracias por toda tu ayuda, realmente aprendí mucho, me quedo sin palabras para darte las gracias. :)
 
Bueno después de renegar mucho tiempo con los .asm de ambos programas logre juntarlos y que "convivan". El programa compila perfectamente y no se encuentra ningún error.

Pero hay un problema que estoy intentando resolver desde ayer y ya probé muchas cosas y no me funcionaron. El problema es que cuando comienza la transmisión de datos, al simularlo con el MPLAB puedo ver que transmite bien el bit de inicio pero cuando tiene que mandar el siguiente bit el programa se queda atascado en las dos instrucciones señaladas de la imagen y no se mueve mas, el programa se traba ahí.
Al probar simular paso a paso el programa que enviaste en el último mensaje se puede ver que no pasa este problema y que corre fluidamente.

Al principio pensé que era un tema de configuración errónea en algún lado, pero no parece ser eso. Quizás haya algún problema que no estoy viendo con el TMR0.

Sin más, adjunto el programa

Código:
;************************** Asignacion de pines *********************************************************************************
;                                                       ____________
;     		                                       +5V -|1   \__/  8|- GND
;LED y buzzer que indican escritura de datos en EEPROM -|2         7|- LED indicador de estado de GP2 (util en interrupciones)
;               	  	                Datos conv A/D -|3 12F675  6|- Al puerto serie         
;   		                               Int. Inicio -|4_________5|- Int. parada/transferir
;						 	    
;********************************************************************************************************************************

;
; Los registros utilizables son del 32 al 95 para este modelo de PIC
;

;-------------------------------------------------------------
; Define el PIC
;-------------------------------------------------------------
				list 		p=12f675
				#include 	P12F675.INC
				__CONFIG    _MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _PWRTE_ON
				errorlevel -302 			;prevents error code for this chipset

;-------------------------------------------------------------
; Declaracion de variables
;-------------------------------------------------------------

;
; NOTA: Lo que se agrego para que funcione el RS-232 usa las posiciones de memoria [32 ... 56], de modo que no hay que usarlas en el programa principal
;

RXBUFF		equ			d'00041'	; RX buffer, 8 bytes [20..27] (en hexadecimal)
PROC232		equ			d'00042'
TXCNT		equ			d'00043'
TXVAR		equ			d'00044'
RXCNT		equ			d'00045'
RD_PTR		equ			d'00046'
WR_PTR		equ			d'00047'
RXCHAR		equ			d'00048'
FSRTMP		equ			d'00049'
PTRL		equ			d'00050'
PTRH		equ			d'00051'
TEMP		equ			d'00052'

; Banderas
RXFLAG		equ			d'0'	; 1 = RX en progreso  (el numero es la posicion dentro del byte)
TXFLAG		equ			d'2'	; 1 = TX en progreso  (idem arriba)

; Constantes 
;******************************************************************
Tx_Pin		equ			d'1'	; Tx_Pin = GP1    (el numero significa que va a ser reemplazado como "bsf   GPIO,X", donde X es el numero este)
Rx_Pin		equ			d'5'	; Rx_Pin = GP5    (para el momento en que se transfieran los datos el buzzer y led van a estar apagados, no se va a estar muestreando)
 
W_ISR		equ			h'5C'		; ISR 'W'
S_ISR		equ			h'5D'		; ISR 'STATUS'
P_ISR		equ			h'5E'		; ISR 'PCLATH'
F_ISR		equ			h'5F'		; ISR 'FSR'
;******************************************************************

conversion		equ			d'00057'
direccion		equ			d'00058'
CounterA		equ			d'00059'
CounterB		equ			d'00060'
CounterC		equ			d'00061'
reiniciar		equ			d'00062'
doblev			equ			d'00063'
dirleida		equ			d'00064'
datoleido		equ			d'00065'
contador		equ			d'00066'
aux				equ			d'00067'

;-------------------------------------------------------------
; Define donde empieza el programa y a donde dirigir las interrupciones
;-------------------------------------------------------------

resetear		org			0				;indica empezar el programa
				goto		calib			;I would guess that your code starting at address 0 (the reset vector) consists of more than four instructions - if an interrupt handler exists, you have to jump around it.
											;va a configurar las cosas y despues a "principal"

				org			4				;indica a donde ir si hay una interrupcion
				btfsc		INTCON,2
				goto		INT_TMR0		;si la interrupcion es por el TMR0 (usado para el RS232), va a esa interrupcion
				btfsc		INTCON,1
				goto		INT_GP2			;si la interrupcion es por GP2, va a esa interrupcion
				RETFIE				

;-------------------------------------------------------------
; Subrutina de calibración del RC interno
;-------------------------------------------------------------
calib			bsf 		STATUS,RP0    					;Bank 1
				call 		3FFh          					;Get the cal value
				movwf 		OSCCAL       					;Calibrate
				bcf			STATUS,RP0
;-------------------------------------------------------------
; Configuración entradas y salidas (GP4 entrada analogica y GP2 entrada INT exterior)
;-------------------------------------------------------------
configurar		CLRF		STATUS
				bcf			STATUS,RP0      ;se pasa al banco 0
				movlw		b'00001101'     ;[configura 1)"justificado a la izquierda" (todos los bit comprimidos hacia la izquierda del restultado), 2)Vref en Vdd ]
				movwf		ADCON0          ;[3)entrada analogica en GP4. 4)no empieza la conversion y esta operable (ultimos 2 bits)                        ]
				clrf 		GPIO 			;limpia las salidas
				movlw 		b'00000111'		;[desactiva el comparador de tension y quedan libres GP1,GP2 y GP0]
				movwf 		CMCON 			;
				bsf 		STATUS,RP0 		;se pasa al banco 1
				movlw		b'00011000'		;configura 1)toma el divisor de tiempo fosc/8. 2)configura GP4 como entrada analogica y las otras como digitales I/O
				movwf 		ANSEL 			;
				movlw 		b'011100'       ;Configura GP2, GP3, GP4 como entradas y GP0, GP1, GP5 como salidas.
				movwf 		TRISIO
				movlw		b'11001000'		; Sin pull-ups y sin prescaler para TMR0
				movwf		OPTION_REG		 ; se genera la interrupcion con flanco ascendente de GP2
				bcf			STATUS,RP0		;se pasa al banco 0
				movlw		b'10111000'
				movwf		INTCON			;configura habilitadas las interrupciones y GP2/INT externa (y TMR0), y las IOC
				movlw		b'00000100'		;habilita ioc en GP2
				movwf		IOC
				call		Init232			;deja preparada la linea de salida de RS232
				goto		principal		;TERMINA DE INICIALIZAR REGISTROS Y COMIENZA EL PROGRAMA

;********************************************************************************
; Rutina de servicio de interrupción cuando llega un bit por el puerto serie

; Las interrupciones son generadas cada 104uS por TMR0 a 9600bps
; Las operaciones son por IOC (Interrupción por cambio de estado)
;******************************************************************************** 

INT_TMR0
	bcf		INTCON,2	; limpia la bandera de interrupcion
ISR	movwf	W_ISR		; Guardar W-Reg
	swapf	STATUS,W	; No cambiar los bits de STATUS
	movwf	S_ISR		; Guardar STATUS reg
	clrf	STATUS		; Limpiar el registro STATUS
	movf	PCLATH,W	; Poner PCLATH
	movwf	P_ISR		; Guardar PCLATH
	movf	FSR,W		; Poner FSR
	movwf	F_ISR		; Guardar FSR

;  Prueba con GP5 (Rx_Pin)
ISR_IOC	btfss	INTCON,GPIF	; IOC "bit de inicio" ¿Interrupción?
	goto	ISR_SET		; No, saltar
	movf	GPIO,W		; Si, leer GPIO
	bcf		INTCON,GPIF	; Limpiar la bandera de interrupción IOC
	btfsc	GPIO,Rx_Pin	; ¿Rx_Pin = 0? (bit de inicio)
	goto	ISR_XIT		; No, Polaridad equivocada, saltar
	bsf		PROC232,RXFLAG	; Indicar Rx en progreso
	movlw	d'10'		; (1 bit de inicio + 8 de datos + 1 de parada)	
	movwf	RXCNT		; Inicializar el conteo de bits

	bcf	INTCON,T0IF		; Limpiar la bandera de interrupción de TMR0
	movlw   -d'52'+d'39'; 1/2 bit (52uS)	
	movwf	TMR0
	goto	ISR_X		; GP3 = 0 (IOC) y salir
; Limpiar la bandera de interrupción de TMR0
; Preparar TMR0 para la siguiente interrupción.
ISR_SET bcf     INTCON,T0IF     ; Limpiar la bandera de interrupción de TMR0
        movlw   -d'104'+2       ; Establecer 104uS
        addwf   TMR0,f
;  Poner el bit en la salida serial
ISR_TX
	btfss	PROC232,TXFLAG	; ¿TX en progreso?
	goto	ISR_RX		; No, saltar
	movf	TXCNT,W		; Obtener el conteo de bits
	bnz		ISR_TX0		; No, saltar envíar el siguiente bit
	movlw	d'10'		; 10 bits (inicio + 8 datos + detener)
	movwf	TXCNT		; inicializar el contador de bits de Tx
	goto	ISR_TX1		; Envíar el bit de inicio de transmisión
ISR_TX0
	rrf		TXVAR,f		; Cambiar lsb dentro de C
	bsf		TXVAR,7		; Poner el bit 7 para el bit de parada
	btfsc	STATUS,C	; Salta si C = 0
	bsf		GPIO,Tx_Pin	; Pin Tx = 1
	btfss	STATUS,C	; Salta si C = 1
ISR_TX1
	bcf		GPIO,Tx_Pin	; Pin Tx = 0
	decfsz	TXCNT,f		; Se envío el último bit cambiado?
	goto	ISR_RX		; No, saltar
	bcf	PROC232,TXFLAG	; Si, indicar fin de transmisión

;  Subrutina de recepción 
ISR_RX
	btfss	PROC232,RXFLAG	; ¿RX en progreso?
	goto	ISR_XIT		; No, saltar, en caso de
	movf	WR_PTR,W	; Poner WR_PTR (RXBUFF + 00..07)
	movwf	FSR			; Establecer la inderección
	bcf		STATUS,C	; Limpiar Carry, si el dato es 0
	btfsc	GPIO,Rx_Pin	; ¿Rx_Pin = 0?
	bsf		STATUS,C	; No, poner Carry, dato = 1
	rrf		INDF,F		; rotar el bit del caracter
	decfsz	RXCNT,F		; ¿10 bits?
	goto	ISR_XIT		; No, saltar
	rlf		INDF,F		; Si, eliminar el bit de parada
;  Aquí ya está lleno el buffer con el caracter RXBUFF[WR_PTR] 
	bcf		PROC232,RXFLAG	; Limpiar la bandera (Rx en progreso)
;  Si WR_PTR + 1 = RD_PTR el buffer esta lleno y salir, si no
;  incrementar la variable WR_PTR para recibir el siguiente caracter.
	incf	WR_PTR,W	; W = WR_PTR + 1
	andlw	RXBUFF+h'07'; Esto funciona para 20..27
	xorwf	RD_PTR,W	; WR_PTR+1 = RD_PTR ¿lleno?
	skpz				; Si, Ignorar el nuevo caracter
	incf	WR_PTR,F	; Si no, sumarlo al buffer
	bcf		WR_PTR,3	; Mantener en el rango de 20..27

ISR_X
	bsf	STATUS,RP0		; Banco 1
	movlw	1<<Rx_Pin	; Mascara para Rx_Pin/GP3 IOC
	xorwf	IOC,F		; Invertir Rx_Pin/GP3 IOC
	bcf	STATUS,RP0		; Banco 0
;  Restaurar Contexto
ISR_XIT
	movf	F_ISR,W
	movwf	FSR			; Restaurar FSR	
	movf	P_ISR,W	
	movwf	PCLATH		; Restaurar PCLATH	
	swapf	S_ISR,W	
	movwf	STATUS		; Restaurar STATUS	
	swapf	W_ISR,F
	swapf	W_ISR,W		; Restaurar W-reg	
	retfie				; Regresar de la interrupción	

;-------------------------------------------------------------
; SUBRUTINA DE INTERRUPCION
;-------------------------------------------------------------
;NOTA: cuando se pone a 1 GP2, se produce una interrupcion. Si la misma dura mas de 0.5 sg, se transfieren los datos por RS232 a una pc. Si dura menos, se reinicia el programa.

INT_GP2			bcf			INTCON,1		;limpia la bandera de interrupcion de GP2
				movwf		doblev			;guarda el dato de w antes de la iterrupcion
				bsf			GPIO,0			;indica que se acepto una interrupcion
				call		demora0.1
				btfss		GPIO,2			
				goto		volver
				call		demora0.1
				btfss		GPIO,2
				goto		volver
				call		demora0.1
				btfss		GPIO,2
				goto		volver
				call		demora0.1
				btfss		GPIO,2
				goto		volver
				call		BAJAR_DATOS		
				goto		volver		

volver			bcf			GPIO,0
				bsf			reiniciar,0		;marca que hay que reiniciar
				bcf			INTCON,INTF		;y borra la bandera de que ocurrio una interrupcion
				movf		doblev,w		;reestablece el valor de w antes de volver
				RETFIE

;-------------------------------------------------------------
; SUBRUTINA DE TRANSFERENCIA DE DATOS A PC POR RS232
;-------------------------------------------------------------
BAJAR_DATOS		call		TITULO			;escribe el titulo de la transmision
				movlw		d'0'			;empieza a leer los datos de la EEPROM desde la direccion 0.
				movwf		dirleida
leerotro		call		LEER_DATO
				movlw		d'8'			;"contador" se resta cada vez que se envia un bit
				movwf		contador
				movf		datoleido,w		;carga el dato leido del puerto A/D
desarmar		andlw		b'00000001'		;se queda con el ultimo bit
				movwf		aux
				movlw		b'00000001'
				subwf		aux,1
				btfss		STATUS,C
				goto		mandar1			;dio cero, o sea que ERA UN UNO
				goto		mandar0			;dio negativo, o sea que ERA UN CERO
mandar			call		Put232
				rrf			datoleido,1
				decfsz		contador,1
				goto		desarmar		;si no se transmitieron todavia los 8 bits, continua desarmando y enviando los bits el byte que fue convertido
				call		enter			;si ya se transmitieron los 8 bits, "teclea un enter" y busca otro byte
				incf		dirleida,1		
;				movf		direccion,w		;carga la direccion hasta la que se grabo, y la resta de la direccion actual transmitida. Cuando sean iguales se detiene el proceso.
				movlw		b'01111111'
				subwf		dirleida,w
				btfsc		STATUS,C		;corrobora si la resta dio resultado "negativo"
				goto		leerotro		;si dio negativo hay que seguir transmitiendo		
				retlw		0				;si ya se llego al numero de datos tomados se detiene el proceso

mandar1			movlw		d'49'			;carga el ASCII del uno
				movwf		TEMP
				goto		mandar
mandar0			movlw		d'48'			;carga el ASCII del cero
				movwf		TEMP
				goto		mandar

;******************************************************************
; Subrutinas Put232 y Get232
;****************************************************************** 
Put232
	btfsc	PROC232,TXFLAG	; ¿TX en progreso?
	goto	Put232			; Si, saltar y esperar
	movwf	TXVAR			; Rellenar caracter
	bsf		PROC232,TXFLAG	; Iniciar TX
	return

Get232
	movf	RD_PTR,W
	xorwf	WR_PTR,W	; ¿RD_PTR = WR_PTR? (buffer vacio)
	bz		Get232		; Si, hacer un bucle, y esperar un caracter
	movf	FSR,W		; Ponerlo y guardar FSR
	movwf	FSRTMP
	movf	RD_PTR,W
	movwf	FSR			; Poner la indirección
	movf	INDF,W		; Poner el caracter RXBUFF[RD_PTR]
	movwf	RXCHAR		; Guardarlo para después
	movf	FSRTMP,W
	movwf	FSR			; Restaurar FSR
	incf	RD_PTR,W	; Incrementar RD_PTR
	andlw	b'100111'	; Mantener en el rango de 20..27
	movwf	RD_PTR
	movf	RXCHAR,W	; Tomar el caracter recibido
	return
;****************************************************************** 
; Subrutina Init232
;****************************************************************** 
Init232
	movlw	RXBUFF			; Poner la dirección del buffer circular Rx
	movwf	RD_PTR			; Iniciar el buffer circular RD_PTR
	movwf	WR_PTR			; 	""		""		""		 WR_PTR
	clrf	PROC232			; Limpiar el enclave RS232
	clrf	TXCNT			; Inicializar la variable TXCNT
	bsf     GPIO,Tx_Pin		; Poner Tx_Pin en estado desocupado
	return

;******************************************************************
; Subrutina que genera un "Enter del teclado"
;****************************************************************** 

enter	movlw	d'13'		; Cargo un Cr (Carriage Return)
		movwf	TEMP
		call	Put232
		movlw	d'10'		; Cargo un Lf (Line Feed)
		movwf	TEMP
		call	Put232
		return
								
;-------------------------------------------------------------
; Programa principal
;-------------------------------------------------------------
				
principal		movlw		d'0'
				movwf		GPIO			;apaga todos los leds			
				movwf		direccion		;comienza a grabar datos desde la posición d'0' de la EEPROM
				movwf		reiniciar		;apaga la bandera que indica si hay que reiniciar el programa por una interrupcion de menos de 0.5sg

inicio			btfss		GPIO,3			;pregunta para empezar conversion cada 30 segundos
				goto		nada
				goto		continuar
nada			bcf			reiniciar,0		;mientras no esta activo el programa se borra la bandera de reiniciar
				goto		inicio

continuar		btfsc		reiniciar,0		;si detecta que hay que reiniciar, reinicia
				goto		resetear
convertir		call		CONVERSORAD
				bsf			STATUS,RP0		;pasa al banco 1 (donde se maneja la EEPROM)
				movf		conversion,w
				movwf		EEDATA			;y lo deja listo para grabar									CONFIGURACION DE DATOS A GRABAR EN EEPROM
				movf		direccion,w		;tambien carga la direccion donde se va a grabar el dato
				movwf		EEADR
				incf		direccion,1		;deja seteado donde se va a grabar el proximo dato				
				call		ESCRIBIR_EEPROM
				bsf			GPIO,5			;avisa que se grabo un dato
				call		demora0.1
				bcf			GPIO,5
				call		demora30
				goto		continuar		;vuelve a preguntar si hay que reiniciar y sigue juntando datos

;-------------------------------------------------------------
; SUBRUTINA QUE OBTIENE EL VALOR DEL CONVERSOR A/D (GP4)
;-------------------------------------------------------------
CONVERSORAD		bsf			ADCON0,1    	;comienza la conversion A/D				
convierte		btfsc		ADCON0,1		;espera a que convierta el dato
				goto		convierte
				movf		ADRESH,w        ;pasa el resultado de la conversion a w
				movwf		conversion		;y luego a la variable conversion
				retlw		0

;-------------------------------------------------------------
; SUBRUTINA DE ESCRITURA DE DATOS EN EEPROM (se deben haber cargado EEDATA y EEADR)
;-------------------------------------------------------------
ESCRIBIR_EEPROM	bsf 		STATUS,RP0 		;Bank 1                                						
				bsf 		EECON1,WREN 	;Enable write
				bcf			INTCON,GIE
				movlw		0x55 			;Inicio de las intrucciones para EECON2
				movwf		EECON2
				movlw		0xAA 		
				movwf		EECON2			;Fin de las intrucciones para EECON2
				bsf 		EECON1,WR 		;Start the write											
				bcf        	EECON1,WREN     ; disable Write
				bsf 		INTCON,GIE 		;habilita las interrupciones
				bcf       	STATUS,RP0      ; Banco 0 
				retlw		0

;-------------------------------------------------------------
; SUBRUTINA DE LECTURA DE DATOS DE LA EEPROM (cargar en "dirleida" la direccion del dato a leer)
;-------------------------------------------------------------
LEER_DATO		bsf 		STATUS,RP0 		;Bank 1
				movf 		dirleida,w		;carga la direccion a leer
				movwf 		EEADR 			;Address to read
				bsf 		EECON1,RD 		;EE Read
				movf 		EEDATA,W		;Move data to W
				movwf		datoleido
				retlw		0

;-------------------------------------------------------------
; SUBRUTINA DE RETARDO DE 30 SEGUNDOS
;-------------------------------------------------------------
;demora30		movlw		D'153'
;				movwf		CounterC
;				movlw		D'49'
;				movwf		CounterB
;				movlw		D'161'
;				movwf		CounterA
;loop1			decfsz		CounterA,1
;				goto		loop1
;				decfsz		CounterB,1
;				goto		loop1
;				decfsz		CounterC,1
;				goto		loop1
;				retlw		0	

;PIC Time Delay = 2,00000200 s with Osc = 4000000 Hz
demora30	movlw	D'11'
			movwf	CounterC
			movlw	D'38'
			movwf	CounterB
			movlw	D'93'
			movwf	CounterA
loop1		decfsz	CounterA,1
			goto	loop1
			decfsz	CounterB,1
			goto	loop1
			decfsz	CounterC,1
			goto	loop1
			retlw	0

;-------------------------------------------------------------
; SUBRUTINA DE RETARDO DE 0.1 SEGUNDOS
;-------------------------------------------------------------
demora0.1		movlw		D'130'
				movwf		CounterB
				movlw		D'221'
				movwf		CounterA
loop2			decfsz		CounterA,1
				goto		loop2
				decfsz		CounterB,1
				goto		loop2
				retlw		0	
	
;-------------------------------------------------------------
; SUBRUTINA DE TITULO DE LA TRANSMISION
;-------------------------------------------------------------

TITULO			
	movlw	'D'			; Un caractér (1 Byte)		
	movwf	TEMP		; Lo muevo a TEMP
	call	Put232		; Lo envío
	movlw	'a'
	movwf	TEMP
	call	Put232
	movlw	't'
	movwf	TEMP
	call	Put232
	movlw	'o'
	movwf	TEMP
	call	Put232
	movlw	's'
	movwf	TEMP
	call	Put232
	movlw	':'
	movwf	TEMP
	call	Put232
	call	enter
	call	enter		; deja 2 espacios como margen
	retlw	0			

				END

y también la imagen de donde se traba el programa al simular paso a paso.

Saludos a todos
 

Adjuntos

  • traba del programa.jpg
    traba del programa.jpg
    144.8 KB · Visitas: 7
Saludos.
Voy a usar este ultimo programa en assembler como una libreria .INC para adjuntarlo en mi programa principal.
Veo que no pudiste separar el código y crear una librería, con la cual te será más fácil el trabajo.
Así que la adjunto para que puedas dedicarte a lo que es únicamente tu programa. ;)
Bueno después de renegar mucho tiempo con los .asm de ambos programas logre juntarlos y que "convivan". El programa compila perfectamente y no se encuentra ningún error.

Pero hay un problema que estoy intentando resolver desde ayer y ya probé muchas cosas y no me funcionaron. El problema es que cuando comienza la transmisión de datos, al simularlo con el MPLAB puedo ver que transmite bien el bit de inicio pero cuando tiene que mandar el siguiente bit el programa se queda atascado en las dos instrucciones señaladas de la imagen y no se mueve mas, el programa se traba ahí.
Al probar simular paso a paso el programa que enviaste en el último mensaje se puede ver que no pasa este problema y que corre fluidamente.
Por lo qué no te funcione ahora tu programa, puede ser debido a disposiciones de RAM y retardos.

Notas:
Dentro del archivo viene un sencillo ejemplo de uso.
Para cambiar de 9600bps a 4800bps, se tienen solamente que modificar los tiempos en la librería.
Período de 9600bps = 104µs, y para 4800bps = 208µs.

Suerte.
 

Adjuntos

  • 12F675 Soft_RS232 Library.rar
    29.9 KB · Visitas: 5
Recién probé hacerlo de esa forma con el archivo .inc y me sucede exactamente lo mismo.
Tuve que hacerle muy leves modificaciones a la librería esa que pasaste para que sea compatible con mi programa (le puse en otras posiciones de registros las variables, y puse que pueda haber una interrupción externa en GP2 en el registro OPTION). También agregué una subrutina que hace el trabajo de "tocar un enter" en la transmisión.

El problema es al segundo carácter en la simulación, el primero sale bien pero se traba el segundo carácter según el MPLAB. Físicamente no sucede nada en la línea, con el hyperterminal no veo nada.

Adjunto todos los archivos tal cual los tengo ahora compilando perfectamente y con la librería .inc que pasaste (con las pequeñas modificaciones).

Gracias !
 

Adjuntos

  • Datalogger.rar
    28.5 KB · Visitas: 6
Recién probé hacerlo de esa forma con el archivo .inc y me sucede exactamente lo mismo.
Tuve que hacerle muy leves modificaciones a la librería esa que pasaste para que sea compatible con mi programa (le puse en otras posiciones de registros las variables, y puse que pueda haber una interrupción externa en GP2 en el registro OPTION). También agregué una subrutina que hace el trabajo de "tocar un enter" en la transmisión.

El problema es al segundo carácter en la simulación, el primero sale bien pero se traba el segundo carácter según el MPLAB. Físicamente no sucede nada en la línea, con el hyperterminal no veo nada.

Adjunto todos los archivos tal cual los tengo ahora compilando perfectamente y con la librería .inc que pasaste (con las pequeñas modificaciones).

Gracias !
Ese es el problema, que cambias de posición la variable RXBUFF
Esa variable necesita estar inicializada en la posición 0x28 ya que necesita de 8 Bytes.
Y dentro de las subrutinas del programa (Ahora Librería), se hace referencia a las locaciones que ocupa.
Si cambias esa variable de lugar, el programa ya no funcionará. Así que no la cambies de su bloque.

La subrutina que usas para la conversión AD no está adaptada para el programa.
Ya tienes problemas por ese lado, y con las rutinas para trabajar con la EEPROM también.
No sé si estés copiando partes de otros programas, para hacer tu programa, pero no está bien.
Ya que lo más probable es que no fueron diseñados para trabajar como tu requieres.

Lo que necesitas por ahora, es ponerte a estudiar :estudiando: como funcionan los registros del PIC,
y podrás comprender en donde tienes los errores de tu programa.
El manejo de los bancos de memoria, es importante para acceder de forma correcta a ellos.
Si no lo haces, tu programa por bien que compile, jamás funcionará. :cool:

Adjunto un ejemplo usando la librería, pero ahora trabajando con el ADC a 8 Bits.
También adjunto una foto trabajando con el programa SPCTRL configurado para recibir el resultado.
Se puede notar que el potenciómetro se encuentra al 50%, y el valor mostrado es 127.

Ahora ya solo te resta trabajar con la EEPROM, pero no te preocupes, ya que es muy fácil.

Suerte.
 

Adjuntos

  • 12F675_ADC.gif
    12F675_ADC.gif
    28.7 KB · Visitas: 9
  • 12F675 Soft_RS232 Library + ADC.rar
    33.4 KB · Visitas: 9
Última edición:
Atrás
Arriba