Interrupción RS-232 en PIC C de CCS

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.
Código:
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;   
            }
      }
 
Última edición por un moderador:
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.
 
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:

Código:
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.
 
Última edición por un moderador:
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.
 
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
 
Última edición:
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.
 
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
 
Buenas tardes compañeros del foro:

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

Código:
#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.
 
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.
 
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
 
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
 
TRILO-BYTE, gracias por la respuesta que me enviaste !!!!! (y):aplauso::aplauso:

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? :confused:

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

PHP:
///////////////////////////////////////////////////////////////////////////

#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); 

}
}
 
Última edición por un moderador:
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,",;");

ptr = strtok(string, term);

while(ptr!=0) {
puts(ptr);
ptr = strtok(0, term);
}

// Prints:
one
two
three


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
 
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? :confused:
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.
 

Adjuntos

  • 16F628A Cadenas RS-232.rar
    32 KB · Visitas: 41
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!!!!!
 
Última edición:
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
 

Adjuntos

  • CONTADOR DUPLEX.rar
    169.2 KB · Visitas: 11
Atrás
Arriba