Pic 24f travamento no tratamento de interrupção serial.

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Pic 24f travamento no tratamento de interrupção serial.

Mensagempor Eduardo Augusto » 10 Jun 2014 09:29

Olá pessoal, tudo bem? Sou novato aqui no forum rs, mas vamos lá

De forma breve, estou me iniciando em projetos com os uC's pic24f e estou tendo um pouco de dificuldade na parte da serial, rs.
Criei um aplicativo em visual c++ que envia um protocolo de bytes para o uC, como estou trabalhando com interrupção de RX, fica fácil tratar os bytes que estou recebendo, no entanto estou notando que isto esta atrapalhando processamento de outras interrupções, como a de multiplexação de displays, SPI, e etc...
Estou dando para a porta serial baixa preferencia na interrupção... as preferencias na hora de tratar a interrupção são enumeradas, se me lembro bem rs, de 0 a 7. Sendo 0 a de menor preferencia e 7 a de maior preferencia.
Portanto
Código: Selecionar todos
_U1RXIP = 4; preferencia da int rx
 _T5IP = 5;   preferencia da int timer 5
_INT1IP = 6; preferencia da int int1 para bit banging

Estou tratando o protocolo que recebo de forma simples, não sei o erro esta nele rs.
Código: Selecionar todos
void __attribute__((interrupt,no_auto_psv)) _U1RXInterrupt(void)
{
 protocolo[auxiliar_protocolo] = recebe_byte_UART1();
   
     if(auxiliar_protocolo == 20)    /* se vetor protocolo estiver cheio */
    {
        if( protocolo[0] == 0xAA && protocolo[1] == 0x01 && protocolo[19] == 0xAA ) /* se for protocolo de atualização de dados */
        {
              /* faz  oque tem que fazer */
            _U1RXIF = 0; /* Limpa flag */
        }
        else if(   protocolo[0] == 0xAA  /* se for protocolo de request de dados */
                && protocolo[1] == 0x03
                && protocolo[3] == 0xAA)
        {
                 /* faz  oque tem que fazer */       
                _U1RXIF = 0; /* Limpa flag */
        }
        else
        {
            for(auxiliar_protocolo = 0; auxiliar_protocolo <= 20; auxiliar_protocolo++) /*limpa vetor reseta auxiliar_protocolo*/
            {   protocolo[auxiliar_protocolo] = 0;  }
            auxiliar_protocolo = 0;
           _U1RXIF = 0; /* Limpa flag */
        }
    }
    else
    {         
        auxiliar_protocolo++;       
    }
     _U1RXIF = 0; /* Limpa flag */
}


Lendo no forum da microchip o manual de referencias do uC vi algumas coisas sobre limpar um bit de over run OERR mas ainda não estou muito esclarecido de seu funcionamento rs.

Desde já agradeço pela atenção :D .
Não é possível dormir com todas mulheres do mundo, mas deve-se fazer o esforço.
Avatar do usuário
Eduardo Augusto
Byte
 
Mensagens: 105
Registrado em: 03 Mar 2014 08:57
Localização: São Paulo, SP

Re: Pic 24f travamento no tratamento de interrupção serial.

Mensagempor xultz » 10 Jun 2014 09:41

Cara, eu estou mexendo com PIC24F mas não estou usando porta serial, então talvez o que eu diga esteja errado.
Mas pela minha experiência com outros PICs, acontece o travamento da porta serial se ela receber mais bytes do que você ler. Por exemplo, se você não fizer uma ISR prá tratar o recebimento, e receber mais bytes que o buffer da serial (nos PICs 16 e 18, esse buffer é de 1 ou 2 bytes), a serial trava, levanta o flag de OverRun, e só volta a funcionar se resetar a USART zerando e setando o bit de USART Enable.
Eu não entendi direito o teu problema, eu só fiquei preocupado com as "instruções": /* faz oque tem que fazer */
O ideal (no meu ponto de vista e sempre procuro trabalhar assim) é que a ISR da porta serial seja a mais simples possível, prá ser rápida: recebe o byte, e analisa o protocolo por meio de uma máquina de estados. Os blocos do tipo /* faz oque tem que fazer */ sempre ficam fora da ISR, e sabem que devem fazer algo por meio de flags que a ISR gera. desta forma, mesmo que chegue um byte enquanto o programa /* faz oque tem que fazer */, a ISR vai ler e tratar. O perigo é o código /* faz oque tem que fazer */ ser lento demais, e bytes chegarem durante esta execução e a ISR não tratar porque está ocupada fazendo outra coisa.
98% das vezes estou certo, e não estou nem aí pros outros 3%.
Avatar do usuário
xultz
Dword
 
Mensagens: 3001
Registrado em: 13 Out 2006 18:41
Localização: Curitiba

