0
\$\begingroup\$

I am struggling in trying to put a UART Port working (no flow control and no parity bit) in a PIC32MX in order to comunicate with a Fingerprint for too long, so I decided to get back to you guys. I just can put the fingerprint reader in digital I/O's because I have no more UART PORTs available. There's no problem for the TX pin but when it comes to enable RX pin (CN interrupt) I am seeing a problem.

This is the Fingerprint Reader I am using an this is the datasheet for the PIC.

I am using the CN4/RB2 Port for the Interrupt (Rx) and the RB0 to transmit. The compiler is XC32.

#include "NVMem.h"
#define Baudrate        4800   //bps
#define OneBitDelay     (1000000/Baudrate)  // microseconds
#define DataBitCount          8             // no parity, no flow control
#define UART_RX               TRISBbits.TRISB2  // UART RX pin
#define UART_TX               LATBbits.LATB0    // UART TX pin
#define UART_RX_DIR           TRISBbits.TRISB2 // UART RX pin direction
#define UART_TX_DIR           TRISBbits.TRISB0 // UART TX pin direction

int volatile readB = 0;
unsigned char UART_Receive(void);
void UART_Transmit(const char);

void __ISR(_CHANGE_NOTICE_VECTOR, ipl5) ChangeNoticeHandler(void)
{
readB = PORTB;      // Read PORTB to clear CN4 mismatch condition
if (readB){
    UART_Transmit(UART_Receive());
}

LATDINV = 0x0F;     // PORTG = 0xff;    // Toggle outputs.
IFS1CLR = 0x0001;   // Be sure to clear the CN interrupt status
}

unsigned char UART_Receive(void)
{
unsigned char DataValue = 0;
    unsigned char i = 0;

while(UART_RX==1);
delay_us(OneBitDelay);
delay_us(OneBitDelay/2); 
for (  i = 0; i < DataBitCount; i++ )
{
    if ( UART_RX == 1 )   //if received bit is high
    {
        DataValue += (1<<i);
    }
    delay_us(OneBitDelay);
}
if ( UART_RX == 1 )       //Stop bit should be high
{

        return DataValue;
}
else                      //some error occurred !
{
        delay_us(OneBitDelay);
        return 0x000;
}
}


void UART_Transmit(const char DataValue)
{
/* Basic Logic
   TX pin is usually high. A high to low bit is the starting bit and
   a low to high bit is the ending bit. No parity bit. No flow control.
   BitCount is the number of bits to transmit. Data is transmitted LSB     first.
*/
// Send Start Bit
UART_TX = 0;
delay_us(OneBitDelay);
unsigned char i;

for ( i = 0; i < DataBitCount; i++ )
{
    //Set Data pin according to the DataValue
    if( ((DataValue>>i)&0x1) == 0x1 )   //if Bit is high
    {
        UART_TX = 1;
    }
    else      //if Bit is low
    {
        UART_TX = 0;
    }
    delay_us(OneBitDelay);
}

//Send Stop Bit
UART_TX = 1;
}


void FingerprintRun(Task * task){
 CNCON = 0x8000;                 // Enable CN module

 CNEN = 0x00000010; // Enable individual CN pin CN4
 CNPUE = 0x00000010; // Enable weak pull up for pin CN4

 UART_TX = 1;           // TX pin is high in idle state
 UART_RX_DIR = 1;       // Input
 UART_TX_DIR = 0;       // Output

 readB = PORTB;

 IPC6SET = 0x00140000; // Set priority level=5
 IPC6SET = 0x00030000; // Set Subpriority level=3

 IEC1SET = 0x0001; // Enable Change Notice interrupts

UART_Transmit ('H');
UART_Transmit ('i');
UART_Transmit ('\r');

while(UART_RX==0){
    asm("nop");
}

while(1)
    {
    }
}

While debugging the Program Counter never goes to the interrupt.

\$\endgroup\$
9
  • \$\begingroup\$ usually you use an RX char interrupt source from the UART module rather than individual pin interrupt. Also see this question: electronics.stackexchange.com/questions/135638/… \$\endgroup\$
    – Icy
    Commented Jan 14, 2016 at 15:37
  • \$\begingroup\$ Well I am not using the RX interrupt source from the UART module because I have no more available. Not only this, I have no PPS (peripheral pin select) in this Pic. I am reusing an old design. \$\endgroup\$
    – scuba
    Commented Jan 14, 2016 at 15:41
  • \$\begingroup\$ Don't understand? Why no more available? \$\endgroup\$
    – Icy
    Commented Jan 14, 2016 at 15:43
  • 1
    \$\begingroup\$ @Icy I think he's trying to bit-bang a 'software UART', but I don't see any attempt to read or write bits at any particular baud-rate - no delays or timing anywhere in the code ... \$\endgroup\$
    – brhans
    Commented Jan 14, 2016 at 15:55
  • 1
    \$\begingroup\$ I don't think there are ready-made delay_us/delay_ms functions in XC32 for the PIC32. microchip.com/forums/m769139.aspx has some info on writing your own. \$\endgroup\$
    – brhans
    Commented Jan 14, 2016 at 16:26

1 Answer 1

1
\$\begingroup\$

your line: CNEN = 0x00000010; // Enable individual CN pin CN4

should be: CNEN = 0x00010000; // Enable individual CN pin CN4

and similar for CNPUE

You also need to implement timing in your software as per @brhans comments

Using delays in your interrupt routine is not be good practice - the CPU will not be able to do any other processing - including responding to other interrupts, in the time it takes to read each character, much better to start a timer and sample the port bit on that timers interrupt.

\$\endgroup\$
1
  • \$\begingroup\$ So can you give me a brief explanation of how to use the timer in this case. \$\endgroup\$
    – scuba
    Commented Jan 14, 2016 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.