Continue to Site

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.

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

PORTA Problems on PIC16F886

Status
Not open for further replies.

beeson76

New Member
I am using a PIC16F886 to interface with a LCD and 12 switches. When a switch is pushed, it comes up on a the LCD. Well I have 8 switches tied to pins on PORTB and Im using the internal pullup resistors. On PORTA I am using RA1,2, 4 for the control lines to the LCD and PORTC for the data lines.

I have 4 switches on RA0, 4, 5, 6. Whenever I push a switch on these 4 pins, it displays on the LCD but it doesnt go away. It just kinda locks up. Here is my code, but I think it is more of a hardware problem or config problem. And help is greatly appreciated.


I may have figured out what is wrong with it, but I need help fixing the problem now

I am getting on PORTA along with PORTB 5 volts from pin to ground.

When I hit a switch on PORTB is goes to 0 volts. Which is good I think

When I hit a switch on PORTA is goes to 0 volts, but it never gets released. Therefore it acts like a constant switch push.

Any suggestions on how I can fix it, please?

Code:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Whenever a switch is pushed, that switches name is displayed on an LCD Display.
//Here are the names of the Buttons:
//
//Name						--	Wire			Pin on Connector		Pin on Microchip PIC16F886
//			
//							--	Red/Black		1						RC4						
//							--	Pink/Black		2						RC5
//							--	Black			8						Tied to Ground
//	 						--	White/Black		9						RC6
//							--	Orange/Black	10						RC7
//							--	Gray			11						RB0
//							--	Tan				12						RB1
//							--	White			13						RB2
//							--	Orange			14						RB3
//							--	Brown			15						RB4	
//							--	Pink			3						RB5
//							--	Dark Blue		4						RB6
//							--	Light Blue		5						RB7
//
//The PIC16F886 Microcontroller from Microchip is being used.
//2x16 LCD Display being used
//
//Programming was tough for this because of LCD concerns.  I had to program so that the LCD would not blink constantly
//(refresh).  That is why I had to use the while statement as an interrupt.  Also lcd_clear() when put into the program
//was a big reason for this blink (ecspecially it being in a while statements that constantly loops.  Everytime it 
//hit the lcd_clear() function, it would refresh (blink).  Therefore inside the 3 nested while loop, I had to make it
//so that it only cycled 1 time--only one time in order for it to clear the "10LKGN..." for the first line and "PLEASE..."
//for the second line.  The only way I could think of doing it is to create the "char b" variable and keep it outside the 
//third nested while loop (it is located in the main while loop under "b = 0;"  This resets char b so that it can be used
//again in a different while loop.  In the inner nested while loop, at the end, I make "b = 1;"  Because of this statement, 
//the lcd_clear() statement is only cycled once.
//
//Programmed into this program is a debounce of 10 ms.  It is a very simple debounce statement.  It mainly consists of
//a while statement with a debounce statement followed by another while statement.  The first while statement test to see
//if a button is pressed.  If a button is pressed, a pause of 10ms is done, followed by another check of the button press.
//If the button is stilled pressed, the while loop continues.  If the button is not pressed, the while loop is broken 
//and it jumps back to the next while loop and tests again.  Therefore the debounce in this program is 10ms.
//
//Please noticed commented out lines.  There may be some left in, so further development can take place.  Further development 
//may consists of ideas or thoughts that are not yet programmed.  There may also still be left in this program some statements 
//that simply don't do anything.  This is also left in so further development may take place.
//
//If the whole program is not commented out, it is simply because of rehashing the same thing over and over again.  I 
//commented out the first part, so everything after that is the same comments except specifically changing specific names.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define _LEGACY_HEADERS
#include <htc.h>
#include "lcd.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////DEFINE STATEMENTS
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define SW1			RA0
#define	SW2			RA3
#define	SW3			RA5
#define SW4			RA6
#define	SW5			RB0
#define	SW6			RB1
#define SW7			RB2
#define SW8			RB3
#define SW9			RB4
#define SW10		RB5
#define SW11		RB6
#define SW12		RB7

#define DelayS(T)		{unsigned char i; for (i = 0; i < T * 10; i++) __delay_ms(100);}	//Delay Macro
#define _XTAL_FREQ				4000000								//Needs to be set for __delay_ms
//#define DEBOUNCE		10*1000/256									//Switch Debounce Count = 10ms/(256us/tick)
//#define DEBOUNCELOW(PIN)

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////CONFIGURATION FUSES (BITS)
////Master Clear Reset enabled & Internal RC No Clock & Watchdog Timer Disable & Power Up Timer On & Brown Out Reset Disabled &
////Low Voltage Porgramming Disabled & Code Unprotect
__CONFIG (MCLREN & INTIO & WDTDIS & PWRTEN & BORDIS & LVPDIS & UNPROTECT);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


