# Interrupción RS-232 en PIC C de CCS



## decoymech (Ene 26, 2010)

Hola soy nuevo aqui y estoy aprendiendo a usar el compilador CCS para programar PIC's.
Mi duda es acerca de la interrupción INT_RDA la cual no me funciona ya que intento enviar un caracter por la terminal virtual en Proteus y me debe de regresar ese mismo caracter en un LCD, pero nada, creo ni siquiera entra a la interrupción. Ojalá puedan ayudarme. No tengo ningun problema en lenguaje ensamblador pero al intentarlo hacer en C no puedo.
Este es el codigo de programa:
----------------------------------------------------------------------------------

```
#include <16F887.h>
#fuses HS, NOWDT, NOPUT, MCLR, NOPROTECT, NOCPD, NOBROWNOUT, NOIESO, NOFCMEN, LVP, BORV40, NOWRT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=pin_C6, rcv=pin_c7, bits=8, parity=N)
#use fast_io(B)
#use fast_io(C)
#include <LCD.c>

char ch;
#INT_RDA                            //SERVICIO DE INTERRUPCIÓN POR RS232
void rda_isr()
{
ch = getchar();			    //Lee dato recibido
puts("Recibido");                      //Desplega recibido en el LCD
}

void main()			    //Principal
{
   set_tris_C(0x10111111);	    //C6->Salida; C7->Entrada
   lcd_init();
   enable_interrupts(INT_RDA);      //Habilita interrupción por recepción RS232
   enable_interrupts(GLOBAL);       //Habilita interrupcion global
   for( ; ; )
   {
      lcd_gotoxy(1,1);
      printf(lcd_putc,"\n\r Valor %c",ch);
   }
}
```
-----------------------------------------------------------------------------------
Gracias


----------



## decoymech (Ene 28, 2010)

Bueno aunque no respondieron ya solucione el problema ja.
La versión de CCS que tenia era la 4.023 y tiene un error para la interrupción ya que la cambie a la 4.093 y funciono perfectamente.

De cualquier forma Gracias!!!


----------



## tuxandres (Jul 7, 2010)

decoymech dijo:


> Bueno aunque no respondieron ya solucione el problema ja.
> La versión de CCS que tenia era la 4.023 y tiene un error para la interrupción ya que la cambie a la 4.093 y funciono perfectamente.
> 
> De cualquier forma Gracias!!!


 

Yo tengo un problema parecido, ya que lo tengo con un pic 18f4550 la transmision del pic-pc funciona pero la del PC-PIC no. modifique mi rutina para que hiciera eco es decir que me devuelva lo que recibe pero me devuele caracteres en blanco o "raros". Y como todo jejej simulado en proteus y puertos seriaes virutales funciona OK. nose que pueda ser.. si me pueden ayudar o decirme donde conseguiste la verison completa dela version 4.93 de CCS. para probar a ver si es eso. gracias


----------



## ByAxel (Jul 8, 2010)

Prueba la versión 4.104 del CCS que han corregido varios de los ya conocidos y fastidiosos bugs del CCS.

Saludos.


----------



## sacosta93 (Oct 25, 2013)

Necesito ayuda es que tengo un proyecto el cual necesita que en un pic contenga un programa el cual sea un contador ascendente de 0 a 99 y cuando use un switch o pulsador lo que haga sea enviar a otro pic que comience un contador de 99 a 0 pero el programa debe estar en el pic master lo e intentado pero no se como hacer para que el envio de datos sea recibido por el pic esclavo se que tiene que ser con los pines tx y rx estoy usando un pic 16f877a coloco el esquema el cual ya tengo los contadores el problema es que no como hacer para que el pic esclavo comience cumplir su funcion e buscado pero todos son con pantallas LCD lo necesito es con 2 7 segmentos uno para las unidades y otro las decenas


----------



## D@rkbytes (Oct 26, 2013)

Te daré una ayuda sobre como hacer la recepción de datos usando interrupción por USART y luego mostrar el valor en dos displays de 7 segmentos.
El circuito trabaja en modo multiplex para controlar los dos displays.

En la simulación no usé resistencias limitadoras ni transistores de conmutación para hacerla sencilla.
Eso lo debes tener en cuenta al montar el circuito físicamente.

Suerte.


----------



## luis1234567890 (Mar 26, 2014)

Hola. Viendo el datasheet hice este pequeño programa para enviar datos de la pc al pic y quisiera usar la librería del ccs para que se entienda más, pero no se como utilizarla muy bien por que a la hora de recibir el dato solo lo transmite repetidas veces el mismo dato y no espera el otro dato a transmitir.

```
void main()
{
trisb=0b00000100;//configurar pin de transmisor y de receptor
trisa=0;//puerto digital
porta=0;
osccon=0b01101100;//oscilador interno
ansel=0b00000000;//pines digitales
txsta=0b00100100;//8bits modo asincrono
rcsta=0b10010000;// 8bits modo asincrono
spbrg=25;//9600baudios
while (true)
{
if (bit_test(pir1,5)==1)//lleaga de informacion
{    bit_clear(pir1,5);
       porta^=255;
      txreg=rcreg; //transmitir informacion
 while(bit_test(txsta,1)==0);
}
}
}
```


----------



## Saint_ (Mar 27, 2014)

Hola @luis1234567890, por lo que veo en tu probra mas tratas de decivir un  dato por le puerto serie par aluego reenviarlo, si es asi, este el el codigo que hace la misma tarea.

```
#include <16f877a.h>
   #fuses   xt,nowdt
   #use     delay(clock=4000000)
   #use     rs232(baud=9600, xmit=PIN_c6,rcv=PIN_c7) //configura el puerto serie
   unsigned int8  dato_rx,estado_puerto=255;
   void main()
   {
      while(true)
      {
         if(kbhit()==1)          //pegunta si llego dato al puerto serie y esta
         {                       //listo para su lectura
            dato_rx=getc();      //recupera el llegado al puerto serie
            output_a(estado_puerto);
            estado_puerto^=255;
            putc(dato_rx);     //envia el mismo dato llegado por el puerto serie
         }
      }
   }
```
Esta informacion se encuentra en el help del CCS.


----------



## luis1234567890 (Mar 27, 2014)

bueno gracias muchas gracias me sirvió para entender mucho mas


----------



## juaann (Jul 25, 2014)

Hola estoy usando ccs v5 y quiero realizar una cominicacion serie entre dos PIC16F628A. nose que estoy haciendo mal, pero no logro hacerlo funcionar. dejo el codigo del receptor y transmisor:

Transmisor:

```
#include <16F628A.H>
#fuses INTRC_IO,NOWDT,NOMCLR
#use delay(clock=4000000)   
#use RS232(uart1,BAUD=9600,BITS=8,PARITY=N)
#byte PORTB=0x06
 
#INT_RB
void envio(){
   while (!bit_test(PORTB,5));
   putc(0xff);
}
void main() {
   enable_interrupts(INT_RB);      // Habilita la interrupcion del puerto B ( RB4 - RB7).
   enable_interrupts(GLOBAL);      // Habilita las interrupciones globales.
   
 set_tris_b( 0xF0 ); 
 while(true){ 
 } 
 
 }
```

Receptor:


```
#include <16F628A.H>
#fuses INTRC_IO,NOWDT,NOMCLR
#use delay(clock=4000000)   
#use RS232(uart1,BAUD=9600,BITS=8,PARITY=N)
 #use fast_io(a)
 #use fast_io(b)
char dato;
#INT_RDA
void interrupt_serie(){
      dato=getc();
}
void main (){
   enable_interrupts(INT_RDA);
   enable_interrupts(INT_RB);      // Habilita la interrupcion del puerto B ( RB4 - RB7).
   enable_interrupts(GLOBAL);      // Habilita las interrupciones globales.
   
   set_tris_b(0xf0);
   
while(true){

}    
}
```


