TODOPIC
FORO TÉCNICO => Telefonía, GPS y Microcontroladores => Mensaje iniciado por: Izat en 19 de Diciembre de 2012, 07:26:02
-
Buenos días.
Antes de nada quiero agradecer la función de este foro, me esta ayudando mucho para llevar adelante mi proyecto.
Este es mi primer post,necesito que me echen una mano, he leído muchísimo y no soy capaz de encontrar la solución.
Estoy tratando de recibir datos de un modem GSM(de audiotel) a través del RS232. El pic es el 18f4550.
La idea es que cuando reciba un SMS el pic genere una interrupción(rda) y que guarde el SMS en una cadena de caracteres, para luego posteriormente trabajar con ella.
El problema está en que el SMS llega al modem, y este al pic(lo veo por que conecte unos diodos led entre MAX 222 y el pic, para que parpadeen cuando llega un dato, tanto de entrada como de salida) pero la interrupción se queda colgada, supongo que sea por el gets, pero probando con el getc o el kbhit parece como que no se activara.
Os muestro parte del código. Descarto que sea el hardware, por que si que envía comandos al modem, y este los lee sin problemas, como por ejemplo mandar un sms.
#include <18f4550.h>
#device adc=10
#fuses HS,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,CPUDIV1,NOVREGEN,NOPBADEN,NOPUT
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7,parity=N,bits=8)
#define use_portd_lcd TRUE
#define use_portb_kbd TRUE
#include <string.h>
#include <lcd.c>
#use standard_io(A)
#use fast_io(D)
// variables
char cadena[40];
int flag=0x00,i;
long int ntotal=2232;
#INT_RDA
void serial_isr(void){
gets(cadena);
flag=1; // lo utilizo para que el en main entre en la funcion procesaSMS
}
void iniciar_modem (void){
output_high(PIN_C2); //enceder modem GSM
delay_ms(25000); //espera a que se inicie
printf("AT+IRP=9600\r\n"); // velocidad
delay_ms(2000);
printf("ATE0\r\n");
delay_ms(2000);
printf("AT+CMGF=1\r\n"); // modo texto
delay_ms(2000);
printf("AT+IFC=0,0\r\n"); //control de flujo off
delay_ms(2000);
printf("AT+CPIN=%Ld\r\n",ntotal); // cogido pin
delay_ms(10000);
printf("AT+CNMI=2,2,0,0\r\n"); // configuro para que en cuanto llegue un mensaje lo envie el modulo gsm por el puerto serie
delay_ms(2000);
}
void procesaSMS(void){ // muestra la cadena recibida en la LCD
printf(lcd_putc,"%s",cadena);
delay_ms(2000);
for (i=0;i<40;i++){ // lee la cadena, si algún dato es T , el sms es valido
if (cadena=='T'){
lcd_putc("\f");
lcd_gotoxy(1,1);
lcd_putc("valido");
delay_ms(2000);
flag=0;
break;
}
}
lcd_putc("\f");
lcd_gotoxy(1,1);
lcd_putc("no valido");
delay_ms(2000);
flag=0;
}
void main (void){
lcd_init();
iniciar_modem();
lcd_gotoxy(1,2);
lcd_putc("modem listo");
delay_ms(2000);
lcd_putc("\f");
enable_interrupts(int_rda);
enable_interrupts(GLOBAL);
while (true){
lcd_gotoxy(1,2);
lcd_putc("esperando SMS");
if (flag==1){
procesaSMS();
flag=0;
}
}
}
Inicia bien el modem, se conecta a la red, cuando entra en el while, y aunque el flag=0, se activa la interrupción, pero no tiene por que , ya que el modem no envía ningún dato.
Como ha entrado en la interrupcion, se queda ahí colgado, supongo que por el gets....
En definitiva, que la interrupción no se activa cuando debiere, y ademas, esta se queda colgada
Alguna idea??
Gracias
-
Intenta con esto y adaptalo a tu aplicación:
#define BUFFER_SIZE 60 //Buffer size you can adjust this size
char buffer[BUFFER_SIZE]; // buffer
char b=0x00; // Last characters recived
int xbuff=0x00;
void RDA_isr(void)
{
if(kbhit()){
b=getc();
buffer[xbuff++]=b; // add character to the buffer vector
if(xbuff==buffer_size) xbuff=0x00;//reset
}
return ;
}
-
Muchas gracias por la contestación.
He añadido el código que me indicaste y nada, la interrupción sigue sin activarse cuando envío SMS.
Tengo un led conectado al Rx para ver si hay actividad, y cuando mando el sms , el led parpadea dos veces, osea que mensaje llega.
El problema esta en que la interrupción no entra.
Un saludo
-
Tal vez puedas armar un sniffer del puerto serie para ver en la PC que es lo que esta contestando el modem. Tal vez esta devolviendo un error.
Saludos!!
-
Hola Izat.
Reemplaza el gets por getc.
http://www.todopic.com.ar/foros/index.php?topic=37758.0
Saludos.
-
Hola a todos, despues de varios meses he vuelto con el proyecto.
Lo cierto es que no se por donde tirar, llevo varias semanas y no logro hacerlo funcionar.
El proyecto lo he reducido a lo mínimo y el problema esta en que la interrupción RDA se inicia cuando no debe, este es el código:
#include <18f4550.h>
#device adc=10
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,CPUDIV1,NOVREGEN,NOPBADEN,NOPUT
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7,parity=N,bits=8)
#define use_portd_lcd TRUE
#define use_portb_kbd TRUE
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <lcd.c>
#use standard_io(A)
#use fast_io(D)
//#use fast_io(C)
#int_rda //La interrupción rda hace parpadear un led, para comprobar que entra la interrupción
void rd_isr(void){
output_high(PIN_C1);
delay_ms(1000);
output_low(PIN_C1);
delay_ms(1000);
}
// PROGRAMA PRINCIPAL
void main (void){
setup_SPI(FALSE);
setup_PSP(PSP_DISABLED);
enable_interrupts(GLOBAL);
enable_interrupts(int_RDA);
while (true) {
}
}
El problema esta en que la interrupción entra todo el rato, y no debería ya que no se esta enviando ningún dato por el puerto.El led parpadea infinitamente...
Yo entiendo que no debería de hacer nada(bucle while) hasta que llegase algún dato al pin C7 y entrase en la interrupción.
Que opináis?
Un saludo
-
Hola izat.
Usar pausas dentro de la interrupcion: ERROR FATAL.
Pon el pin de RC7 como entrada: set_tris_c.
Sigue probando.
-
Hola de nuevo y gracias por la contestación.
Hice unos cuantos cambios y el problema es que ahora no se activa la interrupción.
He sacado los retardos de la rutina de la interrupción y le he puesto que active un flag para que en el main haga parpadear al led.
Este es el código:
#include <18f4550.h>
#device adc=10
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,CPUDIV1,NOVREGEN,NOPBADEN,NOPUT
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7,parity=N,bits=8)
#define use_portd_lcd TRUE
#define use_portb_kbd TRUE
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <lcd.c>
#include <kbd.c> //Libreria para teclado matricial
#use standard_io(A)
#use fast_io(D)
#int_rda
void rd_isr(void){
flag=1;
// PROGRAMA PRINCIPAL
void main (void){
setup_SPI(FALSE);
setup_PSP(PSP_DISABLED);
set_tris_C(0b10000000);
enable_interrupts(GLOBAL);
enable_interrupts(int_RDA);
flag=0;
while (true) {
switch (flag){
case 1:
output_high(PIN_C1);
delay_ms(1000);
output_low(PIN_C1);
delay_ms(2000);
flag=0;
break;
case 0:
output_high(PIN_C1);
break;
}
}
}
El resultado es que se queda siempre el led encendido, es decir que no entra la interupcion.
Para activarla, lo hacia con el modem GSM conectado al rs232, pero lo he simplificado todo a lo mínimo y ahora le llevo al pin C7 0 o 5v , entiendo que con esto es suficiente para que se activase la interrupción.
Un saludo
-
Hola, primero verifica que el micro esta funcionando correctamente, prueba el siguiente codigo:
while(true)
{
output_toggle(PIN_C1);
delay_ms(500);
}
El led debe parpadear cada medio segundo.
Luego, puedes usar un soft monitor de puerto serie, verifica que salen datos validos por el uart, puedes usar proteus.
while(true)
{
delay_ms(1000);
}
Si no tienes monitor, pues solo ponle un led y verifica que parpadee.
Luego puentea el TX con el RX del micro y coloca el siguiente codigo en la int_rda.
#INT_RDA
void serie(void)
{
output_toggle(PIN_C1);
}
while(true)
{
delay_ms(1000);
Si hay toggle del led, ps ya esta a avanzar con el codigo.
Saludos!!
-
Hola KALLITOS,
Acabo de hacer lo que me comentaste.
Comprobé el buen funcionamiento del micro con la primera rutina, el led parpadea.
También funciona perfectamente la rutina que envía un dato por el TX.
El problema llega cuando puenteo el RX con el TX, haciendo la interrupción y la rutina ultima que me indicaste.He observado que lo que ocurre es que en el momento de puentearlos deja de enviar el dato, por lo que no entra la interrupción, es decir, que el TX se ve que envía dato, pero al conectarlo con el RX se para. El código es este:
#include <18f4550.h>
#device adc=10
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,CPUDIV1,NOVREGEN,NOPBADEN,NOPUT
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7,parity=N,bits=8)
#define use_portd_lcd TRUE
#define use_portb_kbd TRUE
#include <string.h>
#include <lcd.c>
#include <kbd.c>
#use standard_io(A)
#use fast_io(D)
#int_rda
void serie(void)
{
output_toggle(PIN_C1);
}
// PROGRAMA PRINCIPAL
void main (void){
set_tris_C(0b10000000);
enable_interrupts(GLOBAL);
enable_interrupts(int_RDA);
setup_SPI(FALSE);
setup_PSP(PSP_DISABLED);
while(true)
{
printf("X");
delay_ms(1000);
}
}
He probado con dos pic y pasa lo mismo, estoy empezando a pensar que sea el compilador, lo estoy haciendo con el MPLAB IDE v8.87 pickik3 y el ccs compiler 4.104.Hasta ahora todos los programas que he hecho han funcionado bien, menos el tema de las interrupciones.
Un saludo, y gracias
-
Coloca esta sentencia.
#use fast_io(c)
-
nada, lo acabo de poner y sigue igual.
Hace una cosa muy extraña, si se inicia con el led apagado y toco con el dedo el RX se enciende el led, lo comento por que tampoco debería de ser normal que haga esto.
-
Hola!
He conseguido activar la interrupción con el RX y el TX puenteados, lo he conseguido deshabilitando las interrupciones en la rutina de interrupción.
El problema ahora es que el led se queda parpadeando siempre, una vez que se activa la interrupción se queda parpadeando incluso cuando desconecto el RX del TX
Este es el nuevo codigo:
#include <18f4550.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,CPUDIV1,NOVREGEN,NOPBADEN,NOPUT
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7,bits=8,parity=N)
#use fast_io(c)
//Interrupcion RDA
#int_rda
void serie(void)
{
disable_interrupts(GLOBAL);
disable_interrupts(int_RDA);
output_toggle(PIN_C1);
}
// PROGRAMA PRINCIPAL
void main (void){
set_tris_C(0b10000000);
setup_SPI(FALSE);
setup_PSP(PSP_DISABLED);
//enable_interrupts(GLOBAL);
//enable_interrupts(int_RDA);
while(true)
{
enable_interrupts(GLOBAL);
enable_interrupts(int_RDA);
printf("X");
delay_ms(1000);
}
}
Un saludo
-
Hola, verifica el pin mclr ya que no usas el
#fuse NOMCLR
Otra es que para que borre el flag de interrupcion de RDA debes leer el dato recibido,(no me fije en el codigo de ejemplo que puse anteriormente) de la siguiente manera
#int_rda
void serie(void)
{
int8 dato;
output_toggle(PIN_C1);
}
saludos.
-
Hola, ya esta solucionado al parecer el el fuse NOMCLR
Al puentear el RX con el TX genera perfectamente la interrupción, ahora añadiere esto al código completo con el módem GSM.
El código funcionando es este, por si os puede interesar:
#include <18f4550.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,CPUDIV1,NOVREGEN,NOPBADEN,NOPUT
#fuses NOMCLR
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=pin_C6, rcv=pin_C7,bits=8,parity=N)
#use fast_io(c)
//Interrupcion RDA
#int_rda
void serie(void){
int8 dato;
dato = getc();
output_toggle(PIN_C1);
}
// PROGRAMA PRINCIPAL
void main (void){
enable_interrupts(GLOBAL);
enable_interrupts(int_RDA);
set_tris_C(0b10000000);
output_low(PIN_C1);
setup_SPI(FALSE);
setup_PSP(PSP_DISABLED);
while(true){
printf("X");
delay_ms(1000);
}
}
Muchas gracias, iré posteando mis avances para poder compartirlos
Un saludo
-
Que bueno !!!