TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: BossDiablo en 10 de Abril de 2007, 17:43:20
-
El problema q tengo es q no se como rotar bien un numero. Les voy a poner lo q he hecho para q vean q a primera vista parece q esta todo bien, pero q luego no sale.
#include <18f452.h>
device adc=8
#use delay(clock=8000000)
#fuses NOWDT,HS, NOPROTECT, NOOSCSEN, NOBROWNOUT, NOPUT, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define EEPROM_SDA PIN_D1 //definimos los pines donde...
#define EEPROM_SCL PIN_D0 //la eeprom ira conectada
#include <Flex_lcd_cursor.c> //Libreria del LCD
#include <24256.c> //Libreria memoria eeprom
int8 IntHi,IntLo,Intensidad;
long int Intensidad2;
void Realizar_Medida(void)
{
Intensidad2=0;
IntHi=IntLo=0;
Intensidad=50;
printf(lcd_putc,"\fGuardando datos en");
printf(lcd_putc,"\nla memoria .......");
Intensidad2=(long int)((Intensidad*10); //Como resultado nos dan entre 9 y 16 bits, es decir un long int.
delay_ms(1);
IntLo=Intensidad; //Aqui guardo los 8 bits bajos, ya que la variable IntLo es de tipo int8
IntHi=Intensidad>>8; //Aqui desplazo ocho bits hacia la derecha, y guardo el resultado en la variable IntHi
delay_ms(1);
printf(lcd_putc,"\fIcc= %u.%u A",IntHi,IntLo);
delay_ms(5000);
Aqui solo esta una parte del programa, pero lo q no entiendo es xq no me sale el resultado q me tiene q salir por el lcd
Salu2 y gracias
-
Y qué valores toma intensidad antes de hacer la multiplicación??
Puede que Intensidad * 2500 , supere el máximo valor de la variable!!
-
Y qué valores toma intensidad antes de hacer la multiplicación??
Puede que Intensidad * 2500 , supere el máximo valor de la variable!!
He modificado un poco el tema y he puesto Intensidad * 10 asi seria un long int, ya que intensidad valdra como mucho 255.
Suponemos q la intensidad vale 255*10= 2550. Yo quiero sacar por el lcd 25.50
-
Veo varias cosas ahí que no me gustan
1) Intensidad2 , donde lo declaras y de qué tipo es?
2) Si tienes 2550, piensas que tomando el byte alto y el bajo, tendrás 25 y 50 respectivamente?
Si eso crees, te estas confundiendo muchísimo lo que es el sistema binario con el decimal.
Si quieres mostrarlo de esa forma haz algo asi como
IntHi = Intensidad2 / 100;
IntLo = Intensidad2 - IntHi*100;
Saludos
-
Tambien puedes usar la funcion MAKE8 de CCS para hacer lo que ha dicho el compañero maunix.
Esta funcion obtiene de una variable de 16 o 32 bits el byte que selecciones mediante el parámetro offset:
IntLo = MAKE8(Intensidad2, 0);
IntHi = MAKE8(Intensidad2, 1);
-
Mario, lo que pasa es que lo que quiere el amigo en cuestión es teniendo 2550, quiere tener 25 en un registro y 50 en otro, al menos eso interpreto de su ejemplo verbal (no del código).
En el código hace otra cosa, y por eso creo que no ve lo que espera ver.
Cuando habla de 2550, segun sus números es en decimal,no en hexa.
Saludos
-
Mario, lo que pasa es que lo que quiere el amigo en cuestión es teniendo 2550, quiere tener 25 en un registro y 50 en otro, al menos eso interpreto de su ejemplo verbal (no del código).
En el código hace otra cosa, y por eso creo que no ve lo que espera ver.
Cuando habla de 2550, segun sus números es en decimal,no en hexa.
Saludos
Sip, lo q quiero hacer es separar ese numero decimal para guardarlo en una memoria eeprom y despues leerla y eviar el dato atraves del puerto serie. El valor de tension es un numero entero de 0-255, q lo obtengo atraves del puerto analogico de la siguinete forma:
set_adc_channel(0);
delay_us(200);
Intensidad=read_adc();
delay_us(200);
Lo q me has dicho de como mostralo no funciona (Solo funciona para valores menores de 26): IntHi = Intensidad2 / 100;
IntLo = Intensidad2 - IntHi*100;
Por cierto, para enviar por el puerto serie he visto q solo es necesario unicializar #use RS232.
Ej: value=read_ext_eeprom (30); //Suponemos q el dato esta en la direcion 30 de la memoria
putchar(value); // Con esto envio el dato por el puerto serie
delay_ms(7);
Lo estoy haciendo bien o he metido la gamba
-
Porque no trabajas el dato siempre en 16 bits??
Si lo toma el conversor a 10 bits lo tienes guardado en una int16...
Lo grabas en la eeprom como int16, lo sacas de ella como int16, lo muestras como int16 y por ultimo lo envias como int16.
Lo unico mas complejo es interpretarlo en el comm como int16, pero si buscas en la informacion de printf, veras que hoy puede enviar datos de 16 bits. :mrgreen: :mrgreen:
Marcos
-
Para hacer el manejo de memoria en 16 bits (lectura y escritura de la EEPROM) debes usar las funciones de la libreria external_eeprom.c que viene entre los drivers del CCS. :roll: :roll: :roll:
-
Sip, lo q quiero hacer es separar ese numero decimal para guardarlo en una memoria eeprom y despues leerla y eviar el dato atraves del puerto serie. El valor de tension es un numero entero de 0-255, q lo obtengo atraves del puerto analogico de la siguinete forma:
Lo q me has dicho de como mostralo no funciona (Solo funciona para valores menores de 26):
IntHi = Intensidad2 / 100;
IntLo = Intensidad2 - IntHi*100;
Bien, vamos por partes. Quiero que primero resolvamos el tema de que comprendas cómo mostrar los datos y luego vemos lo de la eeprom ¿te parece?
He cometido un error de omisión. IntLo, no debe ser de 8 bits, sino de 16 bits.
Lo otro que puedes hacer para no tener tanto inconveniente es lo siguiente
long int tmpint;
tmpint = Intensidad2 / 100;
IntHi = tmpint;
tmpint = Intensidad2 - IntHi*100;
IntLo = tmpint;
Vamos con un ejemplo
// Intensidad2 = 3426
tmpint = 3426 / 100 = 34
IntHi = 34
tmpInt = 3426 - (34 * 100) -> tmpint = 26
IntLo = 26
El uso del tmpint como variable intermedia nos garantiza que las operaciones no sobrepasen el máximo valor de la variable de 8 bits (255).
Prueba esto y si funciona, seguimos con lo demás.
Nota: no hace falta hacer el delay_us(200) después de la conversión.
-
Ya he solucionado el tema del mostrar los numeros. Lo q he hecho ha sido coger el primer cogido q me digiste, declarar la funcion Intensidad como int16, asi me sale perfectamente. El ultimo apunte q has hecho, lo he probado y no funciona asi q he cogido el primero q me digiste. Al fi¡nal me queda el cogido asi:
int16 Intensidad2,Intensidad;
void Realizar_Medida(void)
{
medidas++;
IntHi=IntLo=TenHi=TenLo=0;
printf(lcd_putc,"\fGuardando datos en");
printf(lcd_putc,"\nla memoria .......");
}
set_adc_channel(0);
delay_us(200);
Intensidad=read_adc();
delay_us(200);
Intensidad2 =(Intensidad * 10);
IntHi = Intensidad2 / 100;
IntLo = Intensidad2 - (IntHi*100);
write_ext_eeprom(dir,IntHi); //El dividir esto me sirve para guardar los valores en la eeprom en forma de 8 bits.(Lo he hecho asi, xq la aprte alta es el numero entero y la parte baja son dos decimales.
dir++;
delay_ms(1);
write_ext_eeprom(dir,IntLo);
dir++;
delay_ms(1);
}
void Visualizar(void)
{
printf(lcd_putc,"\fIcc= %u.%u A",IntHi,IntLo); //
delay_ms(7000);
}
Esta parte del programa se va a repetir unas 100 veces, aqui os he puesto la captura de la intensidad, falta la de la tension q es igual.
Despues me muevo por el LCD y me voy a esta parte:
int8 PC;
void Datos_PC(void)
{
printf(lcd_putc,"\fConfigure el PC");
printf(lcd_putc,"\nModo 9600 baudios");
printf(lcd_putc,"\n8 bits, no-paridad");
printf(lcd_putc,"\nPulse ENTER");
delay_ms(500);
while(input(PIN_D5));
for (dir=1;dir=201; dir++){ //La direccion 0 esta reservada para almacenar el numero de medidas
PC=read_ext_eeprom(dir); // Leer dato de EEPROM/
delay_ms(1);
putc(PC); // Envio dato a PC
delay_ms(7);
puts("."); //Envio el punto para separar la parte decimal de la entera
di++;
PC=read_ext_eeprom(dir)
delay_ms(7);
puts(",");
}
Creo q seria una cosa, asi para leer los datos de la eeprom y enviarlos por un puerto serie al PC. Os comneto q creo q usare el printf para enviar los datos por el puerto serie, pero no se q funcion hay q poner.
Salu2 y muchas gracias, me estais sirviendo de mucha ayuda. Cuando acabe el proyecto os colgare todo el codigo, q es bastante grande
-
BossDiablo, y ahora? no entendí tu nueva duda o solo querías compartir tu código?
De todas formas, no veo porqué no te funcionó lo último que puse, ya que es lo mismo, con la diferencia que le asignas al final una variable de 16bits a una de 8 bits pero como la de 16bits solo tiene datos en su byte menos significativo, esto no es problema.
-
Lo q quiero decir es si de esta forma estoy enviando bien los datos atraves del puerto serie.
Inicializo el #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
int8 PcHi, PcLo;
int16 dir;
void Datos_PC(void)
{
dir=0;
printf(lcd_putc,"\fConfigure el PC");
printf(lcd_putc,"\nModo 9600 baudios");
printf(lcd_putc,"\n8 bits, no-paridad");
printf(lcd_putc,"\nPulse ENTER");
delay_ms(500);
while(input(PIN_D5));
PcHi=read_ext_eeprom(dir); // Leer dato de EEPROM/
delay_ms(1);
dir++;
PcLo=read_ext_eeprom(dir);
delay_ms(1);
printf ("%u.%u",PcHi,PcLo);
delay_ms(7);
}
Quiero saber si esta parte de mi codigo es capaz de enviar los datos, es decir, si estoy enviando bien los datos atraves del puerto serie.
Ej: PcHi=15 y PcLo=87 //Estos son los valores q estan almacenados en las direcciones 0 y 1 de la eeprom
Con el printf intento q en el PC me salga esto como resultado: 15.87
Esto esta bien hecho o debo usar putc????
-
Parece estar correcto, pero no lo puedo verificar porque no uso el CCS.
Saludos
-
Maunix--> Muchas gracias por tu ayuda. prometo colgar mi proyecto cuando lo acabe. Consiste en captar la tension y la intensidad de un panel fotovoltaico y representar la curva caracteristica en el PC(Realizaremos un barribo con un Convertidor Sepic, para ello modificaremos el ciclo de servicio con la PWM del PIC. El Lcd sirve para moverme por el menu, y seleccionar la accion a realizar. En estos momentos estamos estudiando la posibilidad de incorporar una nueva placa con un sensor de temperatura y uno de irradiancia.
Salu2 y muchas gracias
-
De nada, me alegra que les vayan saliendo bien las cosas.
-
Esta bien, si lo que quieres hacer es lo que explicas.
Lo que no veo bien es que manejes un dato de 16 bits que lo necesitas como en flotante, mediante el uso de dos bytes separados.
El CCS te permite manejar todo como un flotante, incluso enviarlo al puerto, no te olvides que en la memoria vas a tener datos en hexadecimal, y podrias llegar a tener problemas al querer enviarlo.
Marcos
-
Lo que no veo bien es que manejes un dato de 16 bits que lo necesitas como en flotante, mediante el uso de dos bytes separados.
El CCS te permite manejar todo como un flotante, incluso enviarlo al puerto, no te olvides que en la memoria vas a tener datos en hexadecimal, y podrias llegar a tener problemas al querer enviarlo.
Marcos
hola
A q te refieres con esos problemas?? Yo creo q el numero 15 del ejemplo estara guardado como 0x0E en la memoria (Si no me equivoco), a la hora de enviarlo se transforma en un entero, ya q tengo puesto q el valor de la variable sea %u
Salu2
-
Marcos, usar un número entero para cálculos no está mal, es más , en muchos casos es muy recomendable!!
Por ejemplo, si uno por ejemplo quiere hacer un cálculo que será de quiere trabajar en milivoltios, se puede usar en coma flotante o un entero. De hecho si el elemento que adquiere los datos (como un A/D) solamente tiene precisión en saltos de a 1 valor y máximo 1023 valores, no hay inconvenientes en esto.
Los cálculos se agilizan asombrosamente y muchas veces eso hace que el proyecto se pueda o no se pueda realizar con un pic en cuestión.
Te invito a que hagas una multiplicación
float a,b;
a = b*10.0;
y luego
long int a,b;
a = b*10;
y revisa cuanto demora una y otra operación.
Saludos
-
Una ultima duda. En referencia a la memoria eeprom 24LC256. El caso es q al compilar el programa no me da ningun error y yo veo que esta bien, pero cuando lo intento simular con el proteus 6.5 SP5 me da un error. Si quito las instrucciones de la memoria externa (init_ext_eeprom(), write_ext_eeprom(dir,men), value=read_ext_eeprom(dir)), funcionan perfectamente el resto de las cosas. El error es el siguiente:
PROSPICE - Internal Exception: access violation in module 'ISIS.EXE'.
Real Time Simulation failed to start
Warning: [U1] at boot-up: No instruction cycles were executed - processor may never have made it out of reset!
Real Time Simulation FAILED.
Una parte del codigo es esta:
//PcHi=read_ext_eeprom(dir); // Leer dato de EEPROM/
delay_ms(1);
dir++;
//PcLo=read_ext_eeprom(dir);
delay_ms(1);
printf(" %u.%u ",PcHi,PcLo); // Envio dato a PC
delay_ms(7);
Como veis tengo sesabilitado las funciones esas. La init_ext_eeprom() esta inicializada en el main
Salu2
-
Lo que entiendo del mensaje de error es que según dice, el microcontrolador nunca sale del estado de reset.
Te sugiero eches un vistazo a la sección de simuladores del foro y preguntes allí. Te darán mas ayuda que acá.
PD: no uso proteus por eso no te puedo ayudar puntualmente en este caso.
Saludos