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.

Pic16f877a function generator project...

Status
Not open for further replies.

si2030

Member
Dear All,

This is the thread I will be sticking with, with regard to this project I am working on from now on. I have included a picture of the dev board I have built and the schematic as well.

Some background. I decided to start this project as I needed a function generator for other projects and yes I could actually buy one for a bit of money and no time but I thought what was the fun in that... so my real driver was to learn something... start a challenging project and something might rub off.

There are a number of projects out there on this subject however I chose to base mine on another project which can be found here... It was very good but used two PIC chips and I thought it might be a good idea to work this from just one chip... to this end I have built a development board for which I have included a picture... Further I am including the schematic as well.

IMG_2490_1.JPG schematic.jpg


All is going fairly well but alas I find myself floundering again.... and again its to do with the interrupt routine.

Here is my current problem...

I have both the keyboard and the encoder working off PORTB. The keyboard connects via RB7-4 to RD7-4 and the encoder attaches to RB0/1.

For the keyboard I have set weak pullups (set in PIC_INT) so when a user presses a button they connect a pin in RB7-4 to a pin in RD7-4 all of which are held to "0".

I have to stress it all works perfectly when I set the inputs for PORTB as B'11110000' in the PIC_INT or (pic initialisation routine) - see below:

Code:
PIC_INIT
		clrf	STATUS		; DO INITIALIZATION, SELECT BANK 0
		clrf	INTCON		; CLEAR INT-FLAGS, DISABLE INTERRUPTS
		clrf	PCLATH		; KEEP IN LOWER 2KBYTE
	
		clrf	PORTA		; ALL PORT OUTPUT SHOULD OUTPUT LOW.
		clrf	PORTB		; ALL PORT OUTPUT SHOULD OUTPUT LOW.
		clrf	PORTC		; ALL PORT OUTPUT SHOULD OUTPUT LOW.
		clrf	PORTD		; ALL PORT OUTPUT SHOULD OUTPUT LOW.
		clrf	PORTE		; ALL PORT OUTPUT SHOULD OUTPUT LOW.
	
		bcf		STATUS, RP1	; FOR BANK 1 RP1=0 RP0=1.
		bsf		STATUS, RP0	; SELECT BANK 1.
	
		clrf    PORTB		;LATCH ALL LOW.
		movlw   B'11110000'	;RB4-RB7 INPUTS. 
		movwf	TRISB	
			
		movlw	B'00000000'	; RD4-7 INPUTS.
		movwf	TRISD
		
		bcf		OPTION_REG, NOT_RBPU	
							;ENABLE WEAK PULL-UPS.
							;ON PORT B.
	
		bcf		STATUS, RP1	; FOR BANK 0 RP1=0 RP0=0.
		bcf		STATUS, RP0	; SELECT BANK 0.

		bcf		STATUS,IRP	;MAKING SURE THAT THE FIRST PAGE OF THE FSR
							; IS SELECTED.
		
		return

HERE IS MY ISSUE:

If I now change the setting of PORTB so it recognises RB0/1 as inputs:

Code:
movlw   B'111100[COLOR="red"]11[/COLOR]'	;RB4-RB7 INPUTS. 
		movwf	TRISB

It locks up and does not interrupt for the keyboard. However if I turn the encoder it interrupts perfectly..

I have tried all manner of things to try and get this to work (pretty much the whole of last week) but I cannot figure this out. I even tried to set the PINS RD7-4 high and not set the weak pullups for PORTB and then, in the interrupt set the RD7-4 pins low and then turn on the weak pullups and then test for the key... this also didnt work...

Incidentally, the interrupts are set in the routines:

1.3 EE_FREQ_DOESNT_EXIST
1.4 EE_FREQ_EXISTS

NOTE: if no values are detected in the EEPROM then the encoder interrupt is disabled... that is the encoder is only enabled in EE_FREQ_EXISTS and once the user enters freq the encoder interrupt is enabled. To test this I loaded an frequency into the EEPROM of 100. To do this I set 07 = 0 06 = 0 and 05 = 01. The rest I left as "FF".

From what I see this is all about the interrupt routine (maybe) and you do not have to delve into any of the other code which is now quite long... but works.... I have included the .ASM FILE as well as the three include files.

View attachment FUNCTION GENERATOR 1-3.zip


I am hoping someone might look at the interrupt routine or the PIC_INITALISATION routine and see an obvious problem... its most probably something really simple.

