Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

10/01/2012 #1

Avatar de mecatronix89

Ejecución de varias rutinas a la vez en un PIC
Hola. ¿Qué tal? No encontré algo así en el foro y por ello abrí el tema.

El problema que tengo es que estoy programando un PIC16F887 a 20MHz con CCS y necesito que una rutina se ejecute sin importar que otra rutina se ejecute en el PIC.
O sea, como si estuviera ejecutándose en un segundo plano.

Lo que tengo es lo siguiente, el PIC controla un LCD el cual despliega un menú que falta terminar pero el punto principal es que me muestra la temperatura en tiempo real utilizando un LM35.
Luego tengo otra rutina que de acuerdo a un LDR me enciende 1 ó 2 relevadores según esté más oscuro para las luces del auto.

Pero pues o me muestra cosas en el LCD o me controla los relevadores, y quiero que todo funcione al mismo tiempo.
Aparentemente claro, entendiendo que el PIC realiza un proceso a la vez a alta velocidad.

Código:
#include<16F887.h>
#device ADC=10
#fuses HS,NOWDT,NOLVP,MCLR,NOPROTECT
#use delay(clock=20000000)
#define use_portb_lcd TRUE
#include<LCD.C>
#define M PIN_D7 // 1 MENU
#define T PIN_D6 // 2 TEMPERATURA
//--------------------------------------------------------------------
int x;
long int ADC;
float temp,aux;
//--------------------------------------------------------------------
void config(void){
    set_tris_d(0xF0);
    set_tris_a(0x0F);
    setup_adc(ADC_CLOCK_INTERNAL|VSS_VDD);
    setup_adc_ports(sAN0);
            set_adc_channel(0);
    setup_comparator(NC_NC_NC_NC);
}
void config2(void){
    set_tris_d(0xF0);
    set_tris_a(0x0F);
    setup_adc(ADC_CLOCK_INTERNAL|VSS_VDD);
    setup_adc_ports(sAN1);
            set_adc_channel(1);
    setup_comparator(NC_NC_NC_NC);
}
void main(void){

    config();
    lcd_init();
            delay_ms(1000);
            lcd_gotoxy(1,1);
            lcd_putc("   BIENVENIDO");
                delay_ms(1000);
        for (x=0;x<=2;++x){
            lcd_gotoxy(1,2);
            lcd_putc("CARGANDO SISTEMA");
                delay_ms(400);
            lcd_gotoxy(1,2);
            lcd_putc("----------------");
                delay_ms(400);
        }goto MENU;
//-------------------------- --RELEVADORES-- ----------------------------//
INICIO:
config2();
    if(!input(PIN_C6)){
        delay_us(20);
LUCES:
        do{
            ADC=read_adc();
                delay_ms(800);
            if(ADC<=600){
                output_d(0b0000001);
            }else{
                    output_d(0x00);
                }
            if(ADC<=300){
                output_d(0b00000011);
            }else{
                    output_d(0x01);
                }
            if(ADC>600){
                output_d(0x00);
            }
                if(input(PIN_C6)){
                    output_d(0x00);
                    goto INICIO;
                }else{
                    goto LUCES;
                }

        }while(TRUE);
    }else{goto INICIO;}
//-----------------------------LCD MENU-------------------------------//
MENU:
        do{
            lcd_gotoxy(1,1);
            lcd_putc("      MENU      ");
            lcd_gotoxy(1,2);
            lcd_putc("   TEMP   C/C   ");
    if (input(T)){
        goto TEMPERATURA;
    }
        }while(TRUE);


TEMPERATURA:
        lcd_gotoxy(1,1);
        lcd_putc("    TEMP EXT");
            delay_ms(300);
        lcd_gotoxy(1,2);
        printf(lcd_putc,"INICIANDO SENSOR");
        do{
    if (input(M)){
        goto MENU;
    }
            delay_ms(1000);
            temp=read_adc();
            temp=(temp*300)/614;
            if(temp!=aux){
                lcd_gotoxy(1,2);
                printf(lcd_putc," < < < %0.0f'C > > >",temp);
                    delay_ms(400);
                lcd_gotoxy(1,2);
                printf(lcd_putc,"  - -  %0.0f'C  - -  ",temp);
                aux=temp;
            }
    if (input(M)){
        goto MENU;
    }
        }while(TRUE);
}
Ahí el código con las configuraciones de los ADC separada para que no se confunda el LCD ni el código de el LDR

