Monday, 30 May 2016

microcontroller - Fingerprint Reader on Pic32mx


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



Answer



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.


No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...