Counter programing in 8051 using asm language

Status
Not open for further replies.

Disha Karnataki

Full Member level 5
Joined
Jul 20, 2013
Messages
249
Helped
9
Reputation
18
Reaction score
8
Trophy points
18
Location
india
Activity points
2,231
i am doing a counter programing in 8051 using asm language inorder to count pulses at p3^4 pin for 1second here i have programmed one timer as timer & another timer as counter when i simulate this program it is working fine but it's showing different count on hardware when i reset at different instance please figure out what is problem in my programing.

Code:
org 0000h
ljmp main
org 001bh
ljmp isrt1                    //isr routine
org 0100h
main:mov p1,#00h
mov p3,#0ffh
mov tmod,#15h          //timer0 as counter & timer1 as timer
mov ie,#88h				   //timer interrupt for timer1
mov th1,#00h
mov tl1,#00h
mov r0,#0eh						 //for 1 second delay
setb tr0
k1:setb tr1						//start timer
cjne r0,#00h,k1
clr tr0
o1:mov p1,tl0
sjmp o1
isrt1:                                 //isr routine
clr tr1
djnz r0,l12
l12:										   //creating 1 second delay
mov th1,#00h
mov tl1,#00h
reti
end
 
Last edited by a moderator:

Re: to count pulses using 8051

You didn't clear the timer flags. You didn't handle your interrupt so well. You have to keep in mind that interrupt can occur anytime and anywhere in your program. Although, you don't need any interrupt to detect rpm input. Also your code isn't neatly wrote. Here is what I did. I didn't tested it, so you can give it a try and see if it works....

Code:
org 0000h
jmp main

org 001bh
reti			//not in use
			//isr routine
org 0100h

Initialize:
mov p1,#00h
mov p3,#0ffh
mov tmod,#15h		//timer0 as counter & timer1 as timer

main:
mov th0,#00h
mov tl0,#00h
mov th1,#03ch
mov tl1,#0b0h
mov r0,#014h		//for 1 second delay, assuming 12MHz clock
setb tr0

loop:
setb tr1
jnb tf1,$
clr tf1
clr tr1
djnz r0,loop
clr tr0
clr tf0
cjne th0,#00h,overflow	//check if rpm exceeded the reading capacity
mov p1,tl0
setb p3.7		//connect a LED here
jmp main

overflow:
clr p3.7		//pin will set again only when rpm is readable
jmp main

end

You also didn't mentioned what crystal value you are using and what would be the maximum RPM you are going to deal with... Its a project based on timing, so these things are needed to mention.
 

Re: to count pulses using 8051

it is an ac fan & rpm on the motor of fan is written as 1250rpm which is obviously the max speed i am doing pov with mounted pcb & uc 8051 which has 11.0592mhz crystal.After fitting this assembly i wanted to know the exact rpm(which may get lowered due to the assembly mounted) for that reason i wrote the program on finding rpm of the motor.

- - - Updated - - -

genovator it is not required to clear the timer flags in isr routine as the software does for us

- - - Updated - - -

how loading 3c,b0 will give you 1sec delay as per me it should be th0=00h,tl0=00h so time delay when setb tr0 is 65536-0000=65536. 65536*1.086us=.07071s
therefore 0.07071*14=1sec(approx) right??

- - - Updated - - -

how loading 3c,b0 will give you 1sec delay as per me it should be th0=00h,tl0=00h so time delay when setb tr0 is 65536-0000=65536. 65536*1.086us=.07071s
therefore 0.07071*14=1sec(approx) right??
 

Re: to count pulses using 8051

You'r right. Flags are cleared automatically when timer interrupt is called. I removed the interrupt, so now you will need that....

In 12MHz crystal, TH1 & TL1 values are determined by,

12 Mhz/12= 1MHz
( 1 / 1MHz ) = 1us [This is the least time for single cycle]

Now,
(65536-xxxx)*1us= 50 ms [50ms is a round-up value for easy calculations]
(65536-xxxx)=50,000 [50ms/1us]
xxxx=15536
in hex it is
xxxx=0x3CB0

So TH1=03Ch
and TL1=0B0h
The timer in 16bit mode will take 50ms to count from 15536 to 65536. Then I multiplied it 20 times to make it 1 sec (R0 = 14H = 20 dec)
*************************
In your case, 11.0592MHz, or with 1.086us increment time,

(65536-xxxx)*1.086us= 50 ms [50ms is a round-up value for easy calculations]
(65536-xxxx)=46040 [50ms/1.086us]
xxxx=19496
in hex it is
xxxx=0x3CB0

So TH1=04Ch
and TL1=028h