----------



## D@rkbytes (Jul 26, 2014)

juaann dijo:


> Hola, estoy usando ccs v5 y quiero realizar una comunicación serie entre dos PIC16F628A.
> No sé que estoy haciendo mal, pero no logro hacerlo funcionar.


Suponiendo que se ejecutara la interrupción en el receptor, ¿qué está haciendo la variable dato?
Por lo que veo, sólo está almacenando el dato recibido pero no estás haciendo nada con ella.

Como recomendación; si vas a trabajar con el oscilador interno (4MHz.) baja la velocidad a 4800 o 2400 Bps.


----------



## juaann (Jul 26, 2014)

la idea de la interrupcion RDA es que la ejecute, dsp veo que hago. y bajando la velocidad no funcionó!


----------



## D@rkbytes (Jul 26, 2014)

juaann dijo:


> la idea de la interrupción RDA es que la ejecute, dsp veo que hago. y bajando la velocidad no funcionó!


El código en sí, está bien y si se tiene que ejecutar la interrupción pero como no estás haciendo nada con la variable, es obvio que no veas nada.

Así como está el código del receptor únicamente bajo depuración podrás ver que si se ejecuta la interrupción.

Has algo durante el evento de interrupción RDA o usa la variable dato, por ejemplo; reenvía el dato como eco, enciende un LED o lo que se te ocurra.


----------



## juaann (Jul 27, 2014)

lo estoy viendo en proteus paso a paso y no entra nunca en la interrupcion. y si le digo que encienda un led tampoco funciona.
directamente no entra en la interrupcion


----------



## D@rkbytes (Jul 27, 2014)

Pues quién sabe que estés haciendo mal.
Tienes que poner un breakpoint en dato=getc();, si no el programa sigue corriendo dentro del bucle while.

Para que aclares tus dudas te paso un ejemplo usando interrupción por USART con comunicación PIC a PIC.

Suerte.


----------



## juaann (Jul 28, 2014)

gracias, tu ejemplo si funciona.
Voy a comparar para ver que hago mal!


----------



## gatito11 (Sep 5, 2014)

hola, una pregunta compañeros, se puede hacer uso de varias interrupciones en un solo código?
si es así no tendrán un ejemplo que me puedan proporcionar,  o no se si alguien me pueda direccionar a algún tema que trate o detalle mas a fondo las interrupciones


----------



## D@rkbytes (Sep 5, 2014)

gatito11 dijo:


> Hola. Una pregunta compañeros. ¿Se puede hacer uso de varias interrupciones en un solo código?
> Si es así, ¿tendrán un ejemplo que me puedan proporcionar?
> O no se si alguien me pueda direccionar a algún tema que trate o detalle mas a fondo las interrupciones.


Claro que se puede y con PICC Compiler es muy sencillo, pues cada interrupción se realiza con código independiente.

Los ejemplos los puedes encontrar mirando los códigos adjuntos que existen por el Foro.

Suerte.


----------



## gatito11 (Sep 5, 2014)

y, hay jerarquias en las interrupciones o que puede pasar en caso de que se encuentren dos interrupciones al mismo tiempo?, por que en mi caso, haré uso de varias interrupciones (B0, b4-b7, rs232, i2c) y quisiera saber mas al respecto no se si me podrian recomendar alguno de los topicos del foro, o como lo encuentro, para poder leerlo gracias


----------



## D@rkbytes (Sep 5, 2014)

gatito11 dijo:


> ¿Y hay jerarquías en las interrupciones o que puede pasar en caso de que se encuentren dos interrupciones al mismo tiempo?
> Porque en mi caso haré uso de varias interrupciones (B0, b4-b7, rs232, i2c) y quisiera saber más al respecto.


Cuando se ejecutan dos interrupciones, digamos casi al mismo tiempo, porque alguna debe tener prioridad por algunos microsegundos, entonces se ejecutará la primera y la otra estará en espera.
Por este motivo no es recomendable el uso de retardos cuando se usan interrupciones.
Los retardos congelan la continua ejecución del programa y hacen que no se atiendan las interrupciones al momento de ocurrir.


gatito11 dijo:


> ¿No sé si me podrían recomendar alguno de los tópicos del foro, o cómo lo encuentro, para poder leerlo?


Eso depende del tipo de interrupción que quieras usar, porque en un solo tema no podrás encontrar explicación o uso de todas.

Lo que si te recomiendo leer, es la hoja de datos del PIC que quieras usar, ahí si vienen explicadas todas.

Suerte.


----------



## gatito11 (Ene 10, 2015)

Gracias. Bueno, ahora me encuentro con otro problema.
Ya pude hacer uso de RS232 y de I2C.
El problema es que cuando se ejecuta una parte del código, éste se bloquea.

Está funcionando completamente bien hasta el punto en el que se ejecuta la parte de comparación de un valor para que haga otra tarea.

La parte en negrita del código es la que cuando se ejecuta, falla. Todo funciona bien hasta ese punto.
Debo decir que la función que ejecuta es una conexión por RS232 a un módem GSM.

```
while(TRUE){
      //-------------------- SELECCION PRODUCTO --------------------------------
         if((flag==1)&&(envio==1)){
            //printf(lcd_putc, "\f   Recibido ... \n");
            //printf(lcd_putc, "Pos.%d Dato= %u ", direccion, prod[direccion]);
            
            delay_ms(1000);
            //printf(lcd_putc, "\f\nPos.%d Copy= %u ", direccion, copy[direccion]);
            output_a(copy[direccion]);
            output_high(PIN_E0);
            delay_ms(2000);
            output_a(0x00);
            output_low(PIN_E0);
            copy[direccion]=copy[direccion]-1;
            //printf(lcd_putc, "\f\nPos.%d Copy2= %u ", direccion, copy[direccion]);
            delay_ms(100);
            
            [B]if(prod[direccion]==3){
               for(i=0;i<NUMERO_MENSAJES;i++){
                   //Envio_SMS(); 
                   }
               output_high(PIN_E1);
               delay_ms(1000);
               output_low(PIN_E1);
               }
            
            if(prod[direccion]==0){
                  for(i=0;i<NUMERO_MENSAJES;i++){
                   Envio_SMS(); 
                   }
                  for(i=0;i<9;i++){
                  output_high(PIN_E1);
                  delay_ms(50);
                  output_low(PIN_E1);
                  delay_ms(50);
                  }
               }[/B]
            
            flag=0;
            envio=0;
            prod[0x1F]=0;
            }
          
          //------------------ CONFIGURACION DE ESCLAVO ------------------------
          if(cont==1){
            for(j=0;j<productos;j++){
                  if(j==0){
                     copy[j]=prod[j];}
                  else{
                     copy[j]=prod[j]+copy[j-1];}
                  }
                  
             //printcopy();
            //REESTABLECE LOS VALORES A 0
            cont=0;
            envio=0;
            prod[0x1E]=0;   
            }
      }
```


----------



## D@rkbytes (Ene 10, 2015)

gatito11 dijo:


> La parte en negrita del código es la que cuando se ejecuta, falla. Todo funciona bien hasta ese punto.


Entonces céntrate en la rutina *Envio_SMS();*
Es la rutina que está involucrada en un bucle de la parte que mencionas y que no incluyes.
 Lo demás son instrucciones sencillas como retardos y activación de pines que podrían no afectar.


----------



## gatito11 (Ene 11, 2015)