main()
{
//PORTA = 0x00;										//PORTA is cleared	
PORTA = 0xE9;										//(ob11101001 binary) (0xE9 hex)
													//PORTA7:A0 is set to high,high,high,low,high,low,low,high
													
PORTB = 0x00;										//PORTB is cleared
PORTB = 0xFF;										//(0b11111111 binary) (0xFF hex)  
													//PORTB7:B0 is set to high,high,high,high,high,high,high,high
													
PORTC = 0x00;										//PORTC is cleared
PORTC = 0xF0;										//PORTC is set to high, high, high, high, low, low, low, low


TRISA = 0xE9;										//(0b11101001 binary)	(0xE9 hex)
													//LCD--RA1, RA2, RA4 are Control lines for LCD
													//RA0, RA3, RA5, RA6 are set for switches
													//PORTA7:A0 is set to input,input,input,output,input,output,output,input

TRISB = 0xFF;										//(0b11111111 binary) (0x7C hex)
													//All of PORTB are set for switches
													//PORTB7:B0 is set to input,input,input,input,input,input,input,input
												

TRISC = 0x00;										//(0b00000000 binary) (0x00 hex)
													//All of PORTC is set for LCD
													//PORTC7:C0 is set to output,output,output,output,output,output,output,output
													

ANSEL = 0;											//Initialize A/D Ports off
ANSELH = 0;											//Initialize ........
//ADCON0 = 0;
//ADCON1 = 0;
CM1CON0 = 0;										//Initialize Comparator 1 off
CM2CON0 = 0;										//Initialize Comparator 2 off

OPTION = 0b01010101;								//OPTION REG
													//xbxxxxx101  1:64
													//xbxxxx0xxx  Prescaler set to Timer0
													//xbxxx1xxxx  (T0SE) set to Increment on high-to-low transition on T0CKI pin
													//xbxx0xxxxx  (T0CS) Internal instruction cycle clock
													//xbx1xxxxxx  (INTEDG) Interrupt on rising edge of INT pin
													//xb0xxxxxxx  (RBPU) PORTB pull-ups are enabled by individual PORT latch values
RBPU = 0;											//Don't think I need this, but to be safe...PORTB Weak Internal Pullups enabled
WPUB0 = 1;											//COL_1 Weak pullup is individually ENABLED--INPUT 
WPUB1 = 1;											//COL_2 Weak Pullup is inidivdually ENABLED--INPUT
WPUB2 = 1;											//Not being used...Weak Pullup is individually ENABLED
WPUB3 = 1;											//ROW_1 Weak Pullup is individually ENABLED--INPUT
WPUB4 = 1;											//ROW_2 Weak Pullup is individually ENABLED--INPUT
WPUB5 =	1; 											//ROW_3 Weak Pullup is individually ENABLED--INPUT
WPUB6 = 1;											//ROW_4 Weak Pullup is individually ENABLED--INPUT
WPUB7 = 1;											//COL_3 Weak Pullup is individually ENABLED--INPUT


lcd_init();											//LCD Display is Initialized...See LCD.C file and LCD.h
lcd_clear();

char a;													//
char b;													//

while (1)
	{
		lcd_goto(0);									//Go to Line 1 Position 1
		lcd_puts("Hello");								//Display ""
		lcd_goto(40);									//Go to Line 2 Position 1
		lcd_puts("Press Button");						//Display "Press Button"
		b = 0;
		
		while (SW1 == 0)								//While SW1 is 0(Low)(Pressed)...
			{
				__delay_ms(10);							//Delay 10 ms (Switch Debounce)
				while (SW1 == 0)						//Check to see if SW1 is low after Debounce
					{
						for (a = b; a < 1; a++)			//For Statement to cycle lcd_clear only once
							{
								lcd_clear();			//lcd_clear should only cycle once because a = (b = 0)
							}
				
						lcd_goto(0);					//On LCD go to Position 1 (Line 1, Position 0)
						lcd_puts("SW1 Pressed");		//Display ""
						b = 1;							//Char B is now 1 so For Statement cycles once
					}
			}
		while (SW2 == 0)								//While ROW_2 is 0(Low)(Pressed)...
			{											//
				__delay_ms(10);							//
				while (SW2 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...		
						lcd_goto(0);					//...
						lcd_puts("SW2 Pressed");		//Display ""
						b = 1;							//
					}									//
			}											//
		while (SW3 == 0)								//While ROW_1 is 0(Low)(Pressed)...
			{											//
				__delay_ms(10);							//
				while (SW3 == 0)						//
					{									//...
						for (a = b; a < 1; a++)			//
							{							//	
								lcd_clear();			//...
							}							//...
						lcd_goto(0);					//...
						lcd_puts("SW3 Pressed");			//Display ""
						b = 1;							//
					}									//
			}											//
		while (SW4 == 0)								//If ROW 4 is LOW
			{											//...
				__delay_ms(10);							//
				while (SW4 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...
						lcd_goto(0);					//...
						lcd_puts("SW4 Pressed");			//Display ""
						b = 1;							//
					}									//	
			}											//
				
		while (SW5 == 0)								//and If ROW 1 is LOW...
			{											//...
				__delay_ms(10);							//
				while (SW5 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...
						lcd_goto(0);					//...
						lcd_puts("SW5 Pressed");		//Display ""
						b = 1;							//
					}									//
			}											//
		while (SW6 == 0)								//if ROW 2 is LOW...
			{											//...
				__delay_ms(10);							//
				while (SW6 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...		
						lcd_goto(0);					//...
						lcd_puts("SW6 Pressed");		//Display ""
						b = 1;							//
					}									//
			}											//
		while (SW7 == 0)								//
			{											//...
				__delay_ms(10);							//
				while (SW7 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...
						lcd_goto(0);					//...
						lcd_puts("SW7 Pressed");		//Display "SW7"
						b = 1;							//
					}									//
			}											//
		while (SW8 == 0)								//
			{											//...
				__delay_ms(10);							//
				while (SW8 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...
						lcd_goto(0);					//...
						lcd_puts("SW8 Pressed");		//Display ""
						b = 1;							//
					}									//
			}											//
				
		while (SW9 == 0)								//and If ROW 1 is LOW...
			{											//...
				__delay_ms(10);							//
				while (SW9 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...
						lcd_goto(0);					//...
						lcd_puts("SW9 Pressed");		//
						b = 1;							//
					}									//
			}											//
		while (SW10 == 0)								//
			{											//...
				__delay_ms(10);							//
				while (SW10 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...		
						lcd_goto(0);					//...
						lcd_puts("SW10 Pressed");		//Display ""
						b = 1;							//
					}									//
			}											//
		while (SW11 == 0)								//
			{											//...
				__delay_ms(10);							//
				while (SW11 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...
						lcd_goto(0);					//...
						lcd_puts("SW11 Pressed");		//Display ""
						b = 1;							//					
					}									//
			}											//
		while (SW12 == 0)								//
			{											//...
				__delay_ms(10);							//
				while (SW12 == 0)						//
					{									//
						for (a = b; a < 1; a++)			//
							{							//
								lcd_clear();			//...
							}							//...
						lcd_goto(0);					//...
						lcd_puts("SW12 Pressed");		//Display ""
						b = 1;							//
					}									//
			}											//
		
	}													//
}														//
 