Re: Pic 24f travamento no tratamento de interrupção serial.

Mensagempor Eduardo Augusto » 10 Jun 2014 11:12

Xultz

Sobre a instrução /*faz oque tem que fazer*/ foi pra abreviar rs, mas em um caso é uma intrusção de envio de valores de ad de 32bits e em outro caso é concateção de valores e afins.

primeiro caso
Código: Selecionar todos

valor_ganho = 0x0F ^ protocolo[1];
valor_filtro  =  0xF0 ^ protocolo[1];

valor_calibracao = valor_calibracao | protocolo[3];
valor_calibracao = (valor_calibracao<<8)|protocolo[4];
valor_calibracao = (valor_calibracao<<8)|protocolo[5];
valor_calibracao = (valor_calibracao<<8)|protocolo[6];

valor_divisoes = valor_divisoes|protocolo[7];
valor_divisoes = (valor_divisoes << 8)|protocolo[8];


segundo caso
Código: Selecionar todos
unsigned char temp;
temp = valor_medio_ad >> 24;
envia_byte_UART1(temp);
temp = valor_medio_ad >> 16;
envia_byte_UART1(temp);
temp = valor_medio_ad >> 8;
envia_byte_UART1(temp);


Tomarei como nota sua forma de tratar a ISR da porta serial, de forma a simplicar com o utilização de flags. Deixando somente poucas instruções ali, visando diminuit o tempo da ISR.

quando você disse:

(...) se você não fizer uma ISR prá tratar o recebimento, e receber mais bytes que o buffer da serial (nos PICs 16 e 18, esse buffer é de 1 ou 2 bytes), a serial trava, levanta o flag de OverRun, e só volta a funcionar se resetar a USART zerando e setando o bit de USART Enable. (...)

Creio que meu problema mora ai... como posso ter certeza que este problema que você mencionou não esteja ocorrendo?
Em meu codigo estou lendo todos os bytes que vem da porta e os guardando em um buffer de 20 posições que é o tamanho do maior frame de dados... Pelo que você mencionou, e pelo que eu entendi, a não ser que enquanto eu esteja processando alguma informação dentro da ISR alguns bytes cheguem no buffer da porta serial e travam o periferico.. Seria isso??
Você pode explicar melhor, acho que não entendi legal isso :?: .
Minhas funçoes de enviar e receber bytes...
Código: Selecionar todos
void escreve_UART1(unsigned char Data)
{
    while ( U1STAbits.UTXBF);   
    U1TXREG = Data;
}

unsigned char recebe_byte_UART1(void)
{
     while (!U1STAbits.URXDA);   // verifica se RX esta ocupado
     return U1RXREG;    // retorna valor de rx
}



Na aplicação de alto nível estou dando times de 100ms a cada envio de request de dados...
Não sei se você ja trabalhou com o visual c++ no ponto de enviar bytes pela porta serial, mas por se tratar de plataforma .net é bem semelhante com visual basic ou visual c#, o metodo é meio chatinho, mas a solução que encotrei foi:

Código: Selecionar todos
auto data = gcnew array<Sytsem::Byte> { 0xAA, 0x03, 0xAA}; // cria um vetor de bytes chamado data
serialPort1->Write(data,0,data->Lenght); // envia data apartir de sua posição 0


Creio que em alto nível as coisas estejam funcionando bem, usei o hyperterminal, e esta ok... Os bytes são enviados conforme quero.

Agradeço pela atenção :D
Não é possível dormir com todas mulheres do mundo, mas deve-se fazer o esforço.
Avatar do usuário
Eduardo Augusto
Byte
 
Mensagens: 105
Registrado em: 03 Mar 2014 08:57
Localização: São Paulo, SP

Re: Pic 24f travamento no tratamento de interrupção serial.

Mensagempor ze2 » 10 Jun 2014 13:07

há anos não tenho contato serial mc<-->pc. o último foi num pic18f (que acho que só tem 2 níveis de prioridade) que acionava displays e leds multiplexadamente. fiz algo assim:

//setar bits de prioridades no mc... claro
#pragma interrupt_level 1
static void interrupt low_priority serial(void)
{
if (RCIF) {RCIF=0;rtx();}
}
e a rtx() fazia aguma coisa que não interessa agora. Agora permita-me levantar uma hipótese de como capturar num buffer de 20 bytes.

unsigned char dado[20],i=0;
void rtx(void)
{
dado[i]=RXREG;
i++;
if (i>19) i=0;
}
ou algo mais elegante com ponteiro que até hoje não entendo direito... uma oportunidade para aprender

note a ausência de while(xxx); que tente a prender o processamento tornando a continuidade do processamento dependente de interrupts. (o que pode estar acontecendo no seu caso)

