Jump to content

Recommended Posts

Posted

Boas.

Estou com alguns problemas em configurar a USART na PIC18f2520, se alguém me conseguir ajudar agradecia,

O que eu pretendo fazer é o seguinte, ao clicar numa tecla do teclado, quero que essa mesma tecla seja impressa na porta série, para tal configurei a usart para receção e transmissão, o código que elaborei foi o seguinte:

void interrupt tempo()
{

        
    /*TMR0IF=0;
        
        if (RA0==1){ num='1';}
        else{ num='2';}*/
        
        
        
        
        if((TXIE==1)&&(TXIF==1)) {
       do{
                        TXREG=imprimir[carater++];
                        
                        
                }
                while((imprimir[carater]!=0));
                carater=0;                
    
        }
        if((RCIF==1)&&(RCIE==1)){
                vec[i] = RCREG;
                RCIF=0;
                
        }

}


void main()
{
        TRISA=0b00101111;
        TRISB=0b00001111;
        ADCON1=0b00001111;// Apenas o AN0 está definido como saída digital--> posteriormente deve-se mudar para anaçógica, para textar o ADCON
        TRISC6=0;        
        TRISC7=1;        
        
        //habilitar interrupções
        GIE=1;                
        IPEN=1;                
        GIEL=1;        
        
        // Configurar EUSART para transmissão
        
        TXEN=1;        
        SYNC=0;        
        BRGH=1;
        SPBRG=255;        //baud rate de 9.6k        
        SPEN=1;
        TXIP=1;                
        TXIE=1;
        
        // Configurar EUSART para receção
        
        CREN=1;
        RCIE=1;
        RCIP=1;
        RCIF=0;

        // Configurar timer 0
        
        TMR0ON=1;        
        T08BIT=0;                 
        TMR0IE=1;                
        TMR0IP=1;
        TMR0IF=0;         
        T0CS=0;                
        PSA=0;                
        T0PS2=1;                
        T0PS1=1;                
        T0PS0=1;
        
        
        while(1){
        
                sprintf(imprimir, "carater %c",vec[0]);   
        
        }
}

de vez  em quando aparece-me o carater correto na porta série, mas não sempre, não consigo perceber porquê:/ se alguém me conseguir ajudar agradecia.

Cumprimentos,

Fred Gomes.

Posted

Para começar, uns concelhos:

1. Evita aceder aos bits individuais nos registos durante a inicialização, em vez disso mete o valor no registo duma vez.

2. Activa periféricos apenas depois de totalmente configurados.

3. Activa as interrupções só depois dos periféricos que as vão gerar terem sido inicializados.

4. Inicializa totalmente todos os registos dos periféricos a usar; não dependas dos valores de 'POR'.

Quanto ao teu código abaixo, a que acrescentei comentários, tens um erro na rotina de interrupção; cada execução da rotina apenas pode gravar um byte no registo TXREG, pois ele não é um FIFO. Não podes fazer o ciclo para enviar a string toda de uma vez, tens de fazer :

if ((TXIE==1) && (TXIF==1))   // Se isto é uma interrupção de transmissão e estão activas
{
  if (imprimir[carater] != 0)
  {
    TXREG = imprimir[carater++];     // Copia o caracter em 'imprimir[carater]' para
                                     // o buffer de envio. Limpa o indicador de interrupção
  }  else 
    carater=0;                         // Quando acabar a string volta ao principio
}

Este código vai estar continuamente a enviar a string, mesmo que não haja nada a entrar pela porta série (onde presumo estar ligado o teclado). Seria preferível activares o envio apenas após receberes algo e desactivares quando a string fosse toda enviada. Outra coisa, cuidado com a variável 'i'; no teu código não está inicializada.

O teu código, comentado:

void interrupt tempo()
{
  if ((TXIE==1) && (TXIF==1))   // Se isto é uma interrupção de transmissão e estão activas
  {
    do
    {
      TXREG = imprimir[carater++];     // Copia o caracter em 'imprimir[carater]' para
                                       // o buffer de envio
    } while ((imprimir[carater]!=0));  // Repete até ao final (byte == 0) da string
    carater=0;                         // Quando acabar a string volta ao principio
  }
  if ((RCIF==1)&&(RCIE==1))    // Se isto é uma interrupção de recepção e estão activas
  {
    vec[i] = RCREG;  // Coloca em 'vec[i]' o valor recebido da porta série
    RCIF=0;          // Limpa o indicador de interrupção de recepção                 
  }
}


void main()
{
  TRISA=0b00101111; // RA{0,1,2,3,5} = In, RA{4,6,7} = Out
  TRISB=0b00001111; // RB{0,1,2,3} = In, RB{4,5,6,7} = Out
  ADCON1=0b00001111;// Vref = Interna, RA{0..7} = Analog in
  TRISC6=0;         // RC6 = Out
  TRISC7=1;         // RC7 = In
        
  // Habilitar interrupções
  GIE=1;            // Activa interrupções de alto nível
  IPEN=1;           // Usa dois níveis de interrupção
  GIEL=1;           // Activa interrupções de baixo nível
        
  // Configurar EUSART para transmissão
  TXEN=1;           // Activa transmissão
  SYNC=0;           // Modo asincrono
  BRGH=1;           // BRG em High Baud Rate
  SPBRG=255;        // Baud rate de 9.6KBd, a 40MHz        
  SPEN=1;           // Activa a porta série
  TXIP=1;           // Considera a interrupção de envio como alto nível
  TXIE=1;	    // Activa a interrupção de envio
        
  // Configurar EUSART para receção
  CREN=1;           // Activa recepção
  RCIE=1;           // Activa a interrupção de recepção
  RCIP=1;           // Considera a interrupção de recepção como alto nível
  RCIF=0;           // Limpa o indicador de recepção

  // Configurar timer 0
  TMR0ON=1;         // Activa o Timer0
  T08BIT=0;         // Timer0 com 16 bits
  TMR0IE=1;         // Activa a interrupção por Overflow
  TMR0IP=1;         // Considera a interrupção do Timer como alto nível
  TMR0IF=0;         // Limpa o indicador de Overflow
  T0CS=0;           // Clocking por CLKO, a 10MHz
  PSA=0;            // Clocking do Timer0 do prescaler
  T0PS2=1;          // Prescaler a 1/256
  T0PS1=1;                
  T0PS0=1;
        
  while(1)
  {
    // Coloca no buffer 'imprimir' o texto 'carater ' seguido do conteudo de vec[0]
    sprintf(imprimir, "carater %c",vec[0]);   
  }
}

Já agora, umas perguntas :

1. A frequência do 'clock' é mesmo 40 Mhz ? Se não fôr não estás a transmitir/receber a 9.6 KBd.

2. Se todas as interrupções são de alto nível, para que usas isso ?

3. Para que testas se as interrupções estão activas no ISR ? Se não estivessem não haveria a interrupção.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.