I sincerely hope someone can help me here...

Kind Regards

Simon
 
Issue Synthesized...

Hi there,

I have decided to go back to basics. I have created a much simplified cut down version of my full program focusing on the interrupt and simply flashing LEDS if an INTERRUPT occurs.

The problem I am now having with this set up is that the interrupt doesnt work at all.

How I think it should work:

1. The PIC is initialised - Sets PORTB to the following B'11110011' (makes RB7-4 RB0/INT RB1 all inputs) sets RD7-4 high.

2. Goes to MAIN where it sets RD7-4 high. Sets the INTERRUPTS ON (RBIE and INTE) clears RBIF and INTF.

3. Goes to LOOP.... waiting for an interrupt.

4. An INTERRUPT occurs. Sets a flag and returns. Using a btfsc the flag sends the program to a small branch where it clears the INTERRUPT flag set in the INTERRUPT routine.


Pretty simple really except all the LEDs flash at the start (that works) and then nothing... press a button and.. nothing :(

Stepping through the program indicates it should work....


I am setting RD7-4 high and making RB7-4 low and inputs. I have 4x4 keyboard connected. If I press a button then there is a connection made between one of the high RD7-4 pins to one of RB7-4 input pins.. if a rise occurs (PORTB weak pullups have been disabled) as a result of making this connection from RD7-4 (set to 5V) then there should be an interrupt.

There is are three lines of code that wait for PORTB to be cleared in the interrupt.

Code:
BUTTONS_CLEAR
		movf	PORTB,F
		btfss	STATUS,Z
		goto	BUTTONS_CLEAR


By the way the LEDs are also on PORTD but on RD3-0. However when they are reset I make sure RD7-4 is still high.........

Its probably something simple.

I have included the .ASM file.
View attachment INTERRUPT 2-0.asm

Hoping someone will have a look.

Kind Regards

Simon
 
hi Simon,
I will try your program in Oshonsoft later today.
I hope its complete.

EDIT:
I think most PICs are 8 bit not 9...;).......... more to come later.
Code:
FLASH        
        movlw    B'111111111'    ;RD4-7 HAVE LEDS ON THEM (DEV BOARD) SET THESE
                            ;PORTS HIGH.
        movwf    PORTD        ;NOW SEND THIS TO THE ACTUAL PORT
        call    WAIT_15MS    ;FLASH FOR 15MS.
        movlw    B'11110000'    ;NOW TURN THEM OFF.
        movwf    PORTD        ;SEND THIS TO THE ACTUAL PORT AGAIN.
        call    WAIT_64MS    ;FLASH FOR 15MS.        
        return

FLASH2        
        movlw    B'111111100'    ;RD4-7 HAVE LEDS ON THEM (DEV BOARD) SET THESE
                            ;PORTS HIGH.
 
Last edited:
hi Simon.
In Oshonsoft the Interrupt is called OK, every time a high occurs on PORTB 7 thru 4, it waits in the BUTTON loop until the PORTB goes low, works it way thru the ISR and then goes to the LOOP subr and waits for the next PORTB change.
The ISR is called on every PORTB ok.
 
Hi Eric,

Hey I was wondering how you would set this project up in Oshonsoft... I have looked at this and it seems really good to work with.

