Autor Tema: Duda RS232  (Leído 3496 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Duda RS232
« en: 26 de Febrero de 2010, 14:22:43 »
Hola:

Tengo un programa en labview que está formado por 8 interruptores y mediante VISA envio el byte por el puerto COM1 del ordenador. En el otro extremo tengo una placa con un PIC16F877A esperando recibir el byte. La funcion FGETC me permite detectar un caracter pero como puedo hacer para detectar NO el caracter sino el numero. Por ejemplo,si con los interruptores envio el numero 8 puedo detectar el numero 8 y no su caracter equivalente en ASCII?

un saludo

aitor

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Duda RS232
« Respuesta #1 en: 26 de Febrero de 2010, 15:54:07 »
Hola

El micro no entiende de ASCII, solo recibe el byte y ya ... el problema esta en el envío desde el PC, que estas enviando un ASCII. Ahora, lo que puedes hacer es restarle '0' al valor leído por el PIC y tendrás el valor que quieres.

Saludos
El papel lo aguanta todo

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Duda RS232
« Respuesta #2 en: 26 de Febrero de 2010, 16:38:39 »
Como muy bien dice el amigo MLO si recibes ASCII arreglalo con otro ASCII (Como aquello que decía mi agüela de que la mancha de mora1 con otra mora se quita)  :D :D :D

Código: C#
  1. char c;
  2. int8 i;
  3.  
  4. c=getc();
  5. i = c-'0';

Asi si con el PC le envía un '8' entonces '8'-'0'=8 (sean cuales sean los códigos ASCII del '0' y del '8' ya que el del '8' será exactamente 8 mayor que el del '0')  :mrgreen:

1 Mora
« Última modificación: 26 de Febrero de 2010, 16:42:54 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado darck_khronos

  • PIC18
  • ****
  • Mensajes: 493
Re: Duda RS232
« Respuesta #3 en: 27 de Febrero de 2010, 00:31:41 »
Labview siempre te mandara Ascii, ya lo que es la decodificacion, es cuuestion de tus variables y tambien del dato que esten enviandole a Labview

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Re: Duda RS232
« Respuesta #4 en: 28 de Febrero de 2010, 10:41:50 »
Hola:

gracias a todos por las respuestas pero la verdad es que no me funciona. Adjunto la vi de labview y el codigo en CCS por si veis algo que esté mal (sobre todo en la parte de labview).

un saludo

aitor

Desconectado pablomanieri

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 639
Re: Duda RS232
« Respuesta #5 en: 28 de Febrero de 2010, 11:35:38 »
Como muy bien dice el amigo MLO si recibes ASCII arreglalo con otro ASCII (Como aquello que decía mi agüela de que la mancha de mora1 con otra mora se quita)  :D :D :D

Código: C#
  1. char c;
  2. int8 i;
  3.  
  4. c=getc();
  5. i = c-'0';

Asi si con el PC le envía un '8' entonces '8'-'0'=8 (sean cuales sean los códigos ASCII del '0' y del '8' ya que el del '8' será exactamente 8 mayor que el del '0')  :mrgreen:

1 Mora



solo le falta hacer un cast a lo que restas

Código: [Seleccionar]
i=(int)(c-'0');


En realidad los codigos Ascii de los numeros del 0 al 9 en hexadecimal van de
0x30 a 0x39, por lo tanto si le restas '0', es decir le restas 0x30, obtienes el numero del 0 al 9 en hexadecimal, con esto lo conviertes a entero y listo.

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Re: Duda RS232
« Respuesta #6 en: 28 de Febrero de 2010, 14:58:40 »
Hola:

he modificado ligeramente el código empleando las interrupciones pero sigue sin funcionar. Lo adjunto por si le veis algun error.

Código: [Seleccionar]
// ******************  CONFIGURACION DEL MODO PWM ******************************
//
//       T_PWM=1/Freq_PWM
//       T_PWM=(PR2+1)*4*TOSC*TMR2_PREESCALER
//
//                         T_PWM
//       PR2=  (---------------------------)-1
//                4*TOSC*TMR2_PREESCALER 
//
//       CTPWM=(CCPR1L:CCP1CON<5:4>)*TOSC*TMR2PREEESCALER 
//
//       CTPWM es el ciclo de trabajo y no puede superar el valor del periodo                               
//       de la señal PWM por lo que es posible que no se utilicen los   
//       10 bits de resolución que tiene 
//
//
//                                    CTPWM
//       CCPR1L:CCP1CON<5:4>= ----------------------
//                             TOSC*TMR2PREEESCALER
//
//       El valor del duty maximo es CCPR1L:CCP1CON<5:4>=1000
//
//       Frecuencia de la señal PWM=250 Hz
//       OSCILADOR= 4MHZ
//       TMR2_PREESCALER=16
//       T_PWM= 4 ms
//       PR2=250       
//
// *****************************************************************************

#include <16f877a.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,NOCPD,BROWNOUT
#use delay(clock=4000000)
//#use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7,bits=8,stream=HOSTPC)
#use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7,bits=8,parity=N)
#use fast_io(c)
#use fast_io(d)
#use fast_io(b)

int8 display7seg(int8 valor){
   switch (valor){
      case 0:
         return 0b11111100;
         break;
      case 1:
         return 0b01100000;
         break;
      case 2:
         return 0b11011010;
         break;
      case 3:
         return 0b11110010;
         break;
      case 4:
         return 0b01100110;
         break;
      case 5:
         return 0b10110110;
         break;
      case 6:
         return 0b00111110;
         break;
      case 7:
         return 0b11100000;
         break;
      case 8:
         return 0b11111110;
         break;
      case 9:
         return 0b11100110;
         break;}
         }

int8 aux,dig_1,dig_2;
int16 num;
char c;

#int_rda
void serial_isr(){
c=getc();   
}

void main(void){
set_tris_c(0x00);
set_tris_d(0x00);
set_tris_b(0x00);
output_c(0x00);
output_d(0x00);
output_b(0x00);
setup_timer_2(T2_DIV_BY_16,249,1);
setup_ccp1(CCP_PWM);
//set_pwm1_duty(CCP_OFF);
enable_interrupts(GLOBAL);
enable_interrupts(int_rda);
while(1){
output_high(PIN_C4);
output_low(PIN_C5);
//c=fgetc(HOSTPC);
aux=(int8)(c-'0');
switch (aux){
      case 2:
         num = 10;
         dig_1=(num/10);
         dig_2=(num-(dig_1*10));
         output_b(display7seg(dig_1));
         output_d(display7seg(dig_2));
         set_pwm1_duty(num*100);
         delay_ms(30);
         break;
      case 4:
         num = 20;
         dig_1=(num/10);
         dig_2=(num-(dig_1*10));
         output_b(display7seg(dig_1));
         output_d(display7seg(dig_2));
         set_pwm1_duty(num*100);
         delay_ms(30);
         break;
      case 8:
         num = 30;
         dig_1=(num/10);
         dig_2=(num-(dig_1*10));
         output_b(display7seg(dig_1));
         output_d(display7seg(dig_2));
         set_pwm1_duty(num*100);
         delay_ms(30);
         break;
      case 16:
         num = 40;
         dig_1=(num/10);
         dig_2=(num-(dig_1*10));
         output_b(display7seg(dig_1));
         output_d(display7seg(dig_2));
         set_pwm1_duty(num*100);
         delay_ms(30);
         break;
      case 32:
         num = 50;
         dig_1=(num/10);
         dig_2=(num-(dig_1*10));
         output_b(display7seg(dig_1));
         output_d(display7seg(dig_2));
         set_pwm1_duty(num*100);
         delay_ms(30);
         break;
      case 64:
         num = 60;
         dig_1=(num/10);
         dig_2=(num-(dig_1*10));
         output_b(display7seg(dig_1));
         output_d(display7seg(dig_2));
         set_pwm1_duty(num*100);
         delay_ms(30);
         break;
      case 128:
         num = 70;
         dig_1=(num/10);
         dig_2=(num-(dig_1*10));
         output_b(display7seg(dig_1));
         output_d(display7seg(dig_2));
         set_pwm1_duty(num*100);
         delay_ms(30);
         break;}
   }
}

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Duda RS232
« Respuesta #7 en: 28 de Febrero de 2010, 15:54:52 »
Si usas fast_io() debes poner correctamente los tris(), en este caso el del puerto C, pin 7 de recepción de la USART cuyo tris debe ser 1 (entrada).

Prueba ahora y dinos como te va.


Código: C#
  1. // ******************  CONFIGURACION DEL MODO PWM ******************************
  2. //
  3. //       T_PWM=1/Freq_PWM
  4. //       T_PWM=(PR2+1)*4*TOSC*TMR2_PREESCALER
  5. //
  6. //                         T_PWM
  7. //       PR2=  (---------------------------)-1
  8. //                4*TOSC*TMR2_PREESCALER  
  9. //
  10. //       CTPWM=(CCPR1L:CCP1CON<5:4>)*TOSC*TMR2PREEESCALER  
  11. //
  12. //       CTPWM es el ciclo de trabajo y no puede superar el valor del periodo                                
  13. //       de la señal PWM por lo que es posible que no se utilicen los    
  14. //       10 bits de resolución que tiene  
  15. //
  16. //
  17. //                                    CTPWM
  18. //       CCPR1L:CCP1CON<5:4>= ----------------------
  19. //                             TOSC*TMR2PREEESCALER
  20. //
  21. //       El valor del duty maximo es CCPR1L:CCP1CON<5:4>=1000
  22. //
  23. //       Frecuencia de la señal PWM=250 Hz
  24. //       OSCILADOR= 4MHZ
  25. //       TMR2_PREESCALER=16
  26. //       T_PWM= 4 ms
  27. //       PR2=250      
  28. //
  29. // *****************************************************************************
  30.  
  31. #include <16f877a.h>
  32. #fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,NOCPD,BROWNOUT
  33. #use delay(clock=4000000)
  34.  
  35. #use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7,bits=8,parity=N)
  36.  
  37. #use fast_io(c)
  38. #use fast_io(d)
  39. #use fast_io(b)
  40.  
  41. int8 aux,dig_1,dig_2;
  42. int16 num;
  43. char c;
  44.  
  45. int8 display7seg(int8 valor){
  46.    switch (valor){
  47.       case 0:
  48.          return 0b11111100;
  49.          break;
  50.       case 1:
  51.          return 0b01100000;
  52.          break;
  53.       case 2:
  54.          return 0b11011010;
  55.          break;
  56.       case 3:
  57.          return 0b11110010;
  58.          break;
  59.       case 4:
  60.          return 0b01100110;
  61.          break;
  62.       case 5:
  63.          return 0b10110110;
  64.          break;
  65.       case 6:
  66.          return 0b00111110;
  67.          break;
  68.       case 7:
  69.          return 0b11100000;
  70.          break;
  71.       case 8:
  72.          return 0b11111110;
  73.          break;
  74.       case 9:
  75.          return 0b11100110;
  76.          break;
  77.     }
  78. }
  79.  
  80. #int_rda
  81. void serial_isr(){
  82.    c=getc();  
  83. }
  84.  
  85. void main(void){
  86.  
  87.   set_tris_c(0b10000000);
  88.   set_tris_d(0x00);
  89.   set_tris_b(0x00);
  90.  
  91.   output_c(0x00);
  92.   output_d(0x00);
  93.   output_b(0x00);
  94.  
  95.   setup_timer_2(T2_DIV_BY_16,249,1);
  96.   setup_ccp1(CCP_PWM);
  97.  
  98.   c=0x00;
  99.  
  100.   enable_interrupts(GLOBAL);
  101.   enable_interrupts(int_rda);
  102.  
  103.   while(1){
  104.     output_high(PIN_C4);
  105.     output_low(PIN_C5);
  106.     if(c!=0x00){
  107.       c=0x00;
  108.       aux=(int8)(c-'0');
  109.       switch (aux){
  110.        case 2:
  111.          num = 10;
  112.          dig_1=(num/10);
  113.          dig_2=(num-(dig_1*10));
  114.          output_b(display7seg(dig_1));
  115.          output_d(display7seg(dig_2));
  116.          set_pwm1_duty(num*100);
  117.          delay_ms(30);
  118.          break;
  119.       case 4:
  120.          num = 20;
  121.          dig_1=(num/10);
  122.          dig_2=(num-(dig_1*10));
  123.          output_b(display7seg(dig_1));
  124.          output_d(display7seg(dig_2));
  125.          set_pwm1_duty(num*100);
  126.          delay_ms(30);
  127.          break;
  128.       case 8:
  129.          num = 30;
  130.          dig_1=(num/10);
  131.          dig_2=(num-(dig_1*10));
  132.          output_b(display7seg(dig_1));
  133.          output_d(display7seg(dig_2));
  134.          set_pwm1_duty(num*100);
  135.          delay_ms(30);
  136.          break;
  137.       case 16:
  138.          num = 40;
  139.          dig_1=(num/10);
  140.          dig_2=(num-(dig_1*10));
  141.          output_b(display7seg(dig_1));
  142.          output_d(display7seg(dig_2));
  143.          set_pwm1_duty(num*100);
  144.          delay_ms(30);
  145.          break;
  146.       case 32:
  147.          num = 50;
  148.          dig_1=(num/10);
  149.          dig_2=(num-(dig_1*10));
  150.          output_b(display7seg(dig_1));
  151.          output_d(display7seg(dig_2));
  152.          set_pwm1_duty(num*100);
  153.          delay_ms(30);
  154.          break;
  155.       case 64:
  156.          num = 60;
  157.          dig_1=(num/10);
  158.          dig_2=(num-(dig_1*10));
  159.          output_b(display7seg(dig_1));
  160.          output_d(display7seg(dig_2));
  161.          set_pwm1_duty(num*100);
  162.          delay_ms(30);
  163.          break;
  164.       case 128:
  165.          num = 70;
  166.          dig_1=(num/10);
  167.          dig_2=(num-(dig_1*10));
  168.          output_b(display7seg(dig_1));
  169.          output_d(display7seg(dig_2));
  170.          set_pwm1_duty(num*100);
  171.          delay_ms(30);
  172.          break;
  173.       }
  174.     }
  175.   }
  176. }
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Re: Duda RS232
« Respuesta #8 en: 28 de Febrero de 2010, 17:06:08 »
Hola:

Gracias Redpic por tus conocimientos. Por cierto, la linea 108 es incorrecta. Se debe quitar la instrucción c=0x00.

Un saludo

aitor

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Duda RS232
« Respuesta #9 en: 28 de Febrero de 2010, 17:35:32 »
Entonces ¿te ha funcionado?  :shock:

Hola:

 Por cierto, la linea 108 es incorrecta. Se debe quitar la instrucción c=0x00.


¿Por qué? es una buena forma de asegurarte de que c vale 0x00 antes de habilitar la #int_rda ... pero si la quieres quitar no debe haber problema. Creo humildemente que se puede quitar pero no veo por qué se debe quitar.  :shock:

Yo siempre inicializo las variables antes de usarlas, así me aseguro de que antes de empezar a funcionar mi programa tienen las condiciones iniciales que explícitamente yo deseo.

Si en mi bucle while(1) testeo la condición de if(c!=0x00) quiero asegurarme de que c vale exactamente 0x00 hasta que se reciba algo por la USART, de ahí el c=0x00; antes de entrar en él.

Es una pequeña manía que me ha ahorrado muchos dolores de cabeza.  :mrgreen:
« Última modificación: 28 de Febrero de 2010, 17:39:05 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado aitorsp

  • PIC18
  • ****
  • Mensajes: 296
Re: Duda RS232
« Respuesta #10 en: 28 de Febrero de 2010, 17:52:41 »
Entonces ¿te ha funcionado?  :shock:

Hola:

 Por cierto, la linea 108 es incorrecta. Se debe quitar la instrucción c=0x00.


¿Por qué? es una buena forma de asegurarte de que c vale 0x00 antes de habilitar la #int_rda ... pero si la quieres quitar no debe haber problema. Creo humildemente que se puede quitar pero no veo por qué se debe quitar.  :shock:

Yo siempre inicializo las variables antes de usarlas, así me aseguro de que antes de empezar a funcionar mi programa tienen las condiciones iniciales que explícitamente yo deseo.

Si en mi bucle while(1) testeo la condición de if(c!=0x00) quiero asegurarme de que c vale exactamente 0x00 hasta que se reciba algo por la USART, de ahí el c=0x00; antes de entrar en él.

Es una pequeña manía que me ha ahorrado muchos dolores de cabeza.  :mrgreen:


Hola:

El codigo que pones es:

if(c!=0x00){      
c=0x00;      
aux=(int8)(c-'0');      

Entonces nada mas entrar en el if, c=0x00 y aux tomara ese valor. A mi me funciona sólo si quito esa instrucción.
un saludo

aitor

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Duda RS232
« Respuesta #11 en: 28 de Febrero de 2010, 17:52:48 »
Me confundo ...

Si esta en el while .... cuando hagas la conversion ya no habra dato no? porque lo hiciste cero. Creo que mejor seria con un flag, asi lo hago yo y no me ha dado lios.

Saludos
El papel lo aguanta todo

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Duda RS232
« Respuesta #12 en: 28 de Febrero de 2010, 19:33:44 »
Perdón, perdón, perdón. Creía que te referías al primer c=0x00; no al segundo. efectivamente el segundo hay que moverlo debajo de donde se usa para calcular el valor de aux.  :oops:

Y MLO tiene razón, yo también "levanto" un flag en la interrupción que es el que detecto en el main() y no uso directamente la variable de recogida del dato.
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RALF2

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2060
Re: Duda RS232
« Respuesta #13 en: 01 de Marzo de 2010, 08:09:48 »
Que tal amigos!
Aprovecho este enlace para hacerles una consulta  :mrgreen:
Tengo un pic16f876A @ 8Mhz
Y estoy empleando dos interrupciones una por el timer0 cada 5ms y otra por recepcion serial (int_rda) @ 9600bps, ahora bien el problema que presento, es con la interrupcion por recepcion, ya que no recibe el caracter que le envio (solo un caracter a la vez) :5]
Estoy empleando los pines por hardware del pic para recepcion.

Alguna idea de que podra ser?

Gracias

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Duda RS232
« Respuesta #14 en: 01 de Marzo de 2010, 09:31:06 »
A mostrar código, porque no veo el problema!  :mrgreen:
No contesto mensajes privados, las consultas en el foro


 

anything