PIC32MX - UART TX interrupt ISR activation problem

Have you got the greatest 48 bit multiplier ever conceived? Prove it - post your code here.

Moderator: phalanx

Post Reply
Drugo
Posts: 6
Joined: Mon Mar 07, 2011 11:25 am

PIC32MX - UART TX interrupt ISR activation problem

Post by Drugo » Mon Mar 07, 2011 11:35 am

Hello everyone,
after having read the PIC32MX UART and interrupt documentation I can't fix the problem and I'm stuck with my project. That is, how to manage the TX Interrut Service Routine using PIC32MX795F512L. In the sense that, once I configure UART2 to generate interrupt after data transmission, the TX ISR is continuously called and U2TXIF is always 1, even if I reset it with an instruction at the end of the UART ISR.

I explain better my problem with the UART example present in MPLAB C32 Suite, which can be open through "uart_interrupt.mcp" project file. To test this project I'm using Microchip Explorer 16 Demo Board.
In this project, originally, it's just enabled the UART RX interrupt (instruction INTEnable(INT_SOURCE_UART_RX(UART2), INT_ENABLED)). Therefore, to trigger the ISR also when I transmit a character, after that instruction I added the corresponding INTEnable(INT_SOURCE_UART_TX(UART2), INT_ENABLED) one assigning also the ISR priority and subpriority (see comment: /*** CODE I ADDED TO MICROCHIP EXAMPLE ***/). But in this case the project doesn't work properly, because ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void) ISR function is continuously called. I attach the related code to be more clear. In this code I didn't add all the code I need to manage character transmission, because before I have to properly manage the UART TX ISR operation.

Please, since I don't find a solution to this problem and I'm stuck on the project, can anyone help me? Many many thanks!

Code: Select all