Hi, if you have a multimeter you can check the pins on the uC itself, it'll indicate which one is "latching". Have you tried external pull-up (or pull-down?) resistors?
Cheers.
 
Before the press of the switch, the button is high...around 5 volts. At pressing the button, the voltage drops to zero. But when I let up on the button, the 0 voltage still remains. I guess it doesnt unlatch. Any reason why you think it would do that? Does it sound like hardware or software as the problem? It happens on the whole PORTA, but PORTB which has 8 switches works just fine.

I appreciate you help very much.

Thanks.
 
Last edited:
dude, I'm troubleshooting the same thing here. Probably your pull up resistors need to be of a certain value range. usually you need to consider the effect of voltage division for an input. A PIC's threshold is around 3V. So a ratio of resistor network from Vcc to Gnd need to be of the properly configured too. Hope this helps.
 
I am using momentary switches.

@Vizier87. Can you be more specific. I am still pretty new at this. So your saying I shouldn't be using 10k resistors, but rather smaller resistors.

Thanks for you help.
 
I am using momentary switches.

@Vizier87. Can you be more specific. I am still pretty new at this. So your saying I shouldn't be using 10k resistors, but rather smaller resistors.

Thanks for you help.

I thought you'd knew this but I'm posting this anyway:
**broken link removed**

So basically you need to configure your resistors in a way which allows the output to be more than 3.0V when the switch is turned on. I had for mine: R1= 1-10k and R2= 47-100k for a nice output. But this is for an active-high config, if yours is an active low, then you can do the math. :)
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top