• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

26 bits wiegand encode problem

Status
Not open for further replies.

helloleong

New Member
Hi, im writing c-code to receive the 26 bits wiegand data in pulse wave form. PIC16F272, MPLAB IDE v8.50, MPLAB in circuit debugger ICD2, Hi-Tech ANSI C Compiler. And im using the PORTB interrupt to detect the card as the code below.

Code:
unsigned long int EMCardNo;

void interrupt isr(void) 
{
        CLRWDT();   //Clear watchdog timer
		
        //----- PORTB Interrupt -----//
	if (RBIE && RBIF && 0x30) //Mask off other bits
	{ 	
                temp=PORTB;  //Read PORTB
                temp&=0x30; //Leave only the necessary bit

                if(temp && 0x20) //D0=0
                {
		     EMCardNo=0;
		     EMCardNo=EMCardNo<<1;
		     EMCardNoCounter++;
                }
                else  //D1=0
                {
                     EMCardNo=1;
		     EMCardNo=EMCardNo<<1;
		     EMCardNoCounter++;
                }

		RBIF = 0; //Clear interrupt flag
		Delay_Routine(6); //Wait until pulse end 50usec
	}
}
RB5 is D0
RB4 is D1

The problem was when I sawp the card the module did generate 26 bits, but the PIC software only could capture until 6 bits. Im using the watch window and run to watch the bits. Something weird happen, when i change the EMCardNo to unsigned long int the counter at watch window didnot change at all but the EMCardNo did change its value, but the value was is not consistent for the same card.
And when i change to unsigned char, the EMCardNo and counter did change its value but not consistent also.

Did anybody face this problem before? Does it got to do with the c-compiler library? And how can i check on the simulator timing for the if condition to run how many sec?

Thanks everybody.
 

Pommie

Well-Known Member
Most Helpful Member
As the RB interrupt is edge triggered there is no need to have a delay in the ISR and this could be causing your problem.

Also, the lined if (RBIE && RBIF && 0x30) is if (bool && bool && true) and so the last term is redundant.

Not knowing what wiengand is and unable to google it, how do you know when one set of bits ends and another begins?

Mike.
 

helloleong

New Member
Hi, Mike. Thanks for your reply. At first im doin using polling base, but the pic cannot enter the if statement.
So I change to interrupt base by refering this Old Nabble - PIC - [PIC] - Wiegand decoding and reading

Thanks for your remind for if (RBIE && RBIF && 0x30), im trying to mask of other bit of portb, because other pin will use as capasitive sense button.
I do not want other pin trigger to enter this if statement.

The reader of 26bit wiegand will generate a 0 pulse when the card swap to the reader by 2 data line D1 and D0.
D1 and D2 will always stay high. When a card present, D1 and D0 will generate 0 pulse, D1=1, D0=0. And D1 and D0 will not generate 0 pulse at the same time.

Did anyone use MPLAB with Hi-tech C free version. I heard got alot of problem when compile.

Thanks
 

Pommie

Well-Known Member
Most Helpful Member
May I suggest a few changes to your code. By doing a bit of logic you can work out which bit caused the IOC interrupt to fire.

This code does that,
Code:
        temp=PORTB;      //Read PORTB
        changed=temp^previous;    //find only pins that have changed
        newhigh=changed&previous; //and have gone from low to high
        newlow=change&(~previous);//find pins that are new lows
        previous=temp;
After the above code newhighs will have a bit set for each pin that went from low to high and newlows from high to low. This eliminated the need for the delay.

So, your code would now look like,
Code:
unsigned long int EMCardNo;
unsigned char previous;

void interrupt isr(void) 
{
unsigned char changed,temp,newlow,newhigh;
    CLRWDT();   //Clear watchdog timer
		
        //----- PORTB Interrupt -----//
    if (RBIE && RBIF)    //Mask off other bits
    {     
        temp=PORTB;      //Read PORTB
        RBIF=0;          //clear interrupt

        changed=temp^previous;       //find only pins that have changed
        newhigh=changed&previous;    //and have gone from low to high
        newlow=changed&(~previous);  //find pins that are new lows
        previous=temp;

        if(newlow & 0x20) //D0 went low
        {
             EMCardNo=0;
             EMCardNo=EMCardNo<<1;
             EMCardNoCounter++;
        }
        if(newlow & 0x10) //D1 went low
        {
             EMCardNo=1;
             EMCardNo=EMCardNo<<1;
             EMCardNoCounter++;
         }
    }
}
Note that in your original code you had if(temp && 0x20) which will test if temp is none zero. To test bit 5 it should be if(temp & 0x20).

Mike.
 
Last edited:

helloleong

New Member
Thanks Mike, Now i have put a test port to test does it go into the PORTB interrupt. But it does not get in to it when i swap card.

