TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: sggtav en 16 de Abril de 2010, 23:15:35
-
Bueno estoy haciendo un programa bastante largo con un pic 16F877A, y como es la primera vez que utilizo este pic, la verdad que desconozco un poco el tema de la configuración de los puertos, ya que tiene la posibilidad de no solo usarse como digital sino como analógica.
Lo que quiero es ver si me pueden ayudar con 2 cosas. Una es con la configuración de esta ultima que creo que es con ADCON NOSE SI ES 0 O 1 y la otro es con las interrupciones. La idea es hacer interrupciones mediante el pin RB0.
E intentado escribir un programa y simularlo, pero este no anda. Me gustaria ver si alguien me puede decir que estoy haciendo mal.
Bueno aca paso una parte del programa. Desde ya muchas gracias...
;******************************************************************* Zona de datos ********************************************************
list p=16f877 ; Defino el procesador
#include <p16f877.inc> ; Adjunto librerias a utilizar del pic
__CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _PWRTE_ON & _LVP_ON & _CPD_OFF & _BODEN_OFF & _WDT_OFF & _HS_OSC
;************************************************************ Zona de comienzo programa e interrupcion**************************************
ORG 0 ;DIRECCION NORMAL
clrf PCLATH ;Borro la bandera la interrupcion
goto normal ;Me voy a donde comienza el programa normalmente
ORG 4 ;DIRECCION INTERRUPCION
movwf w_temp ;pongo en la variable lo que habia en trabajo
movf STATUS,W ;Muevo el registro status a w
movwf status_temp ;Mando la configuracion de status a mi variable
goto interrupcion ;Me voy a hacer la interrupción
;___Atiendo la interrupcion__________________________________________________________________________
interrupcion
clrf STATUS ;ME ASEGURO QUE ESTOY EN EL BANCO 0
bcf INTCON, GIE ;desavilito cualquier otra interrupcion que pueda ocurrir
btfsc INTCON, INTF ;RBIF ;Se genero una interrupcion?
goto generoint ;si se va a atender la interrupcion
; goto restaurar ;no fue algo raro salgo
;___Restaurar todo como estaba anter____________________________________________________________________
restaurar ;parte para salir de la interrupcion y dejar todo como estaba
movf status_temp,w ;recupero los registros ante de la interrupcion
movwf STATUS ;y los dejo como estuban antes de la misma
swapf w_temp,f
swapf w_temp,w
bcf INTCON,INTF ;Limpia las interrupciones pendientes
bsf INTCON,GIE ;habilito las interrupciones
retfie
;********************************************* Configuracion de los puertos del pic *******************************************************
normal
clrf STATUS
bsf STATUS,RP0 ;Acceso al banco 1
movlw b'00000111'
MOVWF ADCON0 ;adcon1 me parece Desavilito los salidas analogicas del puerto a
movlw b'00000000' ;Configuro todo como salida el PUERTO A
MOVWF TRISA
movlw b'00000001' ;Configuro todo como salida menos el ultimo bit de interrupcion
MOVWF TRISB
movlw b'00000000' ;Configuro todo como salida el PUERTO B
MOVWF TRISC
movlw b'00000000' ;Configuro todo como salida el PUERRO C
MOVWF TRISD
movlw b'00000000' ;Configuro todo como salida el PUERRO E
MOVWF TRISE
bsf INTCON,GIE ;habilito las interrupciones
movlw b'10010000' ;Habilito la interrupcion INT y la general
movwf INTCON
bcf OPTION_REG, INTEDG ;La interrupcion se abilita por flanco de bajada
bcf STATUS,RP0 ;Acceso al banco 0
Espero alguna respuesta pronta.
-
Saludos sggtav
En la rutina de control de la interrupción creo que tienes un problema de lógica debido a que debes preguntar primero cual fue la clase de interrupción que causo que el micro se interrumpiera. Aquí (http://http://www.todopic.com.ar/foros/index.php?topic=26806.0) un link que puede orientar. Espero que te sirva la infor.
Saludos.
-
en este post (http://www.todopic.com.ar/foros/index.php?topic=28832.0) colgue un programa que utiliza la int externa para un 16f877, mira a ver si te vale.
un saludo
-
para configurar el puerto A como E/S digital debes hacerlo en el ADCON1, en los bits 0 al 3 debes cargar 011X(1). Fijate que despues de que configuras los puertos no haces nadas mas, entonces ahí el micro queda desubicado, lo tenes que dejar en un ciclo infinito asi
loop nop
goto loop
end
1 no importa el valor que le pongas a ese bit 0 ó 1
la rutinas assembler siempre deben tener un END
mira aqui (http://lc.fie.umich.mx/~ifranco/DATASHEET/uC/Manual_PIC16F87X.pdf) un manualcito de ese pic en español
-
Jhozate, te agradezco por comentarme bien los registro del adcon1. Ahora estoy seguro bien cual tengo que usar.
Por supuesto que termine en end, es que solo copie un pedazo del programa.
Una pregunta mas, al configurar ADCON 1 con ej: 0000 0110, el puerto E tambien se configura como digitales? y ambos puertos, A y E, se pueden configurar tanto como entrada y como salida. Pregunto esto porque en el puerto E tengo conectado a otro integrado por I2C por lo que tengo que usar las 2 opciones.
Bueno paso la configuración del banco aver si esta bien, en este caso todo como salida, solo me interesa que el puerto A Y E, funcionen como digital.
normal
clrf STATUS
bsf STATUS,RP0 ;Acceso al banco 1
movlw b'00000110'
MOVWF ADCON1 ; Desavilito los salidas analogicas del puerto a todo digital
movlw b'000000' ;Configuro todo como salida el PUERTO A
movwf TRISA
movlw b'00000000' ;Configuro todo como salida
movwf TRISB
movlw b'00000000' ;Configuro todo como salida el PUERTO B
movwf TRISC
movlw b'00000000' ;Configuro todo como salida el PUERRO C
movwf TRISD
movlw b'000' ;Configuro todo como salida el PUERRO E
movwf TRISE
bcf STATUS,RP0 ;Acceso al banco 0
Desde ya agradezco a todos por la colaboración.
-
Bueno continuo con este hilo pero con otro problema. En este caso al momento de grabar el pic. Resulta que no tuve ningún problema la primera vez, anduvo de 10, pero ahora resulta que quiero cambiar el programa y me tira error cuando verifica, cuando lo leo hay otro programa ni idea... y no me deja borrarlo tampoco. E intentado casi de todo.
Alguien me puede ayudar porque la verdad nose como solucionar el problema para que me deja grabar un nuevo programa
desde ya muchas gracias.
-
:? como le pusiste los fuses, haber si lo has protegido contra escritura y lectura. si no es asi comprueba el cableado. con mi programador solo vale su cable usb o tira errores, tiene un par de filtros en los extremos. por icsp lo mismo, los tuve que hacer con la tierra apantallada, aunque de vez en cuando a base de ser cabezota lo hacia, reiniciaba el prog, movia cables lectura, escritura, vuelta atras... :( me dio bastantes problemas.
-
Mira probé 700 forma distinta cambiando los fuses, yo supongo que el primer programa lo grave con protección de escritura, pero lo raro que no me deja ni borrarlo, con los 2 programadores lo mismo.
Mira este son los fuses originales que uso
__CONFIG _CP_OFF & _DEBUG_OFF & _PWRTE_ON & _LVP_OFF & _CPD_OFF & _BODEN_OFF & _WDT_OFF & _HS_OSC & _WRT_OFF
Osea mmm nose que puede ser. La verdad que ya me esta poniendo nervioso este pic.
Les muestro una foto para que tengan idea que es lo que hace funcionar, el diceño es totalmente mio- Basicamente un plc
(http://img402.imageshack.us/img402/2131/dsc02341s.jpg)
-
pues hombre los fuses estan bien, no tienes mas pics para probar antes de ponerlo en esa placa, a ver si por alguna razon te lo frió
-
No tengo mas pics, lo raro es que el primer programa lo cargue y anduvo de 10. Quedo funcionando 2 horas. Luego lo saco quiero poner otro programa y no me dejaba. Lo leía y veía otro programa adentro que ???... después varios intento no pude hacer nada. Al otro dia, intento cargar de vuelta un prog, y anduvo, lo prove de 10, pero cuando quiero cambiar de nuevo el programa, el mismo problema, solo con la diferencia que no pude cargar ningun programa mas.
La verdad un misterio... Ni siquiera me deja borrarlo al pic. El programador seguro que anda bien, ya que tengo 2 y exactamente lo mismo con ambos.
Alguien alguna vez le a pasado esto??
-
Bueno gente, les digo que solucione el tema cambiando el pic. Me dolio un poco el bolsillo pero lo solucione.
Bien ahora tengo otro problema, es con respecto al bus i2c, yo tengo dispuesto a el pic tal que el bus esta conectado al puerto E, en el bit 0 e 1.
Podría ver usado el del pic, pero me entere tarde que tenia uno, asi que lo que estoy haciendo ahora es un prog para hacer andar el bus. Anteriormente realice pruebas exitosas con el 16f84 a 4mhz, ahora tengo problemas con el 16f877 a 20mhz. Queria ver si alguien me puede ayudar a solucionar el problema. Les paso mi prog para que puedan ver y ayudarme un poco. El mismo solo lee cuando se habilita el bit de interrupción
ESPERO QUE ME PUEDAN AYUDAR, es un poco largo el código, pero agradecería de su ayuda. Disculpen los errores en el mismo
;******************************************************************* Autómata Programable***************************************************
list p=16f877A ; Defino el procesador
#include <p16f877A.inc> ; Adjunto librerias a utilizar del pic
__CONFIG _CP_OFF & _DEBUG_OFF & _PWRTE_ON & _LVP_OFF & _CPD_OFF & _BODEN_OFF & _WDT_OFF & _HS_OSC & _WRT_OFF
;************************************************************** Declaro de variables *******************************************************
CBLOCK 0x25
status_temp ;respaldo del registro de status cuando hay interrupcion
w_temp ;respaldo del registro de trabajo cuando hay interrupcion
Datosfirth ;Se almasenan los pits de la entrada en crudo
DatosIN1 ;Aqui se almasenan los bist de las entradas 0 a la 7
DatosIN2 ;Aqui se almasenan los bist de las entradas 8 a la 15
contadoretardo ;Aqui se almasena la cuenta del retardo de los 4 micros del bus
contadorretardo2 ;Aqui se almasena la cuenta del retardo de los 20ms del bus
contadorretardo3 ;Aqui se almasena la cuenta del retardo de los 20ms del bus
PCF8574_Dato ;Aquí guarda el resultado del dato leído o que se va a escribir.
I2C_ContadorBits ;Cuenta los bits a transmitir o a recibir.
I2C_Dato ;Dato a transmitir o recibido.
I2C_Flags ;Guarda la información del estado del bus I2C.
PCF8574_DireccionLectura ;Almasen de codigo del integrado cuando trabaja
ENDC
;******************************************************** Variables de puertos del pic en el programa **************************************
;____________________PUERTO E_______________________________________________¦
#DEFINE SCL PORTE,0 ;Línea SCL del bus I2C ¦
#DEFINE SDA PORTE,1 ;Línea SDA del bus I2C ¦
;___________________________________________________________________________¦
#DEFINE I2C_UltimoByteLeer I2C_Flags,0 ;último byte a leer por el maestro
;************************************************************ Zona de comienzo programa e interrupcion**************************************
ORG 0 ;DIRECCION NORMAL
clrf PCLATH ;Borro la bandera la interrupcion
goto principal ;Me voy a donde comienza el programa normalmente
ORG 4 ;DIRECCION INTERRUPCION
goto interrupcion ;Me voy a hacer la interrupcion
;************************************************************ Interrupcion *****************************************************************
interrupcion
movwf w_temp ;pongo en la variable lo que habia en trabajo
movf STATUS,W ;Muevo el registro status a w
movwf status_temp ;Mando la configuracion de status a mi variable
clrf STATUS ;ME ASEGURO QUE ESTOY EN EL BANCO 0
bcf INTCON, GIE ;desabilito cualquier otra interrupcion que pueda ocurrir
btfsc INTCON, INTF ;FLAG INTERRUPCION Se genero una interrupcion?
;---------------IR PROGRAMA INTERRUPCION-----
goto generoint ;si se va a atender la interrupcion
;--------------------------------------------
goto restaurar
restaurar ;parte para salir de la interrupcion y dejar todo como estaba
movf status_temp,w ;recupero los registros ante de la interrupcion
movwf STATUS ;y los dejo como estuban antes de la misma
swapf w_temp,f
swapf w_temp,w
bcf INTCON,INTF ;Limpia las interrupciones pendientes
bsf INTCON,GIE ;habilito las interrupciones
retfie
;************************************************************ Configuracion puertos del pic*************************************************
principal
clrf STATUS
bsf STATUS,RP0 ;Acceso al banco 1
movlw b'00000110'
movwf ADCON1 ;Desavilito las salidas analogicas
movlw b'111111' ;Configuro todo como entrada PUERTO A
movwf TRISA
movlw b'00000001' ;Configuro todo como salida menos el ultimo bit de interrupcion
movwf TRISB
movlw b'00000000' ;Configuro todo como salida el PUERTO B
movwf TRISC
movlw b'00000000' ;Configuro todo como salida el PUERtO C
movwf TRISD
bcf TRISE,2
bsf INTCON, INTE ;Habilito las interrupciones del puerto B0
bcf OPTION_REG, INTEDG ;La interrupcion se abilita por flanco de bajada
bsf INTCON,GIE ;habilito las interrupciones
bcf STATUS,RP0 ;Acceso al banco 0
;************************************************************ Programa principal***********************************************************
;Programa principal:
clrf PORTB
stard
movf DatosIN1, W
movwf PORTC
movf DatosIN2, W
movwf PORTD
goto stard
;*******************INTERRUPCION*************************************************INTERRUPCION**********************************************
generoint ;Programa para atender la interrupcion
;primera lectura
movf b'01000011',W ;paso a trabajo la direccion del primer integrado
movwf PCF8574_DireccionLectura;paso la direccion a esta variable para poder leer este integrado
call Retardo_10ms ;Retardo para asegurarnos que no fue un rebote
call PCF8574_Lee ;leo la info que hay en el bus del primer micro
movwf DatosIN1 ;almaseno probisoriamente los datos recibidos aca
;segunda lectura
movf b'01000001',W ;paso a trabajo la direccion del segundo integrado
movwf PCF8574_DireccionLectura;paso la direccion a esta variable para poder leer este integrado
call PCF8574_Lee ;leo la info que hay en el bus del primer micro
movwf DatosIN2 ;almaseno probisoriamente los datos recibidos aca
goto restaurar
;___SUBRUTINA PARA LA COMUNICACION PCF8574____________________________________________________________
PCF8574_Lee ; Para leer la info del micro
call I2C_EnviaStart ; Envía la condición de Start.
movlw PCF8574_DireccionLectura; Apunta al expansor de lectura.
call I2C_EnviaByte
bsf I2C_UltimoByteLeer
call I2C_LeeByte ; Lee el puerto.
movwf PCF8574_Dato ; Lo guarda en el registro correspondiente.
call I2C_EnviaStop ; Acaba de leer.
movf PCF8574_Dato,W ; Recupera el valor del dato leído.
return
;___SUBRUTINA PARA LA COMUNICACION del BUS I2C_________________________________________________________
SDA_Bajo ; Subrutina "SDA_Bajo"
bsf STATUS,RP0 ; Configura la línea SDA como salida.
bcf SDA
bcf STATUS,RP0
bcf SDA ; SDA en bajo.
return
SDA_AltaImpedancia ; Subrutina "SDA_AltaImpedancia"
bsf STATUS,RP0 ; Configura la línea SDA entrada.
bsf SDA ; Lo pone en alta impedancia y, gracias a la
bcf STATUS,RP0 ; Rp de esta línea, se mantiene a nivel alto.
return
SCL_Bajo ; Subrutina "SCL_Bajo"
bsf STATUS,RP0
bcf SCL ; Configura la línea SCL como salida.
bcf STATUS,RP0
bcf SCL ; La línea de reloj SCL en bajo.
return
SCL_AltaImpedancia ; Subrutina "SCL_AltaImpedancia"
bsf STATUS,RP0 ; Configura la línea SCL entrada.
bsf SCL ; Lo pone en alta impedancia y, gracias a la Rp
bcf STATUS,RP0 ; de esta línea, se mantiene a nivel alto.
SCL_EsperaNivelAlto
btfss SCL ; Si algún esclavo mantiene esta línea en bajo
goto SCL_EsperaNivelAlto ; hay que esperar.
return
; Subrutina "I2C_EnviaStart" ------------------------------------------------------------
I2C_EnviaStart
call SDA_AltaImpedancia ; Línea SDA en alto.
call SCL_AltaImpedancia ; Línea SCL en alto.
call Retardo_4micros ; Tiempo tBUF del protocolo.
call SDA_Bajo ; Flanco de bajada de SDA mientras SCL está alto.
call Retardo_4micros ; Tiempo tHD;STA del protocolo.
call SCL_Bajo ; Flanco de bajada del reloj SCL.
call Retardo_4micros
return
; Subrutina "I2C_EnviaStop" -------------------------------------------------------------
I2C_EnviaStop
call SDA_Bajo
call SCL_AltaImpedancia ; Flanco de subida de SCL.
call Retardo_4micros ; Tiempo tSU;STO del protocolo.
call SDA_AltaImpedancia ; Flanco de subida de SDA.
call Retardo_4micros ; Tiempo tBUF del protocolo.
return
; Subrutina "I2C_EnviaByte" -------------------------------------------------------------
I2C_EnviaByte
movwf I2C_Dato ; Almacena el byte a transmitir.
movlw 0x08 ; A transmitir 8 bits.
movwf I2C_ContadorBits
I2C_EnviaBit
rlf I2C_Dato,F ; Chequea el bit, llevándolo previamente al Carry.
btfsc STATUS,C
goto I2C_EnviaUno
I2C_EnviaCero
call SDA_Bajo ; Si es "0" envía un nivel bajo.
goto I2C_FlancoSCL
I2C_EnviaUno
call SDA_AltaImpedancia ; Si es "1" lo activará a alto.
I2C_FlancoSCL
call SCL_AltaImpedancia ; Flanco de subida del SCL.
call Retardo_4micros ; Tiempo tHIGH del protocolo.
call SCL_Bajo ; Termina el semiperiodo positivo del reloj.
call Retardo_4micros ; Tiempo tHD;DAT del protocolo.
decfsz I2C_ContadorBits,F ; Lazo para los ocho bits.
goto I2C_EnviaBit
call SDA_AltaImpedancia ; Libera la línea de datos.
call SCL_AltaImpedancia ; Pulso en alto de reloj para que el esclavo
call Retardo_4micros ; pueda enviar el bit ACK.
call SCL_Bajo
call Retardo_4micros
return
; Subrutina "I2C_LeeByte" ---------------------------------------------------------------
I2C_LeeByte
movlw 0x08 ; A recibir 8 bits.
movwf I2C_ContadorBits
call SDA_AltaImpedancia ; Deja libre la línea de datos.
I2C_LeeBit
call SCL_AltaImpedancia ; Flanco de subida del reloj.
bcf STATUS,C ; En principio supone que es "0".
btfsc SDA ; Lee el bit
bsf STATUS,C ; Si es "1" carga 1 en el Carry.
rlf I2C_Dato,F ; Lo introduce en el registro.
call SCL_Bajo ; Termina el semiperiodo positivo del reloj.
call Retardo_4micros ; Tiempo tHD;DAT del protocolo.
decfsz I2C_ContadorBits,F ; Lazo para los 8 bits.
goto I2C_LeeBit
btfss I2C_UltimoByteLeer ; Si es el último, no debe enviar el bit de reconocimiento ACK.
call SDA_Bajo ; Envía el bit de reconocimiento ACK porque todavía no es el último byte a leer.
call SCL_AltaImpedancia ; Pulso en alto del SCL para transmitir el
call Retardo_4micros ; bit ACK de reconocimiento. Este es tHIGH.
call SCL_Bajo ; Pulso de bajada del SCL.
call Retardo_4micros
movf I2C_Dato,W ; El resultado se manda en el registro de
return ; de trabajo W.
;___Retardos___________________________________________________________________________________________
;Retardo de 4micros para la comunicacion del bus
Retardo_4micros
movlw .0 ; 1 set numero de repeticion 230
movwf contadoretardo ; 1
Hegaint
decfsz contadoretardo , 1 ; es el tiempo 0 ?
goto Hegaint
return ; 2+2 Fin.
;Retardo de 10 milisegundo para asegurarnos que no fue un rebote
Retardo_10ms
movlw .99 ; 1 set numero de repeticion (B)
movwf contadorretardo2 ; 1 |
AAA movlw .100 ; 1 set numero de repeticion (A)
movwf contadorretardo3 ; 1 |
BBB decfsz contadorretardo3, 1 ; 1 + (1) es el tiempo 0 ? (A)
goto BBB ; 2 no, loop
decfsz contadorretardo2, 1 ; 1 + (1) es el tiempo 0 ? (B)
goto AAA ; 2 no, loop
return
;-----------------------FIN_____________________________________________
END