Página 1 de 1

Recepção Serial no PIC (>70 caracteres)

MensagemEnviado: 22 Nov 2009 19:01
por wandersonrainer
Olá a todos,

estou implementando um sistema no qual o PIC recebe de um determinado equipamento strings de tamanhos de 7, 17 ou 75.
As de tamanho 7 e 17 o programa consegue recebê-las normalmente e voltar à sua operação normal. Porém, ao receber 75 caracteres, o programa trava.
Alguém sabe se existe um buffer com determinado tamanho para recepção pela USART?

Obrigado a todos.

PS: A recepção está sendo feita vai interrupção.

MensagemEnviado: 22 Nov 2009 19:20
por Jozias del Rios
Pode postar o código?

postando o codigo

MensagemEnviado: 22 Nov 2009 19:24
por wandersonrainer
Código: Selecionar todos
#include <string.h>

#locate  rc_reg=0x1A


char  msg[80];
char  conteudo[3];
char  chegou;
int   flag=0;
int   cont=0;
int   end=0x80;
char  fim;
int   x=0;
int   c;
int   tam;

#byte porta=0x05
#byte portb=0x06
#byte portc=0x07
#byte portd=0x08
#byte porte=0x09
#byte txsta=0x98
#byte rcsta=0x18


#bit  rs = porte.2
#bit  enable = porte.1
#bit  led=portb.7
#bit  bt1=portb.0
#bit  bt2=portb.1
#bit  bt3=portb.2
#bit  bt4=portb.3

void comando_lcd(int caractere)
{
   rs=0;
   enable=1;
   portd=caractere;
   delay_ms(3);
   enable=0;
}

void escreve_lcd(int caractere)
{
   rs=1;
   enable=1;
   portd=caractere;
   delay_ms(3);
   enable=0;
}

void inicializa_lcd()
{
   comando_lcd(0b00111100);
   comando_lcd(0b00001100);
}

void limpa_lcd()
{
   comando_lcd(0b00000001);
}

void limpa_msg(void)
{
   tam=strlen(msg);
   for(x=0;x<tam;x=x+1)
   {
      msg[x]=0;
      printf("%c",msg[x]);
      delay_ms(100);
   }
   x=0;
}

#int_rda
void  recebido(void)
{
   
   chegou=rc_reg;
     
   msg[cont]=chegou;
   
   cont=cont+1;
   
   if(chegou==0x0A)
   {
   flag=flag+1;
   }
   
   if(flag>=2)
      {
         if(cont>4 && cont<10)//Testa se 2 vezes 0x0A é refetente a AT OK
         {
         limpa_lcd();
         comando_lcd(0x80);
         printf(escreve_lcd, "FOI ATOK");
         comando_lcd(0xC0);
         printf(escreve_lcd, "%u", cont);
         comando_lcd(0xC4);
         tam=strlen(msg);
         printf(escreve_lcd,"%u",tam);
       
         cont=0;
         flag=0;
         limpa_msg();
         }
         if(cont>10 && cont<20)//Teste se 2 vezes 0x0A é refetente a +CMTI
         {
         limpa_lcd();
         comando_lcd(0x80);
         printf(escreve_lcd, "FOI +CMTI");
         comando_lcd(0xC0);
         printf(escreve_lcd, "%u", cont);
         cont=0;
         flag=0;
         limpa_msg();
         }
         [b]if(cont>50 && flag>4)
         {
         limpa_lcd();
         comando_lcd(0x80);
         printf(escreve_lcd, "FOI +CMGR");
         comando_lcd(0xC0);
         printf(escreve_lcd, "%u", cont);
         cont=0;
         flag=0;
         led=~led;
         delay_ms(200);
         led=~led;
         delay_ms(200);
         led=~led;
         delay_ms(200);
         //limpa_msg();
         //tam=strlen(msg);
         }[/b]

      }
   
 
}



void main()
{
   set_tris_a(0b00000000);
   set_tris_b(0b00001111);
   //set_tris_c(0b00000000);
   set_tris_d(0b00000000);
   set_tris_e(0b00000000);
 
   porta=0;
   portb=0;
   portc=0;
   portd=0;
   porte=0;
   
   fim=26;
   
   //txsta=0b10100100;
   //rcsta=0b10010000;
   
   inicializa_lcd();
   limpa_lcd();
   
   comando_lcd(0x80);
   printf(escreve_lcd,"TESTE GERAL");
   
   //printf("ATE0\n\r");
   
   //printf("AT+CMGD=1\n\r");
   delay_ms(200);
   
   enable_interrupts(global);
   enable_interrupts(int_rda);
   
//!   printf("AT+CMGF=1\n\r");
//!   delay_ms(500);
//!   
//!   printf("AT+CMGD=1\n\r");
//!   delay_ms(500);
      limpa_msg();
   while(1)
   {
   
      if(bt1==0)
      {
         while(bt1==0)
         {
         }
      printf("AT\n\r");
      }
      if(bt2==0)
      {
         while(bt2==0)
         {
         }
      printf("AT+CMGF=1\n\r");
      }
      if(bt3==0)
      {
      printf("AT+CMGR=1\n\r");
         while(bt3==0)
         {
         }
      }
      if(bt4==0)
      {
      printf("AT+CMGD=1\n\r");
         while(bt4==0)
         {
         }
      }
   }
}



