Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

traffic lighting systems using MCU

Status
Not open for further replies.

zh3ng

Newbie level 5
Joined
Dec 29, 2009
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,369
PIC16F628A

I'm a newbie with PIC programming. I'm trying to program PIC16F628A for 10 secs delay, after the delay 10sec is done, it will control the relay from RA2's pins.
Below this is the code, but its not working, can somebody help me and tell me what is wrong?

list p=16f628a
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _LVP_OFF & _BODEN_ON & _MCLRE_OFF

#include <p16F628a.inc>





cblock
d1
d2
d3
endc



; program starts here

main
org 0x00

movlw 7
movwf CMCON

clrf PORTA
clrw
tris PORTA ; porta all output
clrf PORTB
movlw 0xf0 ; pb4-7 inputs
tris PORTB
bsf STATUS, RP0 ; bank 1
bcf OPTION_REG, NOT_RBPU ;internal pullups on port B enabled
bcf STATUS, RP0 ;bank 0


Call Delay

movlw 0x04 ; RA2 is output
movwf PORTA


Delay
;1999996 cycles
movlw 0x11
movwf d1
movlw 0x5D
movwf d2
movlw 0x05
movwf d3
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto $+2
decfsz d3, f
goto Delay_0

;4 cycles (including call)
return


end
 

Re: PIC16F628A

Consider making these changes:

1. use the timer modules, that is exactly what they are for. All you need to do is configure them and load a starting value into them. When their contents reaches maximum, they roll over the zero and generate an interrupt. Create an interrupt routine that reloads the timer again, ready for the next period. You can either use the interrupt routine to do other things as well or you can use it to increment a software counter if you need even longer delays.

2. Change the start of your code. At the moment you place the program at 0x00 with the org directive. However, the interrupt vector is fixed at address 0x04 so if an interruot occurs, it will make your program jump to your clrw instruction which is not what you want (especially as you have the WDT disabled!). At org 0x00 place an instruction "goto main", at org 0x04 place your interrupt routine or if you decide not to use interrupts, place a retfie instruction instead then place your 'main' at the next free address. So when the program starts, it jumps over the interrupt code to a better starting place.

3. Software delay loops are not usually a good solution, use the timers if possible but if you must use them, be careful that the WDT is really turned off or it will time out and cause a reset while in the delay loops. Remember the WDT causes a reset approximately every 18mS but you don't clear it at all in a 10 S loop.

Off topic:
if you are pasting code on edaboard, it is much easier to read if you enclose it in code tags. Just before the code, click the box just above the message window with the word "Code" in it. At the end of your program, click it again to restore normal operation. It will ensure the code is left as it is and not re-formatted by the board software.

Brian.
 

Re: PIC16F628A

Thanks so much brian, i will try you advice. But I still confuse with the coding, need to learn every single command.
 

Re: PIC16F628A

no too sure if this is correct but cblocks must have a address where to start because the first several bytes in the memory are reserved. so try this:
Code:
...

cblock 0x20
d1
d2
d3
endc 

...

as betwixt stated, the interrupt vector is at 0x04 and its always good practice to start your program at 0x05

Code:
; program starts here

org 0x00
goto main

org 0x05
main
...

When ever you write to TRISA or TRISB etc you must be in bank 1
Code:
bsf STATUS,RP0

movlw 0x00
movwf TRISA

movlw 0xF0
movwf TRISB

bcf OPTION_REG, NOT_RBPU

bcf STATUS, RP0

So give that a go and tell me how you went :)

Cheers
Roman
 

Re: PIC16F628A

Thanks smartie, its working well. I'm trying to add this delay to another 8 led chaser project,..do you think can help me on this? where to insert the code.
Thanks brother !
 

PIC16F628A

Hi,
Here's the complete code (with some changes):
Code:
	LIST P=16F628A
	__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _LVP_OFF & _BODEN_ON & _MCLRE_OFF

	#INCLUDE <P16F628A.inc>

	CBLOCK 0x20
		d1, d2, d3
	ENDC

	ORG 0x00
	GOTO MAIN
;=========================================
Delay
	;1999996 cycles
	movlw 0x11
	movwf d1
	movlw 0x5D
	movwf d2
	movlw 0x05
	movwf d3
	Delay_0
	decfsz d1, f
	goto $+2
	decfsz d2, f
	goto $+2
	decfsz d3, f
	goto Delay_0

;4 cycles (including call)
return

;============================================
MAIN
	MOVLW	.7
	MOVWF	CMCON
	CLRF	CCP1CON
	BANKSEL	TRISA
	CLRF	TRISA
	MOVLW	0xFF
	MOVWF	TRISB
	BSF		OPTION_REG, NOT_RBPU
	BANKSEL	PORTA
	CLRF	PORTA
	CALL	Delay
	BSF		PORTA, 2
	GOTO	$
