PIC16F1829 UART RX中断无法使用MPLABX和XC8编译器

时间:2017-09-04 05:12:47

标签: c interrupt pic uart firmware

我是为8位PIC编写固件的新手,可以使用我的代码的一些帮助。我将PIC16F1829用于获取RX命令的LED模块。我只是试图在RX引脚上接收到某个值时启用基本设置,例如打开LED,但是甚至无法实现。

希望让UART通过中断工作,但是甚至无法在主循环中使用轮询。我的中断向量在下面的代码中被注释掉了。

RX引脚:RC5

TX引脚:RB7

用于打开和关闭LED的引脚:RA5

引脚RA5正常工作,可以打开和关闭LED。 TX引脚工作正常,但我还没有确认中断TXIF是否也不起作用,就像RCIF不能正常工作一样。

我试过读RCIF和PIR1bits.RCIF。他们都编译了。两个人都没有工作。我在两个不同的LED模块上尝试了两个不同的PIC。它们打开,但读取RX引脚并不起作用。

变量RXIN最初被定义为3,因此由于主循环内的RXIN--循环,灯在启动时闪烁3次,所以我知道它正在进入主循环。但据我所知,RCIF中断在RX引脚接收时没有触发。

我已经在示波器上确认使用相同的波特率将信号送入RX和TX引脚,因此我认为波特率配置正确(300波特,8N1。)我还在示波器上确认RX接收器接收强而干净的5V信号。到目前为止,轮询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 个答案:

答案 0 :(得分:0)

如果出现某种错误,某些微控制器会停止接收字节。一定要清除这些错误。通常通过清零一些UART控制寄存器位。

答案 1 :(得分:0)

解决了问题

我不确定究竟是什么解决了问题,但我将分享我所做的主要更改和新代码。

  1. 我启用了TXIE。 TXIF几乎总是很高,因此它会产生 连续中断。我没有看到启用TX中断的原因, 虽然可能有一个好的。如果你想TX等到TXIF 不是零和传输,否则为什么要使用旗帜?

  2. 我的中断启用顺序错误。我应该 启用外围设备,然后启用它们各自的中断 必要的,然后是PEIE,最后是GIE。

  3. 我没有在我的中断中处理FERR和OERR,尽管他们可能 被解雇并导致中断。

  4. 我的原始代码中也设置了RXDTSEL错误。这是新的工作代码。现在它只是回显RX信号并使LED闪烁发送的次数。

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