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