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.

generate user defined pulses using pic18f4550

Status
Not open for further replies.

vterminater

New Member
what i have to do is generate 3 pulses 1)on 2)off 3)on the time for each pulse is given by the user(i have to give those values using labview;will do that once this is done)This is what i tried using pic18f4550 with external clock 20Mhz...when i checked output through simulator the code keeps executing here:goto here...so even the first delay does not end...any help???:(


#include<p18f4550.inc>
CONFIG WDT= OFF; disable watchdog timer
CONFIG MCLRE = ON; MCLEAR Pin on
CONFIG DEBUG = ON; Enable Debug Mode
CONFIG LVP = OFF; Low-Voltage programming disabled (necessary for debugging)
CONFIG FOSC = HS
;for external clocK
Td1 equ 0x00
Td2 equ 0x01
Td3 equ 0x02
Td equ 0x03
org 0
goto start
org 0x20
start:clrf TRISD
movlw 0x32
movwf Td1
movlw 0x64
movwf Td2
movlw 0xc8
movwf Td3
movlw 0xff
movwf PORTD
movlw b'10111000'
movwf T0CON
movff Td1,Td
call delay
movlw 0x00
movwf PORTD
movff Td2,Td
call delay
movlw 0xff
movwf PORTD
movff Td3,Td
movlw 0x00
movwf PORTD

org 0x60
delay:movlw 0x05
mullw Td
movff PRODL,TMR0L
movff PRODH,TMR0H
bcf INTCON,TMR0IF
here:goto here
return
end
 
Last edited:
Your program is doing exactly what you told it to: the "here: got here" line is a tight loop that never ends. I suspect that you are trying to set the Timer0 to some value and then wait until it times out. There are a couple of ways to do that but the simplest is to test for the timer overflow bit - something like (completely untested and off the top of my head):

here: btfss TMR0IF, INTCON
bra here
return

I have not checked all of your code, but I would suspect that you need to turn the timer on after you set the counter value and off again after it times out.

Also, remember that the timers count upwards and the key event is when they roll over from 0xffff to 0x0000. The way it looks, the larger the value you pass to your delay routine, the shorter will be the delay.

Susan
 
well i tried what you said but still
here: btfss TMR0IF, INTCON
bra here

keeps getting executed....can ya please lett me know what my delay program should be??and is the isr right?:confused:
 
The instruction should be,
Code:
here		btfss	INTCON,TMR0IF   ;swapped
		bra	here
		return
However, you have a few other errors. Timer 0 is not set to use the internal clock, the program has nowhere to go after the third delay and you load timer 0 in the wrong order.
Code:
#include<p18f4550.inc> 	 
		config	WDT=OFF		; disable watchdog timer 
		config	MCLRE=ON	; MCLEAR Pin on 
		config	DEBUG=ON	; Enable Debug Mode 
		config	LVP=OFF		; Low-Voltage programming disabled (necessary for debugging) 
		config	FOSC = HS
;for external clocK  
Td1		equ	0x00 
Td2		equ	0x01 
Td3		equ	0x02 
Td		equ	0x03 

		org	0 
start		clrf	TRISD	 
		movlw	0x32 
		movwf	Td1 
		movlw	0x64 
		movwf	Td2 
		movlw	0xc8 
		movwf	Td3 
		movlw	0xff 
		movwf	PORTD 
		movlw	b'10[COLOR="red"]0[/COLOR]11000' 
		movwf	T0CON 
		movff	Td1,Td	 
		call	delay 
		movlw	0x00 
		movwf	PORTD 
		movff	Td2,Td	 
		call	delay 
		movlw	0xff 
		movwf	PORTD 
		movff	Td3,Td	 
		movlw	0x00 
		movwf	PORTD 
[COLOR="red"]		call	delay
hang		goto	hang[/COLOR]

delay		movlw	0x05	 
		mullw	Td	 
[COLOR="red"]		movff	PRODH,TMR0H  ;swapped
		movff	PRODL,TMR0L  [/COLOR]
		bcf	INTCON,TMR0IF 
here		btfss	[COLOR="red"]INTCON,TMR0IF[/COLOR]
		bra	here
		return
		
		end
You also had various org statements that aren't needed.

Mike.
 
OK - I've looked a bit closer at you code and some things stand out.

When you initialise the T0CON register, your value is b'10111000'. This is interpreted as followed:
- TMR0ON = 1 -(bit 7) - turns the timer on which is probably a bit premature at this point in the program
- T08BIT = 0 - 16 bit count - OK
- T0CS = 1 - I think this may be the source of your problem as this uses the external T0CKI pin as the clock source
- T0SE = 1 - as long as the pin is being toggled, either setting here will work
- PSA = 1 - disable the prescaler
- T0PS = 000 - doesn't matter as the prescaler is off

You need to make sure the T0CKI pin is being toggled - in the simulator this means setting up the correct settings. HOWEVER, as you have been talking about delays and timers, I suspect you should be using the system clock as the timer source in which case the T0CS bit should be 0.

There are many other posts in this forum and elsewhere on the Internet that describe how to set up a delay routine. Basically you need to understand what the system clock is - you say you are using a 20MHz external clock and I can't see anything else that says you are using the PLL or other clock options so I assume this means the instruction cycle will be 4MHz or 250nSec.

Next you need to know the amount of the delay you want - in 250nSec increments. Lets say you want a 1mSec delay - that equates to 4000 (decimal) clock pulses. Remembering that the timers count UP, and the rollover is from 0xffff to 0x0000 (you are using the 16 bit timer option), you need to calculate 65535 - 4000 (0x10000 - 0xFA0) which gives 0xF060.

The next step is to set the timer value. If you look at the data sheet you will see that you need to set this as 2 byte transfers and it is very clear that you need to write the high byte first and then the low byte. What you write to for the high byte is a buffer that writting to the low byte will transfer simultaneously to the timer to it gets the full 16 bit value at one time.

Then you should clear the TMR0IF flag and turn on the timer.

By the way, I can't see ANY code that could be taken as as an ISR (Interrupt Service Routine) as you have not set anything up in either the low or high priority interrupt vector, nor have you set the various status bytes that control the operation of the interrupts on the PIC18F4550.

Susan
 
By the way, I can't see ANY code that could be taken as as an ISR (Interrupt Service Routine) as you have not set anything up in either the low or high priority interrupt vector, nor have you set the various status bytes that control the operation of the interrupts on the PIC18F4550.

Hi Susan,

He doesn't need any code as he is only setting and clearing the interrupt flag (TMR0IF), not the interrupt enable bit (TMR0IE) and so no interrupt will be triggered. Edit, just realised you state he hasn't setup the interrupt flags. Excuse my confusion.

Mike.
 
Last edited:
oki i think i know my mistakes now lemme know if am rite

1) since tmr0 is up counter instead of loading td*5 into counter register i have to load 65536-td*5..(think i would need some 16 bit subtraction technique for this)
2)i should have assigned tmr0h before tmr0l

