У меня есть PIC16F628A, который я пытаюсь прочитать с UART. Без прерываний он нормально читает первые 3 байта, но выдает ошибку OERR. Чтобы бороться с этим, я подумал, что было бы хорошо прерывание и загрузка любых полученных байтов в переменную буфера, которую можно было бы прочитать позже (кольцевой буфер типа массива char). Но прерывание не срабатывает, и у меня закончились идеи.
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
Я упростил прерывание до включения света:
extern interrupt isr(void)
{
RB5 = 1;
}
Но это не срабатывает. Проект считывает сканер штрих-кода по серийному номеру и обрабатывает штрих-код. Кто-нибудь может предложить некоторую помощь?
РЕДАКТИРОВАТЬ
Хорошо, раз вы, кажется, не понимаете. Я собираюсь опубликовать фактические процедуры:
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;
}
Я знаю, что это не ВСЕ, но этого должно быть достаточно, чтобы диагностировать, почему прерывания не срабатывают. ЭТО ВСЕ, ЧТО МНЕ НУЖНО! Запуск прерываний.
Я использую MPLab с компилятором Hi-Tech C. Который из мануала автоматически сохраняет состояние и восстанавливает его при входе/выходе прерывания.
TRISB1 необходимо установить на 1, чтобы настроить RB1 (RX) в качестве входа. Я не уверен, что такое по умолчанию, так что это может быть нормально.
Вам необходимо очистить флаг прерывания приема (RCIF), прочитав регистр приема (RCREG). Кроме того, поскольку регистр приема имеет двойную буферизацию, вам может потребоваться прочитать его более одного раза.
Таким образом, ваша процедура прерывания должна выглядеть примерно так:
extern interrupt isr(void)
{
while (RCIF)
{
char ch;
RB5 = 1;
ch = RCREG; // normally would go into an array and increment a counter
}
}
Я не знаю, является ли это вашей единственной проблемой, поскольку вы указываете, что вообще не входите в процедуру прерывания. Но это правильный способ чтения символов из приемного буфера.
=======================================
РЕДАКТИРОВАТЬ:
Не знаю, поможет это или нет, но в этом посте перед включением прерываний код сначала очищает FIFO. (Их код также очищает флаг RCIF, но, поскольку он доступен только для чтения на вашем чипе, в этом нет необходимости.)
ch = RCREG; // clear FIFO
ch = RCREG;
ch = RCREG;
// then enable interruupts ...
unsigned char sci_GetByte() { while(!RCIF) continue; //Block until data in return RCREG; }
Моя проблема заключается в том, чтобы заставить прерывания запускаться.Хорошо, две вещи.
Во-первых, в вашей подпрограмме обработки прерывания вам обычно приходится сбрасывать флаг IF RCIF, чтобы разрешить повторное срабатывание прерывания.
Это не причина, по которой прерывание вообще не срабатывает.
Проблема с вашим кодом заключается в том, что вы определяете функцию как прерывание - и это нормально - что заставляет компилятор автоматически помещать вещи в стек для вас и извлекать их после завершения процедуры. Он также завершает функцию командой «возврат из прерывания» вместо простой команды «возврат».
Чего он не делает, так это связывает функцию с вектором прерывания. Обычно вокруг области вектора прерывания имеется лишь небольшое пространство, поэтому нормально размещать переход по адресу вектора прерывания, который вызывает имя вашей процедуры прерывания.
В зависимости от вашего компилятора есть несколько способов сделать это. Я предлагаю вам прочитать руководство для вашего компилятора о векторах прерываний и пример кода для него.
Я не читал весь ваш длинный пост, но случайно заметил это при беглом просмотре:
внешнее прерывание isr(void) { РБ5 = 1; }
Это определенно неправильно. Я не знаю, что это за условие прерывания, но вы его не очищаете. Процессор зависнет на первом прерывании, потому что он повторно войдет в процедуру прерывания сразу после ее завершения, поскольку условие прерывания все еще активно.
Вы пытались посмотреть на сигнал RS-232 на осциллографе, чтобы убедиться, что скорость передачи данных правильная? Попробуйте передать несколько символов от PIC, чтобы убедиться, что UART имеет правильную настройку скорости передачи данных.
Тиган
void interrupt isr(void) { if(RCIF) sci_LoadBuffer(); LEDStatus = 1; }
void sci_LoadBuffer(void) { rxBuffer[rxBuffIndex] = RCREG; rxBuffIndex = ++rxBuffIndex % MAXBUFFER; }
Тиган
ткросли
ДжастДжефф
АндреКР
Олин Латроп