Pues lo que pasa es que la función *envio_sms() *hasta antes de agregar la interrupción RDA funcionaba perfectamente.
Cuando agregué todo el código de esta interrupción, la parte de *envio_sms() *empezó a fallar.
Digamos que cuando llega a esa parte del código el micro se traba o no sé.
Porque de ahí en adelante ya no hace nada y pues en sí, la funcion envio no tiene ciencia. Mira:


```
void Envio_SMS(){ 
      //char ctrlz = 26; //combinacion de teclas "ctrl+z"
      putc(0x0D);
      putc(0x0A);
      printf("AT+CMGS=\"%s\"\r\n",NUMERO);                           
      delay_ms(1000);
      printf("El prod[%i] tiene %i unidades\rLista total:\r",(direccion+1),prod[direccion]);
      printf("%i, %i, %i, %i, %i, %i, %i, %i, %i, %i\r",prod[0],prod[1],prod[2],prod[3],prod[4],prod[5],prod[6],prod[7],prod[8],prod[9]);//printf("%s",MENSAJE);                                       // 
      printf("estas son las cantidades de prod. restante");     
      delay_ms(500);
      putc(0x1A);//printf("%c",ctrlz); //se envia el mensaje
      putc(0x0D);
      putc(0x0A);
   }
```

No entiendo por qué se traba solo cuando llega a esa parte, si antes de agregar la interrupción funcionaba perfectamente.


----------



## D@rkbytes (Ene 11, 2015)

Bien. Como quiera la rutina contiene variables que no se sabe que valores contengan.
Pero puedes entrar en modo de depuración con ISIS colocando un punto de ruptura.
Por ejemplo, antes de: "*printf("AT+CMGS=\"%s\"\r\n",NUMERO);*"

De ahí te vas paso por paso hasta que en alguna ejecución ya no se consiga retornar, porque no veo llamadas a otras rutinas que puedan ocasionar el problema.
Y si quieres depurar el programa, comenta los *delay_ms()* para que el depurador no se detenga sobre esas instrucciones.

Estaría bien que subas el proyecto completo para poder ejecutarlo y ver mejor lo que sucede.


----------



## gatito11 (Ene 11, 2015)

Lo mas raro es que en proteus no se traba, ahi si hace todo bien, el problema esta ya a la hora de probarlo fisicamente, porque en el simulador lo corre bien, no se a que se pueda deber ese problema
pero al parecer si recibe información porque el master no se traba entonces significa que el dato si llega pero el pic no hace ya nada despues de entrar a esa parte que describo


----------



## D@rkbytes (Ene 11, 2015)

gatito11 dijo:


> Lo más raro es que en proteus no se traba, ahí si hace todo bien.
> El problema está ya a la hora de probarlo físicamente, porque en el simulador lo corre bien.
> No sé a qué se pueda deber ese problema.
> Pero al parecer si recibe información porque el master no se traba, entonces significa que el dato si llega pero el pic no hace ya nada después de entrar a esa parte que describo.


Cambia los* %s*, *%i *y *%c* por *%u* o *%lu,* dependiendo del tipo de variable que uses.
Yo he tenido problemas con *%s* principalmente y dejé de usar ese identificador por lo mismo.


----------



## gatito11 (Ene 11, 2015)

acabo de encontrar el error, bueno mas bien le agregue dos lineas al codigo exactamente en la parte donde se trababa

 if(prod[direccion]==3){ 
*disable_interrupts(GLOBAL);*
               Envio_SMS(); 
* enable_interrupts(GLOBAL);*
               output_high(PIN_E1);
               delay_ms(500);
               output_low(PIN_E1);
               }

            if(prod[direccion]==0){ 
*disable_interrupts(GLOBAL);*
                  Envio_SMS();              
*enable_interrupts(GLOBAL);*
                  for(i=0;i<9;i++){
                  output_high(PIN_E1);
                  delay_ms(50);
                  output_low(PIN_E1);
                  delay_ms(50);
                  }
               }

al parecer esas dos lineas solucionaron el problema, hare mas pruebas pero creo que algunas ocasiones si es necesario deshabilitar las interrupciones, jaja primera vez que tengo ese problema, para que tengan cuidado cuando usen interrupciones


----------



## mendek (May 23, 2015)

Buenas tardes compañeros del foro:

Estoy teniendo problemas con la comunicación y no sé si con la interrupción:


```
#include <16F887.h>

#fuses XT,NOWDT,NOPUT,NOPROTECT
#use delay(clock=4MHz)
#use     rs232(uart1, baud = 9600)
#include <string.h>           // Librería para usar strcmp
#include <stdlib.h>           // Librería para usar atoi
#use fast_io(all)       // Gestión de puertos

char dato=0;              // Valor leidd en el puerto serial

// Servicio de interrupción USART
#int_rda
void recepcion_serial (void)
{
   dato = getc();            // Guardar el dato recibido en "dato_serial"
}

/*----------------------------------------------------------------------------*/ 

void main() {            // Función principal

   set_tris_c(0b10000000);    // Se configura el puerto C cómo salida, menos el 
                              // puerto RX
   output_c(0);
   // Se configura el TMR2 con periodo de 249, prediv de 1:4 y postdiv de 1:1
   set_tris_d(0b00000000);
   setup_timer_2(T2_DIV_BY_4, 249, 1);

   set_pwm2_duty(0);  // Inicia la señal PWM en el pin C2




/*                Inicia la generación de la señal PWM.
                  Se configura el módulo CCP1 en modo PWM
                  con TPWM = 1 ms (FPWM = 1000 Hz)
*/

   setup_ccp2(CCP_PWM);       // La señal PWM se genera a partir de aquí

   enable_interrupts(int_rda);      // Habilitar interrupción USART
   enable_interrupts(global);       // Habilitar interrupciones gloabales.

dato=0;
while(1){

   set_pwm2_duty(dato);         // Inicia la señal PWM en el pin C2
   printf("\r %u ", dato);
}

}
```

Lo que pasa es que al enviarle un valor decimal al puerto, de por ejemplo 450, el valor que me devuelve el pic es 13, cuando me debería de devolver el mismo 450. Y el pic me devuelve el 13, independientemente de que valor le mande.

Adjunto mi simulación.

Sin más de momento me gustaría ver qué es lo que estoy haciendo mal.

De antemano muchas gracias.


----------



## Gudino Roberto duberlin (May 23, 2015)

Hola, bueno tú declaras la variable "dato" con formato caracter, pero la manipulas cómo de tipo numérica.


----------



## D@rkbytes (May 23, 2015)

mendek dijo:


> Lo que pasa es que al enviarle un valor decimal al puerto, de por ejemplo 450, el valor que me devuelve el PIC es 13, cuando me debería de devolver el mismo 450.
> Y el PIC me devuelve el 13, independientemente de que valor le mande.


Recuerda que por el puerto serial únicamente puedes enviar un Byte (8 bits) o sea, hasta 255
La variable Char que estás usando es correcta al igual que INT8, pero ambas son de 8 bits.

Así que no puedes recibir ni enviar valores superiores a 255 por el puerto serie aunque uses variables de 16 bits.


----------



## Scooter (May 24, 2015)

Claro que se puede, pero no de golpe. 
Si el valor es de 16 bits hay que enviar dos bytes etc...


----------



## D@rkbytes (May 24, 2015)

Scooter dijo:


> Claro que se puede, pero no de golpe.
> Si el valor es de 16 bits hay que enviar dos bytes etc...


Obvio. Pero primero lo básico y después ya entramos en ese tema.


----------



## ciberick (Feb 3, 2016)

Hola amigos 

