8051 timer and external interrupt problem???

Hi all,

I'm a newbie to 8051 programming. I program in assembly language on a ATMEL 80c51 with a crystal frequency of 18.432 MHz.

I use timer1 for generating baud rate. Timer1 interrupt is not used. I use external interrupt 0 for communicating with 2 other peripherals.

Timer 0 interrupt is used to check if port pin 1.4 is low or high. and a corresponding message is displayed .

Interrupt 0 has high priority than the timer. the moment I enter into Interrupt Service routine, I stop the timer, clr the timer0 overflow flag and the timer 0 interrupt. After completing the job intended, just before exiting the routine I switch on the TImer0 and set the overflow and timer interrup flags.

The program works only when one of the interrupts are enabled in the code. When both Timer0 and Interrupt0 are set, the program hangs......

Especially after external interrupt0 is activated. what happens is , that timer interrupt doesn't detect the status of pin1.4 and displays the message...but interrupt0 gets activated every time interrupt0 occurs.

I have attached the code below. I think its some kind of a clash between the two interrupts. I would like to have pointers in this regard.

TIA. Regards Gayathri

The code :

;--------------When the program resets it jumps to main label-----------------

org 2000h ; start of main program after reset ljmp main ; goto label "main"

;---------------definition of interrupts--------------------------------------

org 0003h ; int0 vector address ljmp mainint reti

org 000bh ; timer0 interrupt ljmp on_off reti

org 0013h ; int1 vector address reti

org 001bh ; timer1 interrupt reti

org 0023h ; ri & ti reti

;------------------------------Byte Storage

---------------------------------- rub_all: db '{C0816 |{C1916 |{C3216 |' rg: db '$BM',0DH

low: db '{C2800 LOW|' high: db '{C2800 HIGH|'

;-----------------------------code segmenting-----------------------------------

cseg at 0100h ; Code starts from location 0100h

;---------------------------------Main------------------------------------------

main: mov SP,#18h ; Stack pointer initialised to 18h clr A ; Clear accumulator setb IT0 ; Interrupt 0 edge sensitive mov IP,#01h clr RS0 ; Select Register Bank 2 setb RS1 CLR TR0 CLR TF0 setb EA ; Enable all Interrupt CLR EX1 setb EX0 ; Set External interrupt 0(main) clr ET1 ; Clear external timer interrupt setb ES ; Enable serial interrupt

mov r1,#2Eh ; Number of characters in rub_all (46D= 2Eh) mov r0,#40h ; Starting location mov dptr, #rub_all ; Ruball is the label for 'db' lcall receiver ; Fill the db into RAM

lcall sio_init ; serial and timer1 initialization LCALL SIO_TIME ; timer0 initialization

infinite: sjmp infinite

;---------------------------TIMER 0 INTERRUPT SERVICE ROUTINE

------------------on_off: CLR EA clr ri clr ti LCALL SIO_INIT jb p1.4,ok ; if pin is high then go to ok mov r1,#0Bh mov dptr, #low ; displaying'{C2800 LOW|' lcall sender_b ; send to the serial port and display message through device2 sjmp done

ok: mov r1,#0Ch ; character counter mov dptr, #high ; '{C2800 HIGH|' lcall sender_b ; send to the serial port

done: LCALL SIO_TIME SETB EA reti

;------------- end of timer 0 interrupt------------------------------------------

mainint: mainloop: CLR EA push acc push psw push dpl push dph push 10h push 11h push 12h push 13h push 14h push 15h push 16h push 17h push b

lcall sio_init

;;;;; code for communicating with DEVICE1 --- get response from device one( through serial communication)

;;;;code for communication with device2 - for displaying the response.

pop b pop 17h pop 16h pop 15h pop 14h pop 13h pop 12h pop 11h pop 10h pop dph pop dpl pop psw pop acc POP 0A8H

LCALL SIO_TIME SETB EA reti ;--------------------subroutine for "ch_s"

-----------------------------------

ch_s: ; subrutine for transmitting data clr ti ; clear transmit interrupt clr a movc a,@a+dptr ; move the first character mov sbuf,a gon: jnb ti,gon ; wait until transmit interrupt is set inc dptr ; to get next data ret ; ret from subroutine

;--------------------Subroutine for "ch_r"

----------------------------------

ch_r: ; subroutine for receiving data from serial port gch: jnb ri,gch ; wait until receive interrupt is set mov @r1,sbuf ; mov sbuf data to address pointed by r1 mov r3,sbuf cjne r3,#2Eh,ter mov a,#06h ter: inc r1 ; to store next data inc a ; decrement character counter clr ri ; clear receive interrupt ret ; ret from subroutine

;______________________________________________________________________________

;--------------------subroutine for "ch_send"

--------------------------------

ch_send: ; subrutine for transmitting data on serial port clr ti ; clear transmit interrupt mov sbuf,@r0 ; move the first character gone: jnb ti,gone ; wait until transmit interrupt is set ret ; ret from subroutine

;--------------------subroutine for "sender"

--------------------------------

sender_b: setb p1.2 ; select Device2 for communication using a DEMUX clr p1.3 lcall sio_init

send_see: lcall ch_s ; call sub for character transmission djnz r1, send_see ; repeat if counter is not = 0 ret

;--------------------subroutine for "receiver"

-------------------------------- receiver: ; for sending program memory to RAM