#include <plib.h>                    // Peripheral Library
 
 
 // *****************************************************************************
 // *****************************************************************************
 // Section: Configuration bits
 // SYSCLK = 80 MHz (8MHz Crystal/ FPLLIDIV * FPLLMUL / FPLLODIV)
 // PBCLK = 40 MHz
 // Primary Osc w/PLL (XT+,HS+,EC+PLL)
 // WDT OFF
 // Other options are don't care
 // *****************************************************************************
 // *****************************************************************************
 #pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
 #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
 
 // *****************************************************************************
 // *****************************************************************************
 // Section: System Macros
 // *****************************************************************************
 // *****************************************************************************
 #define    GetSystemClock()             (80000000ul)
 #define    GetPeripheralClock()        (GetSystemClock()/(1 << OSCCONbits.PBDIV))
 #define    GetInstructionClock()        (GetSystemClock())
 
 #define DESIRED_BAUDRATE        (9600)      //The desired BaudRate
 
 
 void WriteString(const char *string);
 
 int main(void)
 {
 
     // Configure the device for maximum performance but do not change the PBDIV
     // Given the options, this function will change the flash wait states, RAM
     // wait state and enable prefetch cache but will not change the PBDIV.
     // The PBDIV value is already set via the pragma FPBDIV option above..
     SYSTEMConfig(GetSystemClock(), SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
 
     mPORTAClearBits(BIT_7);         // Turn off RA7 on startup.
     mPORTASetPinsDigitalOut(BIT_7);    // Make RA7 as output.
 
 
     // Explorer-16 uses UART2 to connect to the PC.
     // This initialization assumes 36MHz Fpb clock. If it changes,
     // you will have to modify baud rate initializer.
     UARTConfigure(UART2, UART_ENABLE_PINS_TX_RX_ONLY);
     UARTSetFifoMode(UART2, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
     UARTSetLineControl(UART2, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
     UARTSetDataRate(UART2, GetPeripheralClock(), DESIRED_BAUDRATE);
     UARTEnable(UART2, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));
 
     // Configure UART2 RX Interrupt
     INTEnable(INT_SOURCE_UART_RX(UART2), INT_ENABLED);
     INTSetVectorPriority(INT_VECTOR_UART(UART2), INT_PRIORITY_LEVEL_2);
     INTSetVectorSubPriority(INT_VECTOR_UART(UART2), INT_SUB_PRIORITY_LEVEL_0);
      
     /*** CODE I ADDED TO MICROCHIP EXAMPLE ***/
 
      // Configure UART2 TX Interrupt
      INTEnable(INT_SOURCE_UART_TX(UART2), INT_ENABLED);                           
      INTSetVectorPriority(INT_VECTOR_UART(UART2), INT_PRIORITY_LEVEL_2);
      INTSetVectorSubPriority(INT_VECTOR_UART(UART2), INT_SUB_PRIORITY_LEVEL_0);
  
    /*** END CODE I ADDED TO MICROCHIP EXAMPLE ***/
 
     // configure for multi-vectored mode
     INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
 
     // enable interrupts
     INTEnableInterrupts();
 
 
    WriteString("*** UART Interrupt-driven Application Example ***\r\n");
    WriteString("*** Type some characters and observe echo and RA7 LED toggle ***\r\n");
 
 
     // Let interrupt handler do the work
     while (1);
 
     return 0;
 }
 // helper functions
 void WriteString(const char *string)
 {
     while(*string != '\0')
     {
         while(!UARTTransmitterIsReady(UART2))
             ;
 
         UARTSendDataByte(UART2, *string);
 
         string++;
 
         while(!UARTTransmissionHasCompleted(UART2))
             ;
     }
 }
 void PutCharacter(const char character)
 {
         while(!UARTTransmitterIsReady(UART2))
             ;
 
         UARTSendDataByte(UART2, character);
 
 
         while(!UARTTransmissionHasCompleted(UART2))
             ;
 }
 
 // UART 2 interrupt handler
 // it is set at priority level 2
 void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)
 {
     // Is this an RX interrupt?
     if(INTGetFlag(INT_SOURCE_UART_RX(UART2)))
     {
         // Clear the RX interrupt Flag
         INTClearFlag(INT_SOURCE_UART_RX(UART2));
 
         // Echo what we just received.
         PutCharacter(UARTGetDataByte(UART2));
 
         // Toggle LED to indicate UART activity
         mPORTAToggleBits(BIT_7);
     }
 
     // We don't care about TX interrupt
     if ( INTGetFlag(INT_SOURCE_UART_TX(UART2)) )
     {
         INTClearFlag(INT_SOURCE_UART_TX(UART2));
     }
 }


quadrotornut
Posts: 1
Joined: Thu Oct 06, 2011 4:20 pm

Re: PIC32MX - UART TX interrupt ISR activation problem

Post by quadrotornut » Thu Oct 06, 2011 4:40 pm

This is probably far too late but it might help somebody else:

You can't clear the TXIF it is done in hardware for you when the TX buffer is not empty.

When you don't want to send data anymore you need to clear TXIE. Then set it again when you want to start sending data.

Something like this:
//----------------------------------------------------------------------------
char myBuf[] = {"example"};
char *txPtr;

main()
{
UARTConfigure(UART2, UART_ENABLE_PINS_TX_RX_ONLY); //this is the default configuration so not really required
UARTSetFifoMode(UART2, UART_INTERRUPT_ON_TX_BUFFER_EMPTY | UART_INTERRUPT_ON_RX_NOT_EMPTY); //treat UART buffer as single-byte buffer to make life simple
UARTSetDataRate(UART2, GetPeripheralClock(), 9600); //9600 baud with PBCLK = 20MHz
UARTSetLineControl(UART2, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1); //default config, not really required
UARTEnable(UART2, UART_ENABLE | UART_PERIPHERAL | UART_TX | UART_RX); //enable UART module and IO pins. This will set the TX interrupt flag

INTSetVectorPriority(INT_UART_2_VECTOR, INT_PRIORITY_LEVEL_5); //configure UART1 interrupt

//don't enable U1TX interrupt until ready to transmit stuff
INTEnable(INT_U2RX, INT_ENABLED); //enable receive interrupt

txPtr = myBuf;
INTEnable(INT_U2TX, INT_ENABLED);
while(1);

}
void __ISR(_UART2_VECTOR, ipl5) UART2InterruptVector(void)
{
if (INTGetFlag(INT_U2TX) && INTGetEnable(INT_U2TX)) // transmit buffer empty?
{
if (*txPtr != '\0')
{
UARTSendDataByte(UART2,*txPtr++);
INTClearFlag(INT_U2TX); // buffer is ready, clear interrupt flag
}
else
{
// modemBuffer is empty, clear interrupt enable flag to stop TX
INTEnable(INT_U2TX, INT_DISABLED);
}
}

if (INTGetFlag(INT_U2RX) && INTGetEnable(INT_U2RX)) // something in the receive buffer?
{
while (UARTReceivedDataIsAvailable(UART2))
{
/*place to store rx here = */UARTGetDataByte(UART2); // store bytes in buffer
}
INTClearFlag(INT_U2RX); // buffer is empty, clear interrupt flag
}
}

Post Reply