Quería consultarles como se puede enviar y leer una trama de datos  por rs232, quiero enviar una trama de dos cifras decimales , por ejemplo quiero enviar la siguiente trama :

MAESTRO  PIC16F628A ===> 85 & 25
ESCLAVO   ===> 85 & 25  PIC16F628A 

Despues de recibir la trama tengo que mostrarlos por el Display de 16x2
                ____________________
               |      Decimal 1 :  85     |
               |      Decimal 2 :  25     |
                ____________________


Hasta ahora solo he podido enviar el dato 85 y mostarlos por el display, estoy ocupando el CCS Compiler


----------



## TRILO-BYTE (Feb 4, 2016)

muy facil

debes hacer un printf mas o menos asi:

printf("%d,%d@"decimal1,decimal2);

y se imprimira algo asi:

*85,25@*

ahora el receptor leera la cadena de texto

*85,25@*

donde mis 2 decimales estan separados por una coma y el @ *"puede ser cualquier simbolo"*
indica que la cadena termino

si es que envias mas decimales.

ahora con un token separas el texto indicando al STRTOK la *","* 

y asi de facil

ya con atoi conviertes a decimal el texto

no te dire exactamente como por que seria hacerte tu tarea 

pero si dije basicamente como se hace


----------



## ciberick (Feb 4, 2016)

TRILO-BYTE, gracias por la respuesta que me enviaste !!!!! 

Estoy haciendo dos programas, uno que me envié números desde 0 al 99 en una trama y enviarlo por RS-232. Por ejemplo; 88 & 99 y mostrar lo que envié por un LCD

Y el otro es el que recepciona los datos enviados.
Mi duda es ¿cómo puedo separar eso datos  para mostrarlos? 

Esto es lo que he programado:
Éste programa estará recibiendo constantemente números desde el 0 a 99
Por ejemplo; 88 & 50 o puede ser 05 & 08, los números decimales están separados por "&" = (números 0 al 99) & (números 0 al 99)...

Hasta ahora estoy recibiendo solo un dato que lo envió desde otro micro controlador.
El programa lee el numero y lo muestra en dos display, si me llega el otro dato lo mostraría en otros 2 displays


```
///////////////////////////////////////////////////////////////////////////

#use rs232(baud=9600,xmit=pin_b1,rcv=pin_b2,bits=8)

#define COMUN_1     PIN_b4
#define COMUN_2     PIN_b5
#define COMUN_3     PIN_b6
#define COMUN_4     PIN_b7



int digito[10]  = {0X00,0X01,0X02,0x03,0x04,0x05,0X06,0x07,0X08,0x09};
unsigned int Unidad, Decena;
int8 valor;

#int_rda
void rda_isr(void){
valor = getc();
}

void main(void){
int8 unidades,decenas;
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);

while (true){
unidades = (valor % 10); // Se extraen las unidades.
decenas = (valor % 100)/10; // Se extraen las decenas.

output_low(COMUN_2);
output_high(COMUN_1);
output_a(digito[unidades]); .
delay_ms(2); 
output_low(COMUN_1);
output_high(COMUN_2)
output_a(digito[decerna]);
delay_ms(2); 

}
}
```


----------



## TRILO-BYTE (Feb 4, 2016)

es que estas *MAL*

en getc solo recibes un caracter de 8 bits

una trama es una linea de texto

ejemplo

trilobyte#123#perro#567#perico@

donde tengo en mi trama texto , numeros en texto seprarados por un simbolo y la trama termina con un simbolo diferente

para enviar una trama se envia con printf el texto con mi formato

cadena#numero#cadena#numero#cadena@

seria asi:

printf("%s#%d#%s#%d@",cadena1,numero1,cadena2,numero2); 

te das cuenta que envie un formato para mi trama "mi trama es ejemplo como se hace".

ahora de parte del receptor debemos leer toda la cadena.

no sabemos de que tamaño la va enviar el transmisor

*podemos usar un apuntador*
*char *trama; *

*o podemos usar una cadena definida*
*char trama[15];*

ahora necesitamos 2 cadenas para que reciban los numeros

char numero1[4];
char numero2[4];

y 2 variables tipo entero que reciban el valor de esos numeros

int valor1;
int valor2;

hasta aqui todo debe ser mas claro que una taza de cafe.

luego debemos recibir toda la cadena leida por el transmisor con un *gets*

char trama[10];

#int_rda
void rda_isr(void){
*gets(trama);*
}

una vez leida toda la cadena ahora debes aplicar *STRTOK();*

lo que vaz a hacer es separar con tokens 

este es un ejemplo del CCS del token

se ve que no sabes buscar pues el CCS lo da como ejemplo



> char string[30], term[3], *ptr;
> 
> strcpy(string,"one,two,three;");
> strcpy(term,",;");
> ...




lo que debes hacer es separar tu trama por los simbolos usados *&*

y cada pedacito de texto lo debes guardar en las cadenas que defini 

luego para que esas cadenas de texto se conviertan en un valor numerico debes aplicar *atoi*
que tambien hay muchos ejemplos no me desgastare en explicar.

ese valor en atoi se convierte en numerico y se puede ya guardar en los registros tipo _*int*_

*bien facil*


----------



## D@rkbytes (Feb 4, 2016)

ciberick dijo:


> Estoy haciendo dos programas, uno que me envié números desde 0 al 99 en una trama y enviarlo por RS-232. Por ejemplo; 88 & 99 y mostrar lo que envié por un LCD
> 
> Y el otro es el que recepciona los datos enviados.
> Mi duda es ¿cómo puedo separar eso datos  para mostrarlos?


Es sencillo. Te adjunto unos programas de ejemplo comentados, para que entiendas el proceso.

PD: El ejemplo puede usar cifras con decimales o números enteros.
Si se desea, también se puede enviar el Checksum para comprobar errores de envío.


----------



## ciberick (Feb 5, 2016)

D@rkbytes

se agradece el gesto, revisare el archivo y te comento como me va 

 muchas gracias!!!!!



TRILO-BYTE

también se agradece el gesto, pero me complique mas ...empece a buscar las instrucciones que me indicaste pero por el momento aun estoy en blanco...revisare el archivo que me enviaron y les comento como va resultando todo...

saludos
muchas gracias!!!!!


----------



## ciberick (Feb 5, 2016)

D@rkbyte

Podrías ayudarme porfavor a corregir el programa para ver en que estoy equivocado, me estoy basando en el ejemplo que me enviaste pero aun no logro hacerlo funcionar.

te envie el archivo completo

saludos


----------



## D@rkbytes (Feb 5, 2016)

ciberick dijo:


> Me estoy basando en el ejemplo que me enviaste pero aún no logro hacerlo funcionar.


En los archivos que adjuntas no veo que estés aplicando los procedimientos de los ejemplo que subí.

¿Podrías explicar detalladamente qué es lo que quieres hacer?


----------



## ciberick (Feb 6, 2016)

D@rkbytes

Gracias por responder , te adjunto un archivo con la incorporación de los ejemplos que me mandaste, me sirvió pero igual tengo problema por que no se muestra los números en los Display de 7 segmentos

te mande toda la información disponible, para ver si me puedes ayudar a corregir los errores

nota: también están las instrucciones de los programas

saludos
Muchas Gracias


----------



## ciberick (Feb 6, 2016)

Pude mejorar bastante el programa, sólo me falta sacar la lectura de un bucle.
El programa está leyendo sólo una vez, no se va actualizando.
¿Cuál puede ser el error?

