Comunicar pic18f4550 por rs232

Como puedo comunicar un pic18f4550 por rs232 hacia la PC. Hice el sig. programa en ccs compiler y lo simule en proteus y si se logra la adquisición de datos por la hiperterminal pero al montarlo físicamente la información que se envía al PC es solo basura.
#include <18f4550.h>
#device adc=10
#FUSES INTHS,MCLR,PUT,BROWNOUT
#use delay(INTERNAL=4MHZ)
#use rs232 (BAUD=9600 , XMIT=PIN_C6 , RCV=PIN_C7)
#include <LCD.C>

void main() {
int16 q;
float p;
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
lcd_init();
for (;; ) {
set_adc_channel(0);
delay_us(10);
q = read_adc();
p = 5.0 * q / 1024.0;
printf(lcd_putc, "\\fADC = %4ld", q);
printf(lcd_putc, "\\nVoltage = %01.2fV", p);
printf("ADC = %4ld ", q);
printf("Voltage = %01.2fV\\r", p); // El \\r permite cambiar de línea.
delay_ms(100);
}



pero cuando hago la coneccion fisica por medio de un max232 solo llega pura basura a la hyperterminal de la PC y ya verifique que se reciba la info con codigo ascii espero alguien me pueda decir donde esta el error gracias
 

Adjuntos

  • Sin título.png
    Sin título.png
    48.7 KB · Visitas: 70
Última edición:
cuando manda basura es por que el reloj interno no esta bien configurado

es decir el pic18f4550 tiene un reloj de 4Mhz pero pasa a un prescaler que lo hace funcionar a mayor frecuencia.

¿por que pasa?

pues por que como tiene un modulo USB este debe trabajar a 48Mhz
entonces dependiendo el reloj es el prescaler que usa para llegar a los 48Mhz

pero si no estamos confugurando los FUSES del PLL puede que no nos trabaje la velocidad adecuada
y este haciendo lo que se le da la gana.
esta es la imagen de un cristal a 20 Mhz y se ve como sigue la linea para llegar a los 48mhz

Ver el archivo adjunto Dibujo.bmp


si nosotros usamos el FUSE XT indica que trabaja con un cristal de cuarzo
el FUSE CPUDIV1 indica que no habra prescaler y el CPU trabajara a la frecuencia del cristal externo



yo pondria asi los fuses

#FUSES XT,NOWDT,CPUDIV1,PLL1


eso de los fuses puedes revisarlo en la hoja de datos del PIC y en el CCS en donde dice valid fuses el boton que tiene un icono en forma de bomba
 
Última edición:
Muchas gracias TRILO-BYTE si era el problema de el programa y con la configuracion que me recomendaste quedo ahora tengo que comunicar 2 pics pero creo que sera mas facil por que ya le pude sacar datos al 18f4550. ¿Sera posible hacerlo de un 16f876a a un 18f4550? Bueno lo voy hacer aver que ocurre. Muchas gracias!!!... :)
 

Adjuntos

  • 13.jpg
    13.jpg
    74.4 KB · Visitas: 95
de pic, avr ,pc se puede

solo recuerda que cada fuse es especial para cada micro , el 4550 se le reconfigura el reloj por que como ya dije tiene un modulo USB que debe correr a 48Mhz si se esta usando, si no se usa este modulo se reconfiguran los PLL prescaler y el CPUDIV.
en otros modelos de microcontrolador esto no pasa pues no hay modulos USB.
 
de pic, avr ,pc se puede

solo recuerda que cada fuse es especial para cada micro , el 4550 se le reconfigura el reloj por que como ya dije tiene un modulo USB que debe correr a 48Mhz si se esta usando, si no se usa este modulo se reconfiguran los PLL prescaler y el CPUDIV.
en otros modelos de microcontrolador esto no pasa pues no hay modulos USB.

