0
votes

I am building a device using a PIC32MX250F128D. One of the systems requires use of the UART. Transmitting from the PIC to a putty terminal works fine. However, sending data in the other direction is not working, and I am out of ideas. I am using a cheap USB-UART adapter that uses a CP2102 chip. Link if relevant I am using pins 25 and 26, (RPC0/AN6 and RPC1/AN7) for UART.

  • If the TXEN transmit enabled is on, then any characters typed into putty are returned and printed on putty. This occurs even if RX and TX wires are swapped. The transmit interrupt flag on the PIC is triggered
  • If the TXEN transmit enable is turned off, then putty does not print out any characters. Again, same behavior with wires swapped. No interrupt flags.
  • Disconnecting either the RX or TX wire also cause no reply to putty.
  • Checking the URXDA RX buffer data flag with the debugger, I find that nothing sent gets put in the RX buffer, regardless of settings.
  • UART Loopback is not enabled. This was also checked with the debugger while running.
  • Putting in a loop of code to write to TXREG works as expected, printing characters to putty.
  • The regular code never interacts with either TXREG or RXREG. TX is currently not used in our program, RXREG is only processed in an interrupt routine which, since RXIF or even URXDA ever get flagged, never gets called.

In brief, the wire disconnecting, TXEN disabling, and TX IF seem to indicate that it is not a hardware or connection issue, and that the PIC is in fact mirroring data it receives. However, the PIC never realizes that it receives the data, has no code to mirror data, nor is loopback enabled.

My UART relevant setup code is below. I am using a number of peripherals, so I am also including my entire setup code at the bottom in case the issue lies with peripheral conflicts.

//includes
#include <xc.h>
#include <strings.h>
#include <stdio.h>
#include <sys/attribs.h>//necessary for Interrupt declarations

//configuration
#pragma config IOL1WAY = OFF//allows multiple(?) Peripheal cnfigurations
#pragma config FNOSC = FRCPLL//use 8MHZ FRC with PLL as clock
#pragma config FPLLIDIV = DIV_2//PLL input = 4MHZ
#pragma config FPLLMUL = MUL_24//PLL output=96 MHZ
#pragma config FPLLODIV = DIV_2//48 MHZ Sysclock
#pragma config FPBDIV = DIV_2//24 MHZ peripheal Bus
#pragma config FWDTEN=OFF, CP=OFF, BWP=OFF, OSCIOFNC = ON
#pragma config JTAGEN = OFF         // Disable JTAG

void setup_pps(void)         
 {         
     //asm volatile ("di");//disable all interrupts
     SYSKEY = 0x0;         
     SYSKEY = 0xAA996655;         
     SYSKEY = 0x556699AA;         

     CFGCONbits.IOLOCK = 0;         
     U1RXRbits.U1RXR = 0b0110; // Set U1RX to RPC1         
     RPC0Rbits.RPC0R = 0b0001; // Set U1TX to RPC0
     CFGCONbits.IOLOCK = 1;  

     SYSKEY = 0x0;
     //asm volatile ("ei");//re-enable interrupts
 }