```
while (true)
   {
    
      if(flag_rx)                // Si hay datos en el buffer...
      {
       flag_rx = 0;            // Se limpia la variable. (Bandera de recepción)
       Num_1 = ((trama_serial[0])-48);   Num_3 = ((trama_serial[3])-48);
       Num_2 = ((trama_serial[1])-48);   Num_4 = ((trama_serial[4])-48);   
       //printf("%d%d&%d%d\r",Num_1,Num_2,Num_3,Num_4);
       while(true)
       {
       output_b(0x12);
       output_a(Numeros[Num_1]);
       delay_ms(tiempo);
       output_b(0x22);
       output_a(Numeros[Num_2]);
       delay_ms(tiempo);
       output_b(0x42);
       output_a(Numeros[Num_3]);
       delay_ms(tiempo);
       output_b(0x82);
       output_a(Numeros[Num_4]);
       delay_ms(tiempo);
      }
       }
   }
}
```


----------



## D@rkbytes (Feb 8, 2016)

Es que así no saldrá del segundo bucle, y esa no es la idea.
Debes cerrar la sentencia IF y continuar, para que el código subsecuente se siga ejecutando dentro del bucle principal.


----------



## ciberick (Feb 8, 2016)

D@rkbytes
entonces quedaría así, como el código que te envié,


```
while (true)
   {
    
      if(flag_rx)                // Si hay datos en el buffer...
      {
       flag_rx = 0;            // Se limpia la variable. (Bandera de recepción)
       Num_1 = ((trama_serial[0])-48);   Num_3 = ((trama_serial[3])-48);
       Num_2 = ((trama_serial[1])-48);   Num_4 = ((trama_serial[4])-48);   
       //printf("%d%d&%d%d\r",Num_1,Num_2,Num_3,Num_4);
       while(true)
       }
       output_b(0x12);
       output_a(Numeros[Num_1]);
       delay_ms(tiempo);
       output_b(0x22);
       output_a(Numeros[Num_2]);
       delay_ms(tiempo);
       output_b(0x42);
       output_a(Numeros[Num_3]);
       delay_ms(tiempo);
       output_b(0x82);
       output_a(Numeros[Num_4]);
       delay_ms(tiempo);
           
       }
   }
}
```

ultimas consultas :

1- como puedo estructurar la interrupción RDA, para que se asegure de recibir la trama completa.



```
#INT_RDA
    void RECEPCION_RS232(void)
     
    {
       gets(trama_serial);                  // Se recibe la cadena de datos.
       flag_rx = 1;                  // Se indica recepción completa.
    }
```
2- consulta como puedo hacer que un led sea intermitente mediante una interrupción
, el led que muestra que el micro esta con vida

disculpa, este es la corrección, le quite el while 



```
while (true) 
   { 
     
      if(flag_rx)                // Si hay datos en el buffer... 
      { 
       flag_rx = 0;            // Se limpia la variable. (Bandera de recepción) 
       Num_1 = ((trama_serial[0])-48);   Num_3 = ((trama_serial[3])-48); 
       Num_2 = ((trama_serial[1])-48);   Num_4 = ((trama_serial[4])-48);    
       //printf("%d%d&%d%d\r",Num_1,Num_2,Num_3,Num_4); 
      
       } 
       output_b(0x12); 
       output_a(Numeros[Num_1]); 
       delay_ms(tiempo); 
       output_b(0x22); 
       output_a(Numeros[Num_2]); 
       delay_ms(tiempo); 
       output_b(0x42); 
       output_a(Numeros[Num_3]); 
       delay_ms(tiempo); 
       output_b(0x82); 
       output_a(Numeros[Num_4]); 
       delay_ms(tiempo); 
            
       } 
   } 
}
```


----------



## luis30 (Feb 8, 2016)

2- consulta como puedo hacer que un led sea intermitente mediante una interrupción
, el led que muestra que el micro esta con vida


```
#INT_RDA
    void RECEPCION_RS232(void)
     
    {
       gets(trama_serial);                  // Se recibe la cadena de datos.
       flag_rx = 1;                  // Se indica recepción completa.
    }
```

puedes declarar un pin  como salida ponerlo en estado bajo, y con output_toggle(pinx);
cambias su estado.


```
#INT_RDA
    void RECEPCION_RS232(void)
     
    {
       gets(trama_serial);                  // Se recibe la cadena de datos.
       flag_rx = 1;                  // Se indica recepción completa.
       output_toggle(led);        //cada que entra en la interrupcion cambia de estado el led si es 1 a 0 e inverso

    }
```


----------



## ciberick (Feb 8, 2016)

gracias por responder



Amigo

creo que me exprese mal, pero lo que quiero lograr que la interrupción se asegure que lleguen los 5 datos de la trama,,por ahora esta configuración es básica...como se podría hacer eso



```
#INT_RDA
    void RECEPCION_RS232(void)
     
    {
       gets(trama_serial);                  // Se recibe la cadena de datos.
       flag_rx = 1;                  // Se indica recepción completa.
    }
```


 y con respecto al led intermitente que se enciende  ya paga a un ritmo distinto del programa principal...eso quiero lograr hacer...por que si lo coloco dentro de la interrupcion RDA, SEGUIRA al tiempo de la lectura de datos.......


----------



## luis30 (Feb 8, 2016)

ciberick dijo:


> gracias por responder
> 
> 
> 
> ...



no tengo mucha chance ahorita pero deberia ser algo asi, le hice cambios por que no me funciono la interrupcion.


```
#include <16f628a.h>
#fuses NOMCLR
#fuses INTRC_IO
#FUSES NOWDT                    //No Watch Dog Timer
//#FUSES XT                     //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
//#FUSES RESERVED                 //Used to set the reserved FUSE bits
#use delay (clock=4000000)
#use rs232(baud=9600,xmit=PIN_B2,rcv=PIN_B1,errors)
#define DISPLAY_1     PIN_B4
#define DISPLAY_2     PIN_B5
#define LED_SERIAL    PIN_B6
#use fast_io(a)
#use fast_io(b)
// NUMEROS [0-9] = [ 0  , 1  , 2  , 3  , 4  , 5  , 6  , 7 ,  8  , 9 ]
int Numeros[10]  = {0X00,0X01,0X02,0x03,0x04,0x05,0X06,0x07,0X08,0x09};
int8 datos[4];                   // Arreglo para recibir los datos.
int1 flag_rx = 0;                // Variable bandera de recepción.
int i;


// Servicio de interrupción por recepción de datos RS-232
#INT_RDA
void int_ISR(void)

{
   datos[i]=getc();
   if(i>=5){
   flag_rx=1;
   i=0;
   }
   i++;
}
   
void main (void)
{
   
   int8 unidades,decenas;
   int tiempo = 10;
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   set_tris_a(0x00);
   set_tris_b(0b00000110);
  
   
   while (true)
   {
      if(flag_rx==1)                // Si hay datos en el buffer...
      {
         flag_rx = 0;            // Se limpia la variable. (Bandera de recepción)
         
         unidades = (datos[0],datos[1] % 10);         // Se extraen las unidades.
         decenas  = (datos[3],datos[4] % 100)/10;     // Se extraen las decenas.
         printf("%c%c%C%c%c\r",datos[0],datos[1],datos[2],datos[3],datos[4]);
      }
         output_low(Display_2);
         output_high(Display_1);
         output_a(Numeros[unidades]);        
         delay_ms(tiempo);  
         output_low(Display_1);
         output_high(Display_2);                             
         output_a(Numeros[decenas]);          
         delay_ms(tiempo);  
   }
}
```


----------



## ciberick (Feb 8, 2016)

gracias , lo probare, una consulta sabes si puede hacer esta coneccion:
PC - MAX232 - MAX 485 - MAX 485 - MAX 232 - PIC


----------



## luis30 (Feb 8, 2016)