end

Added after 51 seconds:

About your led chaser, please post the circuit schematic and description, then I can help you.
 

Re: PIC16F628A

Thanks so much Tamid Brother, thanks for your sincere help, I had attached the zip file, contains the led chaser code and the schematic. I willing to modified the led chaser code, so that the pin port A RA2 can send the output signal to control the relay after about 3 minutes delay. Currently I can on the relay when power on without delay. Please help me to modify the code.
 

PIC16F628A

Hi zh3ng,
If I got you correctly, this is what you want, as soon as power is applied there will be a 3 second delay after which the relay is to be turned on. Here is the code for that:
Code:
	LIST P=16F84A
	#INCLUDE <P16F84A.INC>
	__CONFIG _CP_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC
	
	CBLOCK 0x20
		D1, D2, D3
	ENDC

	ORG 0x00
	GOTO MAIN

; Delay 3 000 000 machine cycles
; Duration of the delay 3000 millisecond
; Frequency of the pulsing oscillator 4 MHZ
DELAY
	MOVLW	.13
	MOVWF	D1
	MOVLW	.57
	MOVWF	D2
	MOVLW	.16
	MOVWF	D3
	DECFSZ	D1, F
	GOTO	$-1
	DECFSZ	D2, F
	GOTO	$-3
	DECFSZ	D3, F
	GOTO	$-5
RETURN
;=================================================

MAIN
	BANKSEL	TRISA ;Move to bank 1
	CLRF	TRISA ;Clear tris bits and set to output
	BANKSEL	PORTA ;Move to bank 0
	CLRF	PORTA ;Clear contents of porta
	CALL	DELAY ;3second delay
	BSF		PORTA, 2 ;Turn relay on
	GOTO	$ ;Done
END
 

Re: PIC16F628A

Have you check the LED chaser code? I need you help to guide me where should I insert this delay code in Led Chaser Program. I tried, but not working. Thanks bro

Added after 18 minutes:

The Led Chaser program is working fine, i just need to add the delay relay module inside the program. When power is applied ,the Leds will start running, after 3 minutes running, I need the PIC to turn ON the relay by sending output signal through RA2. Once the relay is ON, it will stay ON and the LEDs are still running untill the power is OFF. I hope u can understand what i mean. Thanks
 

PIC16F628A

Hi zh3ng,
Here delay loop will not be very helpful. You need to use the internal TMR0 to check for time. I've made a program which works fine. Try it:
Code:
	LIST P=16F84A
	#INCLUDE <P16F84A.INC>
	__CONFIG _CP_OFF & _PWRTE_OFF & _WDT_OFF & _XT_OSC
	
	CBLOCK 0x20
		D1, D2, INTC, LCOUNT, RCOUNT
	ENDC

	ORG 0x00
	GOTO MAIN

	ORG 0x04
	GOTO ISR
;========================================================
DELAY
	MOVLW	.221
	MOVWF	D1
	MOVLW	.130
	MOVWF	D2
	DECFSZ	D1, F
	GOTO	$-1
	DECFSZ	D2, F
	GOTO	$-3
RETURN
;=======================================================
ISR
	DECFSZ	INTC ;CHECK FOR 46 TIMES INTERRUPT OCCURRED
	GOTO	$+2 ;DON'T TURN RELAY ON
	BSF		PORTA, 2 ;TURN RELAY ON
	BCF		INTCON, T0IF ;CLEAR TMR0 INTERRUPT FLAG
RETFIE
;=======================================================
MAIN
	BANKSEL	TRISB ;BANK1
	CLRF	TRISB ;PORTB ALL OUTPUTS
	CLRF	TRISA ;PORTA ALL OUTPUTS
	MOVLW	0xA0
	MOVWF	INTCON ;GLOBAL AND TMR0 INTERRUPT ENABLED
	MOVLW	0x87
	MOVWF	OPTION_REG ;PORTB PULL UP DISABLED, 1:256 PRESCALER
	BANKSEL	PORTB ;BANK0
	CLRF	PORTB ;CLEAR CONTENTS OF PORTB
	CLRF	PORTA ;CLEAR CONTENTS OF PORTA
	CLRF	TMR0 ;RESTART TMR0
	MOVLW	.46
	MOVWF	INTC ;FILL CONTENTS OF INTC
	MOVLW	.8
	MOVWF	LCOUNT ;FILL CONTENTS OF LCOUNT
	MOVWF	RCOUNT ;FILL CONTENTS OF RCOUNT