(Struth I seem to be having trouble counting to 8 :( )
 
Hi Eric,

Hey I was wondering how you would set this project up in Oshonsoft... I have looked at this and it seems really good to work with.

(Struth I seem to be having trouble counting to 8 :( )

hi,
Do you have Oshonsoft installed in your PC.?
 
I had it a couple of weeks ago but completely reinstalled the computer a few days ago... I can re download it tonight with no problem...

On the other issue above... I checked the voltage at RB7-4 and all four pins read 1.33V... and this was with the Keyboard removed.. I would have thought these should read 0volts...
 
I had it a couple of weeks ago but completely reinstalled the computer a few days ago... I can re download it tonight with no problem...

On the other issue above... I checked the voltage at RB7-4 and all four pins read 1.33V... and this was with the Keyboard removed.. I would have thought these should read 0volts...

hi,
As you are aware the PORTB7-4 pins have been set as inputs, so how do you pull up these pins with your keypad.?
Measuring open circuit inputs will not give the readings you would expect, they are floating.


EDIT:
Looking at your circuit diagram It appears the PORTB inputs are floating until a key is pressed.?????
 
Last edited:
So if I wanted a system where PORTD was 5Volts and PORTB7-4 was to sit at 0 volts then I need to pull these pins down... say a 10k resister to deck? Would this give me the outcome where you press a key and send those PORTB7-4 pins high?
 
Just thinking about this... In my original design I have used the weak pull up option available as a software setting but it pulls up ALL PINS in PORTB. Having the encoder on PORTB1-0 and having weak pullups with the encoder's middle pin grounded might cause the interrupt to fire on the INTE... I am not sure though..

OK In the larger project above I set the INTE interrupt to 0 and it still failed to work when I made RB0/INT and RB1 to Inputs...
 
Last edited:
Just thinking about this... In my original design I have used the weak pull up option available as a software setting but it pulls up ALL PINS in PORTB. Having the encoder on PORTB1-0 and having weak pullups with the encoder's middle pin grounded might cause the interrupt to fire on the INTE... I am not sure though..

OK In the larger project above I set the INTE interrupt to 0 and it still failed to work when I made RB0/INT and RB1 to Inputs...

hi,
If the intention is to pull up the PORTB 7~4 pins when you press a key, then if you have used weak pull ups this means they are high already.
I would suggest 10K pull downs and 1K pull up via the key contacts.
If you have set the PORTB to interrupt on any change of state on PORTB , you should read the PORTB to clear a mismatch.
 

Attachments

  • AAesp02.gif
    AAesp02.gif
    13.3 KB · Views: 191
Last edited:
Thanks for replying... :)

This issue arose when I set the RB0/INT RB1 pins to inputs on the project at the top of the page. In that example I had already set all of PORTB with weak pullups. When I set these two pins to inputs the system failed to register any keypad interrupts. If I set RB0/INT and RB1 back to outputs it worked perfectly for RB7-4. I have been scratching around for a week trying all manner of things to have both the encoder and the keypad working at the same time but so far no success. I got to thinking I might run all pins low with RD7-4 high and rewrite the keypad routine to determine the key pressed.... so I have been exploring every option I can think of and today I started from scratch with the simple interrupt program... it works on the PC but not on the board. It seemed like a good idea to take out the weak pullups and work from the other way... that is with all pins in PORTB set to ground or (now I know) pulled down.

Do you think not pulling those RB7-4 pins low stopped it from working? ... and is this the best way to have both the encoder and the keypad work via interrupts off PORTB?

Simon
 
Thanks for replying... :)

This issue arose when I set the RB0/INT RB1 pins to inputs on the project at the top of the page. In that example I had already set all of PORTB with weak pullups. When I set these two pins to inputs the system failed to register any keypad interrupts. If I set RB0/INT and RB1 back to outputs it worked perfectly for RB7-4. I have been scratching around for a week trying all manner of things to have both the encoder and the keypad working at the same time but so far no success. I got to thinking I might run all pins low with RD7-4 high and rewrite the keypad routine to determine the key pressed.... so I have been exploring every option I can think of and today I started from scratch with the simple interrupt program... it works on the PC but not on the board. It seemed like a good idea to take out the weak pullups and work from the other way... that is with all pins in PORTB set to ground or (now I know) pulled down.

Do you think not pulling those RB7-4 pins low stopped it from working? ... and is this the best way to have both the encoder and the keypad work via interrupts off PORTB?

Simon
hi,
Can you post a sketch of the keypad circuit showing how its connected to the PORT's?
 
Hi Eric,

Below are the connections for the keypad... There is a 2.2k resistor between the keypad and RD7-4

"FROM THE DATASHEET"

Output Pin
1 COL 1
2 COL 2
3 COL 3
4 COL 4
5 ROW 1
6 ROW 2
7 ROW 3
8 ROW 4

As its connected on the board.

Code:
;    keypad
;                     rb4        rb5         rb6          rb7
;                      |          |           |            |
;                      |          |           |            |
;                      |          |           |            |
;
;                    col 1       col 2       col 3        col 4   
;                 +---------+  +--------+  +--------+   +--------+  
; rd4-------row 1 |    1    |  |   2    |  |   3    |   |   a    |
;                 +---------+  +--------+  +--------+   +--------+ 
;                 +---------+  +--------+  +--------+   +--------+  
; rd4-------row 2 |    4    |  |   5    |  |   6    |   |   b    |
;                 +---------+  +--------+  +--------+   +--------+ 
;                 +---------+  +--------+  +--------+   +--------+  
; rd4-------row 3 |    7    |  |   8    |  |   9    |   |   c    |
;                 +---------+  +--------+  +--------+   +--------+  
;                 +---------+  +--------+  +--------+   +--------+  
; rd4-------row 4 |    *    |  |   0    |  |   #    |   |   d    |
;                 +---------+  +--------+  +--------+   +--------+