OK muchas gracias. Y estoy tratando de comunicar los pics pero el 16f876 esta con un cristal de 4MHZ por lo cual supongo que tendre que tener la misma frecuencia en el 18f4550 pero no se si deverdad lo estoy hciendo bien ya que veo que las diviciones que se hacen en el pll no me dan o mas bien no se como declararlas para que me salgan 4MHZ. El 4550 tiene un cristal de 20MHZ.... :( . Esta bien lo que estoy tratando de hacer? o eso no es posible jeje
 
por un lado.. para cristales mayores o iguales a 4 mhz, el fuse que tenes que poner es HS,
XT es para 4mhz para abajo. 4 mhz esta justo en el limite donde podes usar cualquiera de los 2

pero por otro lado hay que aclarar que la velocidad del puerto rs232 la configuras vos, y se configura de forma independiente a la del oscilador.
podes tener un pic funcionando a 4mhz y otro a 20 mhz, sin embargo la velocidad de la uart la configuras en los pic a 9600 baud y no habría ningún problema.

en fin, resumiendo los pasos que tienes que seguir para configurar los 2 pic:

#FUSES dependiendo si usas un cristal de cuarzo o si usas el oscilador interno pones el que corresponda.. por ejemplo hs, xt, intrc_io etc, también podes usar hspll etc. te recomiendo que abras el archivo 18F4550.h y ahí ves todos los fusibles validos, fíjate para que sirve cada uno y usa los que te hagan falta

luego tu usas esta funcion.. #use delay(INTERNAL=4MHZ) yo la escribo de esta forma #use delay(clock=8000000) para un pic que funciona a 8mhz, tendrías que poner la velocidad a la que funciona cada uno de tus pics, teniendo en cuanta el pll, cpudiv, etc, por ejemplo #use delay(clock=48000000) para 48mhz, o #use delay(clock=4000000) para 4mhz

y por ultimo configuras el puerto rs232, esto es bastante simple, solo tenes que usar

#use rs232 (BAUD=9600 , XMIT=PIN_C6 , RCV=PIN_C7)

obviamente cambias el pin de xmit y rcv por el que corresponda en cada pic y el baud si o si tiene que ser el mismo valor en ambos pic, porque sino no van a poder entenderse. esto es lo que define la velocidad de la trasmisión y es independiente del cristal que use cada uno, pero tenes que tener bien las otras configuraciones para que ande
 
para :darianpc

si tu micro el 4550 corre con un cristal es independiente que otro micro corra a otra velocidad.

los fuses como dije vienen en la datasheet pero en el CCS estan en un icono que tiene forma de bomba y dice Valid Fuses.

el fuse HS sirve para resonadores que no son cristales de cuarzo son parecidos pero diferentes
para un cristal de 20 Mhz es el mismo fuse XT

para un micro que tiene un cristal de 20Mhz

el dibujito que subi sigue la flecha del CPUDIV y este divide a una frecuencia de trabajo independiente a la del cristal

si tienes un cristal de 20Mhz y un CPUDIV1 el CPU trabajara a 20Mhz
pero si tienes el CPUDIV2 el CPU trabajara a 10Mhz siendo el cristal de 20Mhz
 
Bueno, yo estoy haciendo algo similar, pero se trata de comunicar 2 pics (4550 y 2550) a través de rs232. La idea es que el 4550 lea un voltaje y lo envía por rs232 al 2550. Ambos deben mostrar el dato de voltaje en cuestión, y cada pic tiene 2 leds; uno rojo que permanece encendido mientras no haya envío o recepción de datos, y uno verde que enciende cuando ocurre la comunicación. El código que hice funciona perfectamente en Proteus, pero cuando hago el montaje físico, todo funciona menos las pantallas LCD que ni siquiera encienden. Las probé para descartar que estuviesen dañadas, pero las pantallas están perfectamente, por lo que no entiendo cuál es el problema. Les adjunto el código, algunas imágenes y los .hex con la simulación en Proteus para que vean todo en detalle...

Los códigos están en el .rar, pero acá se los dejo:
MAESTRO:

Código:
#include <18F4550.h>
#DEVICE ADC=8
#fuses HSPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use RS232(BAUD=9600, XMIT=PIN_C6, RCV=PIN_C7,enable=pin_a1)
#include <lcd.c>

int16 q;

int main(void)
{
 setup_adc_ports(ALL_ANALOG);
 setup_adc(ADC_CLOCK_INTERNAL);
 set_adc_channel(0);
 lcd_init();
while(1)
{
 output_high(pin_a1);
 delay_ms(20);
 q=read_adc();
 if(q>87)
 {
  output_low(pin_a1);
  lcd_gotoxy(1,1);
  printf(lcd_putc,"Enviado= %Lu",q);
  putc(q);
  output_high(pin_a2);
  delay_ms(100);
  output_low(pin_a2);
  lcd_putc("\f");
 }
}
}

ESCLAVO:
Código:
#include <18F4550.h>
#fuses HSPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use RS232(BAUD=9600, XMIT=PIN_C6, RCV=PIN_C7)
#include <lcd.c>

int16 q;
float volt,b;

#int_RDA
RDA_isr()
{
  q=getc();
  b=q;
  volt=b*5/255;
  output_high(pin_a0);
  output_low(pin_a1);
  lcd_gotoxy(1,1);
  lcd_putc("\f");
  printf(lcd_putc,"Recibido= %f", volt);
  delay_ms(60);
}
int main (void)
{
 lcd_init();
 enable_interrupts(INT_RDA);
 enable_interrupts(GLOBAL);
 for(;;)
 {
  output_low(pin_a0);
  output_high(pin_a1);
 }
}
 

Adjuntos

  • LCD.rar
    177.5 KB · Visitas: 93
  • 2014-10-23 11.50.56.jpg
    2014-10-23 11.50.56.jpg
    331.2 KB · Visitas: 32
  • 2014-10-23 11.53.01.jpg
    2014-10-23 11.53.01.jpg
    318.6 KB · Visitas: 25
La idea es que el 4550 lea un voltaje y lo envíe por rs232 al 2550.
Ambos deben mostrar el dato de voltaje en cuestión, y cada pic tiene 2 leds; uno rojo que permanece encendido mientras no haya envío o recepción de datos, y uno verde que enciende cuando ocurre la comunicación.
El código que hice funciona perfectamente en Proteus, pero cuando hago el montaje físico, todo funciona menos las pantallas LCD que ni siquiera encienden. Las probé para descartar que estuviesen dañadas, pero las pantallas están perfectamente, por lo que no entiendo cuál es el problema.
Trabajar con 48MHz para usar una comunicación por RS-232 a 9600 bps, es un valor muy alto y aparte está mal la palabra de configuración.
Prueba con un valor más bajo, por ejemplo con 8MHz, (Puedes usar el oscilador interno.)

Si vas a usar el ADC a 8 bits, la variable "q" no tiene por que ser de 16 bits.
Muestra el valor usando ceros a la izquierda para que no se confunda la lectura.
Y tampoco es recomendable estar borrando constantemente la pantalla, pues se verán parpadeos.

Cuando corrijas la palabra de configuración y trabajes con una frecuencia menor, ya deberá funcionar físicamente.
 
D@rkbytes: Cuando dices "palabra de configuración" te refieres a los FUSES cierto? Porque vi que efectivamente tenía un par de errores en esa parte debido a que me distraje. :rolleyes:

Ya le bajé un poco la frecuencia y en la simulación corre mucho más rápido, ahora me falta probar en físico, ya contaré como me va montando en protoboard. El problema antes de consultar acá no era tanto la comunicación rs232, la cual parecía funcionar bien, el problema era que las pantallas LCD ni siquiera encendían, y probé hace 12 horas que ambas pantallas están en perfecto estado.

Dejare adjunto cómo van los códigos y las simulaciones hasta ahora...

Por cierto, si dejo la "q" del master en int8, su pantalla LCD en proteus muestra lo que le da la gana; pero si la dejo en int16, entonces muestra el dato correctamente. Obviamente la estoy cagando pero por ahora no me preocuparé tanto por eso, al menos no por ahora...
 

Adjuntos

  • LCD.rar
    176.6 KB · Visitas: 45
D@rkbytes: ¿Cuando dices "palabra de configuración" te refieres a los FUSES cierto?
Porque vi que efectivamente tenía un par de errores en esa parte debido a que me distraje. :rolleyes:
Sip, los fuses forman parte de la palabra de configuración.
Ya le bajé un poco la frecuencia y en la simulación corre mucho más rápido, ahora me falta probar en físico, ya contaré como me va montando en protoboard.
El problema antes de consultar acá no era tanto la comunicación rs232, la cual parecía funcionar bien, el problema era que las pantallas LCD ni siquiera encendían, y probé hace 12 horas que ambas pantallas están en perfecto estado.
Olvidé mencionar que la frecuencia de simulación en ambos microcontroladores la tienes en 4MHz.
Si hubieras realizado las pruebas físicamente y en el supuesto caso que los microcontroladores estuviesen funcionando a 48MHz, simplemente la comunicación serial no se daría.
Se enviarían datos erroneos, pero en proteus muchas cosas funcionan cuando no deberían, y también por estar ambos microcontroladores operando a 4MHz.
La frecuencia de operación en PROTEUS, sí es importante y debes establecerla en sus propiedades.
Por cierto, si dejo la "q" del master en int8, su pantalla LCD en proteus muestra lo que le da la gana; pero si la dejo en int16, entonces muestra el dato correctamente.
Pues debe ser por lo mismo, o por la forma en que estás realizando el programa.
Ya que también en el receptor estás sacando un valor float desde un valor entero de 8 bits. :confused:
 
en proteus muchas cosas funcionan cuando no deberían, y también por estar ambos microcontroladores operando a 4MHz.
La frecuencia de operación en PROTEUS, sí es importante y debes establecerla en sus propiedades.

^ Tienes mucha razón.

Pues debe ser por lo mismo, o por la forma en que estás realizando el programa.

^ Me inclino por lo segundo.

Aún no he logrado probar en el protoboard, solo cuento con el programador JDM y mi Pickit2 Clone aún no está listo; es difícil conseguir una PC con puerto COM...
 
Última edición:
no entendi bien que preguntaste pero supongo que quieres es:

enviar un dato numerico como 123.45
no se puede con putc

enviar 123 tampoco

el RS232 solo envia caracteres mas no numeros

para enviar una cadena debes enviar todo lo que hay en la cadena ejemplo

char cadena="DAVID C";

lo puedo enviar caracter a caracter hasta terminar la cadena con putc puesto que putc envia solo 1 caracter asi:

while(cadena != '\0' )
{
putc(cadena);
i++;
}


como dije este algoritmo es para enviar lo que hay en mi cadena hasta llegar a caracter nulo

hay una manera mas facil que es usar el printf donde imprimimos toda la cadena

printf(%s,cadena);

para enviar un numero debes enviar toda la cadena y en el receptor debes hacer algo que convierta la cadena en un numero
 
por ahi va a lo que me comentas es imposible lo que yo quiero. un poquito mas especifico ejemplo.
salida[0]=123;
salida[1]=123;
salida[2]=123;
salida[3]=123;
enviar salida(completo) via rs232 a labview para en labview descomponer salida en cada uno de sus valores. muchas gracias por responder
 
a caray alguien que no tiene idea de como solucionarlo me dice que estoy mal jaja bueno

es que digamos que quieres enviar 123
lo debes convertir a cadena de caracteres la forma mas facil es el printf en CCS en otro compilador seria algo asi

char *cadena;
int valor=123;
sprintf(cadena,"%d",valor);

asi se transforma el valor entero a cadena y de ahi se envia al puerto

ahora si queremos enviar un valor numerico sin convertir seria asi:

unsigned char valor;
el unsigned es para que valla de 0 a 255 no podemos enviar un int pues es mas grande y ocupa 4 bytes
y seria asi nada mas

putc(valor);
 
jajaja perdon fue un error de gramatica. no queria decir eso perdon. es que lo que yo necesito es enviar varios valores por el mismo buffer. mi proyecto consta de 4 sensores de temperatura. y deceo enviar las lecturas de los ADC, por un mismo buffer y en labview desplegar la informacion de los sensores por separados. y perdon por el comentario esa no era la intencion todavia que busco apoyo. gracias y saludos



y es que sabes que lo habia hecho via usb pero lo migre a rs232 por la compatibilidad de las frecuencias con la lcd. te mando el codigo de usb para haber si logro darme a entender.
while (TRUE)
{
usb_task();
if (usb_enumerated())
{
if (usb_kbhit(1))
{
output_high(PIN_D2);
usb_get_packet(1, Entrada, 3);
if (Entrada[0]==1)
{
output_high(PIN_D3);
set_adc_channel(0);
a=read_adc();
Salida[0]=a*0.4883;
delay_ms(10);

set_adc_channel(1);
b=read_adc();
Salida[1]=b*0.4883;
delay_ms(10);

set_adc_channel(2);
c=read_adc();
Salida[2]=c*0.4883;
delay_ms(10);

Salida[3]=200; //valor arbitrario
Salida[4]=200; //valor arbitrario
Salida[5]=200; //valor arbitrario
Salida[6]=200; //valor arbitrario
Salida[7]=200; //valor arbitrario
usb_put_packet(1, Salida, 8, USB_DTS_TOGGLE); //ESTO ES LO QUE QUIERO HACER
} //VIA RS232 ENVIAR LOS 8 BITS
if (Entrada[0]==0)
{
LED_OFF(PIN_D3);
}
}
}
 
Última edición:
Atrás
Arriba