PIC16F1829 UART RX прерывание не работает с помощью компилятора mplabx и XC8
Я новичок в написании прошивки для 8-битных фотографий и могу использовать некоторую помощь с моим кодом. Я использую PIC16F1829 для светодиодного модуля, который получает команды RX. Я просто пытаюсь получить базовую настройку, такую как включение светодиодов, когда определенное значение получено на RX pin, но даже не могу этого получить.
хотел бы заставить UART работать через прерывания, но даже не может заставить его работать с опросом в основном цикле. Мой вектор прерывания прокомментирован в коде ниже.
RX pin: Проект RC5
TX pin: RB7
Pin для включения и выключения светодиодов: RA5
Pin RA5 отлично работает для включения и выключения светодиодов. TX pin работает, хотя я не подтвердил, если прерывание TXIF также не работает, как RCIF не работает.
Я пробовал читать RCIF и PIR1bits.RCIF. Оба были в сборе. Ни то, ни другое не помогало. Я пробовал это на двух разных фотографиях на 2 разных светодиодных модулях. Они включаются,но чтение RX pin тоже не работает.
переменная RXIN изначально определяется как 3 и, таким образом, из-за rxin-- loop в основном цикле огни мигают 3 раза при запуске, поэтому я знаю, что он входит в основной цикл. Но, насколько я могу судить, прерывание RCIF не срабатывает при приеме на RX pin.
Я подтвердил на осциллографе, что сигнал в RX и из TX-контактов с использованием одного и того же БОДа, поэтому я думаю, что скорость передачи данных настроена правильно (300 бод, 8N1.) Я также подтвердил получение pin-кода осциллографа RX сильный и чистый сигнал 5В. До сих пор ни опрос RCIF, ни использование маршрутизации службы прерываний не работали. Если кто-то видит проблемы с моим кодом, которые я не вижу, ваша помощь будет очень признательна.
мой код:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
// This is for 300 baud rate
#define _BAUD_PRESCALER_LOW_ 0x2A
#define _BAUD_PRESCALER_HIGH_ 0x68
#define _XTAL_FREQ 32000000
#pragma config FOSC = INTOSC // Oscillator Selection->INTOSC oscillator: I/O function on CLKIN pin
#pragma config WDTE = OFF // Watchdog Timer Enable->WDT enabled
#pragma config PWRTE = OFF // Power-up Timer Enable->PWRT disabled
#pragma config MCLRE = OFF // MCLR Pin Function Select->MCLR/VPP pin function is digital input
#pragma config CP = OFF // Flash Program Memory Code Protection->Program memory code protection is disabled
#pragma config CPD = OFF // Data Memory Code Protection->Data memory code protection is disabled
#pragma config BOREN = ON // Brown-out Reset Enable->Brown-out Reset enabled
#pragma config CLKOUTEN = OFF // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
#pragma config IESO = OFF // Internal/External Switchover->Internal/External Switchover mode is disabled
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is disabled
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection->Write protection off
#pragma config PLLEN = ON // PLL Enable->4x PLL enabled
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
#pragma config BORV = LO // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
#pragma config LVP = OFF
int flagRXFramingError = 0;
int flagRXOverrunError = 0;
volatile unsigned char RXIN = 3;
unsigned char UARTRead(){
return RCREG;
}
void writeRXIN(unsigned char a){
RXIN = a;
}
void TX(unsigned char a){
while(!TXIF){}
TXREG = a;
}
int main(int argc, char** argv) {
// SCS FOSC; SPLLEN disabled; IRCF 8MHz_HF;
OSCCON = 0xF0;
// TUN 0;
OSCTUNE = 0x00;
// Set the secondary oscillator
// Wait for PLL to stabilize
while(PLLR == 0)
{
}
// WDTPS 1:65536; SWDTEN OFF;
WDTCON = 0x16;
__delay_ms(5);
GIE = 1; // Global interrupts enabled
__delay_ms(5);
PEIE = 1; // Active peripheral interrupts enabled
__delay_ms(5);
RCIE = 1; // Enable USART Receive interrupt
__delay_ms(5);
TXIE = 1; // Enable USART Transmitter interrupt
__delay_ms(5);
ADIE = 1; // Enable ADC interrupts
__delay_ms(5);
RXDTSEL = 0; // RX is on RC5 pin
__delay_ms(5);
TXCKSEL = 0; // TX is on RB7 pin
__delay_ms(5);
TRISC5 = 1; // RX pin set as input
__delay_ms(5);
SPEN = 1; // Serial Port Enabled
__delay_ms(5);
SYNC = 0; // Asynchronous mode
__delay_ms(5);
RX9 = 0; // 8 bit reception
__delay_ms(5);
TX9 = 0; // 8-bit transmission
__delay_ms(5);
CREN = 1; // Receiver enabled
__delay_ms(5);
TXEN = 1; // Transmitter enabled
__delay_ms(5);
BRG16 = 1; // 16-bit baud generation
__delay_ms(5);
BRGH = 1; // High baud rate enabled
__delay_ms(5);
ABDEN = 0; // Auto baud detect disabled
__delay_ms(5);
// Baud prescaler n = [Fosc/(D*BR)] - 1
SPBRGH = _BAUD_PRESCALER_HIGH_;
__delay_ms(5);
SPBRGL = _BAUD_PRESCALER_LOW_;
__delay_ms(5);
TRISC6 = 0; // IadjPWM pin configured as output
__delay_ms(5);
ANSC6 = 0; // IadjPWM pin not analog input
__delay_ms(5);
TRISA5 = 0; // DimPWM pin configured as output
__delay_ms(5);
LATC6 = 1; // Max current for now until PWM written
__delay_ms(5);
while(1){
// Inline assembly code to clear watchdog timer
//asm("CLRWDT");
/*if(RXIN == 5){
RA5 = 1;
}
else{
RA5 = 0;
}*/
if(PIR1bits.RCIF){
writeRXIN(UARTRead());
//RA5 = 0;
TX(RXIN);
} // end if RCIF
while(RXIN > 0){
RA5 = 1;
__delay_ms(100);
RA5 = 0;
__delay_ms(100);
RXIN--;
}
}
// infinite loop
// never leave this loop
RA5 = 1;
return (EXIT_SUCCESS);
} // end main
/*void interrupt ISR(void){
if(RCIF){// if USART Receive interrupt flag
RA5 = 1;
if(FERR){
flagRXFramingError = 1;
SPEN = 0;
SPEN = 1;
}
if(OERR){
flagRXOverrunError = 1;
CREN = 0;
CREN = 1;
}
while(RCIF){ // RCIF high as long as there is data in FIFO register. Read RCREG to clear RCIF flag
writeRXIN(UARTRead());
}
RA5 = 0;
}
if (TXIF){// if USART Transmit interrupt
TXIF = 0; // Clear interrupt flag
}
} // end ISRs*/
2 ответов
некоторые микроконтроллеры перестают получать байты, если произошла какая-то ошибка. Обязательно очистите эти ошибки. Обычно, очищая некоторые биты регистра управления UART.
РЕШЕНА ПРОБЛЕМА
Я не уверен, что именно решило проблему, но я поделюсь основными изменениями, которые я сделал и новый код.
У меня был включен TXIE. TXIF почти всегда высок, поэтому он генерирует непрерывные прерывания. Я не вижу причин для включения прерываний TX, хотя может быть и хороший. Если вы хотите TX, подождите, пока TXIF не ноль, а передача, иначе зачем использовать флаг?
У меня были прерывания включение в неправильном порядке. Я должен был включено периферийные устройства, затем их отдельные прерывания, если надо, то PEIE, и, наконец, ГНС.
Я не обрабатывал FERR и OERR в моем прерывании, хотя они могут стреляйте и вызывайте прерывания.
также я RXDTSEL установлен неправильно на мой исходный код. Вот новый, рабочий код. Прямо сейчас все, что он делает, это эхо сигнала RX и мигает светодиодами количество раз, которое передается.
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
// This is for 300 baud rate
#define _BAUD_PRESCALER_LOW_ 0x2A
#define _BAUD_PRESCALER_HIGH_ 0x68
#define _XTAL_FREQ 32000000
#define _PIN_DIMPWMPIN_ RA5
#pragma config FOSC = INTOSC // Oscillator Selection->INTOSC oscillator: I/O function on CLKIN pin
#pragma config WDTE = OFF // Watchdog Timer Enable->WDT enabled
#pragma config PWRTE = OFF // Power-up Timer Enable->PWRT disabled
#pragma config MCLRE = OFF // MCLR Pin Function Select->MCLR/VPP pin function is digital input
#pragma config CP = OFF // Flash Program Memory Code Protection->Program memory code protection is disabled
#pragma config CPD = OFF // Data Memory Code Protection->Data memory code protection is disabled
#pragma config BOREN = ON // Brown-out Reset Enable->Brown-out Reset enabled
#pragma config CLKOUTEN = OFF // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
#pragma config IESO = OFF // Internal/External Switchover->Internal/External Switchover mode is disabled
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is disabled
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection->Write protection off
#pragma config PLLEN = ON // PLL Enable->4x PLL enabled
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
#pragma config BORV = LO // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
#pragma config LVP = OFF
int flagRXFramingError = 0;
int flagRXOverrunError = 0;
volatile unsigned char RXIN = 3;
unsigned char RX(){
return RCREG;
}
void writeRXIN(volatile unsigned char a){
RXIN = a;
}
void TX(unsigned char a){
while(!PIR1bits.TXIF); // TXIF is usually 1, only 0 when busy transmitting
TXREG = a;
}
int main(int argc, char** argv) {
// SCS FOSC; SPLLEN disabled; IRCF 8MHz_HF;
OSCCON = 0xF0;
// TUN 0;
OSCTUNE = 0x00;
// Set the secondary oscillator
// Wait for PLL to stabilize
while(OSCSTATbits.PLLR == 0){}
ADCON0bits.ADON = 0;
ANSELA = 0x00;
ANSELB = 0x00;
ANSELC = 0x00;
PIE1bits.ADIE = 0; // Disable ADC interrupts
TRISCbits.TRISC5 = 1; // RX pin set to input
TRISCbits.TRISC6 = 0; // IadjPWM pin configured as output
TRISAbits.TRISA5 = 0; // DimPWM pin configured as output
LATCbits.LATC6 = 1; // Max current for now until PWM written
//UART Init
BAUDCONbits.BRG16 = 1; // 16-bit baud generation
TXSTAbits.BRGH = 1; // High baud rate enabled
BAUDCONbits.ABDEN = 0; // Auto baud detect disabled
// Baud prescaler n = [Fosc/(D*BR)] - 1
SPBRGH = _BAUD_PRESCALER_HIGH_;
__delay_ms(1);
SPBRGL = _BAUD_PRESCALER_LOW_;
__delay_ms(1);
APFCON0bits.RXDTSEL = 1; // RX is on RC5 pin
APFCON0bits.TXCKSEL = 0; // TX is on RB7 pin
TXSTAbits.SYNC = 0; // Asynchronous mode
RCSTAbits.SPEN = 1; // Serial Port Enabled
RCSTAbits.RX9 = 0; // 8 bit reception
TXSTAbits.TX9 = 0; // 8-bit transmission
RCSTAbits.CREN = 1; // Receiver enabled
TXSTAbits.TXEN = 1; // Transmitter enabled
PIE1bits.TXIE = 0; // Enable USART Transmitter interrupt
PIE1bits.RCIE = 1; // Enable USART Receive interrupt
while(PIR1bits.RCIF){
writeRXIN(RX());
}
INTCONbits.PEIE = 1; // Enable peripheral interrupts
INTCONbits.GIE = 1; // Enable global interrupts
while(1){
while(RXIN > 0){
TX(RXIN);
_PIN_DIMPWMPIN_ = 1;
__delay_ms(100);
_PIN_DIMPWMPIN_ = 0;
__delay_ms(100);
RXIN--;
}
}
// infinite loop
// never leave this loop
return (EXIT_SUCCESS);
} // end main
void interrupt ISR(void){
if(PIE1bits.RCIE && PIR1bits.RCIF){ // handle RX pin interrupts
while(PIR1bits.RCIF){
writeRXIN(RX());
}
if(RCSTAbits.FERR){
flagRXFramingError = 1;
SPEN = 0;
SPEN = 1;
}
if(RCSTAbits.OERR){
flagRXOverrunError = 1;
CREN = 0;
CREN = 1;
}
} // end RX pin interrupt handlers
} // end ISRs*/