Here is the schematic showing the resistors being connected.
Schematic..jpg

Hope this helps

Simon
 
Well I think I have this working at its most basic level... I will have to do more work to make sure though. Basically what I had wrong was that none of the PORTB inputs were pulled down so they were floating. I therefore added 10k resistors to each of those pins that were inputs. I also rewired the encoder to have its middle leg go to 5V and also I placed these lines

Code:
bcf		INTCON,RBIF	;CLEAR INTERRUPT ON RB4-7 CHANGE.
		bcf		INTCON,INTF	;CLEAR INTERRUPT FLAG.

within the interrupt routine rather than outside of it...

However the encoder doesnt respond properly yet but thats more coding and a change in resistors I think...
 
OK I have Debounce issues...

Hi Guys,

I have this working however if I hold down a keypad key it continues to register the key entry.

I have tried to identify the key up which should then mean that it should hang until the key is fully up however it continues to register the key press after this check.

PortB is set for inputs as follows:

Code:
movlw   B'11110011'	;RB4-RB7 INPUTS. 
		movwf	TRISB

...and the debounce routine is so....

Code:
BUTTONS_CLEAR
		call WAIT_32MS

		movf	PORTB,W
		andlw   B'11110000'	;MASK OFF BOTTOM NIBBLE (ENCODER USES FIRST 2 BITS).
		movwf	TEMP
		btfss	STATUS,Z
		goto	BUTTONS_CLEAR

		call WAIT_128MS

		bsf		INTCON,GIE	; ENABLE INTERRUPTS.

The idea being that RB1-0 are different interrupts so should be masked off... The delays should provide enough time for the debounce of the key but it doesnt... If I hold down the key the interrupt continues to be fired.

Is there a better way to do this?

Simon
 
Issues with Pages and PCLATH.. I think.

Hi there,

The code further below works correctly in that it accesses locations in a table based on code set in page 00 and then a call to page 01.... As I am working in the second page I have set PCLATH manually to 01 except where I am calling any routines in page 00 where I manually set PCLATH back to 00.

Why is it that I have to still use "lcall" in page 01 but only need to use "goto"? Why doesnt using "call" work when I am moving to a routine in the same (01) page?

If I set PCLATH twice in a row to 01 (or a few lines further down in the code) - that is:

Code:
		movlw	H'01'			
		movwf	PCLATH

.. a few lines of code here...

Code:
		movlw	H'01'			
		movwf	PCLATH

The code then fails. I would have thought the second setting would simply be redundant... what is the significance of this (and PCLATH that I am not aware of)... doesnt setting PCLATH to 01 simply set it to the second 2048 page?

Simon






Code:
	org H'900'
TABLE1:
		addwf	PCL,	F

STR_0:
		DT "DUMMY"
		retlw H'00'
	
STR_1:
		DT "  DDS FUNCTION", H'FF',"GENERATOR VER1.0"
		retlw H'FB'
		retlw H'00'

STR_2:
		retlw H'FC'
		DT "No EEPROM value"
		retlw H'FF'
		DT "stored..."
		retlw H'FB'
		retlw H'00'
					
STR_3:
		retlw H'FC'
		retlw H'FE'
		retlw H'0E'
		DT "Hz"
		retlw H'00'
	
STR_4:
		retlw H'FF'
		DT "# Enter new FREQ"
		retlw H'00'
		
STR_5:
		retlw H'FF'
		DT "# Displayed FREQ"
		retlw H'00'

STR_6:
		retlw H'FF'
		DT "#Entr new EE FRQ"
		retlw H'00'

STR_7:
		retlw ','		
		retlw H'00'
		
STR_8:
		retlw H'FC'
		retlw H'FE'
		retlw H'0E'
		DT "Hz"
		retlw H'FF'
		DT "Entr 1st Num > 0"
		retlw H'00'
		
STR_9:
		retlw H'FC'
		retlw H'FE'
		retlw H'0E'
		DT "Hz"
		retlw H'FF'
		DT "FREQ TO BIG!"
		retlw H'FB'
		retlw H'FF'
		DT "Enter Freq Again"
		retlw H'00'			
	
