Fred Gomes Posted April 14, 2012 at 11:01 AM Report #449131 Posted April 14, 2012 at 11:01 AM 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.
bsccara Posted April 14, 2012 at 02:53 PM Report #449167 Posted April 14, 2012 at 02:53 PM 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.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now