ciberick dijo:


> gracias , lo probare, una consulta sabes si puede hacer esta coneccion:
> PC - MAX232 - MAX 485 - MAX 485 - MAX 232 - PIC



no se si tengas el circuito funcionando armado?, aqui hice cambios a tu codigo, en una oportunidad que tuve, lo que no pude fue simularlo, pero al parecer funciona, creo que estoy multiplexando mal o mi pc es muy lenta, si desactivas las display_1 osea pruebas 7seg separados funciona pero todos a la vez mi pc no lo simula bien. checalo.

PD; el tipo de conexion no sabria asegurarte, pero yo supongo que si deberia funcionar.
saludos!


----------



## D@rkbytes (Feb 8, 2016)

ciberick dijo:


> Últimas consultas:
> 1- ¿Cómo puedo estructurar la interrupción RDA, para que se asegure de recibir la trama completa?


Utilizando una verificación del checksum de los datos. (Sumar los bytes y hacer un And con 0xFF)
Pero por experiencia te garantizo que la recepción de datos usando "gets()" es buena y completa.
Tiene el problema de que si recibe el número 13, lo toma como fin de la cadena.
Para evitar ese inconveniente se pueden enviar los datos numéricos como ASCII.


ciberick dijo:


> 2- ¿Cómo puedo hacer que un led sea intermitente mediante una interrupción?


Por medio de la interrupción por desborde del Timer 1.
Por ser de 16 bits, puedes obtener más tiempo para que ocurra el desborde.

Sobre tu programa, aún sigue mal. 
Te adjunto un ejemplo completo incluyendo la activación del LED por medio del Timer 1.

Suerte.


----------



## huihuang1992 (Feb 13, 2016)

Hola, chicos, estoy haciendo una comunicación entre PIC16F628A y SIM900A(ya la he flasheado, asi que ya esta funcionando).
Pero en cuanto me pongo con la interrupción #INT_RDA, parece que no se entra en la interrupción. Y el código que he hecho es muy simple, para ver si funciona.

```
#include <16f628a.h>
#include <string.h>

#fuses NOWDT   

#fuses NOPROTECT,NOPUT,XT
#fuses MCLR,NOBROWNOUT
#fuses INTRC_IO             // Internal RC Osc, no CLKOUT

#use delay(INTERNAL=4000000)     
#use RS232(BAUD=9600,BITS=8,PARITY=N, XMIT=PIN_B2,RCV=PIN_B1,STOP=1)   


#byte TRISB=0x86 //indicar si es entrada o salida
#byte PORTB=0x06  //indica si esta en nivel alto o bajo 

char movil;
char sms_in;


#INT_RDA      //esta interrupcion despertara el PIC y hara una busqueda de ubicacion y enviar la ubicacion por SMS al numero de movil correspondiente
void RDA_isr(void)
{
   
    movil=getc();
     
    
}

void main(){  

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2 );//usamos un reloj interno, division 2
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
  

TRISB=0b0010011;
PORTB=0x00;

enable_interrupts(INT_RDA); 
enable_interrupts(GLOBAL);


while(true){
   
    strcpy(sms_in,"A");
   if((strcmp(movil,sms_in))=0) //strcmp(s1,s2)==0 significa que s1 es igual que s2
    { printf("ATD0034618354363;\r\n");}  
  }
}
```

El objetivo es cuando recibe el mensaje "A", que me hace una llamada, pero veo que no funciona.
Y también estaba pensando que, en AT commands, si le envio una "A", la respuesta es el siguiente

```
+CMT: "+34618354363","","16/02/13,16:02:28+04"
A
```
Entonces digamOs los caracteres que recibe no es tan simplemente una A, alguna forma para leer solo la parte del mensaje? Y lo más importante es lo de INT_RDA, que no entiendo muy bien.

Gracias por cualquier sugerencia!


----------



## nelsonr (Feb 13, 2016)

Hola amigo tengo una pregunta, ya que tengo dos pic comunicado por rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) me gustaría saber si yo puedo reiniciar el pic 2 por medio de una instrucción enviada del pic1. Y como aria esto de poderse hacer.
gracias de ante manos por su tiempo dedicado.


----------



## D@rkbytes (Feb 13, 2016)

nelsonr dijo:


> Me gustaría saber si yo puedo reiniciar el pic 2 por medio de una instrucción enviada del pic1.
> Y cómo haría esto, de poderse hacer.


Con la instrucción: reset_cpu();


----------



## nelsonr (Feb 17, 2016)

Hola D@rkbytes con un poco de vergüenza  te hago esta pregunta: como yo aplicaría esta instrucción reset_cpu();.
Para que el pic 1  haga llegar al pic 2 la información de reset, Ej.: creo una función en el pic 2 que contenga esta instrucción de reset  y por medio de un parámetro enviado por putc() del pic 1 lo ejecuto ?. 
Como se ordenaría este envió entre pic ?.


----------



## D@rkbytes (Feb 17, 2016)

Es sencillo. Como cualquier comunicación entre microcontroladores.

El maestro envía un comando bajo cierto protocolo o hasta con una simple letra o número que el esclavo interpretará como una orden.

La selección de comandos depende del tipo de envío, cuando son comandos sencillos se pueden identificar y separar con "switch"

En realidad lo que pretendes es muy sencillo y no tiene la menor complicación.


----------



## nelsonr (Feb 18, 2016)

Ok creo  haber comprendido  voy a probar, y te cuento  como me fue.


----------



## nelsonr (Feb 26, 2016)

Listo me funciono bien el dato. Solo me queda una duda porque mi proyecto que es un  panel de botones que dar permiso para entrar o no por una puerta, dependiendo de la clave que insertes. Tiene el problema de que funciona bien 3 o 4 días 24 horas y de repente tiene comportamiento errados y debo reiniciarlo, luego funciona nuevamente bien 3,4 y hasta 5 días y se repite este caso nuevamente.
Por donde debería comenzar  a revisar ?.


----------



## D@rkbytes (Feb 26, 2016)

Tanto el programa del microcontrolador, como el diseño de la tarjeta, tienen mucho que ver.
Un microcontrolador con un programa bien estructurado, montado en una tarjeta bien diseñada, puede estar trabajando continuamente por muchos años.

El programa puede tomar caminos erráticos cuando la estructura no está bien definida.
Y un mal diseño de la tarjeta, puede afectar el comportamiento del microcontrolador.


----------



## daro1276 (Jul 18, 2018)

Hola.
¿Alguien podría ayudarme?
Estoy haciendo un letrero led, pero deseo que cuando reciba un carácter por el Rx, cambie automáticamente el mensaje.
Este el programa que estoy utilizando:


