Electronic – UART Program is Stuck when Enable Interrupt with PIC24F

mplabxpicuart

I'm using PIC24FJ64GB002.
I want to use it for UART by RS232C with my PC.

The problem is that, if I make "IEC0bits.U1TXIE = 1;", the program doesn't work at all.
I mean even LED does not become bright.
However, even if "IEC0bits.U1TXIE = 0", "IEC0bits.U1RXIE = 1" or "IEC0bits.U1RXIE = 0;", the program works except for the matter of the baud rate.

I want to know what is wrong and how to make it right.
But, I guess it can be due to the hardware problem.

And, excuse me for my English as I'm not a native speaker.

My environment;
OS: Windows 7,
IDE: MPLABX,
Compiler: XC16

/* 
 * File:   main_pic24fSerial.c
 * Author: Raven Iqqe
 *
 * Created on 2013/09/26, 18:56
 */

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <uart.h>

#define OUTSTR  "Hello!\0"
#define ALPHA   'A'
#define GRNLED  LATBbits.LATB15
#define YLWLED  LATBbits.LATB14
#define REDLED  LATBbits.LATB13

// CONFIG4
#pragma config DSWDTPS = DSWDTPSF       // DSWDT Postscale Select (1:2,147,483,648 (25.7 days))
#pragma config DSWDTOSC = LPRC          // Deep Sleep Watchdog Timer Oscillator Select (DSWDT uses Low Power RC Oscillator (LPRC))
#pragma config RTCOSC = SOSC            // RTCC Reference Oscillator  Select (RTCC uses Secondary Oscillator (SOSC))
#pragma config DSBOREN = ON             // Deep Sleep BOR Enable bit (BOR enabled in Deep Sleep)
#pragma config DSWDTEN = ON             // Deep Sleep Watchdog Timer (DSWDT enabled)

// CONFIG3
#pragma config WPFP = WPFP63            // Write Protection Flash Page Segment Boundary (Highest Page (same as page 42))
#pragma config SOSCSEL = SOSC           // Secondary Oscillator Pin Mode Select (SOSC pins in Default (high drive-strength) Oscillator Mode)
#pragma config WUTSEL = LEG             // Voltage Regulator Wake-up Time Select (Default regulator start-up time used)
#pragma config WPDIS = WPDIS            // Segment Write Protection Disable (Segmented code protection disabled)
#pragma config WPCFG = WPCFGDIS         // Write Protect Configuration Page Select (Last page and Flash Configuration words are unprotected)
#pragma config WPEND = WPENDMEM         // Segment Write Protection End Page Select (Write Protect from WPFP to the last page of memory)

// CONFIG2
#pragma config POSCMOD = XT             // Primary Oscillator Select (Primary Oscillator Enabled, XT)
#pragma config I2C1SEL = PRI            // I2C1 Pin Select bit (Use default SCL1/SDA1 pins for I2C1 )
#pragma config IOL1WAY = ON             // IOLOCK One-Way Set Enable (Once set, the IOLOCK bit cannot be cleared)
#pragma config OSCIOFNC = OFF           // OSCO Pin Configuration (OSCO pin functions as clock output (CLKO))
#pragma config FCKSM = CSECME           // Clock Switching and Fail-Safe Clock Monitor (Sw Enabled, Mon Enabled)
#pragma config FNOSC = FRCDIV           // Initial Oscillator Select (Fast RC Oscillator with Postscaler (FRCDIV))
#pragma config PLL96MHZ = ON            // 96MHz PLL Startup Select (96 MHz PLL Startup is enabled automatically on start-up)
#pragma config PLLDIV = NODIV           // USB 96 MHz PLL Prescaler Select (Oscillator input divided by 12 (48 MHz input))
#pragma config IESO = ON                // Internal External Switchover (IESO mode (Two-Speed Start-up) enabled)

// CONFIG1
#pragma config WDTPS = PS32768          // Watchdog Timer Postscaler (1:32,768)
#pragma config FWPSA = PR128            // WDT Prescaler (Prescaler ratio of 1:128)
#pragma config WINDIS = OFF             // Windowed WDT (Standard Watchdog Timer enabled,(Windowed-mode is disabled))
#pragma config FWDTEN = ON              // Watchdog Timer (Watchdog Timer is enabled)
#pragma config ICS = PGx1               // Emulator Pin Placement Select bits (Emulator functions are shared with PGEC1/PGED1)
#pragma config GWRP = OFF               // General Segment Write Protect (Writes to program memory are allowed)
#pragma config GCP = OFF                // General Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = ON              // JTAG Port Enable (JTAG port is enabled)