Your process for timer is all same, mine is just a little more accurate (-10us).
In your code, after 1 sec of run time, your program will stuck & keep looping under "o1" subroutine. I don't see any way out...
Try this code to see if it works as you want....
 
Re: to count pulses using 8051

another thing i have changed my program. I tried your program it's working. As i mentioned above that i am using ac fan & i have 3 speeds on the fan's motor rpm mentioned is 1250rpm there are 3 buttons on fan so i dumped the above written program & then i got for 1st(min)speed i have got many different values for it but the most occured value was 7 so i figured out that min speed=7rps.
next for 2nd(medium)speed the speed got after many fluctuations was 15rps & then for max speed i got 20 rps,19rps & 30rps frequently(may be i tried for this speed 100 times) . Then as i am doing pov and if want to prefer a fixed rpm then on which result should i rely or shall i consider 30rps this is hypothetical as it's written on motor speed=1250rpm so rps can't exceed 20.833.

- - - Updated - - -

In your code, after 1 sec of run time, your program will stuck & keep looping under "o1" subroutine. I don't see any way out...
yes i have written it so that the display is retained.Actually uc is not taught yet to us just i am taking my chances but as per your code i got to know that if we want program to remain in infinite loop then we have to use $ sign right?
 

Re: to count pulses using 8051

Hi dear..........I have also tried this type of rpm counter but the major problem i have seen is that if you calculate the revolutions for one second and the multiply it with 60 by using the mcu the number of rpms will always be the multiples of 60......and in this case the rpms will not be exect....
 

Re: to count pulses using 8051

I missed one thing in my code=> You have to reload the high & low values of timer 1 every time you start it, or else it will start counting from 0. For 50ms by 11.0592MHz crystal, it should count from 19496. So add these two lines just before "djnz r0, loop"....

mov th1,#04ch
mov tl1,#028h

Test it again and see if variations on result minimizes...
 

Re: to count pulses using 8051

(65536-xxxx)*1.086us= 50 ms [50ms is a round-up value for easy calculations]
(65536-xxxx)=46040 [50ms/1.086us]
xxxx=19496
in hex it is
xxxx=0x3CB0
So TH1=04Ch
and TL1=028h

yes i have approximated & wrote this code & tested this code

Code ASM - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ORG 0
        MOV P1,#00h      ; PORT P0 CONFIGURED AS OUTPUT PORT
        mov p2,#00h
        MOV P3,#0FFH     ; PORT P3 CONFIGURED AS INPUT PORT
        MOV TMOD,#51h   ; TIMER CONFIGURATION
        SETB TR1         ; START COUNTING PULSES ON P3.5
        MOV R7,#20       ; TIMING REPEATED 20 TIMES
AGN:    MOV TH0,#4cH     ; VALUE IN TH0 FOR 1/20 S DELAY
        MOV TL0,#01H     ; VALUE IN TL0 FOR 1/20 S DELAY
        SETB TR0         ; START TIMER (FOR 1/20 S DELAY) 
        JNB TF0,$        ; WAIT TILL COUNTING IS OVER
        CLR TF0          ; CLEAR TIMER FLAG TF0
        DJNZ R7,AGN      ; REPEAT THIS TIMER 20 TIMES FOR 1S
        CLR TR1          ; STOP COUNTING
        MOV P1,TL1       ; Display Lower byte of count on P0    
        MOV P2,TH1       ; Display Higher byte of count on P2
        SJMP $           ; ENDLESS LOOP (Keep Display)
        END


to vain i got the same results as mentioned in my #3post.
 
Last edited by a moderator:

Re: to count pulses using 8051

Code:
ORG 0
MOV P1,#00h ; PORT P0 CONFIGURED AS OUTPUT PORT
mov p2,#00h
MOV P3,#0FFH ; PORT P3 CONFIGURED AS INPUT PORT
MOV TMOD,#51h ; TIMER CONFIGURATION
SETB TR1 ; START COUNTING PULSES ON P3.5
MOV R7,#20 ; TIMING REPEATED 20 TIMES
AGN: MOV TH0,#4cH ; VALUE IN TH0 FOR 1/20 S DELAY
MOV TL0,#01H ; VALUE IN TL0 FOR 1/20 S DELAY
SETB TR0 ; START TIMER (FOR 1/20 S DELAY) 
JNB TF0,$ ; WAIT TILL COUNTING IS OVER
CLR TF0 ; CLEAR TIMER FLAG TF0
DJNZ R7,AGN ; REPEAT THIS TIMER 20 TIMES FOR 1S
CLR TR1 ; STOP COUNTING
MOV P1,TL1 ; Display Lower byte of count on P0 
MOV P2,TH1 ; Display Higher byte of count on P2
SJMP $ ; ENDLESS LOOP (Keep Display)
END

