Avoiding global variables when using interrupts in embedded systems
There is a de facto standard way to do this (assuming C programming):


Interrupts/ISRs are low-level and should therefore only be implemented inside the driver related to the hardware that generates the interrupt. They should not be located anywhere else but inside that driver.
All communication with the ISR is done by the driver and the driver only. If other parts of the program needs access to that information, it has to request it from the driver through setter/getter functions or similar.
You should not declare "global" variables. Global meaning file scope variables with external linkage. That is: variables that could be called upon with extern keyword or simply by mistake.
Instead, to force private encapsulation inside the driver, all such variables shared between the driver and the ISR shall be declared static. Such a variable is not global but restricted to the file where it is declared.
To prevent compiler optimization issues, such variabels should also be declared as volatile. Note: this does not give atomic access or solve re-entrancy!
Some manner of re-entrancy mechanism is often needed in the driver, in case the ISR writes to the variable. Examples: interrupt disable, global interrupt mask, semaphore/mutex or guaranteed atomic reads.