Receber dados pela usart pic

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Receber dados pela usart pic

Mensagempor daniel.sloczynski » 03 Ago 2011 11:36

segue o código:






#include <16F877.h>
#fuses XT,NOWDT,PUT,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock=4000000)

#include "stdio.h"
#include "LCD.c"



//=======================================configurações usart===========================================


char usart_rx, usart_tx, txreg, rcreg, spbrg;

struct rcsta_reg
{
int rx9d : 1;
int oerr : 1;
int ferr : 1;
int aden : 1;
int cren : 1;
int sren : 1;
int rx9 : 1;
int spen : 1;
} rcsta;

struct txsta_reg
{
int tx9d : 1;
int trmt : 1;
int brgh : 1;
int xxx : 1;
int sync : 1;
int txen : 1;
int tx9 : 1;
int csrc : 1;
} txsta;

// define os endereços das variáveis
#locate rcsta = 0x18
#locate txreg = 0x19
#locate rxreg = 0x1a
#locate txsta = 0x98
#locate spbrg = 0x99
#byte r_pir1 = 0x0c // define o registrador r_pir1
#bit flag_rc = r_pir1.5 // define o flag_rc







//=================================================FUNÇOES PARA CONTROLE DA UART===========================================================

void usart_inicializa ( int vel, boolean brgh )

{
txsta.brgh = brgh; // seleciona o modo do gerador de baud rate
spbrg = vel; // configura o gerador de baud rate

// configura os pinos da USART como entradas !!!!!


#if __device__ == 877
input (pin_c7);
input (pin_c6);
#endif





txsta.sync = 0; // seleciona o modo assíncrono
rcsta.spen = 1; // habilita a USART
txsta.tx9 = 0; // seleciona o modo de 8 bits
txsta.txen = 1; // ativa o transmissor da USART
rcsta.cren = 1; // modo de recepção contínua
}

void usart_transmite (char dado)
{
while (!txsta.trmt); // aguarda o buffer de transmissão esvaziar
txreg = dado; // coloca novo caractere para transmissão
}

char usart_recebe (void)
{
while (!flag_rc); // aguarda a recepção de caracteres
return rxreg; // retorna o caractere recebido
}





Agora o problema!!!!


Espero que alguém possa me ajudar.


Quando utilizo a funcão de recepção"usart_recebe" ela me retorna apenas o primeiro byte do telegrama, o restante é ignorado, sendo que o telegrama que eu mando é de 8 bytes.




O que pode ser?
daniel.sloczynski
Bit
 
Mensagens: 47
Registrado em: 28 Abr 2011 09:13

Mensagempor ze » 03 Ago 2011 15:34

ou eu sou meio burro ou seu sobrenome é impronunciável ou sua função libera só um byte mesmo uai. para receber um pacotinho voce deve estudar o odioso conceito de ponteiro, vetor e matriz em c. algo como:
(modo simplista. tem modo + profissional. portanto aguarde algum homônimo)
Código: Selecionar todos
char recebidos[8]
void usart_recebe (void)
{
char i;
while(i<8)
{
while (!flag_rc); // aguarda a recepção de caracteres
recebidos[i]=rxreg;
i++;
}
}
note que o pacote fica na variável global recebidos[]
pra evoluir ainda mais, o bão mêmo é receber via interrupt. mas aí tem que calejar as mão um pouco pois tem que estudar o hardw
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor andre_luis » 03 Ago 2011 19:01

Não vi referencia ao main() no código acima.
O problema pode estar nele, e não nas rotinas de comunicação, já que ao menos 1 byte recebeu.


+++
"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

Mensagempor daniel.sloczynski » 04 Ago 2011 08:18

Cara, testei o código que você me passou....


Se eu uso ele com o while de aguarda recepção de caracteres ele trava...



Tirando o while, recebe os dois primeiros bytes, os outros são preenchidos com o mesmo valor do segundo byte.


A função que eu uso para enviar:


void modbus_mestre_comando(unsigned char endereco,unsigned char comando,long int posicao,long int valor_tamanho)
{
unsigned char w, buf_485[8];


buf_485[0]=endereco;
buf_485[1]=comando;
buf_485[2]=posicao>>8;
buf_485[3]=posicao;
buf_485[4]=valor_tamanho>>8;
buf_485[5]=valor_tamanho;
Calculo_CRC(6 buf_485); //coloquei a quantidade-1,pois a contagem cálculo só os 6 primeiros bytes
buf_485[6]=CRC_bytes[0];
buf_485[7]=CRC_bytes[1];

for(w=0;w<=7;w++)
{
usart_transmite(buf_485[w]); //ENVIA BUFFER

}

}



Exemplo que eu mando:

modbus_mestre_comando(1,5,100,65280)

Em hexa isso seria: 01 05 00 64 FF 00 CD E5


O que o equipamento que eu mandei esse telegrama deveria me devolver seria os mesmo valores.

Mas só consegui ler os dois primeiros, ou seja, 01 e 05...
daniel.sloczynski
Bit
 
Mensagens: 47
Registrado em: 28 Abr 2011 09:13

Mensagempor ze » 04 Ago 2011 10:42

ah... a tradicional ausência de palavras mágicas... isso é notório neste mundinho virtual. procure pelo menos não esquece-las no real. enfim...

travar na função era previsível. voce pode implementar um timeout tipo
Código: Selecionar todos
timeout=0;
while ((!flag_rc)&&(timeout++<10000));

por isso que eu digo que usar interrupt pode ser mais proveitoso. algo do gênero:

Código: Selecionar todos
#define vazio 0
#define cheio 1
static bit buffer; //ou char se seu compilador não souber lidar com bits
char recebidos[8],i;

static void interrupt serial()
{
if (RCIF) //bit recebi byte: o mesmo do seu flag_rc com nomenclatura do datasheet - já viu ele?
recebidos[i]=RCREG; //registrador de byte recebido: o mesmo do seu rxreg com nomenclatura do datasheet - já viu ele?
i++;if (i>7) {buffer=cheio;i=RCIE=0;};//desabilita interr temporariamente
}


e no main()

Código: Selecionar todos
RCIE=1;//libere a interrupt
...
//no loop principal
...
if (buffer==cheio)
   {
   //use os dados recebidos[] do buffer
   i=buffer=vazio; //libera para nova recepção
   RCIE=1;//reabilita
   }
...

não nunca usei isto. digitei tudo na intuição. portanto... já sabe. pode haver modo melhor
abç
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor daniel.sloczynski » 05 Ago 2011 09:27

Feedback pra galera...


Funfou!!!

Tive que dar uns ajustes, mas tá recebendo legal agora.

Obrigado :)



Abraço!
daniel.sloczynski
Bit
 
Mensagens: 47
Registrado em: 28 Abr 2011 09:13


Voltar para PIC

Quem está online

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

x