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 post
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 post
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 post
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 post
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 post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

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...

Os Mitos do Dinheiro

APENAS R$ 9,90!

CLIQUE AQUI E COMPRE AGORA MESMO!