Ir ao conteúdo
  • Cadastre-se

Ajuda com Interrupção Serial com PIC


Posts recomendados

E ai Pessoal beleza.

Estou com um problema aqui tenho que fazer um programa para comunicar serial mente com um PC porém meu problema e que so posso enviar os valores via serial quando o programa no PC enviar uma pergunta ou seja por exemplo o programa do PC envia o valor 1 e o microcontrolador envia os valores coletados dos sensores exemplo printf("%lu,%lu,%f,%f"x,y,z,a) e depois para de enviar e fica aguardando novamente o valor um do PC e problema e que o o pic tem um programa que fica lendo e controlando a vazão de um fluido e os dados do mesmo são enviados para o PC e não posso ficar com a interrupção ativa.

Fiz um programa para testar a interrupção e ele fica sempre passando pela interrupçaõ apos eu enviar o valor pela serial para que o pic responda.

O programa esta abaixo e peço a ajuda de você para resolver este problema.

Programa de Teste


#include<16f877A.h> // modelo do microcontrolador
#use delay(clock=4000000) //configura clock para 4Mhz
#fuses HS,NOLVP,NOWDT,BROWNOUT,NOPUT,NODEBUG,NOPROTECT,NOWRT,NOCPD //configura fusiveis da MCU
#include<mod_lcd.c>
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) //configura rs232
#include <input.c>
int cont=0;
void main()
{

setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(int_rda);
enable_interrupts(global);

lcd_ini();

while (1)//aqui fica rodando
{
enable_interrupts(global);
printf(lcd_escreve"Display=%i\n\r"cont);
output_high(pin_b0);
delay_ms(400);
lcd_escreve('\f');
output_low(pin_b0);
cont++;
if(cont==125)
cont=0;
}
}

#int_rda
void recebe_serial()
{
printf("%i"cont);
output_high(pin_b1);
}

Link para o comentário
Compartilhar em outros sites

Martins eu tive o mesmo problema, e de tanto tentar usar interrupções desisti e consegui fazer sem... Vou descrever mais ou menos como fiz

Declarei esta variável de escopo global, para receber, só consegui sendo do tipo char, e recebendo um caracter por vez.

char xx[1]=0;

Criei um função fora do Main, antes dele.

Void Receber_RS232() //Função para comunicação com o PC

{

if (kbhit())

{

gets(xx,1);

}

}

E dentro do main mais precisamente, dentro do loop infinito faço uma chamada a função:

Receber_rs232();

Ele testa se tem alguma coisa pra receber, caso positivo joga na variável xx o caracter recebido pelo pic. Como a variável é de escopo global, posso utilizá-la em qualquer ponto do programa para testa-la.

Obs. Ainda não criei a rotina para receber uma string inteira, mas para minha aplicação é necesário apenas de 0 a 9, e neste caso ele recebe o abc completo.

Ah... ainda para facilitar os testes você pode converter a variável xx para valores inteiros, mas só funciona de 0 a 9.

SE = atol(xx);

SE é uma variável inteiro de 8 bits, mas é necessário estar marcado a biblioteca:

#include "stdlib.h"

Conheço pouco e a pouco tempo sobre PIC, mas no meu caso funcionou.

Link para o comentário
Compartilhar em outros sites

Olá Martins e CeDahmer.

Também tive problemas com a interrupção serial (#INT_RDA) no CCS.

Até que um dia, todo problema virou alegria com uma dica de um amigo.

A dica é sempre verificar se há erro de comunicação serial. Segue abaixo o código

#include<16f877A.h> // modelo do microcontrolador

#use delay(clock=4000000) //configura clock para 4Mhz

#fuses HS,NOLVP,NOWDT,BROWNOUT,NOPUT,NODEBUG,NOPROTECT,NOWRT,NOCPD //configura fusiveis da MCU

#include<mod_lcd.c>

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) //configura rs232

#include <input.c>

int cont=0;

void main()

{

setup_comparator(NC_NC_NC_NC);

setup_vref(FALSE);

enable_interrupts(int_rda);

enable_interrupts(global);

lcd_ini();

while (1)//aqui fica rodando

{

enable_interrupts(global);

printf(lcd_escreve"Display=%i\n\r"cont);

output_high(pin_b0);

delay_ms(400);

lcd_escreve('\f');

output_low(pin_b0);

cont++;

if(cont==125)

cont=0;

}

}

#int_rda

void recebe_serial()

{

printf("%i"cont);

output_high(pin_b1);

if (OERR || FERR) // Tratamento de Erro RS232

{

RestartRS232 (); //Rotina que reinicializa a porta

}

}

// Reinicializa a porta RS232

void RestartRS232 (void)

{

SPEN = 1;

CREN = 0;

delay_us (1);

CREN = 1;

delay_us (1);

return;

}

Vejam aí se há alguma melhoria na estabilidade dos seus programas.

Link para o comentário
Compartilhar em outros sites

  • 2 anos depois...
  • 3 meses depois...

Bom dia Galera, sou novo por aqui e necessito da ajuda de vocês para resolver um problema com comunicação serial.

Estou usando um 16F887 para receber uma informação via serial, porém o programa fica preso na interrupção serial ( int_rda ),mesmo que eu não envie nenhum comando, e não executa as instruções que esta dentro do While.

Aguardo ajuda obrigado.

Segue o código

#include <16F887.h> 
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO // habilitando o clock interno
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES NOBROWNOUT //No Reset when brownout detected
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOLVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NODEBUG //No Debug mode for ICD
#use delay(clock = 8000000)
#use rs232(baud=9600, uart, bits=8, Parity=N, Stop=1)

