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.

Pic debounce routine

Status
Not open for further replies.

ssaguiar

New Member
Hi to all.
This is my first post in this forum and I'm glad to be here.

I am working in a project of a controller for a electronic driven oven and have a question about keys debounce / autorepeat I wish to ask.
In this project, there are several keys:
- Set temperature;
- Set time;
- Set toaster on/off;
- Light on;
- On/off;
- Up;
- Down.

In this project, when you push the Up or Down keys, it ill increment / decrement the display value, making a beep each time.
If you keep the key (Up or Down) pressed for more than 2 seconds, the display value will increment faster (2 values per second) and, if you keep the key pressed formore than 4 seconds after that, these values will increment even faster (4 values per second, more or less).
The processo used is thepic16f677, but I can use for develop, the 16f877a, because I have an easyPic4 development board and it's circuit is diferent from the pcb board of the project..

Has anybody any idea on how to make this work, in pic assembler (mpasm)?

Thanks to all for any help.
Sergio
 
Hi,

There are several ways you can achieve keyboard control.
Here are some simple examples.
 

Attachments

  • KEYS.asm
    1.1 KB · Views: 350
Here is a simple program that fast increments up and down after 2 seconds:

HTML:
;****************************************************************
;*     Started 18/6/2009	
;2 Digit UP / Down Counter with FastCount after 2secs
;Port B drives 7 segment display
;Up sw on RA2   Down on RA3
;Units drive on RA0   Tens drive on RA1				*
;* 								*
;****************************************************************

	list P = 16F628	;microcontroller 
	include 	;registers for F628


	__Config 	_cp_off & _lvp_off & _pwrte_on 
		& _wdt_off & _intRC_osc_noclkout & _mclre_off
	
;code protection - off
;low-voltage programming - off
;power-up timer -  on
;watchdog timer - off
;use internal RC for 4MHz - all pins for in-out


;****************************************************************
; variables - names and files
;****************************************************************


		;files for F628 start at 20h 
 		
temp1		equ 20h	;for delay
temp2		equ 21h	;for delay
SwUp		equ 22h	;
SwDwn		equ	23h	;
units		equ	24h	;
tens		equ	25h	;
Sw_Flag		equ	26h	;
FastCount	equ	27h	;

;****************************************************************
;Equates
;****************************************************************
status		equ	0x03
cmcon		equ	0x1F
rp1		equ	0x06
rp0		equ	0x05
portA		equ	0x05
portB		equ	0x06

;****************************************************************
;Beginning of program
;****************************************************************
reset	org	00	;reset vector address	
	goto	SetUp	;goto SetUp
			

table	addwf   PCL,F           ;02h,1  add W to program counter 
        retlw   b'00111111'     ; "0"   -|F|E|D|C|B|A
        retlw   b'00000110'     ; "1"   -|-|-|-|C|B|-
        retlw   b'01011011'     ; "2"   G|-|E|D|-|B|A
        retlw   b'01001111'     ; "3"   G|-|-|D|C|B|A 
        retlw   b'01100110'     ; "4"   G|F|-|-|C|B|-
        retlw   b'01101101'     ; "5"   G|F|-|D|C|-|A
        retlw   b'01111101'     ; "6"   G|F|E|D|C|-|A
        retlw   b'00000111'     ; "7"   -|-|-|-|C|B|A
        retlw   b'01111111'     ; "8"   G|F|E|D|C|B|A
        retlw   b'01101111'     ; "9"   G|F|-|D|C|B|A


;****************************************************************
;* port A and B initialisation					*
;****************************************************************

SetUp	bsf	status,rp0	
	movlw	b'00001100'	;Make RA0,1 out   RA2,3 in
	movwf	05h		;trisA	
	clrf	06h		;trisB Make all RB output
	bcf	status,rp0	;select programming area - bank0 
	movlw	b'10000000'	;Turn off T0CKI, prescale for TMR0=1
	movwf	option_reg		
	clrf 	portB		;Clear Port B of junk 
	clrf	units		;zero the units file		
	clrf	tens		;zero the tens file		
	clrf	Sw_Flag
	movlw	07h		;turn comparators off and enable
	movwf	cmcon		;    pins for I/O functions	
	goto 	Main						
					

;****************************************************************
;* Delay 10mS 		10 x 1,000uS			*
;****************************************************************

D_10mS	movlw	0Ah
	movwf	temp2
D_a	nop
	decfsz 	temp1,f
	goto 	D_a
	decfsz 	temp2,f
	goto 	D_a	
	retlw 	00
		
		
FastUp	btfss	Sw_Flag,2	;First time through loop?
	goto	FU_2		;yes
	btfsc	Sw_Flag,7	;Has 5Hz bit been set?
	goto	FU_3
FU_1	incfsz	FastCount,f	;Increment FastCount
	movlw	d'100'
	xorwf	FastCount,w
	btfss	status,2	;reached 100 loops?
	retlw	00
	clrf	FastCount
	bsf	Sw_Flag,7	;set bit for 5Hz incrementing	
				
