TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: BitLow en 14 de Julio de 2015, 21:44:07

Título: Problema de multiplicación con C18
Publicado por: BitLow en 14 de Julio de 2015, 21:44:07
Hola gente!!,
No tengo mucha experiencia con C18 y me tope con un problema que no soy capaz de resolver si hago “Conta1 = 5 *26 “ el resultado es Conta1 = 65410, si hago “Conta1 = 5*127” el resultado es Conta1 = 123, si multiplico 5* <26 o >127 el resultado es correcto.
Perdí muchísimas horas buscando y tratando de descubrir el problema, ya reinstale el compilador y nada, lo instale en otra PC y nada, cambie de versión del mplabc18-v3.47 a la mplabc18-v3_42-LITE y nada, ya no se qué hacer, si alguien sabe porque pasa esto le voy a quedar más que agradecido. Les paso un ejemplo listo para compilar.

# include <p18f2550.h>

#pragma udata

unsigned int   Conta1=0;
unsigned int   Conta2=0;

void main ( void ){

LOOP:   
      //          FALLA

      Conta1 = 5 * 26;   // Falla si multiplico 5 * < 25
      Conta2 = 5 * 127;  // hasta > 127

      //          OK

      Conta1 = 5 * 25;   // No Falla si multiplico 5 * =< 26
      Conta2 = 5 * 128;  // hasta 5 * =< 127


    goto    LOOP;
}

Gracias y saludos.
Gustavo
Título: Re: Problema de multiplicación con C18
Publicado por: KILLERJC en 14 de Julio de 2015, 22:47:48
Primero que nada evita los goto y las banderas. no deberias usarlas en C. para eso tenes un while(1),

Tengo MPLAB X IDE v2.26 (imagino que es la mas actual)
Con XC8 instalado. Cree un proyecto para un PIC18F2550 con el siguiente codigo:


Código: C
  1. #include <xc.h>   //Aaca viene el p18f2550.h incluido
  2. #define _XTAL_FREQ 20000000
  3.  
  4. unsigned int   Conta1=0;
  5. unsigned int   Conta2=0;
  6.  
  7.  
  8. void main() {
  9.  
  10.     while (1) // Bucle infinito
  11.     {
  12.       Conta1 = 5 * 26;
  13.       Conta2 = 5 * 127;
  14.       Conta1 = 5 * 25;
  15.       Conta2 = 5 * 128;
  16.     }
  17.  
  18. }

Lo simule y los resultados dan exactamente como deberian, mirando paso a paso las variables tengo estos valores:

Conta1 = 130
Conta2 = 635
Conta1 = 125
Conta2 = 640

Y se vuelve a repetir por el while(1)

No se por que estas usando C18 cuando este ya "no existe" mas ahora es XC8 el que usa el MPLAB X
Título: Re: Problema de multiplicación con C18
Publicado por: BitLow en 15 de Julio de 2015, 06:00:48
Gracias  por tu ayuda que por cierto por un lado me sirvió y por el otro me complico, me sirvió el saber que probaste el mismo código en otro compilador y te funciono OK, esto confirmo mi sospecha y buscado en el foro de Microchip encontré que el C18 desde versiones más viejas viene arrastrando problemas con algunas multiplicaciones.

Una solución que proponen y me funciono,  es Conta1 = (int) 5*127, no sé porque pero así funciona bien.
Me la complicaste al decirme que el mplabC18 ya es obsoleto y ahora es el CX8 dentro del entorno MplabX,  justo ahora que le empecé a tomar un poco la mano no me causa gracia tener que ponerme a estudiar una nueva plataforma además de seguir lidiando con el C.

No soy para nada amante del C aunque reconozco que con funciones matemáticas de por medio no hay con que darle, estoy usando el C18 porque estoy embebiendo ASM en C inspirándome en un muy buen post de hace tiempo de WillyP que se llama ASM embebido en C18 explicado.

Gracias.
Título: Re: Problema de multiplicación con C18
Publicado por: KILLERJC en 15 de Julio de 2015, 06:21:27
lo que era MPLAB v8.x + C18 ya no se le da mas soporte desde microchip creo, e intentan justamente usar el MPLAB X y XC8.

Aca en el foro hay una persona que tambien uso XC8 y ademas incluyo algunos archivos .asm, por supuesto cada version de compilador tiene su forma de hacerlo.
Es la unica diferencia que vas a tener, ya que C es C igual en todos los compiladores, lo que cambia si decis que intentas juntar ASM y C es la forma. XC8 tiene un capitulo dedicado a eso, pero bueno, nadie puede decirte que elegir. Y si ya encontraste como hacerlo con C18 mejor aun.

El por que se arregla de esa forma? hacer eso que estas haciendo implica que la multiplicacion se haga en 16bits, es decir el resultado se haga en 16 bits

Conta1 = (int) 5*127

Ejemplo, 5 ocupa un registro de 8bits, 127 ocupa otro registro de 8bits, si multiplicas asi nomas uno asume ( al menos un buen compilador, deberia) asumir que si se va a poner en un registro de 16bits deberia ser justamente la multiplicacion de 16bits.
Pero normalmente hace 5 * 127 ( en 8 bits) y luego esos 8 bits los guarda en el registro de 16bits

distinto es si tenes una variable de 16 bits

int a=5;

Conta1 = a*127

Aca como la variable es de 16 bits y una constante de 8bits, la multiplicacion se va a hacer de 16bits y luego guardarse. lo que hiciste arriba con el (int) es decirle que ese 5 en realidad ocupa 16bits (0x0005) y no 8 ( 0x05 )
Siendo valores constantes el compilador (vuelvo a repetir) DEBERIA, de hacerlo libremente sin tener que definir eso. e incluso hacerlo en la PC y no con el PIC
En fin es un error del compilador.

Lo que podes hacer si no te gusta tanto el C, es generar las ecuaciones y ver el ASM generado, pero aun asi no se acerca a lo bueno del ASM. No tengo idea de cuanto le habra tomado hacer ese calculo en C, con constante obviamente que no deberia haber calculo, pero con una variable si. Por ejemplo en ASM, cualquiera de esas hubiera bastado con 2 rotaciones de 16bits mas 1 suma de 16 bits.