//******************************************************************************
//
// Declarações de Hardware
//
//******************************************************************************

#define led_1 PIN_A0
#define led_2 PIN_A1
#define led_3 PIN_A2
#define led_4 PIN_A3
#define led_5 PIN_A4
#define led_6 PIN_A5

#define led_7 PIN_E0
#define led_8 PIN_E1
#define led_9 PIN_E2

#define led_10 PIN_C0

#define botao_1 PIN_C1
#define botao_2 PIN_C2
#define bota0_3 PIN_C3
#define botao_4 PIN_D0


#use fast_io(A)
#use fast_io(
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)


//******************************************************************************
//
// Variáveis do Sistema
//
//******************************************************************************
unsigned char IMG[7]={0xAA, 0xD0, 0xcc, 0x33, 0xc3, 0x3c};
unsigned char str1[4];

//******************************************************************************
//
// decalração de funções do Sistema
//
//******************************************************************************
// Enviar um comando
void send_str(unsigned char *p, unsigned char s)
{
unsigned char m;
for(m=0; m<s; m++)
{putc(*p);
p++;}
}

// Receber um comando
void receber(){

int8 k;
str1[0]=getchar();
while(str1[0]!= 0xAA){
str1[0]=getchar();}
for(k=1;k<8;k++)
{str1[k]=getchar();}
str1[0]=0x00;

}

//******************************************************************************
//
// Funções de Controle de Interrupções
//
//******************************************************************************

#int_RDA
RDA_isr(){

disable_interrupts(INT_RDA);

receber();

if(str1[3] == 0x01){
delay_ms(200);
output_toggle(led_1);}

if(str1[3] == 0x02){
delay_ms(200);
output_toggle(led_2);}

if(str1[3] == 0x03){
delay_ms(200);
output_toggle(led_3);}

if(str1[3] == 0x04){
delay_ms(200);
output_toggle(led_4);}

enable_interrupts(INT_RDA);
}

//******************************************************************************
//
// Função Main()
//
//******************************************************************************

void main( void )
{
int k = 0;

set_tris_a(0b00000000);
set_tris_b(0b00000000);
set_tris_c(0b00001110);
set_tris_d(0b00000001);
set_tris_e(0b00000000);


setup_adc_ports(NO_ANALOGS|VSS_VDD); // desabilita todas as portas analógicas
setup_adc(ADC_OFF); // desabilita todos os comparadores
setup_spi(FALSE); // desabilita cominicação spi
// frequencia interna do pic é a frequencia do oscilador externo dividido por 4
setup_timer_0( RTCC_INTERNAL | RTCC_DIV_64 );// frequncia do clock dividida por 64
setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // frequencia do clock 1M dividido por 1 para timer 1
setup_timer_2( T2_DIV_BY_4, 0x65, 1 ); // frequencia do clock 1M divido por 1
enable_interrupts( INT_TIMER0 ); // habilita as interrupções geradas pelo timer0
enable_interrupts( INT_TIMER1 ); // habilita as interrupções geradas pelo timer1
enable_interrupts( GLOBAL ); // habilita as interrupções geradas pelo global
enable_interrupts( INT_RDA ); // habilita as interrupções geradas pelo global
// setup_ccp1( CCP_PWM ); // configura ccp1 ( pino c2 como pwm )
// setup_ccp2( CCP_PWM ); // configura ccp2 ( pino c1 como pwm )
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
setup_oscillator(OSC_8MHZ);
// set_pwm1_duty(0); // configura percentual do ciclo ativo do pwm
// set_pwm2_duty(0); // configura percentual do ciclo ativo do pwm

output_low(led_1);
output_low(led_2);
output_low(led_3);
output_low(led_4);
output_low(led_5);
output_low(led_6);
output_low(led_7);
output_low(led_8);
output_low(led_9);


while( true ){ // laço principal laço principal

output_high(led_5);
delay_ms(100);
output_low(led_5);

output_high(led_6);
delay_ms(100);
output_low(led_6);

output_high(led_7);
delay_ms(100);
output_low(led_7);

output_high(led_8);
delay_ms(100);
output_low(led_8);


//! output_toggle(pin_d4); //moitorando chegada de dados

}// fim do laço while
}// fim da função main

Link para o comentário
Compartilhar em outros sites

  • 4 anos depois...

 

08/09/2017

 

Simplificando o exemplo acima para RESET em caso de travamento na recepção de dados pela porta SERIAL.

// COMPILADOR CCS

 

 

 

// Declare estes registradores no inicio no código ==============

// Atenção!!!: o endereço 0xFAB é do registrador RCSTA, no caso abaixo este endereço é para o PIC18F452
// você deve verificar o endereço de acordo com o PIC que você estiver utilizando.Ex: pic16F628A o end. é: 0X18

#bit  SPEN=0XFAB.7
#bit  CREN=0XFAB.4
#bit  FERR=0XFAB.2
#bit  OERR=0XFAB.1

//===================================================


// Reinicializa a porta RS232
void RestartRS232() // Rotina de verificação de erro, chame ela no inicio da função de interrupção:  Veja exemplo abaixo.
{
   if (OERR || FERR) // Tratamento de Erro RS232  
   {                 // Reseta/Limpa erros na usart de recepção
      SPEN = 1;
      CREN = 0;
      delay_us (1);
      CREN = 1;
      delay_us (1); 
   }
}

 

#int_RDA
void  RDA_isr(void)  
{

        RestartRS232(); // Verifica erros de travamento

        //...
        //...

       // seu codigo

}

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!