uma estranha coincidência, neste exato momento estou tentando fazer um atmega16 capturar alguns bytes da serial e mostrar no display. talvez use o método supramencionado ... ou não
abç
ze2
Byte
 
Mensagens: 193
Registrado em: 09 Fev 2009 13:37

Re: Pic 24f travamento no tratamento de interrupção serial.

Mensagempor xultz » 10 Jun 2014 13:38

Primeiro, a função recebe_bytes não tem razão de existir. A questão é a seguinte, a menos que a USART do PIC24 seja muito alienígena (o que não duvido, eu me bati prá caramba prá guardar dados de configuração na flash porque essa droga não tem EEPROM), a interrupção de serial sempre é gerada quando um byte chega. Assim, na ISR não precisa verificar se chegou um novo byte, porque a int só é gerada porque o byte chegou. Então, ao entrar na ISR, lê o byte na cara e na coragem. Dentro da ISR, o ideal é não fazer whiles, muito menos whiles que ficam esperando e não fazem nada, como while (!U1STAbits.URXDA);. Esta instrução não está errada, teoricamente ela só é chamada quando um byte chegou pela ISR, então não travaria aí, mas é muito perigosa.
Se o problema que você está enfrentando é determinístico (ou seja, sempre ocorre quando você executa determinada ação), tenta ficar lendo o bit de Over run prá ver se ele levanta, e você terá certeza que o problema é este. No teu caso, um overrun só ocorre se o código da tua ISR é mais lento que o tempo de recebimento entre um byte e outro (e esse tempo é enorme, o código da ISR tem que ser muito ruim prá acontecer isso, a menos que teu programa esteja travado em outra ISR ruim).
98% das vezes estou certo, e não estou nem aí pros outros 3%.
Avatar do usuário
xultz
Dword
 
Mensagens: 3001
Registrado em: 13 Out 2006 18:41
Localização: Curitiba

Re: Pic 24f travamento no tratamento de interrupção serial.

Mensagempor Eduardo Augusto » 10 Jun 2014 17:04

Ze muito obrigado!

Xultz

Já sofri bastante também pra desenvolver a rotina de gravar na memória flash do benedito. É bem chatinha. Em um geral, migrar dos uC's pic16 e pic18 para o pic24 tem sido um com solavancos mas tem sido bem prazero e recompensante rs.

Consegui resolver meu problema depois de horas lendo esse material de referencia aqui

http://ww1.microchip.com/downloads/en/D ... 026583.pdf

No trecho de interrupção de recebeminto é bem detalhado, seguir a risca que funciona.
Agradeço pela ajuda!!!

Desde já agradeço pela atenção!!
Não é possível dormir com todas mulheres do mundo, mas deve-se fazer o esforço.
Avatar do usuário
Eduardo Augusto
Byte
 
Mensagens: 105
Registrado em: 03 Mar 2014 08:57
Localização: São Paulo, SP

Re: Pic 24f travamento no tratamento de interrupção serial.

Mensagempor andre_luis » 10 Jun 2014 20:05

Eduardo Augusto escreveu:...como estou trabalhando com interrupção de RX, fica fácil tratar os bytes que estou recebendo, no entanto estou notando que isto esta atrapalhando processamento de outras interrupções, como a de multiplexação de displays, SPI, e etc...


Como o xultz mencionou anteriormente, é altamente desaconselhável colocar qualquer outra coisa dentro do tratamento da interrução que não seja apenas setar um flag, ou carregar o valor de quem gerou essa interrução. No seu caso, vejo que é feito o envio de 3 Bytes pela UART, ou seja, no tratamento da Receção você está realizando uma Transmissão, conforme o trecho abaixo, onde inseri comentários:

cpp code
unsigned char temp;
temp = valor_medio_ad >> 24;
envia_byte_UART1(temp); // devido ao while nessa função, somente irá sair daqui após transmitido
temp = valor_medio_ad >> 16;
envia_byte_UART1(temp); // devido ao while nessa função, somente irá sair daqui após transmitido
temp = valor_medio_ad >> 8;
envia_byte_UART1(temp); // devido ao while nessa função, somente irá sair daqui após transmitido


Assumindo uma configuração padão de 8N1, para o caso de um BAUD de 9600, isso representaria ~1ms para cada envio, e são 3 dentro do seu vetor de interrução. Se ao invéz de você enviar esses bytes, mas apenas os bufferizar dentro de uma variável para enviar posteriormente dentro do main(), isso poderá acabar com o problema que você relatou.



+++
"Por maior que seja o buraco em que você se encontra, relaxe, porque ainda não há terra em cima."
Avatar do usuário
andre_luis
Dword
 
Mensagens: 5447
Registrado em: 11 Out 2006 18:27
Localização: Brasil - RJ


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x