now 1 confusion is that to start the second delay do i have to initialize isr at org 0x08
or its ot needed...i can just clear the timer register and stat over again:(


and about the examples
can ya send me links of examples of timers in ASM....i found only c codes which i don understand..!!!
 
Last edited:
You don't need interrupts at all just change your delay routine so it complements the calculated value,
Code:
delay		movlw	0x05	
		mulwf	Td		;this was the wrong instruction
		comf	PRODH		;to negate,
		comf	PRODL		;we complement
		incf	PRODL,F		;and increment
		btfsc	STATUS,Z
		incf	PRODH,F	 
		movff	PRODH,TMR0H  
		movff	PRODL,TMR0L  
		bcf	INTCON,TMR0IF 
here		btfss	INTCON,TMR0IF
		bra	here
		return
Note, you had the mullw instruction and so it was always doing 3*5.

The above should give you a delay of Td uS with a 20MHz clock.

Mike.
 
well the program is working properly but now i thought of improving my program a lil....the limitation of my present program is that my delay can be max upto 255us since i will be taking my input to Td register which is 8 bit...!what if i want a larger delay?!
 
about 500us? and one more question if i want the delay to be lesser than 1us ie frequency of pulse to be more than 1MHz then how??

AND hey i enter T0CON 10111000...the third one from the left which is for external clock does not show the output...only when i enter 0 instead of 1 it works..!!! i have not given any input to T0CKI pin...is that necessary??i thought the oscillator clock is used here!!
 
Last edited:
Answers in order of questions,

To get a 500uS delay I would use timer 2. Set TMR2CON to 0b00100101 and PR2 to 124 and PIE1,TMR2IF will get set every 500uS. Set TMR2CON to 0b01001101 for 1mS. To get multiples use a variable to count them.
Or, set timer 0 prescaler to 16 and multiply the value by 156 to get very close (499.2uS).

Less than 1uS, no problem, the timers are already being clocked every 200nS.

I would guess that the T0CKI pin is picking up an oscillation from somewhere. Try tying it low with a resistor and see what happens.

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top