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.
Hello can someone tell me why my interrupt does not respond, with the debugger, I always get z = 0
double z; main { . . . . . . while(1) { CC1_M2 = 0x0001;// 001=>capture on posirtive Flanke CC1_T01CON = 0x0047; CC1_CC8IC = 0x00C0; // Interrupt enable und z = Periode ; }//end of while }// end of main void Drehzahl_messung(void) interrupt(0x18) { Periode = 100; }
or what I have since forgotten Thanks
Sorry, I can't help with your problem, since I don't work with the C166 processor.
But one thing to think about is your assign of the double value in the interrupt handler.
Is the C166 processor capable of writing a double (or if it is just an alias for a float) atomically? If not, then the main loop may read broken values if the interrupt happens in the middle of a read, unless you synchronizes the accesses, possibly by _atomic_/_endatomic_.
Another thing: Are floating point operations supported in both the interupt handler and the main program at the same time?
Does it work if you declare z volatile?
volatile double z;
I see a couple of things.
Your interrupt priority is on level zero which will never allow it to vector so you need to move it off of zero.
Secondly I didn't see where you globally enabled interrupts?
Thirdly, not sure of the code sequence but if you are looking for a interrupt on the rising edge of P2.8 then here is your example slightly modified.
#include <xc167.h> double z; double Periode; void main (void) { CC1_M2 = 0x0001;// 001=>capture on posirtive Flanke CC1_T01CON = 0x0047; CC1_CC8IC = 0x0044; // Interrupt enable und, ILVL = 1 PSW_IEN = 1; // globally enable interrupts while(1) { z = Periode ; }//end of while }// end of main void Drehzahl_messung(void) interrupt(0x18) { Periode = 100; }
Hope this helps
You can not resolve 'atomic-acess problem' with volatile - what 'volatile' does, it tells to the compiler "do not optimize a call to the variable, use explicit storage location to work with". The storage location for double is more than 16-bit word so additional guard mechanism still required.
-- Nikolay.
Yes, in this case the original code both misses the 'volatile' keyword and any code to make sure that it is isn't modified in the middle of a read.
You can not resolve 'atomic-acess problem' with volatile
I'm not suggesting it would. I'm suggesting that it may solve the original problem by not allowing writes to the variable z to be optimized out. It's worth a try.
Hello Firstly, I would like to thank all the people who tried to help me The problem was simply the PSW register in the
PSW_IEN = 1;
and also with the priority of the interrupt
CC1_CC8IC = 0x0044;
and that has works I just wanted to test whether my Prograam to interrupt and the changes worked. I will now in the interrupt a speed measurement program
Thanks Chris Wunderlich Thanks to all
"The problem was simply the PSW register in the"
This represents a third problem.
You still have to think about the other two. Use volatile and protect the read of the variable from being interrupted.
Hello altogether
Hello westermark
I have now a second problem: I have used volatile but I still get no good results I must measure the period between two positive transition flanks .. sometimes I have good result but does not remain constant, over and over period = 0, what could be the reason? I have to change my code or the funktion with which I will measure the time (periode)
double periode; volatile int Timer_alt; volatile int Timer_neu; volatile int Timer_Diff; void main (void) { . . . . . while(1) { CC1_M2 = 0x0001; //Bit3 allocated to Timer T0/T7 ,Bit 210 001=>capture on posirtive Flanke CC1_T01CON = 0x0047; //Bit6 0=>Timer is enabled ,Bit3 1=>Timer Mode,Bit210 111=>Timer Resolution 25,6 µs CC1_CC8IC = 0x0044; // Interrupt enable und Interrupt Flag enable PSW_IEN = 1; // globally enable interrupts periode = Timer_Diff*0.0000256; // Periode }//end of while }// end of main /* __|----|___|----|___|----|____ */ //010101 void Drehzahl_messung(void) interrupt 24 { Timer_alt = CC1_CC8 ; // Timer contents captured do{ }while (P2 & 0x0100); //wait of the Low signal Timer_neu = CC1_CC8 ;// Timer contents captured Timer_Diff = Timer_neu - Timer_alt; }
Thanks for your help
What is generating your pulses?
Have you verified that you don't have a bouncing signal, in which case the pulse may have ended before you enter your ISR. This will result in a zero length being sampled.
Timer_alt and Timer_neu don't need volatile if they are only used inside the ISR. The volatile keyword is only needed when a variable may be asynchronously updated by other code or the hardware.
The ISR may asynchronously update a variable with relation to the main loop. But the ISR does not see any asynchronous update (unless you support nested interrupts).
If the input signal produces bouncing, then you should learn your ISR to not assign to the global Timer_Diff variable until after you have figured out if you sampled a bounce or a real signal, i.e. that the pulse had a certain minimum length.
Another thing: Is there a reason for the use of a double? You can often use fixed-point arithmetic for handling this kind of data. But it depends a bit on what further evaluations you need to do with the value.
I must measure the period between two positive transition flanks ..
Now you are measuring the high period.
You wait for the trailing pulse edge in the interrupt - very bad!
No need to declare Timer_alt and Timer_neu volatile, but Timer_Diff must be volatile.
Reading Timer_Diff in the main loop needs to be atomic.
Timer_alt and Timer_neu must be unsigned, else the pulse width calculation fails. Timer_Diff should also be unsigned. Timer_neu is actually not needed, as it is the captured timer value in CC1_CC8.
Capture mode initialization should be outside the loop.
Try this:
static unsigned int Timer_alt; static volatile unsigned int Timer_Diff; void main (void) { float periode; unsigned int diff; . . . . . CC1_M2 = 0x0001; //Bit3 allocated to Timer T0/T7 ,Bit 210 001=>capture on posirtive Flanke CC1_T01CON = 0x0047; //Bit6 0=>Timer is enabled ,Bit3 1=>Timer Mode,Bit210 111=>Timer Resolution 25,6 µs CC1_CC8IC = 0x0044; // Interrupt enable und Interrupt Flag enable PSW_IEN = 1; // globally enable interrupts while(1) { _atomic( 0); diff = Timer_Diff; _endatomic(); periode = (float)diff*0.0000256f; // Periode }//end of while }// end of main /* __|----|___|----|___|----|____ */ //010101 void Drehzahl_messung(void) interrupt 24 { Timer_Diff = CC1_CC8 - Timer_alt; Timer_alt = CC1_CC8; }
The Timer_Diff value is not correct until after the second interrupt.
Thanks for your Help
It works now I have changed little the program , and it worked,now ; I can read the period. with the _atomic and _endatomic the compiler has always ERROR. perhaps i have to file a Haeder. but I hope that I get no problems when I write my programme
static unsigned int Timer_alt; static volatile unsigned int Timer_Diff; static volatile double periode; void main (void) . . . . . CC1_M2 = 0x0001; //Bit3 allocated to Timer T0/T7 ,Bit 210 001=>capture on posirtive Flanke CC1_T01CON = 0x0047; //Bit6 0=>Timer is enabled ,Bit3 1=>Timer Mode,Bit210 111=>Timer Resolution 25,6 µs PSW_IEN = 1; // globally enable interrupts CC1_CC8IC = 0x0044; // Interrupt enable und Interrupt Flag enable while(1) { periode =Timer_Diff*0.0000256; // Periode }//end of while }// end of main void Drehzahl_messung(void) interrupt 24 { Timer_Diff = CC1_CC8 - Timer_alt; Timer_alt = CC1_CC8; }
Thank you
with the _atomic and _endatomic the compiler has always ERROR
that is because you forgot to
#include <intrins.h>
Please write your program according to the guidelines of Sauli Porttila.
oh yes, I have forget to include <intrins.h> I just have to try again .. but I have the variable as declared.
unsigned int Timer_alt; unsigned int Timer_Diff; double periode;
and it works I must write my program as Portila ? I will understand why when the works anyway? and apologised if I ask so many!
Thanks for the explanation
It works because reading the 16-bit value of Timer_Diff is atomic by the processor design. If you had a 32-bit value which you modify in the interrupt and read in the main loop, that would most certainly not work as it does now.