TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: pocher en 05 de Julio de 2008, 01:59:40
-
A ver si me podeis hechar una mano con esto que no me sale.
Tengo en ensamblador el siguiente proceso:
orden1: movf orden1H,0
movwf ordentH
movf orden1L,0
movwf ordentL
call incL
mov sal_orden1,0
andwf PORTB,1
orden2: movf orden2H,0
movwf ordentH
movf orden2L,0
movwf ordentL
call incL
mov sal_orden2,0
andwf PORTB,1
... y así sucesivamente hasta 16
Como podría abreviar esto?
-
Hola pocher:
Una forma seria usar el direccionamiento indirecto, por ejemplo guarda en la RAM tus registros de esta forma:
50 -> orden1H
51 -> orden1L
52 -> sal_orden1
-------------------
53 -> orden2H
54 -> orden2L
55 -> sal_orden2
-------------------
...
-------------------
7D -> orden16H
7E -> orden16L
7F -> sal_orden16
-------------------
Ahora haces:
movlw .16
movwf Contador
movlw H'50'
movwf FSR
Bucle
movf INDF,w
movwf ordentH
incf FSR,f
movf INDF,w
movwf ordentL
call incL
incf FSR,f
movf INDF,w
andwf PORTB,1
incf FSR,f
decfsz Contador,f
goto Bucle
fin goto fin
;------------------------------
Otra forma seria usar tablas.
Javicho.
-
:-/ Muy bien Javicho, esta es la forma mas eficiente ,empleando el fsr y el loop :mrgreen:
Vamos amigo Pocher, a colocar varios de estos :-/ en la respuesta :D
Un abrazo
Norberto
-
Muy bueno, he aprendido a usar FSR+INDF para PICs16. :-/ :-/ nunca antes lo había utilizado.
Ahora, perdonadme por el olvido :D . Se me pasó deciros que la implementación es para un PIC18 y tal cual está no quiere caminar.
Un saludo
-
Creo haber encontrado la razón por la cual no funciona.
El programa principal está escrito en C y dentro de él tengo esta serie de sentencias en ensamblador.
El error que me dá al compilar es "Expression must evaluate to a constant INDF0"
Lo que he hecho es transportar el bloque en ensamblador pasado para PICs18 y ensamblar con MPASMWIN y no ha dado ningún tipo de error.
Por lo tanto creo que el tratamiento del direccionamiento indirecto el compilador CCS no lo contempla.
-
Tal vez te convenga usar Tablas, por ejemplo, puedes crear una tabla con los valores de tus registros en la misma secuencia que el ejemplo anterior y luego haces:
-------------------
movlw .16
movwf Contador
bsf EECON1,EEPGD
bcf EECON1,CFGS
clrf TBLPTRU ;TABLA en ORG H'000700'
movlw H'07'
movwf TBLPTRH
clrf TBLPTRL
Bucle
TBLRD*+ ;lee byte y luego " TBLPTR + 1 "
movf TABLAT,w
movwf ordentH
TBLRD*+
TBLRD*+
movf TABLAT,w
movwf ordentL
call incL
TBLRD*+
TBLRD*+
movf TABLAT,w
andwf PORTB,1
decfsz Contador,f
goto Bucle
fin goto fin
ORG H'000700'
DB 0xn1, 0xn2, 0xn3, 0xn4, 0xn5, .... , 0xn48
-------------------
Donde:
0xn1 -> orden1H
0xn2 -> orden1L
0xn3 -> sal_orden1
-------------------
0xn4 -> orden2H
0xn5 -> orden2L
0xn6 -> sal_orden2
-------------------
...
-------------------
0xn46 -> orden16H
0xn47 -> orden16L
0xn48 -> sal_orden16
-------------------
Saludos
Javicho
PD: Te recomiendo que mejor uses los PIC16, domina bien sus módulos e instrucciones, asi como algunas técnicas importantes de manejo de datos luego recien pasa a los PIC18.
-
Con mucho gusto recogo tus recomendaciones Javicho. Es un placer ir de estudiante.
Voy a estudiarme lo de las tablas para PICs18 que me has dejado. Si alguna vez puedo ayudarte, no dudes que lo haré.
Un saludo.
-
Bueno acá va mi aporte creo que es parecido
SETF fin,0 ;carga el valor 0xFF en el registro fin
NOP ;programa
MOVLW .1 ;se carga en Wreg el número de tabla a buscar
call mensaje ;se llama al gestor de tablas
NOP ;continúa el programa
GOTO $-1 ;en este ejemplo es un bucle infinito
mensaje
CLRF contador,0 ;se pone a cero el contador del offset
MULLW .6 ;se multiplica por 6 el valor que trae Wreg
;esto es porque cada CALL ocupa 4 espacios y cada RETURN
;ocupa 2 espacios de memoria en un 18f452
;por lo tanto cada puntero debe saltar de 6 en 6
loop
CALL sel_tabla ;va al selector de tablas
CPFSGT fin,0 ;compara si w = oxff no salta
RETURN ;y retorna al programa principal
CALL caracter ;muestra el caracter en el display en este ejemplo
INCF contador,f,0 ;incrementa el contador de OFFSET
GOTO loop ;vuelve a repetir el proceso
sel_tabla
MOVF PCL,w,0 ;se actualizan los pclat
MOVF PRODL,w,0 ;se carga el offset en wreg
ADDWF PCL,f,0 ;w llega con el número de tabla multiplicado por 6
;y se suma al PCL para dar el salto
CALL Tabla_0 ;va a la tabla seleccionada
RETURN ;regresa de la tabla con el valor a transferir en w
;y retorna al gestor de tablas
CALL Tabla_1
RETURN
CALL Tabla_2
RETURN
CALL Tabla_3
RETURN
CALL Tabla_4
RETURN
CALL Tabla_5
RETURN
CALL Tabla_6
RETURN
CALL Tabla_7
RETURN
Tabla_0
MOVF PCL,w,0
RLNCF cont,w,0 ;se multiplica el valor del offset por dos y se lo almacena en w
;esto se hace ya que cada RETLW ocupa 2 espacios de memoria
;en un 18F452
ADDWF PCL,f,0 ;se suma el contenido de Wreg que vale contador x 2 al PCL
RETLW 'A'
RETLW 'B'
RETLW 'C'
RETLW 'D'
RETLW 'E'
RETLW 'F'
RETLW 'G'
RETLW 'H'
RETLW 'I'
RETLW 'J'
RETLW 0xFF ;retorna con el valor de 0xFF que es el corte del bucle
Tabla_1
MOVF PCL,w,0
RLNCF cont,w,0 ;se multiplica el valor del offset por dos y se lo almacena en w
;esto se hace ya que cada RETLW ocupa 2 espacios de memoria
;en un 18F452
ADDWF PCL,f,0 ;se suma el contenido de Wreg que vale contador x 2 al PCL
RETLW 'A'
RETLW 'B'
RETLW 'C'
RETLW 'D'
RETLW 'E'
RETLW 'F'
RETLW 'G'
RETLW 'H'
RETLW 'I'
RETLW 'J'
RETLW 0xFF ;retorna con el valor de 0xFF que es el corte del bucle
Tabla_2
MOVF PCL,w,0
RLNCF cont,w,0 ;se multiplica el valor del offset por dos y se lo almacena en w
;esto se hace ya que cada RETLW ocupa 2 espacios de memoria
;en un 18F452
ADDWF PCL,f,0 ;se suma el contenido de Wreg que vale contador x 2 al PCL
RETLW 'A'
RETLW 'B'
RETLW 'C'
RETLW 'D'
RETLW 'E'
RETLW 'F'
RETLW 'G'
RETLW 'H'
RETLW 'I'
RETLW 'J'
RETLW 0xFF ;retorna con el valor de 0xFF que es el corte del bucle
Tabla_3
MOVF PCL,w,0
RLNCF cont,w,0 ;se multiplica el valor del offset por dos y se lo almacena en w
;esto se hace ya que cada RETLW ocupa 2 espacios de memoria
;en un 18F452
ADDWF PCL,f,0 ;se suma el contenido de Wreg que vale contador x 2 al PCL
RETLW 'A'
RETLW 'B'
RETLW 'C'
RETLW 'D'
RETLW 'E'
RETLW 'F'
RETLW 'G'
RETLW 'H'
RETLW 'I'
RETLW 'J'
RETLW 0xFF
Tabla_4
MOVF PCL,w,0
RLNCF cont,w,0 ;se multiplica el valor del offset por dos y se lo almacena en w
;esto se hace ya que cada RETLW ocupa 2 espacios de memoria
;en un 18F452
ADDWF PCL,f,0 ;se suma el contenido de Wreg que vale contador x 2 al PCL
RETLW 'A'
RETLW 'B'
RETLW 'C'
RETLW 'D'
RETLW 'E'
RETLW 'F'
RETLW 'G'
RETLW 'H'
RETLW 'I'
RETLW 'J'
RETLW 0xFF
Tabla_5
MOVF PCL,w,0
RLNCF cont,w,0 ;se multiplica el valor del offset por dos y se lo almacena en w
;esto se hace ya que cada RETLW ocupa 2 espacios de memoria
;en un 18F452
ADDWF PCL,f,0 ;se suma el contenido de Wreg que vale contador x 2 al PCL
RETLW 'A'
RETLW 'B'
RETLW 'C'
RETLW 'D'
RETLW 'E'
RETLW 'F'
RETLW 'G'
RETLW 'H'
RETLW 'I'
RETLW 'J'
RETLW 0xFF
Tabla_6
MOVF PCL,w,0
RLNCF cont,w,0 ;se multiplica el valor del offset por dos y se lo almacena en w
;esto se hace ya que cada RETLW ocupa 2 espacios de memoria
;en un 18F452
ADDWF PCL,f,0 ;se suma el contenido de Wreg que vale contador x 2 al PCL
RETLW 'A'
RETLW 'B'
RETLW 'C'
RETLW 'D'
RETLW 'E'
RETLW 'F'
RETLW 'G'
RETLW 'H'
RETLW 'I'
RETLW 'J'
RETLW 0xFF
Tabla_7
MOVF PCL,w,0
RLNCF cont,w,0 ;se multiplica el valor del offset por dos y se lo almacena en w
;esto se hace ya que cada RETLW ocupa 2 espacios de memoria
;en un 18F452
ADDWF PCL,f,0 ;se suma el contenido de Wreg que vale contador x 2 al PCL
RETLW 'A'
RETLW 'B'
RETLW 'C'
RETLW 'D'
RETLW 'E'
RETLW 'F'
RETLW 'G'
RETLW 'H'
RETLW 'I'
RETLW 'J'
RETLW 0xFF
En este me ayudaron Brunof y Maunix, si le encuentran mejoras avisen.
Lo modifico ya que contenía un error, corregido!!
-
Gracias por la colaboración flacoclau, esa forma ya la conocía, la aprendí hace poco ( http://www.todopic.com.ar/foros/index.php?topic=22322.0 (http://www.todopic.com.ar/foros/index.php?topic=22322.0) ).
Javicho ¿no crees que sobraría un TBLRD*+ de los dos que hay juntos? ya que solo tiene que avanzar una posición.
En el programa que tengo (de momento en PAUSE) me interesaría que en la tabla apareciesen variables en lugar de constantes. Es decir si ponemos:
DB 0x01, 0x02, 0x03 ... toma esos números constantes.
Si ponemos:
Salida1 equ 0x20
Salida2 equ 0x21
Salida3 equ 0x22
DB Salida1, Salida2, Salida3 ... toma como valor de Salida1 el número 0x20, etc.
A mí lo que me interesaría es que tomara el valor del contenido de la posición de memoria 0x20, etc.
¿Se podrá hacer sin usar direccionamiento indirecto?
-
Hola:
Javicho ¿no crees que sobraría un TBLRD*+ de los dos que hay juntos? ya que solo tiene que avanzar una posición.
No sobra porque el PC avanza de 2 en 2, mas bien falta un TBLRD*+, recuerda que esta instrucción primero lee y luego avanza de posición, el cambio es:
...
movf TABLAT,w
andwf PORTB,1
TBLRD*+ ;<- faltó este.
decfsz Contador,f
goto Bucle
fin goto fin
Si lo quieres tener como variables no queda otra que usar el Direccionamiento Indirecto, pero debes tener cuidado porque el tratamiento del mismo en un PIC18 es un tanto diferente en cuanto a sus registros aunque la filosofía es la misma.
Insisto, mejor domina bien los PIC16 luego sigue con los PIC18, asi se te va a hacer mas facil comprender estas cosas, seguro que la aplicación que estas haciendo se puede hacer bien en un PIC16.
Javicho.
-
No, Javicho eso no es así.
Aunque el PC vaya de 2 en 2 con cada instrucción, cuando se encuentra con TBLRD*+ lee el primer elemento de la tabla y luego hace TBLPTR+1 para apuntar al siguiente elemento de la tabla que será el que leerá con el siguiente TBLRD*+, por lo tanto solo hace falta un TBLRD*+ para leer cada elemento de la tabla.
Imposible usar un PIC16, debo de usar un 18F4550 corriendo a 32MHz usando el PLL interno. Si no pasa nada podré controlar un número grande de Servos (muy, muy grande), me faltan estos detalles en ensamblador.
Un saludo
-
Hola amigo Pocher:
Te explico con un ejemplo, digamos que tienes una tabla con 3 datos:
ORG H'000700'
retlw H'05' ;<- posición en memoria de programa H'000700'
retlw H'08' ;<- posición en memoria de programa H'000702'
retlw H'BD' ;<- posición en memoria de programa H'000704'
Cuando se ejecuta TBLRD*+ en la siguiente linea en el registro TABLAT está disponible el valor apuntado previamente en la tabla y el puntero se incrementa en 1. El siguiente código te mostrará como trabaja el TBLRD*+:
bsf EECON1,EEPGD
bcf EECON1,CFGS
clrf TBLPTRU ;apunta a la posición H'000700'
movlw H'07'
movwf TBLPTRH
clrf TBLPTRL
TBLRD*+ ;lee dato 05h y el puntero ahora es H'000701'
movf TABLAT,w ;en TABLAT está el dato 05h
movwf DATO_REG_1
TBLRD*+ ;lee valor xxh y el puntero ahora es H'000702'
movf TABLAT,w
movwf DATO_REG_NO_VALIDO
TBLRD*+ ;lee dato 08h y el puntero ahora es H'000703'
movf TABLAT,w ;en TABLAT está el dato 08h
movwf DATO_REG_2
TBLRD*+ ;lee valor xxh y el puntero ahora es H'000704'
movf TABLAT,w
movwf DATO_REG_NO_VALIDO
TBLRD*+ ;lee dato BDh y el puntero ahora es H'000705'
movf TABLAT,w ;en TABLAT está el dato BDh
movwf DATO_REG_3
fin goto fin
Eso fue paso a paso, pero para leer solo los 3 datos que te interesan ahora debes hacer esto:
bsf EECON1,EEPGD
bcf EECON1,CFGS
clrf TBLPTRU ;TABLA en ORG H'000700'
movlw H'07'
movwf TBLPTRH
clrf TBLPTRL
TBLRD*+ ;lee valor 05h y el puntero ahora es H'000701'
movf TABLAT,w ;en TABLAT está el dato 05h
movwf DATO_REG_1
TBLRD*+ ;lee valor xxh y el puntero ahora es H'000702'
TBLRD*+ ;lee valor 08h y el puntero ahora es H'000703'
movf TABLAT,w ;en TABLAT está el dato 08h
movwf DATO_REG_2
TBLRD*+ ;lee valor xxh y el puntero ahora es H'000704'
TBLRD*+ ;lee valor BDh y el puntero ahora es H'000705'
movf TABLAT,w ;en TABLAT está el dato BDh
movwf DATO_REG_3
fin goto fin
Si necesariamente tienes que usar este PIC18 entonces primero lee bien el datasheet porque hay muchas cosas que difieren respecto a los PIC16.
Nos podrias comentar un poco mas sobre el proyecto que estás haciendo tal vez por ahi puedas recibir algunas nuevas ideas.
Saludos.
Javicho.
-
En el caso de que sea:
ORG H'000700'
retlw H'05' ;<- posición en memoria de programa H'000700'
retlw H'08' ;<- posición en memoria de programa H'000702'
retlw H'BD' ;<- posición en memoria de programa H'000704'
... sí que hay que poner dos TBLRD*+, ya que cada retlw H'05' ocupa dos posiciones de memoria.
Pero en el caso del primer ejemplo que tú pusiste empleabas:
ORG H'000700'
DB 0xn1, 0xn2, 0xn3, 0xn4, 0xn5, .... , 0xn48 ... y aquí solo se necesita un TBLRD*+
¡¡¡ Comprobado con MPLAB !!!
-
Para ilustrar el hecho de que hay que tener cuidado con el manejo de tablas en los PIC18 puse una tabla en la que cada valor ocupa 2 posiciones, pero en vez de poner "DT" puse "DB", porque los "DT" tienen el mismo comportamiento que los "retlw", es decir ocupan 2 posiciones.
Javicho.
-
Gracias por todo Javicho.
Voy ahora a poner un anuncio en el subforo de C, a ver si alguién me dice porqué no funciona el direccionamiento indirecto en CCS.
Y si es error del compilador que la gente lo sepa para evitar pérdidas de tiempo.
Un saludo