send_re: clr a movc a,@a+dptr ; move the first character pointed by DPTR mov @r0,a inc dptr inc r0 djnz r1, send_re ; repeat if counter is not = 0 ret ;------------------------------------------sub routine -SIO init---------------- sio_init: CLR TR0 CLR TF0 CLR ET0 mov tmod,#20h ; select timer1 mov TH1,#0f6h ; reload value for 9600 baud rate =f6 mov scon,#50h ; init.serial control reg. & select mode 1 mov 87h,#80h ; pcon register-to multiply baud rate by 2 setb tr1 ; start timer1 clr ti clr ri ret

SIO_TIME: CLR TR0 CLR TF0 CLR ET0 mov tmod,#21h ; select timer1 AND TIMER 0 mov th0,#00h mov tl0,#00h SETB ET0 setb TR0 RET

;-----------------End of program

--------------------------------------------

;end program end

Reply to
pooja
Loading thread data ...

Instead of doing the serial comms inside an interrupt just set a flag which can be actioned in the main loop.

Try putting the code for timer 1 int in the main loop to see if serial comms works ok.

Also there is an extra pop in int0 isr - Im not sure why this is in there ?

Reply to
Paul

Thanx Paul and Gary..

I set two flags in the interrupt service routines and actioned them in the main loop. Now I do not use the timer interrupt at all. Instead I'm trying to do call the on_off routine in the main loop by default.

the program sequence: main:

1.initialise: Ex0,Ex1,SP,EARegister bank etc. 2.in an infinite loop ( check for the flags that my be set by the ISRs and service the routines. then also perform on_off routine then jmp back to inifinite loop).

The program works well only if this on_off routine is excluded from the main program.

On the other hand, if the flags --- ( set by interrupt Service routines) are not actioned..( if that code is removed) then this on_off routine works fine when included in the main program..

I mean... the on_off routine and the flag servicing routines seem to be mutually exclusive...

Please let me know why the program hangs... What am I missing?? Thanks in advance

Gayathri

Reply to
pooja

Have you tried turning interrups off before checking the flags, then on again after you have checked them?

You may be >Thanx Paul and Gary..

Reply to
DrWho?

Hi,...

why do i have to turn the interrupts off..???

This is what I'm doing: flag1 bit 01h flag2 bit 02h

org 2000h ; start of main program after reset ljmp main ; goto label "main"

org 0003h ; int0 vector address setb flag1 reti

org 0013h ; int1 vector address setb flag2 reti ;------------------------------Byte Storage---------------------------------- rub_all: db '{C0816 |{C1916 |{C3216 |' rg: db '$BM',0DH low: db '{C2800 LOW|' high: db '{C2800 HIGH|'

cseg at 0100h ; Code starts from location 0100h

;---------------------------------Main------------------------------------------ main: mov SP,#55h ; clr A ; Clear accumulator setb IT0 ; Interrupt 0 edge sensitive setb IT1 clr RS0 ; Select Register Bank 2 setb RS1 setb EA ; Enable all Interrupt CLR EX1 setb EX0 ; Set External interrupt 0(main) clr ET1 ; Clear external timer interrupt clr ES ; Enable serial interrupt clr flag1 clr flag2 clr ri clr ti

mov r1,#2Eh ; Number of characters in rub_all (46D= 2Eh) mov r0,#25h ; Starting location mov dptr, #rub_all ; Ruball is the label for 'db' lcall receiver ; Fill the db into RAM

lcall sio_init ; serial and timer1 initialization

infinite:

lcall on_off

jnb flag1,n1 lcall mainint n1: jnb flag2,n2 lcall continue

n2: sjmp infinite

****************************************************************

within mainint I communicate with a device say DEVICE1 within continue I communicate with yet another device say device2

on_off routine displays a message everytime program enters into "infinite:" loop.

I face the following problem. on_off and maintint,continue seem to be mutually exclusive. If "lcall on_off " is removed the program works fine. lcall on_off works fine when the flags 1 and 2 are not checked.

Please let me know what might be the cause???? What am i missing ???

TIA Gayathri

Reply to
pooja

As you say, there must be something you are doing in on_off and (mainint, continue) that are interfering with each other. You'll have to look at the code from those to see why this is. Your interrupt routines are nice and short and shouldn't be a problem.

Reply to
Gary Kato

Hi Gary,...

When I simulate the code on a keil simulator, it works very fine... but when on the actual 89C51, the progtam hangs..... The program misbehaves on my development kit also....

please let me know what might cause these kinds of problems?????

Regards Gayathri

Reply to
pooja

A simulator is just that. It can help you develop your code, but it's not perfect. You can only simulate what the I/O pins see. I don't know if the Keil simulator can simulate things like noise on the I/O lines or not.

Reply to
Gary Kato

In article , Gary Kato writes

No. You can't. AFAIK nothing does that sort of thing.

/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/\ /\/\/ snipped-for-privacy@phaedsys.org

formatting link
\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Reply to
Chris Hills

I seem to remember a setting in some simulator that could inject random noise into I/O stream. Can't remember what simulator that was though.

Reply to
Gary Kato

ROFL!

Reply to
Gary Kato

One of our products included a welder controlled by the embedded computer - we had to have the computer position the welder, then shut down, let the welder fire, then reboot the computer! It is very hard to isolate power supply from spikes on the ground! - RM

Reply to
RickMerrill

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.