We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi is there anyway of knowing if the LPC is receiving pulses on its INT0 pin. I have it already set up like this: IT0 = 1; //Pulses are edge detected EX0 = 1; //interrupt enable bit EA =1; It works fine, but is there anyway to find out if the pulses have stopped coming into this pin? The time the pulses will be present at this pin is unknown. This message is also posted at http://www.8052.com/forum/post.phtml
Presumably you stop getting an interrupt when the pin stops seeing edges? How long it has to be after the last edge before you decide that they have "stopped" is up to you. Hopefully you have a known input frequency and can just use a fixed timeout. If you've got a timer to spare, you could even start it on each incoming pulse, and have it generate an interrupt some time after the last edge. Otherwise, you might just timestamp the last edge in your interrupt handler, and your main loop can check the last timestamp.
Drew Davis, I think you have a good idea about what I want to do, but I do not have a fixed frequency. Can you tell me a litle bit more about this: "If you've got a timer to spare, you could even start it on each incoming pulse, and have it generate an interrupt some time after the last edge. Otherwise, you might just timestamp the last edge in your interrupt handler, and your main loop can check the last timestamp." can you explain this timestamp in more detail please? how to timestamp exactly? Thank you very much
My thought was that if you have a complicated system, including this pulse detector, you might have a free-running timer. The timestamp would just be an integer containing the time the interrupt occurred. That might be simply the value in your timer register. If the possible time you want to measure is longer than the range available with your timer, then you would have a counter for the higher-order bits that is incremented by a timer interrupt routine, with the low-order bits supplied by the timer countdown register. When an edge occurs, and you get an interrupt from that source, the edge interrupt handler copies the current time into some other variable (or data structure). This is the timestamp for the edge. You might have just one other copy, to remember the last time the most recent edge occurred. Or you might want a circular buffer to store the times for the last N edges, if you want to perform some filtering operation on that information. Once you have this timestamp, some other procedure has to check it. Probably, this is your main loop. Every so often (periodically, every time around the loop, scheduled by whatever means you use to schedule tasks in your system), you would check the timestamp, subtract it from the current time to get the time elapsed since the last edge occurred, and decide whether that elapsed time was long enough that the pulses had "stopped". The only way to be sure that the pulses have stopped is to wait an infinite amount of time. In practice, there has to be some rate so low that you're willing to say that the pulses have stopped after a certain amount of time has elapsed since you've seen an edge. Perhaps this time is a fixed amount of time (say, 1 second). Or perhaps it's a function of the pulse rate you've seen -- say, five times the longest gap between pulses, or five times the average of the most recent N pulses. There are any number of ways to decide the pulses have stopped. (Sorry to be so vague, but I can't really offer more specific suggestions as I don't know the details of your application.) Once you've answered the question "how long means stopped", then you have to figure out how to measure that amount of time. You can measure the time since the timestamp, as described above, or you could program a timer to expire when the right amount of time has elapsed, and just keep resetting that timer on every edge.
Drew Davis Thank you very much for you help. I will go over your posted message.
Hi Drew Davis, I have read your response and I really appreciate the time you took to answer it. I have stablished that if after one second a pulse is not sensed then, pulses have stopped coming into the pin. I have set up timer 0 for 1 second "I guess", but when I try it...I do not know how why it does not jump to the ISR evertime TFO is set...that is what should happen rigth? What I am missing here? can you tell. Maybe I am testing it the wrong way? I really appreciate your help. Thank you! void Time_Base(void) { ET0 =1; //enble T0 ISR TR0 = 0; TMOD |= 0x01; TAMOD = 0x00; TH0 = (65536-30720)/256; // 34816 TL0 = (65536-30720)%256; // .2 TF0 = 0; TR0 =1; EA = 1; } void timer(void) interrupt 1 { Time_Base(); Sec_Counter++; if (Sec_Counter == 20) // if 1 sec have passed { Sec_Counter = 0; TR0 = 0; AUXR1 |= 0x08; //reset program } }
You don't really need to completely re-initialize the timer in the ISR. The Time_Base() routine needs to reload TH0 and TL0 (since the LPC932 doesn't seem to have a 16-bit auto-reload mode for its timers), and you need to set TF0 = 0. But it shouldn't need to reset the mode, or enable the interrupts. However, that shouldn't be an issue for correctness. Yes, I would expect that when the timer finishes counting down, it would set TF0, and that the CPU would then jump to the interrupt vector (if EA == 1 and ET0 == 1) When you say it doesn't jump to the ISR every time, you mean that it does jump to the ISR some of the time? Does the interrupt run for a while, and then stop permanently, or do you just miss an interrupt now and then? What sort of debugger do you use? Unless it's an ICE, it can't stop the timers while you're at a breakpoint, so if you put breakpoints in the ISR, the time it takes to look around could cost you an interrupt. Any other interrupts or critical regions in your program that might be interfering?
Hi Drew Davis, I am the using the C51 Keil compiler to do all my projects. I have the evaluation and emulator boards. I am testing this program with the emulator and I am putting breakpoints at the Timer ISR, but when I run the program it seems to never get there and when I stop it (after 10 sec.) then it going through some other parts of the programs. Now, I have some other ISR's which are of a higher priority, but they are not being executed at all. All I have is this timer...do the main procedure and then call the time_base(); and after 2 sec. just reset the program. But just to make sure I am going to create a new project for this timer and its subroutine. Does this help? Thanks
Hi Drew Davis, I have created a new project for this 1 sec timer. It still does not want jump to its isr as TF0 ==1. I think I am testing this program the wrong way. Howeverm, when I am debugging I pull out the Timer 0 peripheral and I see that parameter INT0# is always checked. why is this? what is tis parameter? is this the interrupt zero pin?...I do not know. Thank you.
I'm not sure what you mean by "I see that parameter INT0# is always checked". Do you mean that you're getting external interrupts on the INT0 pin? Interrupt vector 03h? External interrupt 0? Represented by the IE0 flag (TCON.1) and EX0 (IE.0)? What "parameter" are you talking about, and what is doing the checking? Are you running under a simulator, or is this something in your emulator software interface, or what? I don't think you'll get a repeated interrupt to your timer ISR unless you clear TF0. The transition from 0 to 1 is what makes the interrupt occur. The code you posted does clear TF0, though. Does Sec_Counter increase? Is there any extra interrupt hardware in your particular device that needs to be enabled? Check the user's manual and datasheet for the part.
Hi Drew Davis, I do not know what that means INT0#, I do not think is INT0 pin, but is always checked and I do not know why. However, I have noticed that as I single step through the program and timer 0 registers TH0 and TL0 are loaded with their values TF0 gets set right away, but it does not jump to the ISR. Sec_Counter does not increase because it is never getting into the ISR. I am using the emulator. Is there any way you could try it, at least with an emulator. thank you very much
Why don't you post the minimum COMPLETE program that shows the problem. Someone may be able to help you then. Also, what clock frequency are you using? Stefan
Stefan Duncanson, the code is already posted. I am using the internal osc. at 7.373 MHz. The other part of the program are the initialization of ports and the clock source and speed. Nothing else. Thank you
"the code is already posted" You've only posted the bit where YOU think the problem lies. "The other part of the program are the initialization of ports and the clock source and speed. Nothing else." Well, post it then. Stefan
Here is Stefan, this is the whole program I am testing with out success. Thank you #include <Reg932.h> #include <stdio.h> #include <intrins.h> void init(void); void brkrst_init(void); void Time_Base(void); unsigned int Sec_Counter = 0; void Main(void) { P2 = 0x00; P0 = 0x00; init(); // configure ports brkrst_init(); //enable UART break detect Time_Base(); } void init(void) { P0M1 = 0x00; P0M2 = 0xCD; // Quasi-bidirectional P1M1 = 0x00; // Push-pull P1M2 = 0xFF; P2M1 = 0x00; // push pull output P2M2 = 0xFF; P1M1 |= 0x18; // make INT0 and INT1 input pins P1M2 &= 0xE7; ES = 1; // enable UART interrupt EA = 1; } void brkrst_init(void) // This function allows ISP entry through the UART break detect { SCON = 0x50; // select the BRG as UART baud rate source, pg. 60 SSTAT = 0x00; //Timer1 BRGR0 = 0xF0; // 9600 BAUD at @ 7.373MHz internal RC oscillator BRGR1 = 0x02; //timer increments every .0271 microsec. BRGCON = 0x03; // enable BRG, pg. 59 AUXR1 |= 0xC0; // enable reset on break detect, pg. 102 } void UART(void) interrupt 4 //Interrupt number for serial port { RI = 0; // clear receive interrupt flag } void Time_Base(void) { ET0 =1; TR0 = 0; TMOD |= 0x01; TAMOD = 0x00; TH0 = (65536-30720)/256; // 34816 TL0 = (65536-30720)%256; // .2 TF0 = 0; EA = 1; TR0 = 1; } void timer(void) interrupt 1 using 1 { Sec_Counter++; if (Sec_Counter == 20) // if 1 sec have passed { Sec_Counter = 0; P2 = 0xFF; TR0 = 0; } }
This version of the program differs from the earlier one in the timer ISR, which is no longer calling Time_Base(). The ISR needs to clear the overflow flag (TF0) so that the interrupt can re-occur. And since this is a one-shot timer mode, the ISR must also reload the timer registers. I would expect this program to produce one timer interrupt (50 msec after main finishes, assuming the timer values are calcuated correctly). When posting source code, if you put the text between the "pre" and "/pre" tags, it will preserve indentation on the left. Try something like:
void T0_Start (void) { TH0 = (65536-30720)/256; // 34816 TL0 = (65536-30720)%256; // .2 TF0 = 0; } void Time_Base(void) { ET0 =1; TR0 = 0; TMOD |= 0x01; TAMOD = 0x00; T0_Start(); EA = 1; TR0 = 1; } void timer(void) interrupt 1 using 1 { T0_Start(); // start timer again Sec_Counter++; if (Sec_Counter == 20) // if 1 sec have passed { Sec_Counter = 0; P2 = 0xFF; TR0 = 0; } }
Drew Davis I made the changes you posted. It still does not work. I tried it with emulator and it single steps, jumps into the ISR, reloads the timer, but does not clear TF0 flag bit. It increments the sec_counter variable once though. Did you try it yourself. did it work for you. I tried with the actual chip LPC932 revision F and it did not work...I say that because it did not turn on P2 LED's. What would be the next step. #include <Reg932.h> #include <stdio.h> #include <intrins.h> void init(void); void brkrst_init(void); void Time_Base(void); void T0_Start(void); unsigned int Sec_Counter = 0; void Main(void) { P2 = 0x00; P0 = 0x00; init(); // configure ports brkrst_init(); //enable UART break detect Time_Base(); } void init(void) { P0M1 = 0x00; P0M2 = 0xCD; // Quasi-bidirectional P1M1 = 0x00; // Push-pull P1M2 = 0xFF; P2M1 = 0x00; // push pull output P2M2 = 0xFF; P1M1 |= 0x18; // make INT0 and INT1 input pins P1M2 &= 0xE7; ES = 1; // enable UART interrupt EA = 1; } void brkrst_init(void) // This function allows ISP entry through the UART break detect { SCON = 0x50; // select the BRG as UART baud rate source, pg. 60 SSTAT = 0x00; //Timer1 BRGR0 = 0xF0; // 9600 BAUD at @ 7.373MHz internal RC oscillator BRGR1 = 0x02; //timer increments every .0271 microsec. BRGCON = 0x03; // enable BRG, pg. 59 AUXR1 |= 0xC0; // enable reset on break detect, pg. 102 } void UART(void) interrupt 4 //Interrupt number for serial port { RI = 0; // clear receive interrupt flag } void Time_Base(void) { ET0 =1; TR0 = 0; TMOD |= 0x01; TAMOD = 0x00; T0_Start(); EA = 1; TR0 = 1; } void timer(void) interrupt 1 using 1 { T0_Start(); // start timer again Sec_Counter++; if (Sec_Counter == 20) // if 1 sec have passed { Sec_Counter = 0; P2 = 0xFF; TR0 = 0; } } void T0_Start (void) { TH0 = (65536-30720)/256; // 34816 TL0 = (65536-30720)%256; // .2 TF0 = 0; }