2017-09-04 78 views
6

Jestem nowy w pisaniu oprogramowania układowego dla 8-bitowych PIC i mogłem skorzystać z pomocy mojego kodu. Używam PIC16F1829 dla modułu LED, który pobiera polecenia RX. Po prostu próbuję ustawić podstawy tak, jak włączyć diody LED, gdy pewna wartość zostanie odebrana na pin RX, ale nie mogę nawet tego uzyskać.PIC16F1829 UART RX Przerwanie nie działa przy użyciu kompilatora MPLABX i XC8

Chciałbyś, aby UART pracował z przerwaniami, ale nie może nawet uruchomić go z odpytywaniem w pętli głównej. Mój wektor przerwań jest komentowany w poniższym kodzie.

RX PIN: RC5

TX PIN: RB7

diody PIN, aby włączyć i wyłączyć: RA5

Styk RA5 działa dobrze, aby włączyć lub wyłączyć diody LED. TX pin działa, chociaż nie potwierdziłem, czy przerwanie TXIF również nie działa tak jak RCIF nie działa.

Próbowałem przeczytać RCIF i PIR1bits.RCIF. Oba zostały skompilowane. Żadne z nich nie działało. Próbowałem tego na dwóch różnych PIC na 2 różnych modułach LED. Włączają się, ale odczytanie pinów RX również nie działało.

Zmienna RXIN jest początkowo zdefiniowana jako 3, a zatem z powodu pętli RXIN-- w głównej pętli światła migają 3 razy przy uruchomieniu, więc wiem, że wchodzi do głównej pętli. Ale o ile mogę powiedzieć, że przerwanie RCIF nie uruchamia się po odbiorze na pin RX.

Potwierdziłem na oscyloskopie, że sygnał do RX i poza pinami TX używając tego samego baud, więc myślę, że szybkość transmisji jest poprawnie skonfigurowana (300 bodów, 8N1.) Potwierdziłem również na pinach RX oscyloskopu otrzymujących silne i czyste Sygnał 5V. Ani sondowanie RCIF, ani używanie routingu usług przerwań nie zadziałało. Jeśli ktokolwiek może zobaczyć problemy z moim kodem, których nie widzę, twoja pomoc byłaby bardzo doceniana.

Mój kod:

#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*/ 
+1

Opóźnienie 5ms między zapisem do rejestrów jest kompletnym nonsensem. 5 ms to wieczność nawet na brzydkim PIC. Są to chipy na kartach, które są mapowane na pamięć - nie potrzebujesz w ogóle żadnego opóźnienia. (W niektórych szczególnych przypadkach może być konieczne odczekać kilka cykli zegara po ustawieniu kierunku danych dla portu I/O, ale to wszystko.) Zacznij od usunięcia wszystkich opóźnień 5ms. – Lundin

+1

(Jako wzmianka na przyszłość: podczas gdy to pytanie jest w porządku i dotyczy tematu na SO, może być lepiej zapytać na https://electronics.stackexchange.com/, gdy masz pytania dotyczące określonych urządzeń peryferyjnych, takich jak UART na pewnej stronie PIC, na której czają się eksperci z PIC, a pytania dotyczące oprogramowania układowego mikrokontrolerów są tam również doskonale tematyczne.) – Lundin

+0

Niemniej jednak jestem zmuszony to upomnieć, tylko dlatego, że "potwierdziłem na oscyloskopie, że sygnał do RX i poza pinami TX używając tej samej prędkości, więc myślę, że szybkość transmisji jest poprawnie skonfigurowana (300 bodów, 8N1.) Potwierdziłem również na pinach RX oscyloskopu otrzymujących silny i czysty sygnał 5V ". Dostajemy zbyt wiele osadzonych pytań, absolutnie nic nie wskazuje na to, że jakikolwiek sprzęt działa, a więc musimy natychmiast zamknąć/zamknąć/usunąć głos jako zasadniczo nieodwracalny na stronie pytań i odpowiedzi dotyczących oprogramowania; ( –

Odpowiedz

0

rozwiązał problem

Nie jestem pewien, co dokładnie rozwiązać ten problem, ale będę dzielić się większych zmian zrobiłem i nowy kod.

  1. Miałem włączoną opcję TXIE. TXIF jest prawie zawsze wysoki, więc generuje przerwania ciągłe w postaci . Nie widzę powodu, aby włączyć przerwań TX, ale może być dobry. Jeśli chcesz TX czekać, aż TXIF jest nie zero i transmisji, w przeciwnym razie po co używać flagi?

  2. Miałem przerwania umożliwiające w złej kolejności. Powinienem włączyć włączyć urządzenia peryferyjne, a następnie ich indywidualne przerwań, jeśli konieczne, następnie PEIE, a na końcu GIE.

  3. Nie obsługiwałem FERR i OERR w moim przerwaniu, chociaż mogą one być strzelać i powodować przerwania.

Również miałem RXDTSEL ustawić źle w moim oryginalnym kodzie.Oto nowy, działający kod. Teraz wszystko, co robi, to echo sygnału RX i miganie diody LED liczbę razy, która jest transmitowana.

#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*/ 
+0

Myślę, że teraz usuwasz wszystkie oczekujące błędy urządzenia peryferyjnego (resetując urządzenie peryferyjne), a następnie odbiornik zaczął znowu działać ... –

0

Niektóre mikrokontrolery zrezygnować z otrzymywania bajtów jeśli tam był jakiś błąd. Pamiętaj, aby usunąć te błędy. Zwykle kasowanie niektórych bitów rejestru kontrolnego UART.