START
	MOVLW	.1
	MOVWF	PORTB ;RB0 = 1
LLOOP
	DECFSZ	LCOUNT
	GOTO	DOLEFT ;SHIFT IT LEFT
RLOOP
	DECFSZ	RCOUNT
	GOTO	DORIGHT ;SHIFT IT RIGHT
	MOVLW	.8
	MOVWF	LCOUNT ;RELOAD LCOUNT
	MOVWF	RCOUNT ;RELOAD RCOUNT
	GOTO 	START ;RESTART OPERATION
DOLEFT
	RLF		PORTB ;SHIFT LEFT
	CALL	DELAY ;DELAY
	GOTO	LLOOP ;GO BACK
DORIGHT
	RRF		PORTB ;SHIFT RIGHT
	CALL	DELAY ;DELAY
	GOTO	RLOOP ;GO BACK
END
Hope it helps. :) :)
Tahmid.
 

Re: PIC16F628A

Just a word of caution when using the '$' directive in PIC assembler. It means 'the current address' so an instruction such as 'goto $-5' means go back five instructions. It can be awkward to use because if you add or in some instances change an instruction that falls within the jump space, it can cause unpredictable results. The reason being that it will not change the distance of the jump if it becomes smaller or larger because of the instructions being jumped over. for example if you added an extra instruction in the delay, the code may have to be changed to "goto $-6" instead. Over short jumps it is fairly obvious what to do but over larger distances or when jumps start to cross over each other, it can be very difficult to keep track of them all.

A better method is to do this:
Code:
DELAY
   MOVLW   .13
   MOVWF   D1
   MOVLW   .57
   MOVWF   D2
   MOVLW   .16
   MOVWF   D3
 DelayLoop
   DECFSZ   D1, F
   GOTO   DelayLoop
   DECFSZ   D2, F
   GOTO   DelayLoop
   DECFSZ   D3, F
   GOTO   DelayLoop
RETURN

So now the assembler will calculate the offset for you, even if you make changes.
There is a further good reason for doing it this way, if you change to using larger PICs, the code will still work. These devices have wider instructions and all the jumps have to be doubled to work properly. The assembler will take care of that automatically if you change PIC type.

Brian.
 

PIC16F628A

betwixt,
Good suggestion. But I have become accustomed to using $, that's why I wrote it. But yea, I guess it's better to use labels.
 

Re: PIC16F628A

Hi Mr. Tahmid, Thanks so much, its working. Can I use timer1 instead of timer0, because the code in led chaser already using timer0 module.
 

PIC16F628A

Yes, you can use TMR1 instead of TMR0 but the code has to be slightly modified. First in the initialization part somewhere load T1CON:
Code:
   BANKSEL PIE1 ;BANK1
   MOVLW   0xC0
   MOVWF   INTCON ;GIE and PEIE selected
   MOVLW   0x01
   MOVWF   PIE1 ;Enable Timer1 interrupt
   BANKSEL PIR1 ;BANK0
   CLRF       PIR1 ;Clear Interrupt flag
   MOVLW   0x31
   MOVWF   T1CON ;TMR1 on and prescaler 1:8
Make the changes to your interrupt routine:
Code:
;Instead of this:
;BCF      INTCON, T0IF ;CLEAR TMR0 INTERRUPT FLAG 
;Instead of that write:
BCF      PIR1, TMR1IF
Hope this helps. Try that code.
 

Re: PIC16F628A

Tahmid,
Seems doesnt work for Timer1, please kindly check the code i already modified, shown below,....the led not ON and the relay not ON when I apply power.



LIST P=16F628A
#INCLUDE <P16F628A.INC>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _LVP_OFF & _BODEN_ON & _MCLRE_OFF

CBLOCK 0x20
D1, D2, INTC, LCOUNT, RCOUNT
ENDC

ORG 0x00
GOTO MAIN

ORG 0x04
GOTO ISR


;========================================================
DELAY
MOVLW .221
MOVWF D1
MOVLW .130
MOVWF D2
DECFSZ D1, F
GOTO $-1
DECFSZ D2, F
GOTO $-3
RETURN
;=======================================================
ISR
DECFSZ INTC ;CHECK FOR 46 TIMES INTERRUPT OCCURRED
GOTO $+2 ;DON'T TURN RELAY ON
BSF PORTA, 2 ;TURN RELAY ON
BCF PIR1, TMR1IF
RETFIE
;=======================================================


MAIN