// Local Variables Declaration
char str[32] = OUTSTR;

// Prototype Declaration
char outputstr(char *);
void delay(void);

// Main Function
int main(void) {///*
    // Oscillator Setting
    OSCCONbits.COSC = 0b001;    // Current oscillator is FRC with PLL.
    OSCCONbits.NOSC = 0b010;    // New oscillator is 8MHz.

    OSCCONbits.CLKLOCK = 0;
    OSCCONbits.IOLOCK = 0;
    OSCCONbits.LOCK = 0;
    OSCCONbits.CF = 0;
    OSCCONbits.POSCEN = 0;
    OSCCONbits.SOSCEN = 0;
    OSCCONbits.OSWEN = 1;

    // Clock Division Setting
    CLKDIVbits.ROI = 0;         // No division of clock
    CLKDIVbits.DOZE = 0b000;
    CLKDIVbits.DOZEN = 0;
    CLKDIVbits.RCDIV = 0b000;
    CLKDIVbits.CPDIV = 0b00;
    CLKDIVbits.PLLEN = 0;

    // Port Setting
    TRISBbits.TRISB10 = 1;
    TRISBbits.TRISB11 = 1;
    TRISBbits.TRISB13 = 0;  // Red LED
    TRISBbits.TRISB14 = 0;  // Yellow LED
    TRISBbits.TRISB15 = 0;  // Green LED
    LATB = 0;

    // UART Pin Setting
    RPINR18bits.U1RXR = 11;
    RPOR5bits.RP10R = 3;

    // AD Converter Setting
    AD1PCFG = 0xFFFF;       // Disable all A/D convertion.

    // Interrupt Setting
    SRbits.IPL = 0b111;     // CPU Interrupt Priority
    INTCON1bits.NSTDIS = 0; // Interrupt nesting is enabled.

    // UART Setting
    U1MODEbits.UARTEN = 1;
    U1MODEbits.UEN = 0b11;
    U1MODEbits.USIDL = 0;
    U1MODEbits.ABAUD = 0;
    U1MODEbits.BRGH = 0;
    U1MODEbits.PDSEL = 0b00;
    U1MODEbits.STSEL = 0;

    U1STAbits.UTXISEL0 = 0;
    U1STAbits.UTXISEL1 = 0;
    U1STAbits.UTXEN = 1;
    U1STAbits.UTXINV = 0;
    U1STAbits.URXISEL = 0b00;

    U1BRG = 207;

    IPC3bits.U1TXIP = 0b001;
    IPC2bits.U1RXIP = 0b001;
    IFS0bits.U1TXIF = 0;
    IFS0bits.U1RXIF = 0;
    IEC0bits.U1TXIE = 1;        // Here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    IEC0bits.U1RXIE = 1;


    // Main Routine
    while(1){
        if(OSCCONbits.CF == 1){
            REDLED = 1;
        }

        GRNLED = 1;
        outputstr(str);

        delay();
    }

    return (EXIT_SUCCESS);
}

// Normal Functions ************************************************************

// String Output
char outputstr(char *string){
    while(*string){                 // Output string until \0 (null).
        while (!IFS0bits.U1TXIF);   // Wait for completion of output
        U1TXREG = *string++;        // Output string and increment string's address.
    }
    YLWLED = 1;

    return(1);
}

void delay(void){
    int i, n;
    for(n=0; n<32; n++){
        for(i=0; i<10000; i++);
    }
}

Best Answer

I'm not familiar with PIC programming so I cannot give you specifics, but I don't see an interrupt service routine (ISR) for the UART in your code. In general, when a UART transmit interrupt is enabled, an interrupt will be generated if the UART can accept a new transmit byte. It will continue interrupting until it receives enough bytes to fill its FIFO or the interrupt is disabled/masked.

The way this is normally done is that the interrupt is left disabled/masked until the main-line wants to send data. The main-line puts the data in a ring-buffer and enables the interrupt.

The interrupt happens, running the ISR. This takes the next available byte from the ring buffer, feeds it to the UART and then returns. If the ISR is called and finds the ring buffer enpty, it disables/masks its own interrupt and returns.

Obviously, this is a very high-level description and there is a lot of detail to worry about, such as synchronizing access to the ring buffer between the mail-line and the ISR.instead of