```
#include <16F887.h>

 

#use delay(clock=20000000)         

#fuses NOWDT, hs, PUT, NOPROTECT

#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_C6,RCV=PIN_C7)

//#use standard_io(d)


char valor;

char valor1;

const char TEXT []={"..."};

const char TEXT1 []={"..."};


int i,j,k,d,n,m,s,DATA;

int1 z=0;

//------------------------------------------------------------------

const char FONT1[32][7] ={

   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,   //        Space

   0xFB,0xFB,0xFB,0xFB,0xFB,0xFF,0xFB,   //        !

   0xF5,0xF5,0xF5,0xFF,0xFF,0xFF,0xFF,   //        "

   0xF5,0xF5,0xE0,0xF5,0xE0,0xF5,0xF5,   //        #

   0xFB,0xF0,0xEB,0xF1,0xFA,0xE1,0xFB,   //        $

   0xE3,0xEA,0xE5,0xFB,0xF4,0xEA,0xF8,   //        %

   0xF7,0xEB,0xEB,0xF7,0xEA,0xED,0xF2,   //        &

   0xF9,0xF9,0xFD,0xFB,0xFF,0xFF,0xFF,   //        '

   0xFD,0xFB,0xF7,0xF7,0xF7,0xFB,0xFD,   //        (

   0xF7,0xFB,0xFD,0xFD,0xFD,0xFB,0xF7,   //        )

   0xFB,0xEA,0xF1,0xFB,0xF1,0xEA,0xFB,   //        *

   0xFF,0xFB,0xFB,0xE0,0xFB,0xFB,0xFF,   //        +

   0xFF,0xFF,0xFF,0xF3,0xF3,0xFB,0xF7,   //        ,

   0xFF,0xFF,0xFF,0xF1,0xFF,0xFF,0xFF,   //        -

   0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0xF3,   //        .

   0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xFF,   //        /

   0xF1,0xEE,0xEC,0xEA,0xE6,0xEE,0xF1,   //        0

   0xFB,0xF3,0xFB,0xFB,0xFB,0xFB,0xF1,   //        1

   0xF1,0xEE,0xFE,0xF1,0xEF,0xEF,0xE0,   //        2

   0xF1,0xEE,0xFE,0xF9,0xFE,0xEE,0xF1,   //        3

   0xFD,0xF9,0xF5,0xED,0xE0,0xFD,0xFD,   //        4

   0xE0,0xEF,0xE1,0xFE,0xFE,0xFE,0xE1,   //        5

   0xF9,0xF7,0xEF,0xE1,0xEE,0xEE,0xF1,   //        6

   0xE0,0xFE,0xFD,0xFB,0xF7,0xF7,0xF7,   //        7

   0xF1,0xEE,0xEE,0xF1,0xEE,0xEE,0xF1,   //        8

   0xF1,0xEE,0xEE,0xF0,0xFE,0xFD,0xF3,   //        9

   0xFF,0xF3,0xF3,0xFF,0xF3,0xF3,0xFF,   //        :

   0xF3,0xFB,0xF3,0xF3,0xFF,0xF3,0xF3,   //        ;       

   0xFD,0xFB,0xF7,0xEF,0xF7,0xFB,0xFD,   //        <

   0xFF,0xFF,0xF1,0xFF,0xF1,0xFF,0xFF,   //        =

   0xF7,0xFB,0xFD,0xFE,0xFD,0xFB,0xF7,   //        >

   0xF1,0xEE,0xFE,0xFD,0xFB,0xFF,0xFB};  //        ?


const char FONT2[32][7] ={

   0xF1,0xEE,0xFE,0xF2,0xEA,0xEA,0xF1,   //        @

   0xFB,0xF5,0xEE,0xEE,0xE0,0xEE,0xEE,   //        A

   0xE1,0xF6,0xF6,0xF1,0xF6,0xF6,0xE1,   //        B

   0xF1,0xEE,0xEF,0xEF,0xEF,0xEE,0xF1,   //        C

   0xE1,0xF6,0xF6,0xF6,0xF6,0xF6,0xE1,   //        D

   0xE0,0xEF,0xEF,0xE3,0xEF,0xEF,0xE0,   //        E

   0xE0,0xEF,0xEF,0xE3,0xEF,0xEF,0xEF,   //        F

   0xF1,0xEE,0xEF,0xE8,0xEE,0xEE,0xF1,   //        G

   0xEE,0xEE,0xEE,0xE0,0xEE,0xEE,0xEE,   //        H

   0xF1,0xFB,0xFB,0xFB,0xFB,0xFB,0xF1,   //        I

   0xF8,0xFD,0xFD,0xFD,0xFD,0xFD,0xF3,   //        J

   0xEE,0xED,0xEB,0xE7,0xEB,0xED,0xEE,   //        K

   0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xE0,   //        L

   0xEE,0xE4,0xEA,0xEA,0xEE,0xEE,0xEE,   //        M

   0xEE,0xE6,0xEA,0xEC,0xEE,0xEE,0xEE,   //        N

   0xF1,0xEE,0xEE,0xEE,0xEE,0xEE,0xF1,   //        O

   0xE1,0xEE,0xEE,0xE1,0xEF,0xEF,0xEF,   //        P

   0xF1,0xEE,0xEE,0xEE,0xEA,0xED,0xF2,   //        Q

   0xE1,0xEE,0xEE,0xE1,0xEB,0xED,0xEE,   //        R

   0xF1,0xEE,0xEF,0xF1,0xFE,0xEE,0xF1,   //        S

   0xE0,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,   //        T

   0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xF1,   //        U

   0xEE,0xEE,0xEE,0xF5,0xF5,0xFB,0xFB,   //        V

   0xEE,0xEE,0xEE,0xEA,0xEA,0xE4,0xEE,   //        W

   0xEE,0xEE,0xF5,0xFB,0xF5,0xEE,0xEE,   //        X

   0xEE,0xEE,0xF5,0xFB,0xFB,0xFB,0xFB,   //        Y

   0xE0,0xFE,0xFD,0xFB,0xF7,0xEF,0xE0,   //        Z

   0xF1,0xF7,0xF7,0xF7,0xF7,0xF7,0xF1,   //        [

   0xFF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF,   //        \

   0xF1,0xFD,0xFD,0xFD,0xFD,0xFD,0xF1,   //        [

   0xFB,0xF5,0xEE,0xFF,0xFF,0xFF,0xFF,   //        ^

   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0};  //        _


const char FONT3[32][7] ={

   0xF3,0xF3,0xF7,0xFB,0xFF,0xFF,0xFF,   //        `

   0xFF,0xFF,0xF1,0xFE,0xF0,0xEE,0xF1,   //        a

   0xEF,0xEF,0xE9,0xE6,0xEE,0xE6,0xE9,   //        b

   0xFF,0xFF,0xF8,0xF7,0xF7,0xF7,0xF8,   //        c

   0xFE,0xFE,0xF2,0xEC,0xEE,0xEC,0xF2,   //        d

   0xFF,0xFF,0xF1,0xEE,0xE0,0xEF,0xF1,   //        e

   0xF9,0xF6,0xF7,0xE1,0xF7,0xF7,0xF7,   //        f

   0xFF,0xFF,0xF0,0xEE,0xF0,0xFE,0xF1,   //        g

   0xEF,0xEF,0xE9,0xE6,0xEE,0xEE,0xEE,   //        h

   0xFB,0xFF,0xF3,0xFB,0xFB,0xFB,0xF1,   //        i

   0xFD,0xFF,0xF9,0xFD,0xFD,0xFD,0xF3,   //        j

   0xF7,0xF7,0xF6,0xF5,0xF3,0xF5,0xF6,   //        k

   0xF3,0xFB,0xFB,0xFB,0xFB,0xFB,0xF1,   //        l

   0xFF,0xFF,0xE5,0xEA,0xEA,0xEA,0xEA,   //        m

   0xFF,0xFF,0xE9,0xE6,0xEE,0xEE,0xEE,   //        n

   0xFF,0xFF,0xF1,0xEE,0xEE,0xEE,0xF1,   //        o

   0xFF,0xFF,0xE1,0xEE,0xE1,0xEF,0xEF,   //        p

   0xFF,0xFF,0xF0,0xEE,0xF0,0xFE,0xFE,   //        q

   0xFF,0xFF,0xE9,0xE6,0xEF,0xEF,0xEF,   //        r

   0xFF,0xFF,0xF0,0xEF,0xF1,0xFE,0xE1,   //        s

   0xFB,0xFB,0xF0,0xFB,0xFB,0xFB,0xFC,   //        t

   0xFF,0xFF,0xEE,0xEE,0xEE,0xEC,0xF2,   //        u

   0xFF,0xFF,0xEE,0xEE,0xEE,0xF5,0xFB,   //        v

   0xFF,0xFF,0xEE,0xEE,0xEA,0xEA,0xF4,   //        w

   0xFF,0xFF,0xEE,0xF5,0xFB,0xF5,0xEE,   //        x

   0xFF,0xFF,0xEE,0xF5,0xFB,0xFB,0xF3,   //        y

   0xFF,0xFF,0xE0,0xFD,0xFB,0xF7,0xE0,   //        z

   0xF9,0xF7,0xF7,0xE7,0xF7,0xF7,0xF9,   //        {

   0xFB,0xFB,0xFB,0xFF,0xFB,0xFB,0xFB,   //        |

   0xF3,0xFD,0xFD,0xFC,0xFD,0xFD,0xF3,   //        }

   0xF5,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF};  //        ~

