Ist zwar schon länger her, aber, falls doch noch jemand darüber stolpert, hier einige Gedanken: ganz wichtig - Interruptservice-Routinen sollten so kurz wie möglich gehalten werden und keine extensiven Funktionsaufrufe beinhalten (besonders solche, deren Quellcode man nicht kennt).
Ino S. hat in seiner TMR0_ISR() viele sprintf, strcopy, LCDprintf sowie MCP794XX...-Aufrufe. Das ist mit ziemlicher Sicherheit vom Zeitmanagement her problematisch.
Die Abarbeitung all dieser Dinge hat außerhalb und nach Beendigung der Interruptservice-Routine zu erfolgen (jeweiliges Interrupt-Flag wieder rücksetzen!), zB in einer Schleife, welche auf ein von der Interruptservice-Routine gesetztes Flag prüft, dieses löscht und zur Abarbeitungsfunktion (= TMR0_ISR) für den MCPxxx und dem Display verzweigt. Oder man implementiert eine einfache state-machine.
Was nicht aus den Codeabschnitten hervorgeht, ist, wie oft die TMR0-ISR pro Sekunde angesprungen wird. Kennt man das, dann vergleiche man, wieviel Zeit all die sprintf, strcopy, etc Funktionen benötigen - es wird sich bis zum nächsten TMR0_ISR-Aufruf uU nicht ausgehen und das TMR0-Intervall wäre daher entsprechend zu vergrößern. Werden zudem ev auch Interrupts in den aufgerufenen Funktionen deaktiviert (dann sieht es düster aus)?
Die Interruptservice-Routine für das Abfangen der seriellen Daten unterbricht die TMR0-Interruptservice-Routine, falls etwas daherkommt, da sie die höhere Priorität hat. Auch hier sollte die eigentliche Abarbeitung/Verarbeitung der empfangenen Daten außerhalb der Interruptservice-Routine erfolgen. Zudem würde ich die TMR0-Interruptservice-Routine als high_priority setzen, um ev Unterbrechungen durch andere Interruptservice-Routinen hintanzuhalten.