Is that the code you are using??? Its completely wrong...

Your TL0 value isn't correct. You should first move all the values to their respective registers, then start the timers, or else you can miss some counts on rpm. Your program will stuck on "sjmp $". It will never count again. '$' will keep it looping on the same memory address it is written on. Try the code below with timer 0 as counter, as it was before, or you can switch the timers if you wish...

Code:
org 0000h
jmp main

org 001bh
reti			//not in use
			//isr routine
org 0100h

Initialize:
mov p1,#00h
mov p3,#0ffh
mov tmod,#15h		//timer0 as counter & timer1 as timer

main:
mov th0,#00h
mov tl0,#00h
mov th1,#03ch
mov tl1,#0b0h
mov r0,#014h		//for 1 second delay, assuming 12MHz clock
setb tr0

loop:
setb tr1
jnb tf1,$
clr tf1
clr tr1
mov th1,#04ch
mov tl1,#028h
djnz r0,loop
clr tr0
clr tf0
cjne th0,#00h,overflow	//check if rpm exceeded the reading capacity
mov p1,tl0
setb p3.7		//connect a LED here
jmp main

overflow:
clr p3.7		//pin will set again only when rpm is readable
jmp main

end
 
Re: to count pulses using 8051

you got exact value of 1second but i got 1.00083588second thats it.
my values are th0=4ch tl0=01h i.e in decimal 19457
delay calculation in 8051 with 11.0592mhz crystal: 65536-19457=46079
46079*20(times the loop repeats)=921580
921580*1.086us=1.00083588s
so whatever values have taken are correct no fault.
yes i changed the program & exactly copy pasted it but, only thing is i didnot include is these lines:

Code:
[CODE]org 0000h
cjne th0,#00h,overflow	//check if rpm exceeded the reading capacity
setb p3.7		//connect a LED here
jmp main

overflow:
clr p3.7		//pin will set again only when rpm is readable
jmp main

end

i understood why u included these lines i.e if the motor rpm per second is more than 255 then the overflow should occur but i think in no way i will use such a high speed motor with around 255*60=15300 rpm motor so i didnot include those line in the code am i correct then,will it be right now?? i will try this & inform you shortly.
 

Re: to count pulses using 8051

Okay then, you can use this code if you wish. It will be same.....

Code:
org 0000h
jmp main

org 001bh
reti			//not in use
			//isr routine
org 0100h

Initialize:
mov p1,#00h
mov p3,#0ffh
mov tmod,#15h		//timer0 as counter & timer1 as timer

main:
mov th0,#00h
mov tl0,#00h
mov th1,#04ch
mov tl1,#01h
mov r0,#014h		//for 1 second delay, assuming 12MHz clock
setb tr0

loop:
setb tr1
jnb tf1,$
clr tf1
clr tr1
mov th1,#04ch
mov tl1,#028h
djnz r0,loop
clr tr0
clr tf0
mov p1,tl0
jmp main

end
 
Re: to count pulses using 8051

i used your code in post #9 copy pasted it but.. i got variations in the result same way i do not know what to do so then just considering may be rps at 2nd speed=15rps i wrote a following code to display a led just at 1/4th of a revolution as you can see the sensor position from there at 1/4th of the circumference distance here:https://www.edaboard.com/threads/307667/ see post #9
here is the code i tried a lot using 15rps but in vain did not get the right result then by trial & error i changed some values here & there & got the right display that i was expecting so here is the code :

Code ASM - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
org 0000h
ljmp main
org 0100h
main:mov p1,#00h 
mov p3,#0ffh     
mov tmod,#11h//timer 0,timer 1
mov th0,#0a6h  //these are values tried by trial & error method
mov tl0,#05h  //these are values tried by trial & error method
mov th1,0a0h //these are values tried by trial & error method
mov tl1,80h  //these are values tried by trial & error method
j1:jb p3.3,j1 //sensor senses to start the display?
lcall delay      //delay from sensor position to 1/4th of the circumference
setb p1.7  //lighting only one led 
lcall delay1// retaining the led light for  few ms
clr p1.7         //clearing the set led
lcall delay2  //keeping the led off for remaining 3/4th distance of the circumference
sjmp main //continuously doing this
delay:
setb tr0
l1:jnb tf0,l1
clr tf0
clr tr0
ret
delay1:
setb tr1
l:jnb tf1,l
clr tf1
clr tr1
ret
delay2:
mov th1,#0d9h
mov tl1,#0d9h
setb tr1
m:jnb tf1,m
clr tf1
clr tr1
ret
end