void setup(void)
{
    asm("di");//disable interrupts while performing setup
    //Interrupt vector priorities

    IPC8CLR = 0x0000001F;         // clear priority/subpriority fields 
    IPC8SET = 0x0000000C;         // set UART priority = 3, IPC8<4:2>
    IPC8SET = 0x00000000;         // set UART subpriority = 0, IPC8<1:0>

    INTCONbits.MVEC = 1;//enable multivector interrupts

    //***Pin Setup
    setup_pps();
    //**Digital GPIO Setup
    //set all port pins to digital
    ANSELA=0x0;
    //Set all port pins to output
    TRISA=0x0;
    //SNIP
    //## End Digital GPIO Setup

    //** UART Setup
    U1MODEbits.UEN=0b00;//Use only U1TX and U1RX pins
    U1MODEbits.BRGH=1;//TODO:Determine Baud rate for Reach//note: non-highspeed takes multiple samples->probably better for noise
    U1MODEbits.PDSEL=0;//TODO: Reach parity and data select
    //U1MODEbits.RXINV=1;
    U1STAbits.UTXISEL=0;//Transmit Interrupt type
    U1STAbits.URXISEL=0b01;//01;//Receive Interrupt type-Interrupt when 1/2 full (4 bytes)
    int fpb=24000000;
    int baudrate =38400;//change to set baud rate
    U1BRG=fpb/(4*baudrate)-1;//Baud rate Generator//use 16x if brgh=0 
    //IEC1SET=0x0200;//Transmit Interrupt enable/ should not be needed
    IEC1SET=0x0100;//Enable receive interrupt
    U1STAbits.URXEN=1;//Receive Enable
    U1MODEbits.ON=1;//Enable UART
    U1STAbits.UTXEN=1;//Transmit Enable Enable TODO:Determine if needed for reach
    U1STAbits.URXEN=1;//Receive Enable
    //## End UART Setup

   //SNIP

    asm("ei");//re-enable interrupts
    return;
}

Entire setup

//includes
#include <xc.h>
//#include <p32xxxx.h>
//#include <proc/p32mx250f128d.h>
#include "letters.h"//codes for 7 segment display
#include "pins.h"//refer to ports/latches by function
#include "other.h"//mainly state machine states
#include <strings.h>
#include <stdio.h>
#include "gps.h"//contains variables and functions of gps data
#include <sys/attribs.h>//necessary for Interrupt declarations
//#include <string.h>//may be used for string manipulation, such as selecting files
//#include <stdio.h>//will be needed for file open

//configuration
#pragma config IOL1WAY = OFF//allows multiple(?) Peripheal cnfigurations
#pragma config FUSBIDIO = OFF//USB ID controlled by port, not USB Module
#pragma config FVBUSONIO = OFF//USB VBUS controlled by port, not USB
#pragma config FNOSC = FRCPLL//use 8MHZ FRC with PLL as clock
#pragma config FPLLIDIV = DIV_2//PLL input = 4MHZ
#pragma config FPLLMUL = MUL_24//PLL output=96 MHZ
#pragma config FPLLODIV = DIV_2//48 MHZ Sysclock
#pragma config UPLLIDIV = DIV_2//4 MHZ USB PLL input
#pragma config UPLLEN = ON//Enable PLL for USB
#pragma config FPBDIV = DIV_2//24 MHZ peripheal Bus
#pragma config FWDTEN=OFF, CP=OFF, BWP=OFF, OSCIOFNC = ON
#pragma config JTAGEN = OFF         // Disable JTAG
#pragma config FSOSCEN = OFF        // Disable Secondary Oscillator

void setup_pps(void)         
 {         
     //asm volatile ("di");//disable all interrupts
     SYSKEY = 0x0;         
     SYSKEY = 0xAA996655;         
     SYSKEY = 0x556699AA;         

     CFGCONbits.IOLOCK = 0;         
     U1RXRbits.U1RXR = 0b0110; // Set U1RX to RPC1         
     RPC0Rbits.RPC0R = 0b0001; // Set U1TX to RPC0
     CFGCONbits.IOLOCK = 1;  

     SYSKEY = 0x0;
     //asm volatile ("ei");//re-enable interrupts
 }