Espero me puedan ayudar. Gracias.
10/01/2012 #2

Avatar de reyvilla

Hola un microcontrolador lamentablemente tiene como desventaja que ejecuta una tarea a la vez, a diferencia de un microprocesador que puede ejecutar varias tareas al mismo tiempo, lo que puedes hacer es utilizar interrupciones y de igual manera va a dejar lo que esta haciendo por atender la interrupción, pero no seria notable si trabajas en useg o mlseg...saludoss
10/01/2012 #3

Avatar de mecatronix89

reyvilla dijo: Ver Mensaje
Hola un microcontrolador lamentablemente tiene como desventaja que ejecuta una tarea a la vez, a diferencia de un microprocesador que puede ejecutar varias tareas al mismo tiempo, lo que puedes hacer es utilizar interrupciones y de igual manera va a dejar lo que esta haciendo por atender la interrupción, pero no seria notable si trabajas en useg o mlseg...saludoss
Que caray... buscaré eso de las interrupciones porque se muy poco jeje... Gracias
10/01/2012 #4

Avatar de jaimepsantos

Lo unico que puede hacer es muestrear la temperatura ya sea con un timer o metiendo dentro de un ciclo infinito que haga el muestreo, te cheque asi tambien la LDR, y te muestre en el LCD lo que desees, asi parecera que lo hace al mismo tiempo, por que es inperceptible para el usuario, ademas que no sera critico por que los cambios de temperatura y los cambios de luz no necesitan una respuesta ultrarapida(rango nS), bueno saludos!
10/01/2012 #5

Avatar de mecatronix89

jaimepsantos dijo: Ver Mensaje
Lo unico que puede hacer es muestrear la temperatura ya sea con un timer o metiendo dentro de un ciclo infinito que haga el muestreo, te cheque asi tambien la LDR, y te muestre en el LCD lo que desees, asi parecera que lo hace al mismo tiempo, por que es inperceptible para el usuario, ademas que no sera critico por que los cambios de temperatura y los cambios de luz no necesitan una respuesta ultrarapida(rango nS), bueno saludos!
También es buena idea... llamando la configuracion del adc antes de cada muestreo de cada sensor... creo que trataré esto antas de las interrupciones, me parece más sencillo jeje
11/01/2012 #6

Avatar de Scooter

Lo que hay que hacer siempre, es procurar usar interrupciones y nunca usar bucles vacíos como temporizadores, aprovechar ese tiempo haciendo algo.
11/01/2012 #7

Avatar de Sebastian1989

Estoy de acuerdo con los de arriba, utiliza una interrupción para realizar la segunda rutina cada unos pocos milisegundos, la otra opción es utilizar un microcontrolador propeller que es capaz de realizar 8 rutinas de forma simultanea, lógicamente para tu proyecto te recomiendo seguir con los PIC implementando la interrupción.
11/01/2012 #8

Avatar de aguevara

usa un pic de gama mas alta y usa RTOS de CCS
11/01/2012 #9


Hola... el problema q tienes se me presento hace tiempo, sucedía q para visualizar datos por lcd requieres darle un tiempo (delay); y mientras hacía esto perdía informacion en la recoleccion. Lo único q me aconsejaron era el de estructurar mejor el programa, utilizar las interrupciones de forma más adecuada o por último migrar al pic 18, ya que como dicen los pic gama media no pueden hacer dos cosas al mismo tiempo; el RTOS no es mala idea pero se requiere conocer bien esta herramienta...
SALUDOS
11/01/2012 #10
Excluido


