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;
}