A parte em negrito é a que trava.
O PIC utilizando é o PIC16F877A.

MensagemEnviado: 22 Nov 2009 19:30
por Jozias del Rios
Por favor edite a sua mensagem e use "[code]' ao início e "[/code]" ao fim do código postado, conforme as regras do forum. Os leitores agradecem ;-)

MensagemEnviado: 23 Nov 2009 11:00
por Alesandro F Zagui
A RAM do 16F877 é muito pequena, tente migrar pro 18F452, é compatível pino a pino e em alguns lugares é até mais barato.

MensagemEnviado: 23 Nov 2009 12:30
por leoabubauru
wanderson

Trate o LCD fora da interrupção. Suas rotinas de LCD têm delays de 3ms o que pode realmente travar o micro dependendo da taxa de comunicação e da quantidade de bytes. Ou seja, sua rotina mal terminou (se é que terminou!) de trar um byte e já tem outro chegando. Quando a mensagem é grande (>70 no seu caso) isso vira uma loucura para o uC.

Não acho necessário trocar por um 18F452. O 777 dá conta do recado. Preencha um buffer e trate-o no MAIN. É bem mais seguro!

MensagemEnviado: 24 Nov 2009 18:50
por wandersonrainer
leoabubauru escreveu:wanderson

Trate o LCD fora da interrupção. Suas rotinas de LCD têm delays de 3ms o que pode realmente travar o micro dependendo da taxa de comunicação e da quantidade de bytes. Ou seja, sua rotina mal terminou (se é que terminou!) de trar um byte e já tem outro chegando. Quando a mensagem é grande (>70 no seu caso) isso vira uma loucura para o uC.

Não acho necessário trocar por um 18F452. O 777 dá conta do recado. Preencha um buffer e trate-o no MAIN. É bem mais seguro!


Ok, valeu pela dica. :wink:

MensagemEnviado: 24 Nov 2009 20:04
por Jozias del Rios
Não foi justamente isso que eu falei em outro tópico faz 1 semana?
para o cara tirar "lcd_pos_xy" e "printf" da porcaria da interrupção de recepção da uart....

eu acho que todo microcontrolador deve ser aprendido primeiro a se mexer em ASM, para depois se ir para o C....

tem gente que perde a noção do que acontece por trás completamente!

just my 50 cents
abs!

MensagemEnviado: 24 Nov 2009 20:40
por wandersonrainer
Jozias del Rios escreveu:Não foi justamente isso que eu falei em outro tópico faz 1 semana?
para o cara tirar "lcd_pos_xy" e "printf" da porcaria da interrupção de recepção da uart....

eu acho que todo microcontrolador deve ser aprendido primeiro a se mexer em ASM, para depois se ir para o C....

tem gente que perde a noção do que acontece por trás completamente!

just my 50 cents
abs!


Ok meu caro, mas o problema foi resolvido sem essa alteração.
Foi constatado que, de acordo com as mensagem recebidas pelo equipamento (modem GSM), o programa SEMPRE entrava no segundo IF.
O problema foi resolvido sem retirar as chamadas de escritas no LCD de dentro da interrupção da USART, pois os tempos de recepção dos caracteres, de acordo com a velocidade de transmissão, foram devidamente calculados.

Abs (take it easy).

MensagemEnviado: 24 Nov 2009 23:01
por msamsoniuk
olhae jozias! ponto para o C! hehehe mal ae, eu nao resisti! :)

wandersonrainer escreveu:
Jozias del Rios escreveu:Não foi justamente isso que eu falei em outro tópico faz 1 semana?
para o cara tirar "lcd_pos_xy" e "printf" da porcaria da interrupção de recepção da uart....

eu acho que todo microcontrolador deve ser aprendido primeiro a se mexer em ASM, para depois se ir para o C....

tem gente que perde a noção do que acontece por trás completamente!

just my 50 cents
abs!


Ok meu caro, mas o problema foi resolvido sem essa alteração.
Foi constatado que, de acordo com as mensagem recebidas pelo equipamento (modem GSM), o programa SEMPRE entrava no segundo IF.
O problema foi resolvido sem retirar as chamadas de escritas no LCD de dentro da interrupção da USART, pois os tempos de recepção dos caracteres, de acordo com a velocidade de transmissão, foram devidamente calculados.

Abs (take it easy).

MensagemEnviado: 24 Nov 2009 23:27
por Djalma Toledo Rodrigues
wandersonrainer escreveu: ... mas o problema foi resolvido sem essa alteração....

Compartilha.