from this now can i calculate the rpm of the motor for second speed?? I now how to calculate but i am not getting correct ans i.e i am getting 200rpm it's not possible so can you calculate & tell me?? then i shall tell how i calculated
 
Last edited by a moderator:

Re: to count pulses using 8051

1. Check u r code using external fixed pulse input say 20 pulse / second using other controller. From this u get correct result then u conclude that rpm software ok then check for motor
2. Many times motor rpm may not exact it may have some variation
3. Try to implement code using interrupt
 

Re: to count pulses using 8051

In my code of post #9 you can see I wrote high & low values of timer 1 in two places & both are different. That's a mistake. Every time those values should be 04CH & 028H. Maybe that's causing problem, or something else. Try this code now. I am correcting it...

Code:
org 0000h
jmp main

org 0100h
Initialize:
mov p1,#00h
mov p3,#0ffh
mov tmod,#15h		//timer0 as counter & timer1 as timer

main:
mov th0,#00h
mov tl0,#00h
mov th1,#04ch
mov tl1,#028h
mov r0,#014h		//for 1 second delay
setb tr0

loop:
setb tr1
jnb tf1,$
clr tf1
clr tr1
mov th1,#04ch
mov tl1,#028h
djnz r0,loop
clr tr0
clr tf0
mov p1,tl0
jmp main

end

If you do not wish to use counter, then you can try this....

Code:
org 0000h
jmp main

org 0100h
mov p1,#00h 
mov p3,#0ffh

main:
mov r0,#20
mov tmod,#01h
mov th0,#04ch
mov tl0,#028h
setb tr0
jmp loop

timer:
mov th0,#04ch
mov tl0,#028h
setb tr0

loop:
jb p3.5,increment
jnb tf0,loop
jmp reload


increment:
inc r1
jb p3.5,$
jmp loop

reload:
clr tr0
clr tf0
djnz r0,timer
mov p1,r1		//r1 contains rps value
mov r1,#00h
jmp main

end

Test both of them and see if they work...
 
Re: to count pulses using 8051

i didn't try with post#9 but tried with post#11 first code in #14 which is same as #11post. i got 1st speed=7rps,second speed=15rps,3rd speed=19rps(this had more fluctuations)
as i want to do pov & accurate rpm readings are required. So,i decided to opt for a tachometer & then in tachometer it showed me 1st speed=480rpm
2nd speed=960rpm(here using your code i got 15rps but tacho showed 16rps these are expected variations) & 3rd speed=1150,1100,1200.
so i have decided to go for 2nd speed with speed of 960rpm.
as this is my first pov i want to discuss my programing style the way i am going to approach to write the code.
so whatever programing you gave was showing correct result but only had few rps variation(code in post #11)

- - - Updated - - -

if i decide about my programing here i will not use any interrupts or timer interrupts as a very small mistake may end up into a very huge problem.
so i have decided to pole the pin p3.3(where ir sensor is attached) form this the rotation will start see this post #9 for the arrangement i have done: https://www.edaboard.com/threads/307667/ here sensor is placed above but, i have placed diagonally opposite to the place placed in diagram)
now if i start from the sensor position then, i am going to use 960rpm so rps=16 & time/rotation=62.5ms.i had written a code to dislay a dot every 1/4th of the rotation so that means i should set a led every 62.5ms/4=15.625ms.Am i correct in this regard??
 

Re: to count pulses using 8051

Yes. You have to keep your program on loop until it detects its first IR input. When it detects, set an LED, call a delay for 15.625ms, clear the LED, and loop back to IR detection again. If you wish to count inputs, increment a register which is going to hold the count value. Ignore if count is not important.

Not very important, but still saying that it is better to keep the hole on disk as narrow vertical rectangle '[]' rather than a hole '( )'. But its all same. No harm with a circular hole....






P.S: post 11 isn't same as post 14. Try codes from post 14 only....
 
Re: to count pulses using 8051

hmm..
ya for my first program i tried displaying led at every 15.625ms i.e every 1/4th distance of the circum.
but i didnot get the display properly rather i got the display for per 1/4th rotation after a delay of 62ms(15*4=60) from the sensor position which is nothing but 2ms after the sensor position how is it possible??
 

Re: to count pulses using 8051

which code you mean do u mean rpm finding? then i have used the both code from #14 & before trying your code i also tried code from #12
 

Re: to count pulses using 8051

I mean the code you used to display a LED for 15.625ms which didn't worked properly...

Is the codes from post #14 works??
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…