//------------------------------------------------------------------


//------------------------------------------------------------------

#INT_RDA

void LETRERO(){

salida:

valor=getc();//recibe el dato del pc y lo guarda en valor

valor1=valor;

/////////////////////codigo del pc

}


void main(){

enable_interrupts(global);

enable_interrupts(int_rda);

//LETRERO();

//////////////////////////////////////////////////////////////////////////////////

switch (valor){

//------------------------------------------------------------------RUTA 1

    case 'a':

     char TEXT []={"         RUTA 1               "};

     while(true){

     valor=getc();

     for(j=0;j<8;){

       for(i=d;i<d+8;i++){

         if (TEXT <='?')DATA=~FONT1[TEXT -' '][j];

         else

         if (TEXT <='_')DATA=~FONT2[TEXT -'@'][j];

         else

         if (TEXT <='~')DATA=~FONT3[TEXT -'`'][j];

         if(j==7)DATA=0x00;

         for(k=0;k<8;k++){

           OUTPUT_BIT(PIN_A1,shift_left(&DATA,1,0));

           if(k>=2){

           OUTPUT_HIGH(PIN_A0);

           OUTPUT_LOW (PIN_A0);

           OUTPUT_HIGH(PIN_A0);

           OUTPUT_LOW (PIN_A0);

           }

          }

         }

       //demo

       if(s&8)

       OUTPUT_HIGH(PIN_A3);

       else

       OUTPUT_HIGH(PIN_A2);

       delay_ms(2);

       OUTPUT_LOW (PIN_A2);OUTPUT_LOW (PIN_A3);

       OUTPUT_B(s+=1);

       if(z)j++;   

       z=!z;

       }

       m+=1;

       if(m==2){m=0;n+=1;};

       if(n==12){n=0;d+=1;}

       if(d==20)d=0;

      }

      

      break;

      

      //------------------------------------------------------------------RUTA 2

     case 'b':

      char TEXT1 []={"         RUTA 2               "};

      while(true){

      for(j=0;j<8;){

       for(i=d;i<d+8;i++){

         if (TEXT1 <='?')DATA=~FONT1[TEXT1 -' '][j];

         else

         if (TEXT1 <='_')DATA=~FONT2[TEXT1 -'@'][j];

         else

         if (TEXT1 <='~')DATA=~FONT3[TEXT1 -'`'][j];

         if(j==7)DATA=0x00;

         for(k=0;k<8;k++){

           OUTPUT_BIT(PIN_A1,shift_left(&DATA,1,0));

           if(k>=2){

           OUTPUT_HIGH(PIN_A0);

           OUTPUT_LOW (PIN_A0);

           OUTPUT_HIGH(PIN_A0);

           OUTPUT_LOW (PIN_A0);

           }

          }

         }

       //demo

       if(s&8)

       OUTPUT_HIGH(PIN_A3);

       else

       OUTPUT_HIGH(PIN_A2);

       delay_ms(2);

       OUTPUT_LOW (PIN_A2);OUTPUT_LOW (PIN_A3);

       OUTPUT_B(s+=1);

       if(z)j++;   

       z=!z;

       }

       m+=1;

       if(m==2){m=0;n+=1;};

       if(n==12){n=0;d+=1;}

       if(d==20)d=0;

       valor=getc();

      }

      break;

   }


}
```


----------



## D@rkbytes (Jul 18, 2018)

daro1276 dijo:


> Estoy haciendo un letrero led, pero deseo que cuando reciba un carácter por el Rx, cambie automáticamente el mensaje.


¿Y cuál es el problema?
Te recomiendo que subas tu proyecto dentro de un archivo comprimido, incluyendo el de simulación, ya que nadie se va a poner a realizar tu esquema en proteus.


----------



## daro1276 (Jul 20, 2018)

*M*ira  dejo el c*ó*digo fuente que uso y la simulaci*ó*n  *,* el programa al dar inicio recibe la letra del case y saca el mensaje, pero intento enviar el otro dato y no lo realiza.
*N*o sale del while, y eso que dentro del while est*á* el getc()
*¿ Có*mo podr*í*a solucionar *?*


----------



## D@rkbytes (Jul 20, 2018)

Lo que sucede es que después de ocurrir la interrupción el programa continuará exactamente justo en el lugar en donde fue ejecutada.
Como existen varios bucles, entonces se tendrán que cumplir para que se retome el nuevo valor asignado en la interrupción.
Una solución sería verificar durante los bucles si el valor ha cambiado.
Por ejemplo: if(valor != '1') break;
Y en un caso extremo... if(valor != '1') reset_cpu();


----------



## roberttorres (Jul 20, 2018)

No soy experto en programación pero tal vez deberías de cambiar la estructura de tu código, ejemplo:

```
#INT_RDA
void LETRERO(){
valor=getc();//recibe el dato del pc y lo guarda en valor

Void main{
codigo

  While(true){
    switch (valor){
       case '1':
         codigo;
         break;
        
          case '2':
         codigo;
         break;}
}
}
```


----------



## daro1276 (Jul 20, 2018)

D@rkbytes dijo:


> Lo que sucede es que después de ocurrir la interrupción el programa continuará exactamente justo en el lugar en donde fue ejecutada.
> Como existen varios bucles, entonces se tendrán que cumplir para que se retome el nuevo valor asignado en la interrupción.
> Una solución sería verificar durante los bucles si el valor ha cambiado.
> Por ejemplo: if(valor != '1') break;
> Y en un caso extremo... if(valor != '1') reset_cpu();




Gracias, funciono a la perfeccion

	Mensaje automáticamente combinado: Jul 20, 2018



roberttorres dijo:


> No soy experto en programación pero tal vez deberías de cambiar la estructura de tu código, ejemplo:
> 
> ```
> #INT_RDA
> ...


lo intente hacer y genera problemas, cree void y estoy sacando 22 msj, pero aun asi llevo muchas lineas de codigo

	Mensaje automáticamente combinado: Jul 20, 2018



daro1276 dijo:


> Gracias, funciono a la perfeccion
> 
> Mensaje automáticamente combinado: Jul 20, 2018
> 
> ...


mira este es el codigo que genere


----------



## roberttorres (Jul 22, 2018)

daro1276 dijo:


> lo intente hacer y genera problemas, cree void y estoy sacando 22 msj, pero aun asi llevo muchas lineas de codigo


Ok, veo que tu código es mucho mas extenso y que estas utilizando casi toda la memoria rom del pic, se podría optimizar creando subfunciones que sean iguales en todas tus funciones principales.
Te paso un código de como lo haría yo, no se si funciona en físico, pues no tengo los materiales para probar pero tal vez te sirva de base para mejorar y optimizar tu proyecto.


----------