FU_2	bsf	Sw_Flag,2  ;Up button has been pressed	
	incf	units,f
	movlw	0Ah	   ;put 10 into w
	xorwf	units,w	  ;compare units file with 10
	btfss	status3,2 ;zero flag in status file. Set if units is 10
	retlw	00
	clrf	units
	incf	tens,f
	movlw	0Ah	;put 10 into w
	xorwf	tens,w	;compare units file with 10
	btfsc	status,2 ;zero flag in status file. Set if tens is 10
	clrf	tens				
	retlw	00	;display passes 99 but not below 0
		
		
FU_3	incfsz	FastCount,f	;Increment FastCount
	movlw	d'5'
	xorwf	FastCount,w
	btfss	status,2	;reached 5 loops?
	retlw	00
	clrf	FastCount		
	goto	FU_2			
		
Dwn	btfsc	Sw_Flag,3
	retlw	00
	bsf	Sw_Flag,3
	decf	units,f
	movlw	0FFh	;put FFh into w
	xorwf	units,w	;compare units file with FFh
	btfss	status,2 ;zero flag in status file. Set if units is 10
	retlw	00
	movlw	09
	movwf	units	;put 9 into units file
	decf	tens,f
	movlw	0FFh	;put 0FFh into w
	xorwf	tens,w	;compare tens file with 0FFh
	btfsc	status,2 ;zero flag in status file. Set if tens is 0FFh
	goto	$+2	;tens file is 0FFh
	retlw	00						
	clrf	tens
	clrf	units
	retlw	00	;display  not below 0	
		
;****************************************************************
;* Main 							*
;****************************************************************

Main	btfss	portA,2		;test switch-press for UP
	call	FastUp		;UP switch pressed
	btfss	portA,3		;test switch-press for Down
	call	Dwn		;Down switch pressed
	movlw	b'00000001'	;Make RA0 HIGH for units drive 	
	movwf	portA	
	movf	units,w		;copy unit value into w
	call	table		;unit display value will return in w
	movwf	portB		;output units value
	call	D_10mS		;call delay
	clrf	portB		;clear display
	movlw	b'00000010'	;Make RA1 HIGH for tens drive 	
	movwf	portA			
	movf	tens,w		;copy tens value into w		
	call	table		;tens display value will return in w
	movwf	portB		;output tens value
	call	D_10mS		;call delay
	clrf	portB		;clear display		
	btfsc	portA,3		;bit will be zero when sw is pressed
	bcf	Sw_Flag,3	;button not pressed. Clear down flag
	btfss	portA,2		;bit will be zero when sw is pressed
	goto	Main
	bcf	Sw_Flag,2	;button not pressed. Clear Up flag
	bcf	Sw_Flag,7	;Clear Up repeat flag
	clrf	FastCount
	goto	Main		
		
	END
 
Last edited:
Thanks, my friends, for your answers.
I will try to implement the keys routine and will post here as soon as I have it working.
 
Thanks, my friends, for your answers.
I will try to implement the keys routine and will post here as soon as I have it working.

Hi to all.

I have implemented the keys code in my code but I am still having seveal problems.
I just can't make the display work as expected, nor even the leds.
The keyboard routine, once the turbo is active, it stays on untill we reset the processor.

I wish to know if somebody could help me to understand how to make this work.
In ths aplication, the display is multiplexed with the keys and the leds.
Atached to this message, I have uploaded the source code and the project for Proteus.

I thank you for any help.
 

Attachments

  • oven.zip
    27.1 KB · Views: 158
Firstly you have to convert all the wording to English.
Secondly you have to remove all the unnecessary instructions such as CALL TIMERSET
Thirdly you have to simplify a lot of the routines, such as removing the macros as they are only used once and remove clrw and put it in MAINCONTINUE
Then you have to supply a circuit diagram so we can see how you are multiplexing the displays and what you are really doing.

You have totally gone against everything I have ever taught.
The first thing you do is produce a routine to activate the displays. Then introduce one key and one LED.
During the time when the last display is illuminated you have time to do all sorts of "housekeeping."
This involves looking at the input port and dealing with the data, processing it and storing it.
This is a much simpler way of tackling your requirement and the program will be half the size. And you will be able to understand it.
What you are doing is very simple.
 
Last edited:
Firstly you have to convert all the wording to English.
Secondly you have to remove all the unnecessary instructions such as CALL TIMERSET
Thirdly you have to simplify a lot of the routines, such as removing the macros as they are only used once and remove clrw and put it in MAINCONTINUE
Then you have to supply a circuit diagram so we can see how you are multiplexing the displays and what you are really doing.

You have totally gone against everything I have ever taught.
The first thing you do is produce a routine to activate the displays. Then introduce one key and one LED.
During the time when the last display is illuminated you have time to do all sorts of "housekeeping."
This involves looking at the input port and dealing with the data, processing it and storing it.
This is a much simpler way of tackling your requirement and the program will be half the size. And you will be able to understand it.
What you are doing is very simple.

