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.

8051 PWM with period of 2 sec and 80% duty cycle

Status
Not open for further replies.

jamil916

Newbie level 4
Joined
Dec 20, 2012
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,330
i am currently studying on 8051 PWM and need to generate a PWM period of 2 sec and 80% duty cycle with the use of timer interrupt.
However, when i run it it simply keep looping in the delay loop. Can anyone tell me what is wrong?
Here is the code i use:


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
39
#include <sfr51.inc>
 
    ORG 0000H                   ;
    CLR F0                      ;
    JB F0, lowsignal    ;
    highsignal:
        MOV A, #32              ;
        MOV R7, A               ; 
        SJMP delay         ;
        ORG 000BH                   ;
        CLR F0                      ;
        CLR P1.0                    ;
        
        reti                        ;
    lowsignal:
        MOV A, #8               ;
        MOV R7, A               ; 
        SJMP delay              ;
        ORG 000BH               ;
        SETB F0                     ;
        SETB P1.0                   ;
        
        reti
        
   
    ORG 0030H                   ;
    delay:            
        loop:
            fiftymsdelay:               ; 50ms delay
            MOV TMOD, #01H          ; timer 0, mode 1
            MOV TH0, #3CH           ; 
            MOV TL0, #0B0H          ; load 15,536 (3CB0H) into timer 0
 
            SETB EA                 ; enable timer 0 interrupt
            SETB ET0                ;
            SETB TR0                ; start timer 0            
            DJNZ R7, loop       ; loop 50ms delay 32 times for a 1.6s delay  , 8 times for 0.4 s delay
 
   END

;
 
Last edited by a moderator:

I haven't written 8051 code in eons, but several things don't look right to me.

1) the last line of your loop DJNZ R7, loop will fall through to... what? when R7 is not =0 ?
2) you've got two blocks that are both org'ed at 000Bh. I would have thought you'd get an assembly error for that.
 

I haven't written 8051 code in eons, but several things don't look right to me.

1) the last line of your loop DJNZ R7, loop will fall through to... what? when R7 is not =0 ?
2) you've got two blocks that are both org'ed at 000Bh. I would have thought you'd get an assembly error for that.

I think THE DJNZ R7,loop is not wrong because the instruction DJNZ will count til R7=0 automatically
and for the ORG 000BH, i am not sure bout that but I saw an example that also point to same vector twice :S
 

Hi...
have a close look at the way u have structured your code.....
In the high signal part when u enter the delay subroutine the count in ur R7 register is 32.
in the delay subroutine u configure your timers and enable global & timer interrupts and run the timer.
just after that you dec R7 and check for zero and if false go back to the start of delay subrouine where u again configure the timers.
the point i am trying to make is that you never allow the timer to overflow and cause an interrupt after which u can again reload the timer and decrement r7 to zero and then go to low signal part of the code.

hope that helps....

cheers...
Vijay
 

Hi...
have a close look at the way u have structured your code.....
In the high signal part when u enter the delay subroutine the count in ur R7 register is 32.
in the delay subroutine u configure your timers and enable global & timer interrupts and run the timer.
just after that you dec R7 and check for zero and if false go back to the start of delay subrouine where u again configure the timers.
the point i am trying to make is that you never allow the timer to overflow and cause an interrupt after which u can again reload the timer and decrement r7 to zero and then go to low signal part of the code.

hope that helps....

cheers...
Vijay

Thx for ur advice, i just tried to allow timer to overflow, but it just stuck in the JNB TF1,$ .
is that wrong of using this instruction or is there anything i missed again?
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
39
#include <sfr51.inc>
 
    ORG 0000H                   ;
    CLR F0                      ;
    JB F0, lowsignal    ;
    highsignal:
        MOV A, #32              ;
        MOV R7, A               ; 
        SJMP delay         ;
        ORG 000BH                   ;
        CLR F0                      ;
        CLR P1.0                    ;
        
        reti                        ;
    lowsignal:
        MOV A, #8               ;
        MOV R7, A               ; 
        SJMP delay              ;
        ORG 000BH               ;
        SETB F0                     ;
        SETB P1.0                   ;
        
        reti
        
   
    ORG 0030H                   ;
    delay:            
        loop:
            fiftymsdelay:               ; 50ms delay
            MOV TMOD, #01H          ; timer 0, mode 1
            MOV TH0, #3CH           ; 
            MOV TL0, #0B0H          ; load 15,536 (3CB0H) into timer 0
 
            SETB EA                 ; enable timer 0 interrupt
            SETB ET0                ;
            SETB TR0                ; start timer 0
            JNB TF0,$               ;            
            DJNZ R7, loop       ; loop 50ms delay 32 times for a 1.6s delay  , 8 times for 0.4 s delay
 End;

 