no comprendo, porla velocidad que usa el ck y las aplicaciones que va a hacer no veo problema.

me parece que no comprendes bien lso recursos o mas bien como funciona el pic.
yo nunca me meti a usar un LCD , mencionas que hay tiempso de espera.
pues que si haces el programa bien no le veo problemas.

siempre que hay tiempso de espera como por ejemplo cuando usaba un conversor A/D hay flags, y hoy dia debe incluso haber pedidos de interrupcion.

y mencionas la activacion de reles.

no estas hablando de cosas que realmente requieran velocidad.

hay algo en la estructura del programa que falllas.

---------- Actualizado después de 10 minutos ----------

Sebastian1989 dijo: Ver Mensaje
Estoy de acuerdo con los de arriba, utiliza una interrupción para realizar la segunda rutina cada unos pocos milisegundos, la otra opción es utilizar un microcontrolador propeller que es capaz de realizar 8 rutinas de forma simultanea, lógicamente para tu proyecto te recomiendo seguir con los PIC implementando la interrupción.
solo de curioso me puse a buscar que es eso ??

que increible la mercaderia que hay disponible hoy dia en el mercado.
yo creo que hoy dia un Ingeniero apasionado por este rubro tiene para entretenerse , y no le alcanzarian las 24 hs de el dia con la tecnologia que hay disponible.
11/01/2012 #11

Avatar de mnicolau

Hola, a todo lo que comentaron, te agregaría evitar el uso de los "goto" (tal vez vengas de ASM y por eso los utilizás, a mi también me pasaba al principio). En C podrías utilizar funciones para hacer el direccionamiento de manera adecuada y más eficiente.

Estructurando mejor el programa y utilizando funciones, podés lograr sin problemas lo que estás planteando, sin ninguna necesidad del RTOS, incluso sin utilizar interrupciones en tu caso... recordá que si bien el código se ejecuta en forma secuencial, sin poder hacer rutinas simultáneas, la ejecución del código es tan rápido que podés tomarlas como prácticamente simultáneas.

Saludos
11/01/2012 #12

Avatar de mecatronix89

mnicolau dijo: Ver Mensaje
Hola, a todo lo que comentaron, te agregaría evitar el uso de los "goto" (tal vez vengas de ASM y por eso los utilizás, a mi también me pasaba al principio). En C podrías utilizar funciones para hacer el direccionamiento de manera adecuada y más eficiente.

Estructurando mejor el programa y utilizando funciones, podés lograr sin problemas lo que estás planteando, sin ninguna necesidad del RTOS, incluso sin utilizar interrupciones en tu caso... recordá que si bien el código se ejecuta en forma secuencial, sin poder hacer rutinas simultáneas, la ejecución del código es tan rápido que podés tomarlas como prácticamente simultáneas.

Saludos
Hola gracias por responder, ciertamente jamás programé en ASM jeje entré con Basicprogramando unos PICAXE y creo se me quedó de ahí jeje... y que diferencia tienen las funciones al "GOTO"?

sería algo como esto?

luces() {
instruccion;
instruccion;
.
.
instruccion; }

para crear el bloque de la función? y luego llamarla como: " luces(); "
11/01/2012 #13

Avatar de mnicolau

Ahh yo desconozco Basic, comencé en ASM y es muy común el uso de los goto, así que cuando migré a C costó al principio reemplazarlos.

Las funciones serían tal cual lo comentaste... y si mal no recuerdo, en el libro "Compilador C Ccs Y Simulador Proteus Para Microcontroladores Pic" hay un ejemplo similar al que estás realizando (LCD + control de temperatura), sería cuestión de agregar en un par de líneas la lógica de los relevadores.

De paso te recomiendo ese libro... muy bueno para aprender el tema.

Saludos
11/01/2012 #14


