Librería para multitarea en GCBasic.
2 participantes
Página 1 de 1.
Librería para multitarea en GCBasic.
Después de un tiempo haciendo algunas pruebas de programación multitarea, he visto que en cuanto tienes 6 o 7 tareas ejecutándose el programa se convierte en un lio de variables, contadores, flags, interrupciones, etc.
Para evitar esto y mantener el programa lo más sencillo posible y evitar errores a la hora de asignar contadores, flags, etc. he escrito una pequeña librería que se encarga de todo ese trabajo pesado.
Tal y como está ahora, se pueden ejecutar hasta 8 tareas "simultaneas", aunque se puede aumentar el número si es necesario.
La base de tiempo está establecida en 10 ms, independientemente de la velocidad de reloj, aunque con velocidades "raras" puede no ser muy exacto, pero debería funcionar bién con 4, 8,10,20 MHz.
La base de tiempo está optimizada para reloj de 4 MHz, pero en el archivo hay instrucciones para optimizarla a otras velocidades, aún así el error con otros relojes es de algunos us cada 10 ms, osea que no hay porqué preocuparse a no ser que se necesite mucha precisión.
IMPORTANTE:
Esta librería usa el Timer0, por lo que no se puede usar para otros fines.
Tanto en el archivo de la librería: multitasking.h, como en el ejemplo: multitask_example.gcb hay explicaciones sobre el uso de multitareas.
Los archivos se pueden descargar directamente de aquí (con comentarios en ingles):
https://sourceforge.net/project/showfiles.php?group_id=247157&package_id=301652&release_id=653073
Aquí se puede ver el código con comentarios en español:
Esta es la librería: multitasking.h:
Y este es el ejemplo:
Para evitar esto y mantener el programa lo más sencillo posible y evitar errores a la hora de asignar contadores, flags, etc. he escrito una pequeña librería que se encarga de todo ese trabajo pesado.
Tal y como está ahora, se pueden ejecutar hasta 8 tareas "simultaneas", aunque se puede aumentar el número si es necesario.
La base de tiempo está establecida en 10 ms, independientemente de la velocidad de reloj, aunque con velocidades "raras" puede no ser muy exacto, pero debería funcionar bién con 4, 8,10,20 MHz.
La base de tiempo está optimizada para reloj de 4 MHz, pero en el archivo hay instrucciones para optimizarla a otras velocidades, aún así el error con otros relojes es de algunos us cada 10 ms, osea que no hay porqué preocuparse a no ser que se necesite mucha precisión.
IMPORTANTE:
Esta librería usa el Timer0, por lo que no se puede usar para otros fines.
Tanto en el archivo de la librería: multitasking.h, como en el ejemplo: multitask_example.gcb hay explicaciones sobre el uso de multitareas.
Los archivos se pueden descargar directamente de aquí (con comentarios en ingles):
https://sourceforge.net/project/showfiles.php?group_id=247157&package_id=301652&release_id=653073
Aquí se puede ver el código con comentarios en español:
Esta es la librería: multitasking.h:
- Código:
'_______________________________________________________________________
'
'
' Multitasking functions
'
'_______________________________________________________________________
'
'
' multitasking routines for the GCBASIC compiler
' 2009 Santiago Gonzalez
'
' This library is free software; you can redistribute it and/or
' modify it under the terms of the GNU Lesser General Public
' License as published by the Free Software Foundation; either
' version 2.1 of the License, or (at your option) any later version.
' This library is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
' Lesser General Public License for more details.
' You should have received a copy of the GNU Lesser General Public
' License along with this library; if not, write to the Free Software
' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
'
'_______________________________________________________________________
'
'
'Notas:
'
'La base de tiempo está fijada en 10 ms, pero puede ser cambiada
'reconfigurando el prescaler de Timer0 y el contador: "timer0_val"
'en las primeras lineas de la función: Init_Multitask
'
'La base de tiempo está optimizada para reloj de 4MHz.
'para optimizarla a otros valores de reloj
'editar la primera liea de la función: Interrupt_Timer0.
'
'Actualmente un máximo de 8 tareas están soportadas.
'para aumentar hasta 16 tareas, declarar la variable "flags" as word
'en la función: Init_Multitask
'y añadir los elementos propios de cada tarea en todas las funciones:
'#ifdef Task9...#endif,....
'editando valores con los nuevos nº de tareas (¡cuidado con los nº de flag!)
'
'El valor máximo para el periodo de tareas: "time_Task(n)" es 255
'Para periodos más largos declarar "cont_Task(n)"
'y "time_Task(n)" as word en la funcion: Init_Multitask.
'Pero es desable tener variables tipo byte para un código lo más corto posible.
'
'_______________________________________________________________________
'Initialisation routine
#startup Init_Multitask
Sub Interrupt_Timer0
wait 7 us 'Valor optimizado en us = 17-10/(ChipMhz/4)
TMR0 = timer0_val 'inicializar contador de timer0
#ifdef Task1
cont_Task1 += 1 'incrementar contador de tarea
if cont_Task1 >= time_Task1 then 'si el periodo de tarea es alcanzado
cont_Task1 = 0 'reiniciar contador de tarea
flag_Task1 = 1 'subir flag de tarea
End if
#ifdef Run_Task1
Do_Task1
#endif
#endif
#ifdef Task2
cont_Task2 += 1
if cont_Task2 >= time_Task2 then
cont_Task2 = 0
flag_Task2 = 1
End if
#ifdef Run_Task2
Do_Task2
#endif
#endif
#ifdef Task3
cont_Task3 += 1
if cont_Task3 >= time_Task3 then
cont_Task3 = 0
flag_Task3 = 1
End if
#ifdef Run_Task3
Do_Task3
#endif
#endif
#ifdef Task4
cont_Task4 += 1
if cont_Task4 >= time_Task4 then
cont_Task4 = 0
flag_Task4 = 1
End if
#ifdef Run_Task4
Do_Task4
#endif
#endif
#ifdef Task5
cont_Task5 += 1
if cont_Task5 >= time_Task5 then
cont_Task5 = 0
flag_Task5 = 1
End if
#ifdef Run_Task5
Do_Task5
#endif
#endif
#ifdef Task6
cont_Task6 += 1
if cont_Task6 >= time_Task6 then
cont_Task6 = 0
flag_Task6 = 1
End if
#ifdef Run_Task6
Do_Task6
#endif
#endif
#ifdef Task7
cont_Task7 += 1
if cont_Task7 >= time_Task7 then
cont_Task7 = 0
flag_Task7 = 1
End if
#ifdef Run_Task7
Do_Task7
#endif
#endif
#ifdef Task8
cont_Task8 += 1
if cont_Task8 >= time_Task8 then
cont_Task8 = 0
flag_Task8 = 1
End if
#ifdef Run_Task8
Do_Task8
#endif
#endif
End Sub
Sub Init_Multitask
dim flags as byte 'byte para 8 flags (as word para 16 flags)
#define timer0_val 256-39*(ChipMhz/4)
InitTimer0 Osc, PS0_1/256 'Timer0 configurado para 10 ms
On Interrupt Timer0Overflow Call Interrupt_Timer0
#ifdef Task1
dim cont_Task1 as byte 'contador de tarea
dim time_Task1 as byte 'Periodo de tarea
#define flag_Task1 flags.0 'flag de tarea
#endif
#ifdef Task2
dim cont_Task2 as byte
dim time_Task2 as byte
#define flag_Task2 flags.1
#endif
#ifdef Task3
dim cont_Task3 as byte
dim time_Task3 as byte
#define flag_Task3 flags.2
#endif
#ifdef Task4
dim cont_Task4 as byte
dim time_Task4 as byte
#define flag_Task4 flags.3
#endif
#ifdef Task5
dim cont_Task5 as byte
dim time_Task5 as byte
#define flag_Task5 flags.4
#endif
#ifdef Task6
dim cont_Task6 as byte
dim time_Task6 as byte
#define flag_Task6 flags.5
#endif
#ifdef Task7
dim cont_Task7 as byte
dim time_Task7 as byte
#define flag_Task7 flags.6
#endif
#ifdef Task8
dim cont_Task8 as byte
dim time_Task8 as byte
#define flag_Task8 flags.7
#endif
End Sub
#ifdef Task1
Sub Do_Task1
if flag_Task1 on then
set flag_Task1 off
call Task1
End if
End Sub
#endif
#ifdef Task2
Sub Do_Task2
if flag_Task2 on then
set flag_Task2 off
call Task2
End if
End Sub
#endif
#ifdef Task3
Sub Do_Task3
if flag_Task3 on then
set flag_Task3 off
call Task3
End if
End Sub
#endif
#ifdef Task4
Sub Do_Task4
if flag_Task4 on then
set flag_Task4 off
call Task4
End if
End Sub
#endif
#ifdef Task5
Sub Do_Task5
if flag_Task5 on then
set flag_Task5 off
call Task5
End if
End Sub
#endif
#ifdef Task6
Sub Do_Task6
if flag_Task6 on then
set flag_Task6 off
call Task6
End if
End Sub
#endif
#ifdef Task7
Sub Do_Task7
if flag_Task7 on then
set flag_Task7 off
call Task7
End if
End Sub
#endif
#ifdef Task8
Sub Do_Task8
if flag_Task8 on then
set flag_Task8 off
call Task8
End if
End Sub
#endif
Y este es el ejemplo:
- Código:
'_______________________________________________________________________
'
'
' Multitasking example
'
'_______________________________________________________________________
'
'
' multitasking example for the GCBASIC compiler
' 2009 Santiago Gonzalez
'
' This program is free software; you can redistribute it and/or
' modify it under the terms of the GNU Lesser General Public
' License as published by the Free Software Foundation; either
' version 2.1 of the License, or (at your option) any later version.
' This library is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
' Lesser General Public License for more details.
' You should have received a copy of the GNU Lesser General Public
' License along with this library; if not, write to the Free Software
' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
'
'_______________________________________________________________________
'
'Notas:
'
'**** ¡¡¡Copiar multitasking.h a "../GCBASIC/include" !!! ****
'
'Hay dos maneras de ejecutar las tareas:
'
' 1)- Dentro del bucle principal:
' En este ejemplo, las tareas Task2 y Task3.
' La prioridad de cada tarea está determinada por el orden
' en que son llamadas en el bucle principal,
' icluyendo cualquier otra rutina presente en el bucle principal.
'
' 2)- Dentro de la rutina de interrupciones:
' En este ejemplo, Task1 es ejecutada de esta manera.
' La prioridad está determinada por el número de tarea, esto es:
' Task1 es la más prioritaria, y Task8 la menos.
' Como estas tareas está dentro de interrupciones,
' serán ejecutadas incluso si otra rutina está corriendo
' en el bucle principal. Osea estas tareas tienen prioridad sobre
' las tareas ejecutadas en el bucle principal.
' Este modo debería ser usado con rutinas cortas
' para evitar la superposición de interrupciones.
'
'Entonces, en este ejemplo las prioridades de todas las tareas son estas:
' 1º Task1
' 2º ReadAD
' 3º Task3
' 4º Task2
'
'Este ejemplo hará parpadear 3 leds conectados a PORTB.0, PORTB.1, PORT.2
'Led1 cambiará de estado cada 500 ms y Led2 cada 300 ms.
'Led3 parpadeará con un periodo determinado por el valor ADC leido.
'
'-------------------------- CONFIGURAR MICRO ----------------------------
'------------------------------------------------------------------------
#chip 16F876A, 4 'modelo de pic y velocidad de reloj
#config HS_OSC, WDT_OFF, LVP_OFF, PWRTE_ON
'---------------------- DEFINICIONES DE TAREAS --------------------------
'------------------------------------------------------------------------
#include multitasking.h
#define Task1 led1 'define subrutina de tarea
#define Run_Task1 'Ejecuta tarea dentro de interrupciones
time_Task1 = 50 'x10 ms = la tarea se ejecutará cada 500 ms
#define Task2 led2
time_Task2 = 30
#define Task3 led3
'---------------------------- PRINCIPAL ---------------------------------
'------------------------------------------------------------------------
Dir PORTA.0 in
Dir PORTB out
do
time_Task3 = ReadAD(AN0) 'Establece periodo de lED3 al valor ADC leido
wait 1 ms 'No se porqué, pero sin esto adc no funciona bien
Do_task3
Do_Task2
loop
'----------------------- SUBRUTINAS DE TAREAS ---------------------------
'------------------------------------------------------------------------
Sub led1
if PORTB.0 on then
set PORTB.0 off
else
set PORTB.0 on
End if
End Sub
Sub led2
if PORTB.1 on then
set PORTB.1 off
else
set PORTB.1 on
End if
End Sub
Sub led3
if PORTB.2 on then
set PORTB.2 off
else
set PORTB.2 on
End if
End Sub
Re: Librería para multitarea en GCBasic.
Hay una segunda versión de esta librería con algunas mejoras:
- Se puede (se debe) fijar la base de tiempo en el programa de usuario. De esta forma es mucho más facil crear "multitarea" con distintas bases de tiempo.
- Se puede fijar la duración de cada tarea directamente en unidades de tiempo en vez de en ciclos: us, ms, s. Así se evitan cálculos pesados y no es necesario cambiar la duración de las tareas si se cambia la base de tiempo.
- Hasta 16 tareas normales y 8 tareas largas (LTask), estas LTasks pueden tener un periodo de hasta 65535 veces la base tiempo, con lo que se pueden coseguir periodos de hasta una hora con reloj de 4 Mhz y 65535 us de base de tiempo.
Las tareas normales hasta 255 veces la base de tiempo.
Ahora resulta mucho más facil de usar, evitándose cálculos engorrosos; solo hay que tener en cuenta los límites máximos dependiendo de la velocidad de reloj que se use.
Se puede descargar la librería aquí: multitasking.h
Se agradece cualquier información sobre fallos, sugerencias, etc.
Saludos.
- Se puede (se debe) fijar la base de tiempo en el programa de usuario. De esta forma es mucho más facil crear "multitarea" con distintas bases de tiempo.
- Se puede fijar la duración de cada tarea directamente en unidades de tiempo en vez de en ciclos: us, ms, s. Así se evitan cálculos pesados y no es necesario cambiar la duración de las tareas si se cambia la base de tiempo.
- Hasta 16 tareas normales y 8 tareas largas (LTask), estas LTasks pueden tener un periodo de hasta 65535 veces la base tiempo, con lo que se pueden coseguir periodos de hasta una hora con reloj de 4 Mhz y 65535 us de base de tiempo.
Las tareas normales hasta 255 veces la base de tiempo.
Ahora resulta mucho más facil de usar, evitándose cálculos engorrosos; solo hay que tener en cuenta los límites máximos dependiendo de la velocidad de reloj que se use.
Se puede descargar la librería aquí: multitasking.h
Se agradece cualquier información sobre fallos, sugerencias, etc.
Saludos.
Re: Librería para multitarea en GCBasic.
Otro ejemplo, usando multitasking para generar pwm.
8 leds conectados al puerto B de un 16F627, lo mejor ver un video del efecto en una simulación de ktechlab:
http://piclinux.sourceforge.net/files/videos/rot-led.ogg
8 leds conectados al puerto B de un 16F627, lo mejor ver un video del efecto en una simulación de ktechlab:
http://piclinux.sourceforge.net/files/videos/rot-led.ogg
- Código:
'-------------------------- CONFIGURE MICRO -----------------------------
'------------------------------------------------------------------------
#chip 16F627, 4 'modelo de pic y velocidad de reloj
#config HS_OSC, WDT_OFF, LVP_OFF, PWRTE_ON
'------------------------ TASK's DEFINITIONS ----------------------------
'------------------------------------------------------------------------
#include <multitasking.h>
#define niveles 20 'Niveles de luz (resolucion de pwm)
#define base_time 500 'Tiempo base en us
#define Task1 rota_leds
#define Task1_us 255*base_time 'Periodo de tarea en us
#define Task2 calc_output
#define Task2_us base_time
#define Task7 pwm_period 'Periodo pwm
#define Run_Task7 'Run Task inside interrupt subroutine
#define Task7_us niveles*base_time 'Periodo-pwm = resolucion * base time
#define LTask1 life_led 'LTask es para tareas de periodo largo
#define LTask1_ms 500 'usar LTask cuando periodo > base_time*255
'----------------------------- REGs DEFs --------------------------------
'------------------------------------------------------------------------
#define total_regs 7
#define registro 77 - total_regs
'------------------------------- MAIN -----------------------------------
'------------------------------------------------------------------------
TRISA = 0
TRISB = 0
for contador = 0 to total_regs
FSR = registro + contador 'Establece valores iniciales
INDF = (contador*contador)/3
puerto = puerto xor 255 'parpadea todo los leds
wait 200 ms
Next
wait 500 ms
do 'Bucle principal
Do_Task1
Do_Task2
Do_LTask1
loop
'---------------------------- TASK's SUBs -------------------------------
'------------------------------------------------------------------------
Sub rota_leds
for contador = 0 to total_regs
FSR = registro + contador
prev = INDF
INDF = regprev
regprev = prev
Next
End Sub
Sub calc_output
lectura = 0
FSR = registro
if INDF > cont_Task7 then lectura.0 = 1
FSR += 1
if INDF > cont_Task7 then lectura.1 = 1
FSR += 1
if INDF > cont_Task7 then lectura.2 = 1
FSR += 1
if INDF > cont_Task7 then lectura.3 = 1
FSR += 1
if INDF > cont_Task7 then lectura.4 = 1
FSR += 1
if INDF > cont_Task7 then lectura.5 = 1
FSR += 1
if INDF > cont_Task7 then lectura.6 = 1
FSR += 1
if INDF > cont_Task7 then lectura.7 = 1
PORTB = lectura
End Sub
Sub pwm_period 'esta tarea solo es necesaria para tener cont_task7
nop
End Sub
Sub life_led
PORTA = PORTA xor 1 'invierte salida RA0
End Sub
Re: Librería para multitarea en GCBasic.
Otro ejemplito: voltimetro simple 0-5v
Y un video de la simulación: http://piclinux.sourceforge.net/files/videos/volt0.ogg
Y un video de la simulación: http://piclinux.sourceforge.net/files/videos/volt0.ogg
- Código:
'________________________________________________________________________________
'
' Voltimetro 0-5V
'________________________________________________________________________________
'
#chip 16F876a, 4'MHz
#config HS_OSC, WDT_OFF, LVP_OFF, PWRTE_ON
#include <adc-87X.h>
#include <multitasking.h>
'________________________________________________________________________________
'______ TAREAS __________________________________________________________________
#define base_time 10000 'base de tiempo = 10.000 us = 10 ms
#define Task1 lectura_ADC 'Lectura ADC
#define Task1_ms 200
#define Task2 print_display 'Muestra valores en 7seg
#define Task2_ms 10
#define Task7 led_testigo 'Led parpadeante, testigo de funcionamiento
#define Task7_ms 500
'________________________________________________________________________________
'______ PRINCIPAL _______________________________________________________________
TRISA = 1
TRISB = 0
TRISC = 0
display = 1
adc_conf8 FOSC/32, A1_R0 'Cofigura ADC
adc_open CH0 'Abrir canal 0
do 'Bucle principal
Do_Task1
Do_Task2
Do_Task7
loop
'________________________________________________________________________________
'_______ SUBRUTINAS ____________________________________________________________
Sub lectura_ADC
lectura = adc_read8/5
digito1 = lectura/10 'unidad (entero de la división)
digito2 = SysCalcTempX 'decimal (módulo de la división)
End Sub
Sub print_display
if display = 1 then
valor(digito1)
movwf PORTB
PORTC.4 = 0
PORTC.5 = 1
display = 2
else
valor(digito2)
movwf PORTB
PORTC.4 = 1
PORTC.5 = 0
display = 1
End if
End Sub
Sub led_testigo
PORTC = PORTC xor 1 'invierte RC0
End Sub
Sub valor(lectu) #NR
asm pagesel valor
PCL += lectu
retlw 63
retlw 6
retlw 91
retlw 79
retlw 102
retlw 109
retlw 125
retlw 7
retlw 127
retlw 103
End Sub
Re: Librería para multitarea en GCBasic.
Hola que tal!
Esta muy bueno el gcbasic!
ya lo estoy probando con pikdev para programar y gedit como IDE para programar
Jugando un poco con la rutina que muestras con la multitarea funca muy bien para el
micro que expones, sin embargo veo que no me funciona para un pic18f2550
y me manda la siguiente lista de errores
Great Cow BASIC (0.9 12/8/2009)
Compilando /home/mike/Documentos/GCBasic/rot-led.bas ...
Hecho
Ensamblando programa ...
/home/mike/Documentos/GCBasic/rot-led.asm:283:Error [113] Symbol not previously defined (OPTION_REG).
/home/mike/Documentos/GCBasic/rot-led.asm:283:Error [113] Symbol not previously defined (OPTION_REG).
/home/mike/Documentos/GCBasic/rot-led.asm:285:Error [113] Symbol not previously defined (OPTION_REG).
/home/mike/Documentos/GCBasic/rot-led.asm:285:Error [113] Symbol not previously defined (OPTION_REG).
Hecho.
la modificacion que hice y que me funciono para encender y apagar un led fue la siguiente
'-------------------------- CONFIGURE MICRO -----------------------------
'------------------------------------------------------------------------
#chip 18F2550, 20 'modelo de pic y velocidad de reloj
'------------------------ TASK's DEFINITIONS ----------------------------
'------------------------------------------------------------------------
#include
#define niveles 20 'Niveles de luz (resolucion de pwm)
como verás es lo mismo. solo cambie la info del chip, por lo fuses no me preocupo, pues ya lo probe antes asi con otro programa muy sencillo y si jala tal cual esta (Ya lo probe de forma física )
el asm que me tira este código es el siguiente:
veo que en la libreria de multitasking que nos hiciste favor de publicar lleva una parte en ensamblador que hace referencia al OPTION_REG.
Donde configuras al timer0 para que sea la base de tiempo, sin embargo en el archivo .inc del 18F2550
dicho registro no se encuentra.
tomado de gputils mike@mike:/usr/share/gputils/header$ nano p18f2550.inc
de acuerdo al archivo de configuracion del GcBasic que se encuentra en
mike@mike:/usr/share/GcBasic$ nano gcbasic.ini
el compilador que se utiliza para el ensamblador que genera GcBasic es gputils
Será posible que la rutina no funcione con la familia 18F25XX o en que me estoy equivocando?
Por tu tiempo, muchas gracias!!
***********************************************
Crees que sea util esta información??, la voy a revisar al rato, ya me lanzo a mi casita
http://www.mikroe.com/forum/viewtopic.php?t=21894&sid=433454ea33b6b1a7719d31eeda349bcd
Esta muy bueno el gcbasic!
ya lo estoy probando con pikdev para programar y gedit como IDE para programar
Jugando un poco con la rutina que muestras con la multitarea funca muy bien para el
micro que expones, sin embargo veo que no me funciona para un pic18f2550
y me manda la siguiente lista de errores
Great Cow BASIC (0.9 12/8/2009)
Compilando /home/mike/Documentos/GCBasic/rot-led.bas ...
Hecho
Ensamblando programa ...
/home/mike/Documentos/GCBasic/rot-led.asm:283:Error [113] Symbol not previously defined (OPTION_REG).
/home/mike/Documentos/GCBasic/rot-led.asm:283:Error [113] Symbol not previously defined (OPTION_REG).
/home/mike/Documentos/GCBasic/rot-led.asm:285:Error [113] Symbol not previously defined (OPTION_REG).
/home/mike/Documentos/GCBasic/rot-led.asm:285:Error [113] Symbol not previously defined (OPTION_REG).
Hecho.
la modificacion que hice y que me funciono para encender y apagar un led fue la siguiente
'-------------------------- CONFIGURE MICRO -----------------------------
'------------------------------------------------------------------------
#chip 18F2550, 20 'modelo de pic y velocidad de reloj
'------------------------ TASK's DEFINITIONS ----------------------------
'------------------------------------------------------------------------
#include
#define niveles 20 'Niveles de luz (resolucion de pwm)
como verás es lo mismo. solo cambie la info del chip, por lo fuses no me preocupo, pues ya lo probe antes asi con otro programa muy sencillo y si jala tal cual esta (Ya lo probe de forma física )
- Código:
' led que parpadea
#chip 18F2550, 20 ' modelo del procesador y velocidad del reloj
#define led PORTB.6
main:
TRISB=0
PORTB = 0
led =1
wait 1000 ms
led = 0
wait 1000 ms
goto main
el asm que me tira este código es el siguiente:
- Código:
;Program compiled by Great Cow BASIC (0.9 12/8/2009)
;Need help? See the GCBASIC forums at http://sourceforge.net/forum/?group_id=169286,
;check the documentation or email w_cholmondeley@users.sourceforge.net.
;********************************************************************************
;Set up the assembler options (Chip type, clock source, other bits and pieces)
LIST p=18F2550, r=DEC
#include
CONFIG WDT=OFF, LVP=OFF, MCLRE=OFF, FOSC=HS
;********************************************************************************
;Set aside memory locations for variables
DELAYTEMP EQU 0
DELAYTEMP2 EQU 1
SysWaitTempMS EQU 2
SysWaitTempMS_H EQU 3
;********************************************************************************
;Vectors
ORG 0
bra BASPROGRAMSTART
ORG 8
retfie
;********************************************************************************
;Start of program memory page 0
ORG 12
BASPROGRAMSTART
;Call initialisation routines
rcall INITSYS
;Start of the main program
MAIN
clrf TRISB,ACCESS
clrf PORTB,ACCESS
bsf PORTB,6,ACCESS
movlw 232
movwf SysWaitTempMS,ACCESS
movlw 3
movwf SysWaitTempMS_H,ACCESS
rcall Delay_MS
bcf PORTB,6,ACCESS
movlw 232
movwf SysWaitTempMS,ACCESS
movlw 3
movwf SysWaitTempMS_H,ACCESS
rcall Delay_MS
bra MAIN
BASPROGRAMEND
sleep
bra $
;********************************************************************************
Delay_MS
incf SysWaitTempMS_H, F,ACCESS
DMS_START
movlw 227
movwf DELAYTEMP2,ACCESS
DMS_OUTER
movlw 6
movwf DELAYTEMP,ACCESS
DMS_INNER
decfsz DELAYTEMP, F,ACCESS
bra DMS_INNER
decfsz DELAYTEMP2, F,ACCESS
bra DMS_OUTER
decfsz SysWaitTempMS, F,ACCESS
bra DMS_START
decfsz SysWaitTempMS_H, F,ACCESS
bra DMS_START
return
;********************************************************************************
INITSYS
clrf BSR,ACCESS
clrf TBLPTRU,ACCESS
bcf ADCON0,ADON,ACCESS
bcf ADCON2,ADFM,ACCESS
bsf ADCON1,PCFG3,ACCESS
bsf ADCON1,PCFG2,ACCESS
bsf ADCON1,PCFG1,ACCESS
bsf ADCON1,PCFG0,ACCESS
movlw 7
movwf CMCON,ACCESS
clrf PORTA,ACCESS
clrf PORTB,ACCESS
clrf PORTC,ACCESS
clrf PORTE,ACCESS
return
;********************************************************************************
END
veo que en la libreria de multitasking que nos hiciste favor de publicar lleva una parte en ensamblador que hace referencia al OPTION_REG.
- Código:
movlw 192 'configure Timer0
andwf OPTION_REG,F
movf SysCalcTempA,W
iorwf OPTION_REG,F
clrwdt
Donde configuras al timer0 para que sea la base de tiempo, sin embargo en el archivo .inc del 18F2550
dicho registro no se encuentra.
tomado de gputils mike@mike:/usr/share/gputils/header$ nano p18f2550.inc
- Código:
;==========================================================================
; 18xxxx Family EQUates
;==========================================================================
FSR0 EQU 0
FSR1 EQU 1
FSR2 EQU 2
FAST EQU 1
W EQU 0
A EQU 0
ACCESS EQU 0
BANKED EQU 1
;==========================================================================
;==========================================================================
; 16Cxxx/17Cxxx Substitutions
;==========================================================================
#define DDRA TRISA ; PIC17Cxxx SFR substitution
#define DDRB TRISB ; PIC17Cxxx SFR substitution
#define DDRD TRISD ; PIC17Cxxx SFR substitution
#define DDRE TRISE ; PIC17Cxxx SFR substitution
;==========================================================================
;
; Register Definitions
;
;==========================================================================
;----- Register Files -----------------------------------------------------
UFRM EQU H'0F66'
UFRML EQU H'0F66'
UFRMH EQU H'0F67'
UIR EQU H'0F68'
UIE EQU H'0F69'
UEIR EQU H'0F6A'
UEIE EQU H'0F6B'
USTAT EQU H'0F6C'
UCON EQU H'0F6D'
UADDR EQU H'0F6E'
UCFG EQU H'0F6F'
UEP0 EQU H'0F70'
UEP1 EQU H'0F71'
UEP2 EQU H'0F72'
UEP3 EQU H'0F73'
UEP4 EQU H'0F74'
UEP5 EQU H'0F75'
UEP6 EQU H'0F76'
UEP7 EQU H'0F77'
UEP8 EQU H'0F78'
UEP9 EQU H'0F79'
UEP10 EQU H'0F7A'
UEP11 EQU H'0F7B'
UEP12 EQU H'0F7C'
UEP13 EQU H'0F7D'
UEP14 EQU H'0F7E'
UEP15 EQU H'0F7F'
PORTA EQU H'0F80'
PORTB EQU H'0F81'
PORTC EQU H'0F82'
PORTE EQU H'0F84'
LATA EQU H'0F89'
LATB EQU H'0F8A'
LATC EQU H'0F8B'
DDRA EQU H'0F92'
TRISA EQU H'0F92'
DDRB EQU H'0F93'
TRISB EQU H'0F93'
DDRC EQU H'0F94'
TRISC EQU H'0F94'
OSCTUNE EQU H'0F9B'
PIE1 EQU H'0F9D'
PIR1 EQU H'0F9E'
IPR1 EQU H'0F9F'
PIE2 EQU H'0FA0'
PIR2 EQU H'0FA1'
IPR2 EQU H'0FA2'
EECON1 EQU H'0FA6'
EECON2 EQU H'0FA7'
EEDATA EQU H'0FA8'
EEADR EQU H'0FA9'
RCSTA EQU H'0FAB'
TXSTA EQU H'0FAC'
TXREG EQU H'0FAD'
RCREG EQU H'0FAE'
SPBRG EQU H'0FAF'
SPBRGH EQU H'0FB0'
T3CON EQU H'0FB1'
TMR3L EQU H'0FB2'
TMR3H EQU H'0FB3'
CMCON EQU H'0FB4'
CVRCON EQU H'0FB5'
CCP1AS EQU H'0FB6'
ECCP1AS EQU H'0FB6'
CCP1DEL EQU H'0FB7'
ECCP1DEL EQU H'0FB7'
BAUDCON EQU H'0FB8'
CCP2CON EQU H'0FBA'
CCPR2 EQU H'0FBB'
CCPR2L EQU H'0FBB'
CCPR2H EQU H'0FBC'
CCP1CON EQU H'0FBD'
CCPR1 EQU H'0FBE'
CCPR1L EQU H'0FBE'
CCPR1H EQU H'0FBF'
ADCON2 EQU H'0FC0'
ADCON1 EQU H'0FC1'
ADCON0 EQU H'0FC2'
ADRES EQU H'0FC3'
ADRESL EQU H'0FC3'
ADRESH EQU H'0FC4'
SSPCON2 EQU H'0FC5'
SSPCON1 EQU H'0FC6'
SSPSTAT EQU H'0FC7'
SSPADD EQU H'0FC8'
SSPBUF EQU H'0FC9'
T2CON EQU H'0FCA'
PR2 EQU H'0FCB'
TMR2 EQU H'0FCC'
T1CON EQU H'0FCD'
TMR1L EQU H'0FCE'
TMR1H EQU H'0FCF'
RCON EQU H'0FD0'
WDTCON EQU H'0FD1'
HLVDCON EQU H'0FD2'
LVDCON EQU H'0FD2'
OSCCON EQU H'0FD3'
T0CON EQU H'0FD5'
TMR0L EQU H'0FD6'
TMR0H EQU H'0FD7'
STATUS EQU H'0FD8'
FSR2L EQU H'0FD9'
FSR2H EQU H'0FDA'
PLUSW2 EQU H'0FDB'
PREINC2 EQU H'0FDC'
POSTDEC2 EQU H'0FDD'
POSTINC2 EQU H'0FDE'
INDF2 EQU H'0FDF'
BSR EQU H'0FE0'
FSR1L EQU H'0FE1'
FSR1H EQU H'0FE2'
PLUSW1 EQU H'0FE3'
PREINC1 EQU H'0FE4'
POSTDEC1 EQU H'0FE5'
POSTINC1 EQU H'0FE6'
INDF1 EQU H'0FE7'
WREG EQU H'0FE8'
FSR0L EQU H'0FE9'
FSR0H EQU H'0FEA'
PLUSW0 EQU H'0FEB'
PREINC0 EQU H'0FEC'
POSTDEC0 EQU H'0FED'
POSTINC0 EQU H'0FEE'
INDF0 EQU H'0FEF'
INTCON3 EQU H'0FF0'
INTCON2 EQU H'0FF1'
INTCON EQU H'0FF2'
PROD EQU H'0FF3'
PRODL EQU H'0FF3'
PRODH EQU H'0FF4'
TABLAT EQU H'0FF5'
TBLPTR EQU H'0FF6'
TBLPTRL EQU H'0FF6'
TBLPTRH EQU H'0FF7'
TBLPTRU EQU H'0FF8'
PC EQU H'0FF9'
PCL EQU H'0FF9'
PCLATH EQU H'0FFA'
PCLATU EQU H'0FFB'
STKPTR EQU H'0FFC'
TOS EQU H'0FFD'
TOSL EQU H'0FFD'
TOSH EQU H'0FFE'
TOSU EQU H'0FFF'
de acuerdo al archivo de configuracion del GcBasic que se encuentra en
mike@mike:/usr/share/GcBasic$ nano gcbasic.ini
el compilador que se utiliza para el ensamblador que genera GcBasic es gputils
- Código:
'Assembler to use
'MPASM settings
'Filename, is relative to GCBASIC directory unless a full path is given
Assembler = gpasm
'Parameters
AssemblerParams = --hex-format inhx32 --radix DEC --warning 2 --ignore-case --f$
'GCASM settings
'Assembler = GCASM
'No params needed for GCASM
Será posible que la rutina no funcione con la familia 18F25XX o en que me estoy equivocando?
Por tu tiempo, muchas gracias!!
***********************************************
Crees que sea util esta información??, la voy a revisar al rato, ya me lanzo a mi casita
http://www.mikroe.com/forum/viewtopic.php?t=21894&sid=433454ea33b6b1a7719d31eeda349bcd
maigke- Asiduo del Foro
- Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 47
Localización : Mexico
Re: Librería para multitarea en GCBasic.
Parace que ya quedo la modificacion que realize y ya me compilo y funciono mas o menos, aun tengo que ver que onda con el reloj fue la siguiente
Con eso ya me compilo, solo me falta ver que onda, al menos los leds prenden y si cambia la frecuencia, esto lo estoy revisando con un frecuencimetro.
Espero sea bueno el arreglo
Gracias!!!
pd. ademas de que tuve que cambiar el nombre de la libreria por multitasking2.h para no borrar la tuya
y anexar la modificacion en el /usr/share/GcBasic/include
- Código:
movlw 192 'configure Timer0
andwf T0CON,F ' de acuerdo al link que esta anteriormente este registro es bit a bit igual a OPTION_REG
movf SysCalcTempA,W
iorwf T0CON,F
clrwdt
Con eso ya me compilo, solo me falta ver que onda, al menos los leds prenden y si cambia la frecuencia, esto lo estoy revisando con un frecuencimetro.
Espero sea bueno el arreglo
Gracias!!!
pd. ademas de que tuve que cambiar el nombre de la libreria por multitasking2.h para no borrar la tuya
y anexar la modificacion en el /usr/share/GcBasic/include
mike@mike:/usr/share/GcBasic/include$ ls
3pi.h DS18s20.h lego.h multitasking2.h template.h
adc-87X.h eracer.h lowlevel multitasking.h terminal-pic.h
comp-87X.h gcalpha.h lowlevel.dat srf04.h
mike@mike:/usr/share/GcBasic/include$
maigke- Asiduo del Foro
- Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 47
Localización : Mexico
Re: Librería para multitarea en GCBasic.
Gracias por la informacion... y por la solución!
Para no tener dos archivos puedes probar a sustituir esto:
Por esto:
Si los dos registros son iguales bit a bit, esto debería funcionar.
Si ves que funciona coméntalo para actualizar el archivo.
Saludos.
Para no tener dos archivos puedes probar a sustituir esto:
- Código:
movlw 192 'configure Timer0
andwf OPTION_REG,F
movf SysCalcTempA,W
iorwf OPTION_REG,F
clrwdt
Por esto:
- Código:
#IFDEF VAR(OPTION_REG)
movlw 192 'configure Timer0 16f
andwf OPTION_REG,F
movf SysCalcTempA,W
iorwf OPTION_REG,F
clrwdt
#ENDIF
#IFDEF VAR(T0CON)
movlw 192 'configure Timer0 18f
andwf T0CON,F
movf SysCalcTempA,W
iorwf T0CON,F
clrwdt
#ENDIF
Si los dos registros son iguales bit a bit, esto debería funcionar.
Si ves que funciona coméntalo para actualizar el archivo.
Saludos.
Re: Librería para multitarea en GCBasic.
Maigke... creo que OPTION_REG y T0CON no son exactamente iguales:
En el enlace que pusiste:
Los bits 6 y 7 de OPTION_REG no se usan para timer0, y parece que en los 18f o al menos en algunos de ellos es necesario iniciar el timer0 y decirle que en modo 8 bits... en los 16f timer0 siempre está funcionando y siempre es a 8 bits; no tengo idea de esto, sería cuestión de mirarse el datasheet del pic que estés usando y comprobar esto.
Si esto es así habría que poner a 1 los bits 6 y 7, en #IFDEF VAR(T0CON)
Saludos.
En el enlace que pusiste:
You should set TMR0ON bit, as well as T08BIT to enable Timer0 and set it to 8-bit mode:
Code: T0CON = %11000111
Los bits 6 y 7 de OPTION_REG no se usan para timer0, y parece que en los 18f o al menos en algunos de ellos es necesario iniciar el timer0 y decirle que en modo 8 bits... en los 16f timer0 siempre está funcionando y siempre es a 8 bits; no tengo idea de esto, sería cuestión de mirarse el datasheet del pic que estés usando y comprobar esto.
Si esto es así habría que poner a 1 los bits 6 y 7, en #IFDEF VAR(T0CON)
Saludos.
Re: Librería para multitarea en GCBasic.
Cierto!!! en el pic hay que habilitar el timer y ademas configurar el tamaño del timer 0 ya sea a 16 bits o a 8 bits!
Gracias haré las modificaciones y te tendré al tanto, si esto queda, el multitasking será mucho mejor con los pic18
Gracias haré las modificaciones y te tendré al tanto, si esto queda, el multitasking será mucho mejor con los pic18
maigke- Asiduo del Foro
- Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 47
Localización : Mexico
Re: Librería para multitarea en GCBasic.
Hola analizando la rutina, vi lo siguiente
el movlw 192 carga el siguiente numero binario 1100 0000, poniendo en 11 los bits 7 y 6 del Registro
pero mas abajo vemos un and, dejando el valor que tenian esos bits y limpiando los demas
posterior leemos el registro SysCalcTempA y lo vaciamos en el Option Reg a través de una Or inclusiva
y por ultimo limpiamos el wdt
tomando como base tus comentarios la solucion solo consistira en nuevamente hacer una Or
con el numero 1100 000 al finalizar para no alterar los valores de los bits descargados
forzando así a 1 los valores de los bits 6 y 7 del tmr0
Esos bits sirven para habilitar el TMR0 y ajuste de 8bits el bit6, si esta en 1 el tmr0 es de 8 bits y si es cero esta a 16bits.
Saludos, si hay algun error por fa comentenlo!
veremos que podemos hacer entre todos
gracias
- Código:
movlw 192 'configure Timer0
andwf OPTION_REG,F
movf SysCalcTempA,W
iorwf OPTION_REG,F
clrwdt
el movlw 192 carga el siguiente numero binario 1100 0000, poniendo en 11 los bits 7 y 6 del Registro
pero mas abajo vemos un and, dejando el valor que tenian esos bits y limpiando los demas
posterior leemos el registro SysCalcTempA y lo vaciamos en el Option Reg a través de una Or inclusiva
y por ultimo limpiamos el wdt
tomando como base tus comentarios la solucion solo consistira en nuevamente hacer una Or
con el numero 1100 000 al finalizar para no alterar los valores de los bits descargados
forzando así a 1 los valores de los bits 6 y 7 del tmr0
- Código:
#ifdef var(OPTION_REG)
movlw 192 'configure Timer0
andwf OPTION_REG,F
movf SysCalcTempA,W
iorwf OPTION_REG,F
clrwdt
#endif
#ifdef var(T0CON)
movlw 192 'configura TMR0 PIC18
andwf T0CON,F
movf SysCalcTempA,W
iorwf T0CON,F
movlw 192 'cargamos de nuevo el 0xc0 TTTT TTTT
iorwf T0CON,F ' hacemos un OR con T0CON y lo guardamos ahi mismo Or 1100 0000
clrwdt res en T0Con 11TT TTTT
#endif
Esos bits sirven para habilitar el TMR0 y ajuste de 8bits el bit6, si esta en 1 el tmr0 es de 8 bits y si es cero esta a 16bits.
Saludos, si hay algun error por fa comentenlo!
veremos que podemos hacer entre todos
gracias
maigke- Asiduo del Foro
- Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 47
Localización : Mexico
Re: Librería para multitarea en GCBasic.
Si... exacto, se trata de no tocar los bits 6 y 7 de OPTION_reg que se usan para otras cosasel movlw 192 carga el siguiente numero binario 1100 0000, poniendo en 11 los bits 7 y 6 del Registro
pero mas abajo vemos un and, dejando el valor que tenian esos bits y limpiando los demas
posterior leemos el registro SysCalcTempA y lo vaciamos en el Option Reg a través de una Or inclusiva
y por ultimo limpiamos el wdt
Ok... esa solución debería funcionar.tomando como base tus comentarios la solucion solo consistira en nuevamente hacer una Or
con el numero 1100 000 al finalizar para no alterar los valores de los bits descargados
forzando así a 1 los valores de los bits 6 y 7 del tmr0
Pero, se podría optimizar un poco: dijimos que en los pic16f no queremos tocar los bit 6 y 7, de ahí las dos primeras lineas... pero en los 18f si que queremos modificar esos valores, así que: porqué no usar esas dos primeras lineas precisamente para eso?
Otra cosa que se me pasó es que clrwdt es común en los dos casos, así que se puede quedar fuera de los #ifdef
Y ya puestos a quitar lineas... el movlw 192 también es común osea que también se podría sacar:
- Código:
movlw 192
#ifdef var(OPTION_REG) 'configura TMR0 PIC16F
andwf OPTION_REG,F
movf SysCalcTempA,W
iorwf OPTION_REG,F
#endif
#ifdef var(T0CON) 'configura TMR0 PIC18F
movwf T0CON
movf SysCalcTempA,W
iorwf T0CON,F
#endif
clrwdt
Creo que así también debería funcionar... no?
Re: Librería para multitarea en GCBasic.
Saludos, pues en definitva no funciono como me esperaba, debe haber otros cambios mmm habra que buscarlos mas a fondo.
hice la prueba en hardware y en simulacion del proteus
bueno estaremos siguiendo este caso
hice la prueba en hardware y en simulacion del proteus
bueno estaremos siguiendo este caso
maigke- Asiduo del Foro
- Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 47
Localización : Mexico
Re: Librería para multitarea en GCBasic.
He subido una nueva versión que funciona tanto con Pics como Avrs, debería funcionar también con pic18f, o al menos algunos.
Ahora se pueden crear pwm facilmente, hay que definir la resolución y las salidas:
#define pwm_res 40
#define pwm1_out PORTB.1
#define pwm2_out PORTB.2
Luego para ajustar el duty, por ejemplo:
pwm1_duty = 10
pwm2_duty = variable
He subido un ejemplo al widget de descargas: GcBasic>Ejemplos>pwmled.gcb
El ejemplo más simple, un led que se enciende y apaga progresivamente:
Ahora se pueden crear pwm facilmente, hay que definir la resolución y las salidas:
#define pwm_res 40
#define pwm1_out PORTB.1
#define pwm2_out PORTB.2
Luego para ajustar el duty, por ejemplo:
pwm1_duty = 10
pwm2_duty = variable
He subido un ejemplo al widget de descargas: GcBasic>Ejemplos>pwmled.gcb
El ejemplo más simple, un led que se enciende y apaga progresivamente:
- Código:
' Pwm led en PORTB.0
'------------------------ CHIP CONFIG -----------------------------------
'------------------------------------------------------------------------
#chip 16f628a, 20
#config HS_OSC, WDT_OFF, LVP_OFF, PWRTE_ON, MCLR_ON
'------------------------ MULTITASKING ----------------------------------
'------------------------------------------------------------------------
#include <multitasking.h>
#define base_time 500
#define pwm_res 40
#define pwm1_out PORTB.0
'------------------------ MAIN LOOP -------------------------------------
'------------------------------------------------------------------------
Do
for pwm1_duty = 0 to 40
wait 100 ms
Next
for pwm1_duty = 40 to 0
wait 100 ms
Next
Loop
Temas similares
» GCBasic: Librería ADC para PIC16F87X
» GCBasic: Librería Comparadores para PIC
» Compilador Basic libre para PIC: GCBASIC
» Editor para compilar programas de GCBASIC
» Paquete deb para instalar GcBasic en Ubuntu
» GCBasic: Librería Comparadores para PIC
» Compilador Basic libre para PIC: GCBASIC
» Editor para compilar programas de GCBASIC
» Paquete deb para instalar GcBasic en Ubuntu
Página 1 de 1.
Permisos de este foro:
No puedes responder a temas en este foro.