void setup(void)
{
    asm("di");//disable interrupts while performing setup
    //Interrupt vector priorities
    IPC2CLR = 0x001f;         // clear priority/subpriority fields 
    IPC2SET = 0x0018;         // set timer 2 int priority = 6, IPC2<4:2>
    IPC2SET = 0x0000;         // set timer 2 int subpriority = 0, IPC2<1:0>

    IPC5CLR = 0x1f000000;         // clear priority/subpriority fields 
    IPC5SET = 0x10000000;         // set adc int priority = 4, IPC5<28:26>
    IPC5SET = 0x00000000;         // set adc int subpriority = 0, IPC2<25:24>

    IPC7CLR = 0x001F0000;         // clear priority/subpriority fields 
    IPC7SET = 0x00080000;         // set USB priority = 2, IPC7<20:18>
    IPC7SET = 0x00000000;         // set USB subpriority = 0, IPC7<17:16>

    IPC8CLR = 0x0000001F;         // clear priority/subpriority fields 
    IPC8SET = 0x0000000C;         // set UART priority = 3, IPC8<4:2>
    IPC8SET = 0x00000000;         // set UART subpriority = 0, IPC8<1:0>

    IPC8CLR = 0x001F0000;         // clear priority/subpriority fields 
    IPC8SET = 0x00140000;         // set Input Change priority = 5, IPC8<20:18>
    IPC8SET = 0x00000000;         // set Input subpriority = 0, IPC8<17:16>


    INTCONbits.MVEC = 1;//enable multivector interrupts
//    INTEnableSystemMultiVectoredInt();  //Enable multi vector interrupts
  //  INTEnableInterrupts();//enable interrupts



    //Clock Setup
    OSCCONbits.UFRCEN=0; //USE PLL for USB //Hopefully default, otherwise unlock sequence required to write-->move to setuppps

    //***Pin Setup
    setup_pps();
    //DEVCFG0bits.JTAGEN=0;
    //DDPCONbits.JTAGEN = 0
    //**Digital GPIO Setup
    //set all port pins to digital
    ANSELA=0x0;
    ANSELB=0x0;
    ANSELC=0X4;//leave C2/AN8 as analog
    //Set all port pins to output
    TRISA=0x0;
    TRISB=0x0;
    TRISC=0x4;
    //Set Controller Ports to inputs
    TRISBbits.TRISB5=1;
    TRISBbits.TRISB7=1;
    TRISBbits.TRISB8=1;
    TRISBbits.TRISB9=1;
    TRISCbits.TRISC6=1;
    TRISCbits.TRISC7=1;
    TRISCbits.TRISC8=1;
    TRISCbits.TRISC9=1;

    CNCONBbits.ON=1;//enable input change notification of port B
    CNENBSET=0x0180;//enable input change notification on RB7 and RB8 (kill and mode switch) 
    tmp=PORTB;//clear mismatch
    IFS1CLR=0x4000;//clear interrupt flag
    IEC1SET=0x4000;//enable interrupt

    //## End Digital GPIO Setup

    //** UART Setup
    U1MODEbits.UEN=0b00;//Use only U1TX and U1RX pins
    U1MODEbits.BRGH=1;//TODO:Determine Baud rate for Reach//note: non-highspeed takes multiple samples->probably better for noise
    U1MODEbits.PDSEL=0;//TODO: Reach parity and data select
    //U1MODEbits.RXINV=1;
    U1STAbits.UTXISEL=0;//Transmit Interrupt type
    U1STAbits.URXISEL=0b01;//01;//Receive Interrupt type-Interrupt when 1/2 full (4 bytes)
    int fpb=24000000;
    int baudrate =38400;//change to set baud rate
    U1BRG=fpb/(4*baudrate)-1;//Baud rate Generator//use 16x if brgh=0 
    //UxBRG = FPB / (4 * BAUDRATE) - 1//FPB = 24MHZ in current setup
    //IEC1SET=0x0200;//Transmit Interrupt enable/ should not be needed
    IEC1SET=0x0100;//Enable receive interrupt
    U1STAbits.URXEN=1;//Receive Enable
    U1MODEbits.ON=1;//Enable UART
    U1STAbits.UTXEN=1;//Transmit Enable Enable TODO:Determine if needed for reach
    U1STAbits.URXEN=1;//Receive Enable
    //## End UART Setup

    //** ADC Setup
    //Behavior-Samples AN8 8 times automatically, then generates interrupt. Can read samples either in lower or upper half of buffer at a time.
    ANSELCbits.ANSC2=0b1;//Set C2 as analog
    TRISCbits.TRISC2=0b1;//Set C2 as input
    AD1CON1bits.FORM=0b000;//16 bit integer result
    AD1CON1bits.SSRC=0b111;//auto convert at end of sampling
    AD1CON1bits.CLRASAM=0b1;//When interrupt happens, ASAM will automatically be cleared
    AD1CON1bits.ASAM=0b1;//Auto start sampling at conversion end
    AD1CON2bits.VCFG=0b000;//Use AVSS and AVDD as reference
    AD1CON2bits.SMPI=0b1111;//Interrupt every 16th sample
    AD1CON2bits.BUFM=0b0;//Buffer is not split
    AD1CON3bits.ADCS=0b11;//TAD=4*TPB=167ns
    AD1CON3bits.SAMC=0b01111;//Samples for 15 TAD=2.5uS
    AD1CHSbits.CH0SA=0b1000;//Samples AN8
    IEC0SET=0x10000000;//ADC1 INterrupt enable
    AD1CON1bits.ADON=1;//Enable ADC
    //## END ADC Setup

    //**USB Setup
    //TODO
    //## END USB setup

    //###END pin setup

    //***Timer2 setup
    //This will generate an interrupt every 10 ms to change the display.
    T2CONbits.TCKPS=0b101;//1 Timer clock per 32 peripheral bus clocks
    PR2=3750; //Interrupt flag every 10 ms at pbclk=24mhz
    IEC0SET=0x0200;//Timer 2 Interrupt enable
    T2CONbits.ON=0b1;//enable timer

    asm("ei");//re-enable interrupts
    return;
}
2
1) We are not a debugging service. 2) "In brief, the wire disconnecting, TXEN disabling, and TX IF seem to indicate that it is not a hardware or connection issue, and that the PIC is in fact mirroring data it receives. However, the PIC never realizes that it receives the data, has no code to mirror data, nor is loopback enabled." - contradicts itself. So what is it? 3) Use a debugger.too honest for this site
Have you checked for flow control issues on the USB-Serial port? Without flow control from the PIC32, it might require RTS and CTS to be connected and require DTR, DSR and CD to be connected. This is a common problem with USB-Serial devices, and should be checked before debugging other code.janm
@Olaf I am using a debugger, and that description is accurate. To rephrase, the PIC sends data to the computer, but has no indication of where the data came from. Based on the data sent, it can only logically come from the computer in the first place, but there is no indication in the PIC's status or other registers that it received the data.LucenNox
@Olaf specifically, a pickit3LucenNox
@janm Looking at the hardware flow control, I'm seeing a few options. It looks like I should make sure the pins are in the correct states, and I might be able to short them to the correct state if they aren't. One page mentioned that this occurred with cheaper chips, so I might have to get an FTDI cable. I'd prefer to avoid messing with RTS/CTS if possible, due to pin constraints and that the device that UART will eventually be used to communicate with not having flow control. I'll be looking into this more tomorrow.LucenNox

2 Answers

0
votes

I use the pic32mz and along with the peripheral select registers I also set the pin direction. Something like

//UART2_RXl
TRISCbits.TRISC3 = 1; 
ANSELCbits.ANSC3 = 0;
U2RXR = 0b1100;
//UART2_TX
TRISGbits.TRISG9 = 0; 
ANSELGbits.ANSG9 = 0;
RPG9R = 0b0010;      
0
votes

You could try enabling the error interrupt and see it that triggers your Rx ISR? That might help you track down the issue.

IEC1bits.U1EIE = 1;

Otherwise there's a good example here, it's using the Microchip Peripheral Library, you need to download that separately on the newer xc32 compilers.

https://people.ece.cornell.edu/land/courses/ece4760/PIC32/PLIB_examples/plib_examples/uart/uart_interrupt/source/uart_interrupt.c

Plus, are you setting the Rx pin as an input? It's on PortC1 but I don't see you explicitly setting it as an input.