The first tactic is to architect the overall firmware so that it's OK for interrupts to occur at any time. Having to turn off interrupts so that the foreground code can execute a atomic sequence should be done sparingly. There is often a architectural way around it.
However, the machine is there to serve you, not the other way around. General rules of thumb are only to keep bad programmers from writing really bad code. It is far better to understand exactly how the machine works and then architect a good way to harness those capabilities to perform the desired task.
Keep in mind that unless you really are tight on cycles or memory locations (can certainly happen), that otherwise you want to optimize for clarity and maintainability of the code. For example, if you have a 16 bit machine that updates a 32 bit counter in a clock tick interrupt, you need to make sure that when the foreground code reads the counter that the two halves of it are consistent. One way is to shut off interrupts, read the two words, and then turn interrupts back on. If interrupt latency isn't critical, then that's perfectly acceptable.
In the case where you must have low interrupt latentcy, you can, for example, read the high word, read the low word, read the high word again and repeat if it changed. This slows down the foreground code a little, but adds no interrupt latency at all. There are various little tricks. Another might be to set a flag in the interrupt routine that indicates the counter must be incremented, then do that in the main event loop in the foreground code. That works fine if the counter interrupt rate is slow enough so that the event loop will do the increment before the flag is set again.
Or, instead of a flag use a one-word counter. The foreground code keeps a separate variable that contains the last counter it has updated the system to. It does a unsigned subtract of the live counter minus the saved value to determine how many ticks at a time it has to handle. This allows the foreground code to miss up to 2N-1 events at a time, where N is the number of bits in a native word the ALU can handle atomically.
Each method has its own set of advantages and disadvantages. There is no single right answer. Again, understand how the machine works, then you won't need rules of thumb.
Altough I'm not sure why, this solved my problem.
At Power-On-Reset, ADON bit is cleared, which means it disables the A/D converter by default, right? This means whether or not I disable the A/D converter, it is disabled automatically.
ADCON0bits.ADON = 0;
But, I did add this line to my configuration and it worked, now both external (high priority) interrupt and USART (low priority) interrupt works at the same program.
It is a solution, but i still wonder why it worked.
Best Answer
There is an interrupt flag associated with the interrupt you choose to use. That will tell you which pin was responsible when you service the interrupt (it is set automatically by the pin change). You will reset it in your ISR. That ensures you won't miss an pin change interrupt if your ISR is properly written.
But if the switch is bouncing you'll get additional interrupts when the interrupts have been re-enabled. Maybe sometimes, maybe not other times depending on what the processor is doing. Maybe you'll reset the flag and it will immediately be set again by the hardware before you even exit the ISR, then the interrupt will occur immediately when you exit. You could put a (blocking) delay routine in your ISR but I think most real-time programming folks would be nauseous or possibly physically ill by that point.
Generally manual switches should not be serviced by interrupt routines. Institute a periodic interrupt (typically no faster than 1kHz, and maybe a bit slower depending on the switch- you can also check every n'th time through with a 1kHz interrupt) and you can check and debounce the switch input by polling. You would have the current state of the switch, the previous state and the previous stable state. If you have two readings the same (in a row) that differ from the previous stable state you know you have an edge, and you can discard the polarity of edge you're not interested in (say the release of the switch).