Lamentablemente no programo en CSS pero el problema para mi es que esta mal el programa, el LCD una ves ke le mandas la informacion, la mantiene solo no hace falta estar refrescandolo todo el tiempo. Igualmente yo use un LCD para recibir una señal de control remoto y mostrarla y me anda sin problemas, tambien hice un velocimetro con un pic16f819 y mide, voltaje de bateria, temperatura ambiente, velocidad, kilometros recorridos y todo eso mientras muestra la informacion en 3 displays 7segmentos multiplexados, asique tu problema esta en el programa, tenes recursos de sobra. No puedo ayudarte porque programo en proton.
11/01/2012 #15

Avatar de mecatronix89

biker2k3 dijo: Ver Mensaje
Lamentablemente no programo en CSS pero el problema para mi es que esta mal el programa, el LCD una ves ke le mandas la informacion, la mantiene solo no hace falta estar refrescandolo todo el tiempo. Igualmente yo use un LCD para recibir una señal de control remoto y mostrarla y me anda sin problemas, tambien hice un velocimetro con un pic16f819 y mide, voltaje de bateria, temperatura ambiente, velocidad, kilometros recorridos y todo eso mientras muestra la informacion en 3 displays 7segmentos multiplexados, asique tu problema esta en el programa, tenes recursos de sobra. No puedo ayudarte porque programo en proton.
Gracias amigo... efectivamente está en el programa, cuestión de afinar detalles y algunos cambios... pero ya con algunas ideas iré reestructurandolo

SALUDOS
11/01/2012 #16


Creo que tenes muchos delays, igual explicanos un poco mejor que hace el programa, porque el lcd no puede apagarse solo, a no ser que le mandes la instruccion de borrado. Que es lo que hace, tarda en refrescar la informacion o se cuelga o se apaga el lcd o que hace?
12/01/2012 #17

Avatar de mecatronix89

HOla otra vez, reestructuré un poco el código... construí bloques de funciones. pero al compilarlo me dice que debo de definir cada funcion, puse #define pero me salen muchos otros errores... espero puedan ayudarme en esto...

#include<16F887.h>
#device ADC=10
#fuses HS,NOWDT,NOLVP,MCLR,NOPROTECT
#use delay(clock=20000000)
#define use_portb_lcd TRUE
#include<LCD.C>
#define M PIN_D7 // 1 MENU
#define T PIN_D6 // 2 TEMPERATURA
//--------------------------------------------------------------------
int x;
long int ADC;
float temp,aux;
//-------------------BLOQUES DE FUNCIONES-----------------------------

//CONFIGURACIONES

//ADC LDR//
void adcldr(void){
set_tris_d(0xF0);
set_tris_a(0x0F);
setup_adc(ADC_CLOCK_INTERNAL|VSS_VDD);
setup_adc_ports(sAN1);
set_adc_channel(1);
setup_comparator(NC_NC_NC_NC);
}

//ADC SENSOR//
void adcsen(void){
set_tris_d(0xF0);
set_tris_a(0x0F);
setup_adc(ADC_CLOCK_INTERNAL|VSS_VDD);
setup_adc_ports(sAN0);
set_adc_channel(0);
setup_comparator(NC_NC_NC_NC);
}

//FUNCIONES DE EJECUCIÓN

