Autor Tema: Problema con 16f628a  (Leído 2391 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado fco1306

  • PIC16
  • ***
  • Mensajes: 128
Problema con 16f628a
« en: 02 de Enero de 2012, 19:18:07 »
¿Alguien me puede decir que misterio tienen RB3 y RB4 de este pic?
Tengo el siguiente programa en pic simulator
Código: [Seleccionar]
Define CONF_WORD = 0x3f01
'Pic 16f628A opcion servos con relé
Define CLOCK_FREQUENCY = 4
'Define SIMULATION_WAITMS_VALUE = 1
AllDigital  'todos los pines digitales
Define SEROUT_DELAYUS = 0


'Definición de puertos
Symbol servo1 = PORTA.2
Symbol servo2 = PORTA.3
Symbol servo3 = PORTA.1
Symbol servo4 = PORTA.0
'Symbol bot_desv1 = PORTA.1
'Symbol bot_desv2 = PORTA.3
'Symbol bot_desv3 = PORTA.7
'Symbol bot_desv4 = PORTA.5
Symbol control1 = PORTB.7
Symbol control2 = PORTB.6
Symbol control3 = PORTB.4
Symbol control4 = PORTB.3
Symbol tx_485_enable = PORTB.5

'Definicion entradas-salidas
TRISA = %11100000
TRISB = %11011010


Dim fin_transmision As Byte
Dim bytes_bufer As Byte
Dim usart_imagen(20) As Byte
Dim usart_bufer(20) As Byte
Dim n As Byte
Dim n_usart As Byte
Dim nombre As Byte

fin_transmision = "!"
bytes_bufer = 0
n_usart = 0


Gosub usart_activa_rx
WaitMs 500  'pausa para estabilizar la entrada
'------------------------------------INICIO DEL PUERTO SERIE, TIMER E INTERRUPCONES------------------
Hseropen 9600  'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
INTCON.PEIE = 1  'bit de habilitacion de interrupciones de perifericos(USART), para que funcione la implementación P. SERIE
PIE1.RCIE = 1  'Activa la interrupcion de la USART en modo rx
Enable
INTCON.GIE = 1  'habilita todas las interrupciones globales
'--------------------------------------Inicio Programa--------------------------------------------------
Gosub clear_bufer  'Borra el BUFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
WaitMs 500



main:

If control1 = 1 Then
WaitMs 100
While control1 = 1
Wend
servo1 = 1
WaitMs 1000
servo1 = 0
WaitMs 1000
Endif

If control2 = 1 Then
WaitMs 100
While control2 = 1
Wend
servo2 = 1
WaitMs 1000
servo2 = 0
WaitMs 1000
Endif

If control3 = 1 Then
WaitMs 100
While control3 = 1
Wend
servo3 = 1
WaitMs 1000
servo3 = 0
WaitMs 1000
Endif


If control4 = 1 Then
WaitMs 100
While control4 = 1
Wend
servo4 = 1
WaitMs 1000
servo4 = 0
WaitMs 1000
Endif





Goto main
End                                               





On Interrupt  'Comienzan las rutinas de las interrupciones
Save System  'Guarda los valores del sistema
PIE1.RCIE = 0  'desactiva la interrupcion de la USART en modo rx

Hserget usart_bufer(n_usart)
If usart_bufer(n_usart) > 0 Then
nombre = usart_bufer(n_usart)
n_usart = n_usart + 1
Endif

PIR1.TMR1IF = 0  'borra el flag de salto del tmr1
PIR1.RCIF = 0  'borra el flag de salto de la usart
PIE1.RCIE = 1  'activa la interrupcion de la USART en modo rx


Resume                                           


usart_activa_rx:
WaitMs 100
tx_485_enable = 0
WaitMs 50
Return                                           

usart_activa_tx:
WaitMs 100
tx_485_enable = 1
WaitMs 50
Return                                           


clear_bufer:
For n = 0 To 1  'desbloquea el puerto serie fisico en caso de bloqueo por exceso de entrada de datos
PIE1.RCIE = 0  'deshabilita la interrupcion del modulo serie
RCSTA.CREN = 0  'protocolo de desbloqueo puerto serie
RCSTA.CREN = 1  'protocolo de desbloqueo puerto serie
RCSTA.OERR = 0  'protocolo de desbloqueo puerto serie
Next n
Gosub clearbufer  'borra el bufer por soft de los datos recibidos por el puerto serie
PIR1.RCIF = 0  'borra el flag de salto de la usart
PIE1.RCIE = 1  'activa la interrupcion de la USART en modo rx
Return                                           


clearbufer:  'BORRA E INICIALIZA EL BUFER IMAGEN DEL PUERTO SERIE
Dim c_serial As Byte
For c_serial = 0 To 20  'pasa por cada uno de los bytes del bufer
usart_bufer(c_serial) = 0  'borra bytes del bufer apuntador,
'que nos indica si esa posición del bufer tiene datos
Next c_serial  'repite hasta el total del bufer
c_serial = 0
Return                                           

en el que estoy trabajando.
Tengo los pines rb3  rb4  rb6 y rb7 conectados a una resistencia de 10K y de ésta a masa. En teoría están a cero.
Esta parte de código funciona
If control1 = 1 Then
WaitMs 100
While control1 = 1
Wend
servo1 = 1
WaitMs 1000
servo1 = 0
WaitMs 1000
Endif

Control1 que es b7 permanece a cero y servo1=0.El problema me aparece en la parte de si control 3 y control4 son igual a uno.
El programa se comporta de manera extraña.Servo3 y servo4 que son leds permanecen encendidos. Si conecto un led a las salidas servo1 y servo2 permanecen apagados,tal como indica el programa ya que control1 y control2 son cero.En la simulación funciona bien.
Si desconecto las resistencias de control3 y control4,los leds se encienden,pero si hago masa en alguna de ellas el led correspondiente se apaga.No sé ¿alguna explicación?

Desconectado fco1306

  • PIC16
  • ***
  • Mensajes: 128
Re: Problema con 16f628a
« Respuesta #1 en: 03 de Enero de 2012, 17:54:18 »
Pues después de darle vueltas no encontré el problema .
Monté el circuito de nuevo en una placa de prototipos, cambiando los pines y funciona.Por más vueltas que le dí no fuí capaz de encontrar el error en la electrónica.

Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3510
Re: Problema con 16f628a
« Respuesta #2 en: 05 de Enero de 2012, 06:17:04 »
Hola;
He estado revisando el programa y no veo porqué no funciona.

Si hay un error grave en usart_bufer() y, es que la defines con veinte elementos que son nombrados del 0 al 19, y tu escribes en el 20, este ultimo elemento no pertenece al vector y al escribir en el estas sobre escribiendo posiblemente una variable del sistema o tuya misma, normalmente esto produce cuelgues y cosas raras.

Lo mismo te pasa en la lectura de la variable en la rutina de interrupciones, en este caso como es lectura no afecta, pero también te sales del vector.

Otro tema es que se recomienda poner la rutina de interrupciones después de todas las demás rutinas.
He simplificado la rutina de interrupciones ya que haces operaciones redundantes.
El uso de Hserget ya borra la bandera de interrupciones de la usart cuando el bufer del módulo queda vacío.

Aunque Gosub/Return ya quedaron obsoletos en este lenguaje, la estructura del programa está correcta.
Por otro lado el uso de Gosub/Return ahorra memoria de stack que en esta familia de microcontroladores es de solo 8 niveles.

Para el bucle For:
Cada vez que se ejecuta un bucle For de nuevo, su variable asociada se hace 0 de forma automática.


Código: [Seleccionar]
Define CONF_WORD = 0x3f01
'Pic 16f628A opcion servos con relé
Define CLOCK_FREQUENCY = 4
'Define SIMULATION_WAITMS_VALUE = 1
Define SEROUT_DELAYUS = 0

'Definición de puertos
Symbol servo1 = PORTA.2
Symbol servo2 = PORTA.3
Symbol servo3 = PORTA.1
Symbol servo4 = PORTA.0
'Symbol bot_desv1 = PORTA.1
'Symbol bot_desv2 = PORTA.3
'Symbol bot_desv3 = PORTA.7
'Symbol bot_desv4 = PORTA.5
Symbol control1 = PORTB.7
Symbol control2 = PORTB.6
Symbol control3 = PORTB.4
Symbol control4 = PORTB.3
Symbol tx_485_enable = PORTB.5

'Definicion entradas-salidas
AllDigital  'todos los pines digitales
TRISA = %11100000
TRISB = %11011010

Dim fin_transmision As Byte
Dim bytes_bufer As Byte
Dim usart_imagen(20) As Byte
Dim usart_bufer(20) As Byte
Dim n As Byte
Dim n_usart As Byte
Dim nombre As Byte

fin_transmision = "!"
bytes_bufer = 0
n_usart = 0

Gosub usart_activa_rx
WaitMs 500  'pausa para estabilizar la entrada
'------------------------------------INICIO DEL PUERTO SERIE, TIMER E INTERRUPCONES------------------
Hseropen 9600  'Velocidad del puerto serie e inicializa los comandos de bajo nivel que controlan la USART
INTCON.PEIE = 1  'bit de habilitacion de interrupciones de perifericos(USART), para que funcione la implementación P. SERIE
PIE1.RCIE = 1  'Activa la interrupcion de la USART en modo rx
Enable
INTCON.GIE = 1  'habilita todas las interrupciones globales
'--------------------------------------Inicio Programa--------------------------------------------------
Gosub clear_bufer  'Borra el BUFER IMAGEN y por lo tanto tambien al USART, OBLIGATORIO POR LO MENOS UNA VEZ
WaitMs 500

main:
If control1 = 1 Then
WaitMs 100
While control1 = 1
Wend
servo1 = 1
WaitMs 1000
servo1 = 0
WaitMs 1000
Endif

If control2 = 1 Then
WaitMs 100
While control2 = 1
Wend
servo2 = 1
WaitMs 1000
servo2 = 0
WaitMs 1000
Endif

If control3 = 1 Then
WaitMs 100
While control3 = 1
Wend
servo3 = 1
WaitMs 1000
servo3 = 0
WaitMs 1000
Endif

If control4 = 1 Then
WaitMs 100
While control4 = 1
Wend
servo4 = 1
WaitMs 1000
servo4 = 0
WaitMs 1000
Endif
Goto main
End                                              
'Subrutinas -----------------------------------------------
usart_activa_rx:
WaitMs 100
tx_485_enable = 0
WaitMs 50
Return                                            
usart_activa_tx:
WaitMs 100
tx_485_enable = 1
WaitMs 50
Return                                            
clear_bufer:
For n = 0 To 1  'desbloquea el puerto serie fisico en caso de bloqueo por exceso de entrada de datos
PIE1.RCIE = 0  'deshabilita la interrupcion del modulo serie
RCSTA.CREN = 0  'protocolo de desbloqueo puerto serie
RCSTA.CREN = 1  'protocolo de desbloqueo puerto serie
RCSTA.OERR = 0  'protocolo de desbloqueo puerto serie
Next n
Gosub clearbufer  'borra el bufer por soft de los datos recibidos por el puerto serie
PIR1.RCIF = 0  'borra el flag de salto de la usart
PIE1.RCIE = 1  'activa la interrupcion de la USART en modo rx
Return                                            
clearbufer:  'BORRA E INICIALIZA EL BUFER IMAGEN DEL PUERTO SERIE
Dim c_serial As Byte
For c_serial = 0 To 19  'pasa por cada uno de los bytes del bufer (de 0 a 19 = 20 elementos)
usart_bufer(c_serial) = 0  'borra bytes del bufer apuntador,
'que nos indica si esa posición del bufer tiene datos
Next c_serial  'repite hasta el total del bufer
c_serial = 0 '(Cada vez que se ejecuta el For, c_serial se hace 0 de forma automática)
Return                                            
On Interrupt  'Comienzan las rutinas de las interrupciones (desactiva todas las interrupciones).
Save System  'Guarda los valores del sistema
Hserget usart_bufer(n_usart)
If usart_bufer(n_usart) > 0 and n_usart < 20 Then ' (para n_usart de 0 a 19 = 20 elementos)
nombre = usart_bufer(n_usart)
n_usart = n_usart + 1
Endif
Resume '(Activa las interrupciones de nuevo)  
« Última modificación: 05 de Enero de 2012, 06:37:46 por dogflu66 »
Saludos desde Granada, España.

Desconectado rina

  • PIC10
  • *
  • Mensajes: 45
Re: Problema con 16f628a
« Respuesta #3 en: 16 de Enero de 2012, 12:21:41 »
Pues yo he tenido el mismo problema al cambiar por el pic16f628, pongamos que le intento mandar un pulso entre los 0,5 y 1,5ms y nnai de la china es como si la patilla de pulso del servo tuviera mayor impedancia y pusiera a cero cualquier patilla del puerto A, (que menuda cabronada). Habría que reforzar la corriente del puerto A con un pequeño transistor.
La verdad que fue una cabronada.. había comprado ese pic entre otras razones para tener mas código y cuando fui a hacer una practica con los servos me lleve ese chascazo.. jejeje. Habría que prepararlos para el puerto B. y de paso quedarían las patillas del puerto al que van a los comparadores analógicos libres para poder hacer comparaciones de caídas de tensión.

Un saludo
« Última modificación: 17 de Enero de 2012, 08:12:34 por dogflu66 »

Desconectado rina

  • PIC10
  • *
  • Mensajes: 45
Re: Problema con 16f628a
« Respuesta #4 en: 16 de Enero de 2012, 12:35:14 »
Y bueno el programa no lo entendí muy bien.. Pero me imagino que WaitMs 1000 es =  un pause 1000  (vamos una parada de 1000 milisegundos = a un segundo).
No se, me imagino que lo sabrás pero el pulso que se introduce en un servo es de 0.5 milisegundos  un lado y 1,5 milisegundos el lado contrario según varíes ese intervalo de tiempo el servo se coloca en una posición y otra. Y has de dejar un intervalo de 3minimo a 20maximo milisegundos entre pulso y pulso, algo óptimo seria entre 5 y 10 milisegundos entre pulsos.

Un saludo.
« Última modificación: 17 de Enero de 2012, 08:17:57 por dogflu66 »


 

anything