BANKSEL PIE1 ;BANK1
MOVLW 0xC0
MOVWF INTCON ;GIE and PEIE selected
MOVLW 0x01
MOVWF PIE1 ;Enable Timer1 interrupt
BANKSEL PIR1 ;BANK0
CLRF PIR1 ;Clear Interrupt flag
MOVLW 0x31
MOVWF T1CON ;TMR1 on and prescaler 1:8
MOVLW .100
MOVWF INTC ;FILL CONTENTS OF INTC
MOVLW .8
MOVWF LCOUNT ;FILL CONTENTS OF LCOUNT
MOVWF RCOUNT ;FILL CONTENTS OF RCOUNT
START
MOVLW .1
MOVWF PORTB ;RB0 = 1
LLOOP
DECFSZ LCOUNT
GOTO DOLEFT ;SHIFT IT LEFT
RLOOP
DECFSZ RCOUNT
GOTO DORIGHT ;SHIFT IT RIGHT
MOVLW .8
MOVWF LCOUNT ;RELOAD LCOUNT
MOVWF RCOUNT ;RELOAD RCOUNT
GOTO START ;RESTART OPERATION
DOLEFT
RLF PORTB ;SHIFT LEFT
CALL DELAY ;DELAY
GOTO LLOOP ;GO BACK
DORIGHT
RRF PORTB ;SHIFT RIGHT
CALL DELAY ;DELAY
GOTO RLOOP ;GO BACK
END
 

PIC16F628A

Hi,
You forgot to set the TRIS bits.
The fixed code should be:
Code:
LIST P=16F628A
#INCLUDE <P16F628A.INC>
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _LVP_OFF & _BODEN_ON & _MCLRE_OFF

CBLOCK 0x20
D1, D2, INTC, LCOUNT, RCOUNT
ENDC

ORG 0x00
GOTO MAIN

ORG 0x04
GOTO ISR


;========================================================
DELAY
MOVLW .221
MOVWF D1
MOVLW .130
MOVWF D2
DECFSZ D1, F
GOTO $-1
DECFSZ D2, F
GOTO $-3
RETURN
;=======================================================
ISR
DECFSZ INTC ;CHECK FOR 46 TIMES INTERRUPT OCCURRED
GOTO $+2 ;DON'T TURN RELAY ON
BSF PORTA, 2 ;TURN RELAY ON
BCF PIR1, TMR1IF
RETFIE
;=======================================================


MAIN

BANKSEL PIE1 ;BANK1
CLRF TRISA                       ;-----------You missed this
CLRF TRISB                       ;-----------You missed this
MOVLW 0xC0
MOVWF INTCON ;GIE and PEIE selected
MOVLW 0x01
MOVWF PIE1 ;Enable Timer1 interrupt
BANKSEL PIR1 ;BANK0
CLRF PORTA                       ;-----------You missed this
CLRF PORTB                       ;-----------You missed this
CLRF PIR1 ;Clear Interrupt flag
MOVLW 0x31
MOVWF T1CON ;TMR1 on and prescaler 1:8
MOVLW .100
MOVWF INTC ;FILL CONTENTS OF INTC
MOVLW .8
MOVWF LCOUNT ;FILL CONTENTS OF LCOUNT
MOVWF RCOUNT ;FILL CONTENTS OF RCOUNT
START
MOVLW .1
MOVWF PORTB ;RB0 = 1
LLOOP
DECFSZ LCOUNT
GOTO DOLEFT ;SHIFT IT LEFT
RLOOP
DECFSZ RCOUNT
GOTO DORIGHT ;SHIFT IT RIGHT
MOVLW .8
MOVWF LCOUNT ;RELOAD LCOUNT
MOVWF RCOUNT ;RELOAD RCOUNT
GOTO START ;RESTART OPERATION
DOLEFT
RLF PORTB ;SHIFT LEFT
CALL DELAY ;DELAY
GOTO LLOOP ;GO BACK
DORIGHT
RRF PORTB ;SHIFT RIGHT
CALL DELAY ;DELAY
GOTO RLOOP ;GO BACK
END
Now it should work properly.
 

Re: PIC16F628A

Thanks, its working now. I'm intend to combine this timer1 code, with LEd Chaser code which are in the attachment(help me.zip). Where should I put the code "GOTO ISR".
Please check file pwmc_main107.asm and pwmc_start.inc. After I put GOTO ISR under 0x04, the relay on and off very quickly. IS there anything still need to modify the code?
 

Re: PIC16F628A

Hi,
I've made some changes to the code and it's been attached.
Hopefully, it's fine now.
 
  • Like
Reactions: zh3ng

    zh3ng

    Points: 2
    Helpful Answer Positive Rating
Re: PIC16F628A

Yeah bravoo!!!! great, it is working now. By the way, what is the maximum delay time we can apply on INTC variable? I tried put much longer delay time, but seems not working well? How is the calculation for this timer?

Regards,
Surianto Zheng
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top