Estou tentando desenvolver um protocolo de troca de pacotes por serial que garanta a chegada e a integridade dos pacotes, além da ordenação.
O problema que tenho é que a Serial do dsPIC fica mandando lixo mesmo que eu não escreva nada para o registrador U1TXREG! As mensagens ele envia bem, o problema é que ele não para de mandar lixo. Já comentei todas as linhas do meu código que colocavam algum dado em U1TXREG, mas continuam aparecendo os dados aleatórios no terminal. Não faço mais idéia do que pode ser.
Segue o código que estou desenvolvendo:
comunicacao.c
- Código: Selecionar todos
//============================================================================\\
// Rotinas de Comunicação \\
// Ultima Modificação 05/08/2012 - 11:47 \\
// Por : Emilio Eduardo \\
//============================================================================\\
#include <built_in.h>
#include "comunicacao.h"
//Variáveis de controle de comunicação
unsigned int com_pacotesperdidos; //Numero de pacotes perdidos
unsigned int com_pacotesenviados; //Numero de pacotes enviados -> Sem pacotes de ACK
unsigned int com_pacotesrecebidos; //Numero de pacotes recebidos -> Sem pacotes de ACK
char com_pacotes[COM_TAMBUFFER][COM_TAMARGUMENTOS + COM_TAMPACOTE]; //Fila de pacotes a serem enviados
char com_pacoterecebido[COM_TAMARGUMENTOS + COM_TAMPACOTE];
unsigned short com_iniciofila; //Marca o primeiro pacote da fila
unsigned short com_fimfila; //Marca o último pacote da fila
char* com_byteenviado; //Indica último byte enviado pela interrupcao
char com_pacote_ack[COM_TAMPACOTE + 2]; //Pacote de acknowledgement a ser enviado
bit com_enviandoack; //Indica que está enviando ACK
bit com_aguardandoack; //Indica que não está enviando pacotes pois está aguardando ACK
bit com_ack; //Indica a presença de pacote ack
bit com_enviando; //Indica se a interrupção está correndo
bit com_recebendo;
char com_bufferrecebimento[COM_TAMARGUMENTOS + COM_TAMPACOTE]; //Pacote Recebido
unsigned short com_tamanhorecebido;
char* com_byterecebido;
unsigned short com_ultimopacoterecebido; //Marca o código do último pacote recebido para evitar duplo recebimento
unsigned short com_ultimopacoteadicionado; //Marca o código do último pacote adicionado para saber a numeração
unsigned short com_ultimopacoteenviado;
bit f_com_pacoterecebido;
#define COM_FILACHEIA() ((com_fimfila + 1==com_iniciofila) || (com_fimfila+1==COM_TAMBUFFER && com_iniciofila == 0))
#define COM_FILAVAZIA() (com_fimfila == com_iniciofila)
void com_LigaTimeOut(){ //Inicia o contador do TimeOut
TMR1 = 0; //Reinicia Timer
T1CON.TON = 1; //Liga Timer
com_aguardandoack = 1;
}
void com_EnviaPrimeiroByteACK(){ //Inicia o envio do primeiro byte ACK
com_ack = 0; //Já comecei a enviar o ack
com_enviandoack = 1;
com_enviando = 1;
com_byteenviado = &com_pacote_ack[0]; //Se sim, envia primeiro byte
U1TXREG = *com_byteenviado;
}
void com_EnviaPrimeiroBytedaFila(){ //Inicia o envio do primeiro byte da fila
com_enviando = 1; //E sinaliza
com_byteenviado = &com_pacotes[com_iniciofila][0]; //Envia o primeiro byte
U1TXREG = *com_byteenviado;
}
void com_AvancaInicioFila(){ //Adianta o indicador de inicio da fila
com_iniciofila++;
if(com_iniciofila == COM_TAMBUFFER) com_iniciofila = 0;
}
void com_AvancaFimFila(){ //Adianta o indicador de fim da fila
com_fimfila++;
if(com_fimfila == COM_TAMBUFFER) com_fimfila = 0;
}
unsigned int func_CRC16(char *ptr, unsigned short crc16_tamanho){ //Calcula o CRC16 da mensagem
unsigned short i,j;
unsigned int acc;
unsigned int tmp;
acc = 0xFFFF;
for (i=0; i<crc16_tamanho; i++)
{
acc = acc ^ *(ptr++);
for (j=1; j<= 8; j++)
{
tmp = acc & 0x0001;
acc = acc >> 1;
if (tmp == 1) acc = acc ^ 0xA001;
}
}
return acc;
}
// Interrupção de Recepção
void USART1RXInt() iv IVT_ADDR_U1RXINTERRUPT{
char i; //Contador auxiliar
char com_temp; //Variável que guarda dado recebido
char com_codigomsg; //Variável auxiliar para codigo da mensagem
unsigned int com_CRC, com_CRC2; //Variável auxiliar para CRC
com_temp = U1RXREG; //Le valor recebido
if(com_temp == COM_KEY_PRE || com_temp == COM_KEY_PREACK){ //Se for um ínicio de pacote, inicia contagem
com_byterecebido = &com_bufferrecebimento[0]; //Iniciando o ponteiro de recebimento
*com_byterecebido = com_temp; //Coloca na primeira posição o preâmbulo
com_tamanhorecebido = 1; //Reinicia a contagem
com_recebendo = 1; //Indica que está no meio de um pacote
}else if(com_recebendo && com_tamanhorecebido < (COM_TAMARGUMENTOS + COM_TAMPACOTE - 1)){ //Se já está recebendo e ainda tem espaço no buffer
if(com_temp == COM_KEY_FIM){ //Se recebeu um sinalizador de fim de mensagem
com_recebendo = 0; //Indica que o pacote terminou
com_tamanhorecebido++; //Atualiza a contagem
*++com_byterecebido = com_temp; //Coloca na posição correspondente
com_byterecebido = &com_bufferrecebimento[0]; //Volta ao início para percorrer novamente o vetor para verificar
Lo(com_CRC) = com_bufferrecebimento[com_tamanhorecebido-5] | (com_bufferrecebimento[com_tamanhorecebido-4] << 4); //Traduz o CRC recebido para a variável
Hi(com_CRC) = com_bufferrecebimento[com_tamanhorecebido-3] | (com_bufferrecebimento[com_tamanhorecebido-2] << 4);
com_CRC2 = func_CRC16(com_byterecebido,com_tamanhorecebido - 5); //Calcula CRC dos dados recebidos
if(com_CRC2 == com_CRC || 1){ //Se a mensagem não está corrompida, ótimo, se não descartar
if(((*(++com_byterecebido)) == 0) && ((*(++com_byterecebido)) == 0) && ((*(++com_byterecebido)) == 0) && ((*(++com_byterecebido++)) == 0)){ //Checa se possui Porta e Código de mensagem de ACK = "0000"
com_codigomsg = *++com_byterecebido | (*++com_byterecebido << 4); //Se tiver, copia o argumento pois este é o código da mensagem que foi transmitida com sucesso
if(com_codigomsg == com_ultimopacoteenviado){ //Se este código for o do último pacote enviado, quer dizer que o ACK corresponde à ultima mensagem transmitida.
com_aguardandoack = 0; //Então não é mais necessário aguardar pelo ACK
com_AvancaInicioFila(); //Devemos retirar a mensagem enviada com sucesso da fila
if((!com_enviando) && !COM_FILAVAZIA()){ //Se ainda houver mensagem a ser transmitida e as interrupções de envio não estiverem rodando
com_EnviaPrimeiroBytedaFila();
}
}
}
else{ //Se não for uma mensagem de ACK
for(i=0 ; i < com_tamanhorecebido ; i++){ //Copia o pacote recebido para a caixa de recebimento
com_pacoterecebido[i] = com_bufferrecebimento[i];
}
f_com_pacoterecebido = 1; //Indica que há pacote na caixa
if(com_bufferrecebimento[0] == 128){ //Se o pacote recebido precisa de ACK, devolve ACK
//A partir daqui envia-se o ACK do pacote recebido
com_pacote_ack[5] = com_bufferrecebimento[1]; //Coloca o código do pacote recebido no buffer deACK
com_pacote_ack[6] = com_bufferrecebimento[2];
com_CRC = func_CRC16(com_byterecebido,7); //Calcula-se o CRC do pacote a ser enviado
com_pacote_ack[7] = (Lo(com_CRC) & 0b00001111); //Adicionando o CRC ao pacote
com_pacote_ack[8] = (Lo(com_CRC) >> 4) & 0b00001111;
com_pacote_ack[9] = (Hi(com_CRC) & 0b00001111);
com_pacote_ack[10] = (Hi(com_CRC) >> 4) & 0b00001111;
com_ack = 1; //Indicando que existe ACK a ser enviado.
if(!com_enviando){
com_EnviaPrimeiroByteACK();
}
}
}
}
}
else{ //Se não é um sinal de fim, continua copiando
*++com_byterecebido = com_temp;
com_tamanhorecebido++;
}
}else{ //Se está cheio ou não recebendo
com_recebendo = 0; //Para de receber e espera um caracter de início
}
U1RXIF_bit = 0; //Reseta flag da interrupção
}
//Interrupção de Transmissão
void USART1TXInt() iv IVT_ADDR_U1TXINTERRUPT{
if(*com_byteenviado == COM_KEY_FIM){ //O último byte enviado foi um byte de final?
if(com_enviandoack){
if(!COM_FILAVAZIA() && !com_aguardandoack){ //Se a fila não está vazia e não está aguardando ack
com_EnviaPrimeiroBytedaFila();
}else{
com_enviando = 0; //Se a fila está vazia ou aguardando ack, parei as interrupções
}
com_enviandoack = 0; //Terminei de enviar ack
}
else{
if(com_ack){ //Tem ack para enviar?
com_EnviaPrimeiroByteACK();
if(com_pacotes[com_iniciofila][0] == COM_KEY_PREACK){ //Se o pacote enviado precisa de ack, ligar timeout e sinalizar
com_LigaTimeOut();
com_ultimopacoteenviado = com_pacotes[com_iniciofila][1] | (com_pacotes[com_iniciofila][2] << 4);
com_aguardandoack = 1;
}
}else{
if(com_pacotes[com_iniciofila][0] == COM_KEY_PREACK){ //Se o pacote enviado precisa de ack, ligar timeout e sinalizar
com_LigaTimeOut();
com_ultimopacoteenviado = com_pacotes[com_iniciofila][1] | (com_pacotes[com_iniciofila][2] << 4);
com_aguardandoack = 1;
com_enviando = 0;
}else{
com_AvancaInicioFila(); //Avança o Pacote
if(!COM_FILAVAZIA()){
com_EnviaPrimeiroBytedaFila(); //Envia o primeiro byte do próximo pacote
}
else{
com_enviando = 0;
}
}
}
}
}
else{
U1TXREG = *++com_byteenviado; //Se o último byte não foi de final, manda o próximo
}
U1TXIF_bit = 0; //Apagando flag de interrupção
}
// Interrupção de Timeout
void Timer1Int() iv IVT_ADDR_T1INTERRUPT{
com_aguardandoack = 0; //Não estou mais aguardando ack, quero enviar novamente
if(com_pacotesperdidos != 65535){ //Se não chegou ao máximo, somar mais um pacote perdido
com_pacotesperdidos++;
}
if(!com_enviando){ //Se não for enviar automaticamente, enviar primeiro byte
//com_EnviaPrimeiroBytedaFila();
}
T1CON.TON = 0; //Desliga Timeout
T1IF_bit = 0; //Apaga flag de interrupção
}
// Configuração de Timeout
void com_ConfiguraTimeOut(){
IPC0 = IPC0 | 0x1000; //Timer1 Prioridade= 1
PR1 = COM_TIMEOUT;
T1IF_bit = 0;
T1IE_bit = 1; //Timer 1 Enabled Interrupt
T1CON = 0x8020; //Timer 1 Prescaler = 64;
}
// Configura Serial
void com_ConfiguraUsart1(){
//Configuração USART1
//U1MODE
U1MODEbits.UEN = 0; //TX, RX Ativados, CTS e RTS Desativados
//U1MODEbits.USIDL = 0; //Continuar em IDLE
//U1MODEbits.IREN = 0; //Não é IR
U1MODEbits.RTSMD = 0; //Modo Simplex
//U1MODEbits.WAKE = 0; //Não Acorda
//U1MODEbits.LPBACK = 0; //Sem LoopBack
U1MODEbits.ABAUD = 0; //Desativando Auto-Baud
//U1MODEbits.URXINV = 0; //Estado-Padrão = 1
U1MODEbits.BRGH = 1; //Modo de Alta Velocidade
U1MODEbits.STSEL = 0; //Stop bits = 1
U1MODEbits.PDSEL = 0; //Sem Paridade, 8 bits de dados
U1BRG = BRGVAL; //Configurando Baud-Rate
//U1STA
U1STAbits.UTXISEL1 = 0; //Interrupção a cada Char
U1STAbits.UTXISEL0 = 0;
//U1STAbits.UTXINV = 0; //Estado-Padrão = 1
//U1STAbits.UTXBRK = 0;
U1STAbits.URXISEL = 0b00; //Interrupção a cada Caracter Recebido
//U1STAbits.ADDEN = 0; //Endereços desativados
U1RXIE_bit = 1; //Ativando Interrupção RX
U1RXIF_bit = 0; //Limpando Interrupção RX
U1TXIE_bit = 1; //Ativando Interrupção TX
U1TXIF_bit = 0; //Limpando Interrupção TX
IPC2bits.U1RXIP = 1; //Prioridade RX UART = 1
U1MODEbits.UARTEN = 1; //Ativando UART
U1STAbits.UTXEN = 1; //Ativando Transmissão
}
void com_ConfiguraComunicacao(){ //Inicia as Variáveis e configura o TimeOut e a Usart1
char* ptr;
com_iniciofila = 0;
com_fimfila = 0;
com_ultimopacoterecebido = 1;
com_ultimopacoteadicionado = 1;
com_ultimopacoteenviado = 1;
com_ack = 0;
com_enviandoack = 0;
com_aguardandoack = 0;
com_enviando = 0;
com_recebendo = 0;
com_pacotesperdidos = 0;
ptr = &com_pacote_ack[0];
*ptr++ = COM_KEY_PRE;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
*ptr = COM_KEY_FIM;
com_ConfiguraUsart1();
com_ConfiguraTimeOut();
}
//Adiciona pacote à fila
int com_EnviaPacote(unsigned short com_comando, char com_argumentos[COM_TAMARGUMENTOS], unsigned short com_tamanhoargumentos, char com_recebeack){
char *ptr; //Ponteiro que percorre o pacote
char *ptr2; //Ponteiro auxiliar
unsigned short i; //Contador auxiliar
unsigned int com_crc; //Variável auxiliar
if(!COM_FILACHEIA()){ //Se a fila não está cheia
ptr = &com_pacotes[com_fimfila][0]; //Ponteiro recebe endereço do lugar a ser populado da fila
if(com_recebeack){
*(ptr++) = COM_KEY_PREACK; //Se o pacote precisa de ack, usa o preambulo com ACK
}
else{
*(ptr++) = COM_KEY_PRE; //Se não, usa sem
}
com_ultimopacoteadicionado++; //Qual o código deste pacote?
if(com_ultimopacoteadicionado == 255){ //Se chegou ao fim, volta para o começo. O importante é não repetir muito perto
com_ultimopacoteadicionado = 1;
}
*(ptr++) = (com_ultimopacoteadicionado & 0b00001111); //Adicionando o código ao pacote
*(ptr++) = (com_ultimopacoteadicionado >> 4) & 0b00001111;
*(ptr++) = (com_comando & 0b00001111); //Adicionando o comando ao pacote
*(ptr++) = (com_comando >> 4) & 0b00001111;
ptr2 = &com_argumentos[0]; //Percorrer os argumentos
for(i=0;i<com_tamanhoargumentos;i++){
*(ptr++) = *(ptr2++); //Para adicioná-los ao pacote
}
ptr2 = &com_pacotes[com_fimfila][0]; //Encontrar o começo do pacote
com_CRC = func_CRC16(ptr2, COM_TAMPACOTE - 5 + com_tamanhoargumentos); //Para passá-lo à função CRC
*(ptr++) = (Lo(com_CRC) & 0b00001111); //Adicionando o checksum ao pacote
*(ptr++) = (Lo(com_CRC) >> 4) & 0b00001111;
*(ptr++) = (Hi(com_CRC) & 0b00001111);
*(ptr++) = (Hi(com_CRC) >> 4) & 0b00001111;
*ptr = COM_KEY_FIM; //Adicionando caractere de fim
com_AvancaFimFila(); //Mensagem carregada, aumentando a fila
if(!com_enviando){ //Se ainda não está rodando as interrupções
com_EnviaPrimeiroBytedaFila();
}
return 0; //Retorna que tudo correu bem
}else{
return 1; //Retorna que a fila está cheia
}
}
comunicacao.h:
- Código: Selecionar todos
//============================================================================\\
// Declaracoes de Comunicação \\
// Ultima Modificação 05/08/2012 - 11:47 \\
// Por : Emilio Eduardo \\
//============================================================================\\
#ifndef INC_COMUNICACAO_H
#define INC_COMUNICACAO_H
#define FCY 39613750
#define BAUDRATE 57600
#define BRGVAL ((FCY/BAUDRATE)/4)-1
#define COM_TAMBUFFER 20
#define COM_TAMARGUMENTOS 32
#define COM_TAMPACOTE 10
#define COM_KEY_PREACK 128
#define COM_KEY_PRE 129
#define COM_KEY_FIM 130
#define COM_TIMEOUT 65500
#define COM_MAXTENTATIVAS 5
void com_ConfiguraComunicacao();
//Coloca na fila pacote genérico, com comando e argumentos.
int com_EnviaPacote(unsigned short com_comando, char com_argumentos[COM_TAMARGUMENTOS],unsigned short com_tamanhoargumentos, char com_recebeack);
#endif /*INC_COMUNICACAO_H*/
Espero que alguém saiba por que ele fica enviando lixo pela usart.
Abraços e Obrigado