GIE = 1; //Global Interupt Enable: Enables all unmasked interrupts

RBIE = 1; //Enables the PORTB change interrupt
RBIF = 1; //None of the PORTB general purpose I/O pins have changed state

I did set the PORTB interrupt bit as above, did i miss any thing? Still the same is PIC16F272.
 

Pommie

Well-Known Member
Most Helpful Member
It's almost impossible to find problems with snippets of code. However, only pins that are digital inputs can trigger the interrupt.

Also, there is no such chip as a 16F272.

Mike.
 

helloleong

New Member
Thanks Mike! :)
After i test the interrupt by adding test port. The below codes works, and able to capture the data constantly with the same card.
And i also disable all the interrupt to test the PORTB interrupt only.

Code:
GIE = 1;	//Global Interupt Enable: Enables all unmasked interrupts
RBIE = 1;	//Enables the PORTB change interrupt
RBIF = 1;	//Set interrupt flag (should be not set, but the MCU does not set it self when interrupt)

volatile unsigned long Wiegand=0;
volatile unsigned char WieCounter=0;

void interrupt isr(void) 
 {
	CLRWDT();   //Clear watchdog timer
	
	//----- PORTB Interrupt -----//
	if (RBIE && RBIF && (~PORTB & 0x30)) //mask off bits other than D0&D1 (RB5&RB4)
	{
		//RE2 = 0; //test port
		tempB = PORTB;
		tempB &= 0x30;
			
		if(tempB & 0x20) //D0 detect 0
		{ 
			Wiegand = Wiegand << 1;			
			WieCounter++;
			while(D0==0||D1==0){CLRWDT();} //Signal only capture once (delay)
		}
		else //D1 detect 0	
		{ 	
			Wiegand = Wiegand << 1;
			Wiegand |= 1;
			WieCounter++;
			while(D0==0||D1==0){CLRWDT();} //Signal only capture once (delay)
		}
	}	
}
But, now another problem arise. The watch window value keep on display Reserved Memory for the Wiegand as i assigned it as volatile unsigned long Wiegand=0;

Card Number 119,09292 (Decimal) - 02EE4899 (Hex)
Result:
Varieble Name Value
unsigned char 0x99
unsigned int 0x4899
unsigned short long Reserved Memory
unsigned long Reserved Memory

I search from the internet found the register place in the reserved register for debugger. How can i set to another register address?
Thank you so much.
 

helloleong

New Member
Thanks for everybody who help. Finally Done, will post the code here. Hope it will help other people as well.
Compiler : Hi-tech V9.70 V9.70 (PRO Mode) Trial version
IDE : MPLAB IDE V8.50
Debugger : MPLAB ICD 2
Device : PIC16F727

Code:
volatile unsigned char tempB=0;
volatile unsigned long Wiegand=0;
volatile unsigned char WieCounter=0;

// Initialize for PORTB Interrup-on-change
IOCB = 0b00110000;	// Interrupt-on-change enable for bit4 and 5
RBIE = 1;		// Enables PORTB change interrupt
RBIF = 0;		// Clear PORTB interrupt flag

void interrupt isr(void) 
 {
	CLRWDT();   //Clear watchdog timer
	
	//----- PORTB Interrupt -----//
	if (RBIE && RBIF && (~PORTB & 0x30)) 	// Mask off unnecessary bit
	{   CardDetected(); }			//END: PORTB Interrupt
	
	//----- Other TMR0 Interrupt -----// 
	if (T0IE && T0IF){
	//RD7=0; //Test port led

	 ..//If your other interrupt cause more than 50us, call again the CardDetected() Function
	}

void CardDetected(void)
{
	//RE2=0; 				//Test Port LED
	T0IE = 0;				//Disable other Timer0 Interrupt
	tempB = PORTB;			//Read PORTB
	tempB&= 0x30;			//Mask off unnecessary bit
		
	if(tempB & 0x20) 			//DO detect 0
	{
		Wiegand = Wiegand << 1;	
		WieCounter++;
		while(D0 == 0 || D1 == 0); 	//Wait until D0 return to 1
			
		if(WieCounter == 26)
		{
			T0IE = 1;		//Enable other Timer0 Interrupt
			Wiegand = Wiegand & 0x03FFFFFF; //Mask off unnecessary bit
                                                WieCounter = 0;
		}
	}
	else 				//D1 detect 0
	{
		Wiegand = Wiegand << 1;
		Wiegand |= 1;
		WieCounter++;
		while(D0 == 0 || D1 == 0); 	//Wait until D1 return to 1
			
		if(WieCounter == 26)
		{
			T0IE = 1; 		//Enable Timer0 Interrupt
			Wiegand = Wiegand & 0x03FFFFFF; //Mask off unnecessary bit
                                                WieCounter = 0;
		}
	} RBIF = 0;
}
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top