代码之家  ›  专栏  ›  技术社区  ›  humanistscience

使用MPLABX和XC8编译器时PIC16F1829 UART RX中断不工作

  •  6
  • humanistscience  · 技术社区  · 8 年前

    我刚开始为8位图片编写固件,可能需要一些代码帮助。我使用PIC16F1829作为LED模块,用于接收命令。我只是想得到一些基本的设置,比如当接收到RX引脚上的某个值时打开LED,但我甚至无法得到。

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

    RX引脚:RC5

    TX引脚:RB7

    引脚RA5可以很好地打开和关闭LED。TX引脚正在工作,但我尚未确认中断TXIF是否也像RCIF一样不工作。

    我试过阅读RCIF和PIR1bits。RCIF。他们都编译了。两个人都没有工作。我已经在两个不同的LED模块上的两张不同的图片上试过了。它们打开了,但读取RX pin码在这两种情况下都不起作用。

    我已经在示波器上确认,输入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 回复  |  直到 8 年前
        1
  •  0
  •   E. van Putten    8 年前

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

        2
  •  0
  •   eyllanesc    8 年前

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

    1. 我启用了TXIE。TXIF几乎总是很高,所以它会产生 连续中断。我认为没有理由启用TX中断, 虽然可能有一个好的。如果要发送,请等到TXIF 不是零和传输,否则为什么要使用标志?

    2. 启用外围设备,然后在以下情况下其各自中断:

    3. 在我的打断中,我没有处理FERR和OERR,尽管他们可能会 正在点火并导致中断。

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