Thank you colin55 for your answer.
The circuit diagram is included in the Proteus project.
I have tried everything but have no luck.
Sometimes, the keyboard works with the display.
The leds don't work at all.
First, I have implemented this code without having to use interrupts to be simpler, but I used an osciloscope to see how was the original tming of the displays and leds circuit and I have found that the displays and leds are active this way:
1 - activate display 1 during 2 ms then turn it off;
2 - activate leds during 2 ms then turn it off;
3 - activate display 2 during 2 ms then turn it off;
4 - activate display 3 during 2ms then turn it off and restart.

By this way, the total time is 8ms dvided by the displays and leds (the keying of the transistors).

I though that, to have such behavior, it was best to use interrupts and a state machine's implementation (in the scope, the timing was allways the same even when pressing a key or).

I will try to make the code simpler and will translate the rest of the code to english (I allways do this, but this time, I started to make the comments in portuguese.

Much of the code is more complicated because the original project don't use all the stuff in on port (for example PORTB), they use the keys, display's cathodes and leds cathodes on some pins of the ports B and A, thus why the code sometimes is much more complicated (If the hardware was made more inteligent, I could put all stuff in one port using, for example, mowf PORTB, but I can't, as I have to output pin by pin).

Sergio
 
This is the code, all translated to english.
All tabs set to 4.

Sergio
 

Attachments

  • forno3.asm
    21.4 KB · Views: 255
Last edited:
Here it is, in pdf format.

The leds in RA0 and RA1 just represent the reles wich activate the heaters (main heater and toaster).

Sergio
 

Attachments

  • oven.PDF
    57.9 KB · Views: 299
You have used the wrong micro. Why don't you use a PIC16F628. It has a full port and this will make it easier to drive the displays. You need dropper resistors in the lines to the 7 segment displays.
You need to do a "run-of-four" in the scan routine with three displays and then 8 LEDs. The other three outputs will have to be added to each of the displays as the 8th item. After the "run-of-four" you do a very quick look at the 7 switches.
Draw this up as a matrix and create the scan routine.

What you have to remember is this: You have to spend all your time scanning and displaying the LEDs and 7-segment displays. This will take a full port (PortB) plus 4 lines from PortA. You will need a dedicated line from PortA to drive the buzzer.
This leaves one input-only line unused and two output lines.
Each display will get approx 25% "on-time."

You start by allocating 4 files for the data for the displays and LEDs. These are cleared and the routine looks up a table for the 7 lowest bits and either includes the 8th (or not) for the LED that is also included in the "run." This will put "000" on the dislay. You can include "leading zero blanking." The fourth item in the run simply outputs the data for the LEDs.

Include the debounce in this routine and also the fast increment feature. Allocate a file for the data from the switches and a file for the flags (from the fast forward requirement). You will also need to include the data for the buzzer.

Now you have everything set up.

You simply have one scan routine that does all the work.
 
Last edited:
Dear colin55:

Thank you, my fiend, for your answer.

The problem is exactly this: I can't change this circuit because it is already implemented in a commercial product.
They had one person that made the firmware for them and as they don't have access to the source code and the person is no more available, they ask to make the firmware again, based on the original circuit.

Sergio
 
Last edited:
Who drew the circuit diagram? How can Q7, 8 and 9 work? How are the displays connected?
D5A will be a 5v6 zener. D6A and D6B are around the wrong way.

If you have to follow a previous layout, draw up the scanning diagram - the scanning circuit. I have absolutely no idea how the displays are connected.
 
Last edited:
I had this exact feeling when I started, but, after take a time to see how the circuit works, I got this:

The Q7, Q8 and Q9 works because the V_IN2 voltage is negative (this voltage came from anodes of diodes D1 and D4, in the main supply).

The main supply has no transformer (I just don't agree with this, but those guys want to keep the cost at minimum - again: I don't think this is a good thing to do).

The resistor R3, capacitor C1, resistor R1 and the resistor R2, provides the reference for the main voltage sensor (It's used to see if the main voltage dropped below some level).
The V_IN1, at the cathode of diodes D2 and D3, in power supply, gives the 12 volts voltage thru the C4 capacitor and D7A diode, and, then, the circuit D5A, R4 and Q1 generates the 5 Volts (VCC) wichis used by pic, leds, displays etc..
The reles have supply from the -12 volts, wich is generated by the anodes of D1 and D4 regulated by C3, D6A and D6B. This is why the emiters of the transistors Q7, Q8 and Q9 are tied to ground.

As I said, this is not a circuit of mine and I really don't agree with the lack of a transformer.

Sergio
 
The first thing you do is produce a table with 2 bytes for each digit. The first byte accesses RA 2 4 5 and the second byte access RB4567.
The scan routine will access these two bytes and send them to the displays.
Do this first: Get 000 on the displays.
 
Ok, I'm going to do this.
First, I have two questions:

- Do you think it's best to have the scan code driven by interrupts (as I did) or in the main loop?

- I think I will make 2 routines that will return a byte each from a table as in DECOD_DISPLAY, but one for PORTA and another FOR PORTB. What do you think? Is it best this way, so I just have to see what is the value, call table for PORTA, put the returned value in PORTA (MOVLW PORTA), then make it again, for PORTB?

Thanks again.

Sergio
 
This is what I talk about:

Code:
DECOD_DISPLAY_A:
	MOVWF	TEMP			; Put number in displacement variable
	MOVLW	LOW TABLE_A		; cop to W the 8 LSB bits of the TABLE address
	ADDWF	TEMP,F			; add the value to the displacement variable
	MOVLW	HIGH TABLE_A	; copy to W the upper 5 bits of the TABLE ddress
	BTFSC	STATUS,C		; Test to see if the sum activates the carry bit 
	ADDLW	0x01			; if carry, sum 1 to W
	MOVWF	PCLATH			; sets PCLATH using the TABLE address
	MOVF	TEMP,W			; copy the displacement value to W
	MOVWF	PCL				; copy W to PCL

TABLE_A:
;       A
;	 _______
;   |       |
; F |       | B
;   |   G   |
;    -------
;   |       |
; E |       | C
;   |_______|
;       D
				;	|7|6|5|4|3|2|1|0| -	Bits PORTA
				;	|-|-|B|E|-|A|-|-|
	RETLW	B'00000000'	;	|-|-|B|E|-|A|-|-| -	0
	RETLW	B'00010000'	;	|-|-|B|X|-|A|-|-| -	1
	RETLW	B'00000000'	;	|-|-|B|E|-|A|-|-| -	2
	RETLW	B'00010000'	;	|-|-|B|X|-|A|-|-| -	3
	RETLW	B'00010100'	;	|-|-|B|X|-|X|-|-| -	4
	RETLW	B'00011000'	;	|-|-|X|X|-|A|-|-| -	5
	RETLW	B'00100000'	;	|-|-|X|E|-|A|-|-| -	6
	RETLW	B'00010000'	;	|-|-|B|X|-|A|-|-| -	7
	RETLW	B'00000000'	;	|-|-|B|E|-|A|-|-| -	8
	RETLW	B'00010000'	;	|-|-|B|X|-|A|-|-| -	9

DECOD_DISPLAY_B:
	MOVWF	TEMP			; Put number in displacement variable
	MOVLW	LOW TABLE_B		; cop to W the 8 LSB bits of the TABLE address
	ADDWF	TEMP,F			; add the value to the displacement variable
	MOVLW	HIGH TABLE_B	; copy to W the upper 5 bits of the TABLE ddress
	BTFSC	STATUS,C		; Test to see if the sum activates the carry bit 
	ADDLW	0x01			; if carry, sum 1 to W
	MOVWF	PCLATH			; sets PCLATH using the TABLE address
	MOVF	TEMP,W			; copy the displacement value to W
	MOVWF	PCL				; copy W to PCL

TABLE_B:
					;|7|6|5|4|3|2|1|0| -	Bits PORTB
					;|C|F|D|G|-|-|-|-| -
	RETLW	B'00000000'	;	|C|F|D|G|-|-|-|-| -	0
	RETLW	B'11110000'	;	|X|X|X|X|-|-|-|-| -	1
	RETLW	B'11000000'	;	|X|X|D|G|-|-|-|-| -	2
	RETLW	B'01000000'	;	|C|X|D|G|-|-|-|-| -	3
	RETLW	B'10100000'	;	|X|F|X|G|-|-|-|-| -	4
	RETLW	B'10100000'	;	|X|F|X|G|-|-|-|-| -	5
	RETLW	B'00000000'	;	|C|F|D|G|-|-|-|-| -	6
	RETLW	B'01110000'	;	|C|X|X|X|-|-|-|-| -	7
	RETLW	B'00000000'	;	|C|F|D|G|-|-|-|-| -	8
	RETLW	B'00000000'	;	|C|F|D|G|-|-|-|-| -	9

Wit this, I just have to call DECOD_DISPLAY_A and DECOD_DISPLAY_B and will have the number converted to bcd and ready to be put in PORTA and in PORTB (the diplay's cathodes).

What do you think about this solution? Isn't bette than call all the former conversion stuff I had?

Thanks
 
With the code below, the displays, the leds and the led onoff interrupt to make it blink, are working fine.
I started testing the displays with '0's as you sugeted, and, then added the leds stuff, tested it and, after that, the interrupt stuff and tested it.
I am using the interrup because the led is suposed to be blinking when the oven is waiting for commands or is in pause mode.

Do you think it's ok?

Thanks

Code:
	;**********************************************************************
	;                                                                     *
	;**********************************************************************
	;    Filename:	    oven.asm                                          *
	;    Date:                                                            *
	;    File Version:                                                    *
	;                                                                     *
	;    Author:                                                          *
	;    Company:                                                         *
	;                                                                     *
	;**********************************************************************
	;    Files Required: P16F677.INC                                      *
	;                                                                     *
	;**********************************************************************
	;    PIC 16F677 pinout:                                               *
	;                          |--\/--|                                   *
	;                     Vdd -|1   20|- Vss                              *
	;    RA5/T1CKI/OSC1/CLKIN -|2   19|- RA0/AN0/C1IN+/ICSPDAT/ULPWU      *
	; RA4/AN3/T1G/OSC2/CLKOUT -|3   18|- RA1/AN1/C12IN0-/VREF/ICSPCLK     *
	;            RA3/MCLR/VPP -|4   17|- RA2/AN2/T0CKI/INT/C1OUT          *
	;                     RC5 -|5   16|- RC0/AN4/C2IN+                    *
	;               RC4/C2OUT -|6   15|- RC1/AN5/C12IN1-                  *
	;           RC3/AN7C12IN3 -|7   14|- RC2/AN6/C12IN2-                  *
	;              RC6/AN8/SS -|8   13|- RB4/AN10/SDI/SDA                 *
	;             RC7/AN9/SDO -|9   12|- RB5/AN11                         *
	;                     RB7 -|10  11|- RB6/SCK/SCL                      *
	;                          --------                                   *
	;                                                                     *
	;**********************************************************************

;/****************************************************************************
;* DESCRIPTION: System definitions.
;* RETURN:      none
;* ALGORITHM:   none
;* NOTES:       none
;*****************************************************************************/ 

	ERRORLEVEL -302 ;remove message about using proper bank

	LIST  P=16F677
	INCLUDE <P16F677.INC>
	__CONFIG _BOR_OFF & _FCMEN_OFF & _IESO_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTOSCIO

;/****************************************************************************
;* DESCRIPTION: Program variables and constant definitions.
;* RETURN:      none
;* ALGORITHM:   none
;* NOTES:       none
;*****************************************************************************/ 

TEMPER		EQU 0x20						; Store temperature
TEMP		EQU 0x21						; General use variable
W_TEMP		EQU 0x22						; Temporary W register
STATUS_TEMP	EQU 0x23						; Temporary STATUS register
UNITS		EQU 0x24						; UNITS
TENS		EQU	0x25						; TENS
HUNDREDS	EQU 0x26						; HUNDREDS
AUX			EQU	0x27						; GENERAL AUX. REGISTER
TEMPO0		EQU	0x28
TEMPO1		EQU	0x29
T1_CONTA	EQU 0x2A						; Aux. Timer1 counter
TMR_1MS		EQU	0x2B						; Counter for 1 ms period
TMR_100MS	EQU	0x2C						; Counter for 100 ms period

; Leds
#DEFINE		LED_CMN				PORTC,2		; Leds Anodes

#DEFINE		LED_UP				PORTA,4		; Led UP
#DEFINE		LED_TIMER			PORTB,6		; Led TIMER
#DEFINE		LED_TEMP			PORTB,5		; Led TEMP
#DEFINE		LED_DWN				PORTA,2		; Led DWN
#DEFINE		LED_LIGHT			PORTB,4		; Led LIGHT
#DEFINE		LED_TOASTER			PORTA,5		; Led TOASTER
#DEFINE		LED_ONOFF			PORTC,6		; Led ONOFF

; Displays
#DEFINE		DISP1				PORTC,3		; Anode display DIS0
#DEFINE		DISP2				PORTC,4		; Anode display DIS1
#DEFINE		DISP3				PORTC,5		; Anode display DIS2

;/****************************************************************************
;* DESCRIPTION: Got Start of program.
;* RETURN:      none
;* ALGORITHM:   none
;* NOTES:       none
;***************************************************************************** 
	ORG		0x0000

	GOTO	START

;*****************************************************************************
	ORG 0x0004

	MOVWF	W_TEMP			; save W content to W_TEMP
	SWAPF	STATUS,W		; put STATUS in W...
	MOVWF	STATUS_TEMP		; ... Then save it in STATUS_TEMP

	BCF		PIR1,TMR1IF		; Clear Timer1 Interrupt flag

	MOVLW	0x18			;
	MOVWF	TMR1L			;
	MOVLW	0xFC			;
	MOVWF	TMR1H			; Init TIMER1 with decimal 64536 (interrupt every 1ms)


	INCF	TMR_1MS,F		; Increment TR_1MS (1 ms counter)
	MOVLW	D'100'
	XORWF	TMR_1MS,W		; Is TMR_1MS = 100?
	BTFSC	STATUS,Z		; No, skip if TMR_1MS < 100
	GOTO	INC100MS		; Yes, zero TMR_1MS and inc TMR_100MS
	GOTO	END_INT			; No, exit interrupt

INC100MS
	MOVLW	D'0'			;
	MOVWF	TMR_1MS			; Zero TMR_1MS
	INCF	TMR_100MS,F		; Increment TMR_100MS (100 ms counter)
	MOVLW	D'5'			; 500 ms?
	XORWF	TMR_100MS,W		; Is TMR_100MS = 5 (500ms)?
	BTFSC	STATUS,Z		; No, skip if TMR_100MS < 5
	GOTO	INCCONTA		; Yes, zero TMR_100MS and inc 0,5 seconds counter
	GOTO	END_INT			; No, Exit interrupt

INCCONTA:
	MOVLW	D'0'			;
	MOVWF	TMR_100MS		; Zero 100 ms counter (reached 500ms)	
	BSF		STATUS,RP0		; Bank 1
	BCF		STATUS,RP1		;
	BCF		LED_ONOFF		; LED_ONOFF output

	BCF		STATUS,RP0		; Bank 0
	BCF		STATUS,RP1		;

	MOVLW	D'1'			; Verify if ...
	XORWF	T1_CONTA,W		; passed 1/2 second ...
	BTFSC	STATUS,Z		; 
	GOTO	LEDON			; Led ONOFF is ON? Goto LEDON
LEDOFF:
	BCF		LED_ONOFF		; Turn OFF LEDON_OFF
	GOTO	LEDOUT			; ok, done...
LEDON:
	BSF		LED_ONOFF		; Turn ON LED_ONOFF
LEDOUT:
	DECFSZ	T1_CONTA,F		; Decrement the Counter rRegister
	GOTO	END_INT			; If diferent of zero, exit interrupt
	MOVLW	2				; 
	MOVWF	T1_CONTA		; Restart Counter Register with 2	


END_INT:
	SWAPF	STATUS_TEMP,W	; Restaure STATUS content...
	MOVWF	STATUS			; ... from STATUS_TEMP
	SWAPF	W_TEMP,F		; Restaure W content...
	SWAPF	W_TEMP,W		; ... from W_TEMP.

	RETFIE					; Return from interrupt

;/****************************************************************************
;* DESCRIPTION: Decodes value in W register to display segments for PORTA.
;* RETURN:      none
;* ALGORITHM:   none
;* NOTES:       none
;*****************************************************************************/ 

DECOD_DISPLAY_A:
	MOVWF	TEMP			; Put number in displacement variable
	MOVLW	LOW TABLE_A		; cop to W the 8 LSB bits of the TABLE address
	ADDWF	TEMP,F			; add the value to the displacement variable
	MOVLW	HIGH TABLE_A	; copy to W the upper 5 bits of the TABLE ddress
	BTFSC	STATUS,C		; Test to see if the sum activates the carry bit 
	ADDLW	0x01			; if carry, sum 1 to W
	MOVWF	PCLATH			; sets PCLATH using the TABLE address
	MOVF	TEMP,W			; copy the displacement value to W
	MOVWF	PCL				; copy W to PCL

TABLE_A:
;       A
;	 _______
;   |       |
; F |       | B
;   |   G   |
;    -------
;   |       |
; E |       | C
;   |_______|
;       D
						;	|7|6|5|4|3|2|1|0| -	Bits PORTA
						;	|-|-|B|E|-|A|-|-|
	RETLW	B'00000000'	;	|-|-|B|E|-|A|-|-| -	0
	RETLW	B'00010100'	;	|-|-|B|X|-|X|-|-| -	1
	RETLW	B'00000000'	;	|-|-|B|E|-|A|-|-| -	2
	RETLW	B'00010000'	;	|-|-|B|X|-|A|-|-| -	3
	RETLW	B'00010100'	;	|-|-|B|X|-|X|-|-| -	4
	RETLW	B'00110000'	;	|-|-|X|X|-|A|-|-| -	5
	RETLW	B'00100000'	;	|-|-|X|E|-|A|-|-| -	6
	RETLW	B'00010000'	;	|-|-|B|X|-|A|-|-| -	7
	RETLW	B'00000000'	;	|-|-|B|E|-|A|-|-| -	8
	RETLW	B'00010000'	;	|-|-|B|X|-|A|-|-| -	9


;/****************************************************************************
;* DESCRIPTION: Decodes value in W register to display segments, for PORTB.
;* RETURN:      none
;* ALGORITHM:   none
;* NOTES:       none
;*****************************************************************************/ 

DECOD_DISPLAY_B:
	MOVWF	TEMP			; Put number in displacement variable
	MOVLW	LOW TABLE_B		; cop to W the 8 LSB bits of the TABLE address
	ADDWF	TEMP,F			; add the value to the displacement variable
	MOVLW	HIGH TABLE_B	; copy to W the upper 5 bits of the TABLE ddress
	BTFSC	STATUS,C		; Test to see if the sum activates the carry bit 
	ADDLW	0x01			; if carry, sum 1 to W
	MOVWF	PCLATH			; sets PCLATH using the TABLE address
	MOVF	TEMP,W			; copy the displacement value to W
	MOVWF	PCL				; copy W to PCL

TABLE_B:
						;	|7|6|5|4|3|2|1|0| -	Bits PORTB
						;	|C|F|D|G|-|-|-|-| -
	RETLW	B'00010000'	;	|C|F|D|X|-|-|-|-| -	0
	RETLW	B'01110000'	;	|C|X|X|X|-|-|-|-| -	1
	RETLW	B'11000000'	;	|X|X|D|G|-|-|-|-| -	2
	RETLW	B'01000000'	;	|C|X|D|G|-|-|-|-| -	3
	RETLW	B'00100000'	;	|C|F|X|G|-|-|-|-| -	4
	RETLW	B'00000000'	;	|C|F|D|G|-|-|-|-| -	5
	RETLW	B'00000000'	;	|C|F|D|G|-|-|-|-| -	6
	RETLW	B'01110000'	;	|C|X|X|X|-|-|-|-| -	7
	RETLW	B'00000000'	;	|C|F|D|G|-|-|-|-| -	8
	RETLW	B'00000000'	;	|C|F|D|G|-|-|-|-| -	9

;/****************************************************************************
;* DESCRIPTION: Little Delay to let display show digit.
;* RETURN:      none
;* ALGORITHM:   none
;* NOTES:       none
;*****************************************************************************/ 

DELAY_MS:					; Delay routine - W is the number of ms of delay.
	MOVWF	TEMPO1			; put w in temp variable
	MOVLW	D'250'
	MOVWF	TEMPO0
	DECFSZ	TEMPO0,F
	GOTO	$-1
	DECFSZ	TEMPO1,F
	GOTO	$-5
	RETURN

;/****************************************************************************
;* DESCRIPTION: binary_to_bcd - 8-bits
;* INPUT:		TEMPER  - 8-bit binary number
;* RETURN:      CENTENA - the hundreds digit of the BCD conversion
;*				DEZENA  - the tens digits of the BCD conversion
;*				UNIDADE - the ones digits of the BCD conversion
;* ALGORITHM:   none
;* NOTES:       none
;*****************************************************************************/ 
BINARY_TO_BCD:

	MOVWF	AUX				; sve the value to convert in AUX
	CLRF	UNITS			;
	CLRF	TENS			;
	CLRF	HUNDREDS		; RESET variables
	MOVF	AUX,F			;
	BTFSC	STATUS,Z		; Is the value to convert = 0?
	RETURN					; Yes - Return
							; No
	INCF	UNITS,F			; Increment unit
	MOVF	UNITS,W			;
	XORLW	0X0A			;
	BTFSS	STATUS,Z		; unit = 10d ?
	GOTO	$+3				; No
							; yes
	CLRF	UNITS			; Reset unit
	INCF	TENS,F			; Increment tens
	MOVF	TENS,W			;
	XORLW	0X0A			;
	BTFSS	STATUS,Z		; Tens = 10d ?
	GOTO	$+3				; No
							; Yes
	CLRF	TENS			; Reset tens
	INCF	HUNDREDS,F		; Increment hundreds
	DECFSZ	AUX,F			; End of conertion ?
	GOTO	$-.14			; No - go back to continue the convertion
	RETURN					; Yes

;/****************************************************************************
;* DESCRIPTION: Program Initialization
;* RETURN:      none
;* ALGORITHM:   none
;* NOTES:       none
;*****************************************************************************/ 

START:
	BCF		STATUS,RP0		; Bank 2
	BSF		STATUS,RP1		;
	CLRF	ANSEL			; digital I/O
	CLRF	ANSELH			;	"	"	"
	BCF		STATUS,RP0		; Bank 2
	BSF		STATUS,RP1		;
	MOVLW	B'00000000'
	MOVWF	CM1CON0			; disable comparator
	MOVLW	B'00000000'		; Not necessary?
	MOVWF	CM2CON0			; disable 2nd comparator
	MOVLW	B'00000000'		; Not necessary?
	MOVWF	CM2CON1			; disable 3rd comparator
	BSF		STATUS,RP0		; Bank 1
	BCF		STATUS,RP1		;
	MOVLW	B'00001000'		;
	MOVWF	TRISA			;
	MOVLW	B'00000000'		;
	MOVWF	TRISB			;
	MOVLW	B'10000010'		;
	MOVWF	TRISC			;
	BCF		STATUS,RP0		; Bank 0
	BCF		STATUS,RP1		;
	BCF		SSPCON,SSPEN	; Disable Synchronous Serial Port

	; Turn off all reles, displays and leds
	BSF		LED_CMN			; Leds off
	BSF		DISP1			; Display1 off
	BSF		DISP2			; Display2 off
	BSF		DISP3			; Display3 off

	MOVLW	D'180'			; Init temperature with 180 degrees Celsius
	MOVWF	TEMPER
	MOVLW	2				;
	MOVWF	T1_CONTA		;

	; Init Timer1
	MOVLW	B'00000000'		; Configure TIMER1 for internal clock and prescaler 1:1
	MOVWF	T1CON			; Init Timer1
	MOVLW	0x18			;
	MOVWF	TMR1L			;
	MOVLW	0xFC			;
	MOVWF	TMR1H			; Init TIMER1 with decimal 64536 (interrupt every 1ms)

	BSF		STATUS,RP0		; Bank 1
	BCF		STATUS,RP1		;
	MOVLW   B'00000001'		; Enable TIMER1 Overflow Interrupt
	MOVWF	PIE1
	BCF		STATUS,RP0		; Bank 0
	BCF		STATUS,RP1		;
	CLRF	PIR1			; Clear Peripheral Interrupt Flags
	BSF		INTCON, PEIE	; Enable Peripheral Interrupts
	BSF		T1CON, TMR1ON	; Start TMR1
	BSF		INTCON, GIE		; Enable Global Interrupts


;/****************************************************************************
;* DESCRIPTION: Main Program
;* RETURN:      none
;* ALGORITHM:   none
;* NOTES:       none
;*****************************************************************************/ 

MAIN_LOOP:
	MOVF	TEMPER,W		; Put temperature in W
	CALL	BINARY_TO_BCD	; Decode Temperature to bcd

	BSF		LED_CMN			; Leds off

	MOVF	UNITS,W			; copy units to W
	;MOVLW	D'0'
	CALL	DECOD_DISPLAY_A	; convert
	MOVWF	PORTA			; put it in PORTA
	MOVF	UNITS,W			; copy units to W
	;MOVLW	D'0'
	CALL	DECOD_DISPLAY_B	; convert
	MOVWF	PORTB			; put it in PORTA
	BCF		DISP1			; display 1 on
	MOVLW	D'2'			;
	CALL	DELAY_MS		; delay 2 ms
	BSF		DISP1			; display 1 off

	MOVF	TENS,W			; copy tens to W
	;MOVLW	D'0'
	CALL	DECOD_DISPLAY_A	; convert
	MOVWF	PORTA			; put it in PORTA
	MOVF	TENS,W			; copy tens to W
	;MOVLW	D'0'
	CALL	DECOD_DISPLAY_B	; convert
	MOVWF	PORTB			; put it in PORTA
	BCF		DISP2			; display 1 on
	MOVLW	D'2'			;
	CALL	DELAY_MS		; delay 2 ms
	BSF		DISP2			; display 1 off

	MOVF	HUNDREDS,W		; copy hundeds to W
	;MOVLW	D'0'
	CALL	DECOD_DISPLAY_A	; convert
	MOVWF	PORTA			; put it in PORTA
	MOVF	HUNDREDS,W		; copy hundeds to W
	;MOVLW	D'0'
	CALL	DECOD_DISPLAY_B	; convert
	MOVWF	PORTB			; put it in PORTA
	BCF		DISP3			; display 1 on
	MOVLW	D'2'			;
	CALL	DELAY_MS		; delay 2 ms
	BSF		DISP3			; display 1 off

	BCF		LED_UP			; led UP ON
	BCF		LED_DWN			; led DWN ON
	BCF		LED_TEMP		; led TEMP ON
	BSF		LED_TIMER		; led TIMER OFF
	BSF		LED_LIGHT		; led LIGHT OFF
	BSF		LED_TOASTER		; led TOASTER OFF
	BCF		LED_CMN			; Leds on
	MOVLW	D'2'			;
	CALL	DELAY_MS		; delay 2 ms
	BSF		LED_CMN			; Leds off


	GOTO	MAIN_LOOP		; Back to main loop

	END
 
1 - Use lower case for nmemonics
2. Have you cleared: units, tens, and hundreds before starting?
3. You don't need interrupts. It just makes things more complex.
4. Put the tables in the first page Page0 and go to them. This will simplify the code to:

movf units,w
goto tableA






Here is a very short delay routine

del_2mS

movlw 02
movwf temp1
nop
decfsz temp2
goto $-2
retlw 00

each unit put into temp1 will produce 1mS delay. temp2 will be 00 at start of second and further calls to this delay.
 
Last edited:
1 - Use lower case for nmemonics
2. Have you cleared: units, tens, and hundreds before starting?
3. You don't need interrupts. It just makes things more complex.
4. Put the tables in the first page Page0 and go to them. This will simplify the code to:

movf units,w
goto tableA






Here is a very short delay routine

del_2mS

movlw 02
movwf temp1
nop
decfsz temp2
goto $-2
retlw 00

each unit put into temp1 will produce 1mS delay. temp2 will be 00 at start of second and further calls to this delay.

About the lower case, you mean the asm mneumonics (BTFSC btfsc, ADD add...)?
I use upper case because it's easier for me to read them ( I have some atention deficit).

Thanks to point me the need to clear the units, tens ad hundreds. Just done.

How to make the led blink without interrupt and without loosing time in delays? The delays can break the displays timing, don't? Remember I still have to make the buzzer plays when one key is pressed the first time, make the a/d channel for the temperature sensor read it and monitor the low volatge sensor.

I didn't understand how to use he tables in page 0.
Do I have to put "banksel 0" in the start of the table's codes?

About the deay routine, Thanks for it, but the routine I have in my code isn't good? It can be used for any valu between 1 and 255 ms:
Code:
DELAY_MS:					; Delay routine - W is the number of ms of delay.
	MOVWF	TEMPO1			; put w in temp variable
	MOVLW	D'250'
	MOVWF	TEMPO0
	DECFSZ	TEMPO0,F
	GOTO	$-1
	DECFSZ	TEMPO1,F
	GOTO	$-5
	RETURN

Thanks again for be so kind with me and have all the patience you have.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top