//FUNCION CONTROL//
void CONTROL(void){
do{
ldr();
delay_ms(20);
sensor();
delay_ms(20;
}while(TRUE);
}

//FUNCION MAIN//
void main(void){
CONTROL();
}

//FUNCION LDR//
void ldr(void){
adcldr();
void INICIO(void){
if(!input(PIN_C6)){
delay_us(20);
void LUCES(void){
do{
ADC=read_adc();
delay_ms(800);
if(ADC<=600){
output_d(0b0000001);
}else{
output_d(0x00);
}
if(ADC<=300){
output_d(0b00000011);
}else{
output_d(0x01);
}
if(ADC>600){
output_d(0x00);
}
if(input(PIN_C6)){
output_d(0x00);
INICIO();
}else{
LUCES();
}

}while(TRUE);
}
}else{INICIO();}
}
}

//FUNCION SENSOR//
void sensor(void){
adcsen();
lcd_init();
delay_ms(1000);
lcd_gotoxy(1,1);
lcd_putc(" BIENVENIDO");
delay_ms(1000);
for (x=0;x<=2;++x){
lcd_gotoxy(1,2);
lcd_putc("CARGANDO SISTEMA");
delay_ms(400);
lcd_gotoxy(1,2);
lcd_putc("----------------");
delay_ms(400);
}MENU();

//-----------------------------LCD MENU-------------------------------//
void MENU(void){
do{
lcd_gotoxy(1,1);
lcd_putc(" MENU ");
lcd_gotoxy(1,2);
lcd_putc(" TEMP ");
if (input(T)){
TEMPERATURA();
}
}while(TRUE);

}
void TEMPERATURA(void){
lcd_gotoxy(1,1);
lcd_putc(" TEMP EXT");
delay_ms(300);
lcd_gotoxy(1,2);
printf(lcd_putc,"INICIANDO SENSOR");
do{
if (input(M)){
MENU();
}
delay_ms(1000);
temp=read_adc();
temp=(temp*300)/614;
if(temp!=aux){
lcd_gotoxy(1,2);
printf(lcd_putc," < < < %0.0f'C > > >",temp);
delay_ms(400);
lcd_gotoxy(1,2);
printf(lcd_putc," - - %0.0f'C - - ",temp);
aux=temp;
}
if (input(M)){
MENU();
}
}while(TRUE);
}

}

---------- Actualizado después de 3 minutos ----------

biker2k3 dijo: Ver Mensaje
Creo que tenes muchos delays, igual explicanos un poco mejor que hace el programa, porque el lcd no puede apagarse solo, a no ser que le mandes la instruccion de borrado. Que es lo que hace, tarda en refrescar la informacion o se cuelga o se apaga el lcd o que hace?
hola que tal, no se apaga el LCD, hay 2 fuentes separadas una para pic sensores y lcd y otra para los relevadores, ya que solo tengo de 5vcd y para que no interfieran los relevadores con el control.

el problema es que me muestra la temperatura pero deja de ejecutar la rutina de los relevadores, pero es necesario ejecutarla ya que es el encendido automatico de las luces en caso de que se oscurezca el entorno.
12/01/2012 #18

Avatar de mecatronix89

según acabo de leer, para llamar una función, debo hacer un archivo aparte con extensión ".h" y ahí guardar los bloques de funciones; luego #include nombredelarchivo.h y despues solo llamar alguna de las funciones guardadas.

Es correcto?
12/01/2012 #19

Avatar de arrivaellobo

No es necesario, pero es recomendable separar el proyecto en varios archivos para organizarlo mejor.
Una cosa, para llamar a una función desde otra, ya sea el main o cualquier otra, tiene que estar definida antes de la función desde donde la llamas.
Un ejemplo, si tienes dos funciones, por ejemplo RecojeDatos() y EscribeDatos(), y quieres llamarlas dentro del main, tienes que declararlas antes de éste, no se si me entiendes...

Un abrazo
12/01/2012 #20

Avatar de mecatronix89

arrivaellobo dijo: Ver Mensaje
No es necesario, pero es recomendable separar el proyecto en varios archivos para organizarlo mejor.
Una cosa, para llamar a una función desde otra, ya sea el main o cualquier otra, tiene que estar definida antes de la función desde donde la llamas.
Un ejemplo, si tienes dos funciones, por ejemplo RecojeDatos() y EscribeDatos(), y quieres llamarlas dentro del main, tienes que declararlas antes de éste, no se si me entiendes...

Un abrazo
si ya logré entender como se hace, lo que pasa es que nunca había trabajado con tantos bloques de funciones jeje... pero con ese archivo ".h" con los prototipos de las funciones, ya se compila el código, solo falta reacomodar todo...

GRACIAS
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.