try to follow this flow chart

1.enable timer interrupts
2. config timer
3. load count for high signal
4.run timer
5.keep checking for count=0
yes proceed to 6 .
else run timer again and go to step 5.
(try to decrement the count in the ISR loop and not outside it)
6.load count for low signal and clear the set bit.
7.run timer.
8.keep checking for count=0
yes proceed to 9 .
else run timer again and go to step 5.
(try to decrement the count in the ISR loop and not outside it)
9.go to step 4.

inside the isr routine clear timer flags , decrement count

yes JNB TF0,$ is fine...here the TF0 flag is checked for 0.

plus why dont you try and use the timer in auto reload mode.
 

try to follow this flow chart

1.enable timer interrupts
2. config timer
3. load count for high signal
4.run timer
5.keep checking for count=0
yes proceed to 6 .
else run timer again and go to step 5.
(try to decrement the count in the ISR loop and not outside it)
6.load count for low signal and clear the set bit.
7.run timer.
8.keep checking for count=0
yes proceed to 9 .
else run timer again and go to step 5.
(try to decrement the count in the ISR loop and not outside it)
9.go to step 4.

inside the isr routine clear timer flags , decrement count

yes JNB TF0,$ is fine...here the TF0 flag is checked for 0.

plus why dont you try and use the timer in auto reload mode.
I am a bit confuse, what do u mean by clear timer flags , decrement count inside the isr routine and what is the count? is that the one i use to loop that 50ms delay?
 

sorry for the advice on clearing the timer falgs....since you are using interrupts there is no need for u to clear them....:oops:
yes, when i say count i refer to the value in R7 register...
 

after i try to follow the flow chart, i try this 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
#include <sfr51.inc>
    ORG 0000H                   ;
    highsignal:
        MOV A, #32               ;
        SJMP delay         ;
        ORG 000BH                   ;
        DJNZ R7, RETURN 
        CLR P1.0                    ;
        SJMP lowsignal
     RETURN: RETI   
   
    ORG 0030H                   ;
    delay:            
        loop:
            fiftymsdelay:               ; 50ms delay            
            SETB EA                 ; enable timer 0 interrupt
            SETB ET0                ;
            MOV TMOD, #01H          ; timer 0, mode 1
            MOV TH0, #3CH           ; 
            MOV TL0, #0B0H          ; load 15,536 (3CB0H) into timer 0
            MOV R7, A               ;
            SETB TR0                ; start timer 0
            SJMP $               ;    
     ORG 000BH
     lowsignal:
        MOV A, #8               ; 
        DJNZ R7, RETURN 
        SETB P1.0                   ;
        SJMP highsignal
 End;


however it still stuck in the timer on JNB TF0,$ ...
it seems that it can't even get thoguht the first time
 
Last edited:

i do not see any JNB TF0,$ in your code.....
please make sure u do not write your code in the are where the interrupts are vectored to...
try using the timer in the auto reload mode....it would make your as much easier as you dont have to relosd the initial values back into the timer ....
try configuring in auto reload mode and may be u could use the skeleton code given below:

i have not tested out this code...but u can try it out

ORG 0000H
SJMP main



ORG 0030 ;avoiding interrupts section
main: SETB EA ;ENABLE GLOBAL INTERRUPTS
SETB T0 ;ENABLE TIMER 0 INTERRUPT
Configure timer in auto reload mode…..
CLR C; USING CARRY FLAG FOR SIGNALLING END Of COUNT

high: MOV A,#32;
MOV R7,A;
Enable timer here…..
JNB C,$; JUMP HERE
CLR C;
SETB P1.0; HIGH ON P1.0
MOV A,#8; CONFIGURING COUNT FOR LOW PERIOD
MOV R7,#A
JNB C,$;
CLR C;
CLR P1.0; LOW ON P1.0;
SJMP high;

ORG OOOBH ISR routine
SJMP HERE


ORG 0300H
HERE: ISR_ROUTINE:
DJNZ R7,DOWN
RETI;

DOWN: SETB C;
RETI;


You will have to recalculate the count values as per your need.
 

oh , sorry about that,i changed the JNB TF0,$ to SJMP $ :S
but when i run it step by step, the program just stop there.
it never get into the interrupt once
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top