Tengo PIC16F628A que estoy tratando de leer desde UART. Sin interrupciones, lee bien los primeros 3 bytes pero alcanza un OERR. Para combatir esto, pensé que una interrupción sería buena y cargar los bytes recibidos en una variable de búfer que podría leerse más tarde (búfer de anillo de tipo char de matriz). Pero la interrupción no se activa y me he quedado sin ideas.
CMCON = 0x07; //16F627/8 spcial function reg (RAx is port)
CCP1CON = 0b00000000; //Capt/Comp/PWM off
OPTION_REG = 0b00000000;
T1CON = 0;
INTCON = 0;
PIR1 = 0;
GIE = 0;
PIE1 = 0;
BRGH = 1; /* high baud rate */
SPBRG = 19200; /* set the baud rate */
SYNC = 0; //Async
TXEN = 0; //Disable transmit
TXIE = 0; //Disable transmit interrupt
RCIE = 1; //Enable Receive interrupt
SPEN = 1; //Enable serial pins
CREN = 1; //Enable continuous receive
SREN = 0;
TX9 = ninebits?1:0; /* 8- or 9-bit transmission */
RX9 = ninebits?1:0; /* 8- or 9-bit reception */
PEIE = 1; //Enable external interrupt
GIE = 1; //Enable global interrupt
He simplificado mi interrupción para encender una luz:
extern interrupt isr(void)
{
RB5 = 1;
}
Pero no es desencadenante. El proyecto está leyendo un escáner de código de barras en serie y procesando el código de barras. ¿Alguien puede ofrecer alguna ayuda?
EDITAR
Bueno, ya que parece que no entiendes. Voy a publicar las rutinas reales:
void initialize()
{
CMCON = 0x07; //16F627/8 spcial function reg (RAx is port)
CCP1CON = 0b00000000; //Capt/Comp/PWM off
OPTION_REG = 0b00000000;
T1CON = 0;
INTCON = 0;
PIR1 = 0;
GIE = 0;
PEIE = 0;
PIE1 = 0;
sci_Init(BAUDRATE ,SCI_EIGHT);// Baud set and Bit set
TMR0 = 1000;
T0IE = 0;
PEIE = 1; //Enable external interrupt
GIE = 1; //Enable global interrupt
//Set inputs to input
SetButtons();
//Set relays to output
SetRelays();
TRISB5 = 0;
LEDStatus = 0;
}
unsigned char sci_Init(unsigned long int baud, unsigned char ninebits)
{
int X;
unsigned long tmp;
/* calculate and set baud rate register */
/* for asynchronous mode */
tmp = 16UL * baud;
X = (int)(FOSC/tmp) - 1;
if((X>255) || (X<0))
{
tmp = 64UL * baud;
X = (int)(FOSC/tmp) - 1;
if((X>255) || (X<0))
{
return 1; /* panic - baud rate unobtainable */
}
else
BRGH = 0; /* low baud rate */
}
else
BRGH = 1; /* high baud rate */
SPBRG = X; /* set the baud rate */
SYNC = 0; //Async
TXEN = 0; //Disable transmit
TXIE = 0; //Disable transmit interrupt
RCIE = 1; //Enable Receive interrupt
SPEN = 1; //Enable serial pins
CREN = 1; //Enable continuous receive
SREN = 0;
TX9 = ninebits?1:0; /* 8- or 9-bit transmission */
RX9 = ninebits?1:0; /* 8- or 9-bit reception */
rxBuffIndex = 0;
rxBuffRead = 0;
return 1;
}
void sci_LoadBuffer(void)
{
rxBuffer[rxBuffIndex] = RCREG;
rxBuffIndex = ++rxBuffIndex % MAXBUFFER;
}
unsigned char sci_ReadBuffer()
{
unsigned char byte;
do
{
byte = rxBuffer[rxBuffRead];
}while( byte == 0 ); //Block until valid data
rxBuffer[rxBuffRead] = 0;
rxBuffRead = (++rxBuffRead) % MAXBUFFER;
return byte;
}
void interrupt isr(void)
{
if(RCIF) sci_LoadBuffer();
LEDStatus = 1;
}
Sé que eso no es TODO, pero eso debería ser suficiente para diagnosticar por qué las interrupciones no se activan. ¡ESO ES TODO LO QUE NECESITO! Activación de las interrupciones.
Estoy usando MPLab con Hi-Tech C Compiler. Que del manual guarda automáticamente el estado y lo restaura al entrar/salir de la interrupción.
TRISB1 debe establecerse en 1 para configurar RB1 (RX) como entrada. No estoy seguro de cuál es el valor predeterminado, por lo que puede estar bien.
Debe borrar el indicador de interrupción de recepción (RCIF) leyendo el registro de recepción (RCREG). Además, dado que el registro de recepción tiene doble búfer, es posible que deba leerlo más de una vez.
Por lo tanto, su rutina de interrupción debe parecerse más a esto:
extern interrupt isr(void)
{
while (RCIF)
{
char ch;
RB5 = 1;
ch = RCREG; // normally would go into an array and increment a counter
}
}
No sé si ese es su único problema, ya que indica que no está entrando en la rutina de interrupción en absoluto. Pero lo anterior es la forma correcta de leer los caracteres del búfer de recepción.
======================================
EDITAR:
No sé si esto ayudará o no, pero en esta publicación , antes de habilitar las interrupciones, el código primero borra el FIFO. (Su código también borra el indicador RCIF, pero dado que es de solo lectura en su chip, no es necesario).
ch = RCREG; // clear FIFO
ch = RCREG;
ch = RCREG;
// then enable interruupts ...
unsigned char sci_GetByte() { while(!RCIF) continue; //Block until data in return RCREG; }
mi problema es intentar que se activen las interrupcionesBien, dos cosas.
Primero, dentro de su rutina de interrupción, generalmente debe borrar el indicador IF RCIF para permitir que la interrupción se dispare nuevamente.
Sin embargo, esa no es la razón por la que la interrupción no se activa en absoluto.
El problema con su código es que está definiendo una función como una interrupción, lo cual está bien, que hace que el compilador empuje las cosas a la pila automáticamente y las elimine después de que finalice la rutina. También finaliza la función con un comando de "regreso de interrupción" en lugar de un simple comando de "retorno".
Lo que no hace es vincular la función al vector de interrupción. Por lo general, solo hay una pequeña cantidad de espacio alrededor del área del vector de interrupción, por lo que es normal colocar un goto en la dirección del vector de interrupción que llama el nombre de su rutina de interrupción.
Dependiendo de su compilador, hay varias formas de hacerlo. Le sugiero que lea el manual de su compilador sobre los vectores de interrupción y el código de muestra.
No leí toda tu publicación larga, pero me di cuenta de esto al hojear:
isr de interrupción externa (vacío) { RB5 = 1; }
Esto definitivamente está mal. No sé cuál es la condición de interrupción, pero no la estás eliminando. El procesador se bloqueará en la primera interrupción porque volverá a ingresar a la rutina de interrupción inmediatamente después de que se complete porque la condición de interrupción aún está activa.
¿Ha intentado mirar la señal RS-232 en un osciloscopio para ver si la velocidad en baudios es correcta? Intente transmitir algunos caracteres desde el PIC para asegurarse de que el UART tenga la configuración de velocidad en baudios correcta.
Teagan
void interrupt isr(void) { if(RCIF) sci_LoadBuffer(); LEDStatus = 1; }
void sci_LoadBuffer(void) { rxBuffer[rxBuffIndex] = RCREG; rxBuffIndex = ++rxBuffIndex % MAXBUFFER; }
Teagan
crosley
solojeff
AndreKR
olin lathrop