STR_10:
		retlw H'FC'
		DT "Finish Entering"
		retlw H'FF'
		DT "new FREQ first.."
		retlw H'FB'
		retlw H'00'

STR_11:

STR_12:

STR_13:

STR_14:

STR_15:

STR_16:

STR_17:

		
		
		
		

GET_TABLE1_LOCATION:
		addwf	PCL,F
		
		retlw	STR_0-STR_0		
		retlw	STR_1-STR_0
		retlw	STR_2-STR_0		
		retlw	STR_3-STR_0
		retlw	STR_4-STR_0
		retlw	STR_5-STR_0
		retlw	STR_6-STR_0
		retlw	STR_7-STR_0
		retlw	STR_8-STR_0
		retlw	STR_9-STR_0
		retlw	STR_10-STR_0
		retlw	STR_11-STR_0
		retlw	STR_12-STR_0
		retlw	STR_13-STR_0
		retlw	STR_14-STR_0
		retlw	STR_15-STR_0



TABLE1_OUT:
		movlw	H'01'			
		movwf	PCLATH
		
		movf	STR_NUM,	W
		
		lcall	GET_TABLE1_LOCATION
		
		movwf	INDEX
		
NEXT_CHARACTER
		movf	INDEX,	W	
		lcall	TABLE1
		movwf	TEMP

		movf	TEMP,W
		sublw	H'FE'
		btfsc	STATUS,Z
		goto	SET_NEW_LINE
		goto	CHECK_CHARACTERS
		
		
SET_NEW_LINE
		lcall NEW_LINE_POSITION

		incf	INDEX,	F		

		lgoto	NEXT_CHARACTER
		
		
CHECK_CHARACTERS		
		movf	TEMP,W	
									
		addlw	0		
		btfsc	STATUS,Z
		goto	EXIT_TABLE_SECTION


		lcall	TEST_CHARACTER			

				
		incf	INDEX,	F		

		lgoto	NEXT_CHARACTER

TEST_CHARACTER:
		movf	TEMP,W
		sublw	H'FF'
		btfsc	STATUS,Z
		goto 	NEW_LINE


		
		movf	TEMP,W		
		sublw	H'FD'
		btfsc	STATUS,Z
		goto 	NEW_DIRECTION

		movf	TEMP,W		
		sublw	H'FC'
		btfsc	STATUS,Z
		goto 	CLEAR_LCD
		
		movf	TEMP,W		
		sublw	H'FB'
		btfsc	STATUS,Z
		goto 	DELAY_500
		
		movf	TEMP,W		
		sublw	H'FA'
		btfsc	STATUS,Z
		goto 	DELAY_256
				
		goto	NEW_CHAR

NEW_LINE
		movlw	H'00'			
		movwf	PCLATH
		
		call	LCD_BUSY
		
		call	LCD_LINE2

		movlw	H'01'			
		movwf	PCLATH
		
		return
		
NEW_LINE_POSITION
		incf	INDEX,	F	
		
		movf	INDEX,	W	
		lcall	TABLE1
		movwf	TEMP	
		
		movlw	H'00'			
		movwf	PCLATH
				
		movf	TEMP,W
		call	LCD_LINE1_W
		
		movlw	H'01'			
		movwf	PCLATH
		
		return
		
NEW_DIRECTION
		movlw	H'00'			
		movwf	PCLATH
		
CLEAR_LCD
		movlw	H'00'			
		movwf	PCLATH
		
		call	LCD_BUSY
		
		call	LCD_CLEAR

		movlw	H'01'			
		movwf	PCLATH
		
		return	
		
DELAY_500
		movlw	H'00'			
		movwf	PCLATH
		
		call	WAIT_500MS
		
		movlw	H'01'			
		movwf	PCLATH

		return
						
DELAY_256
		movlw	H'00'			
		movwf	PCLATH
		
		call	WAIT_256MS
		
		movlw	H'01'			
		movwf	PCLATH
		
		return
		
NEW_CHAR
		movlw	H'00'			
		movwf	PCLATH
		
		movf	TEMP,W
		call	LCD_DISP_CHAR
		
		movlw	H'01'			
		movwf	PCLATH
		
		return		
		

EXIT_TABLE_SECTION:
		movlw	H'00'			
		movwf	PCLATH
		return
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top