Ok, noch ein paar mehr Anmerkungen

char* ReadStringAnz(int anz) //Funktioniert einwandfrei
Wenn diese Funktion dieses Verhalten nicht zeigt, ist das lediglich Zufall. Hier gilt natürlich das Gleiche. Wenn du beide Funktionen nutzen willst, wäre Variante 1 (globale Variable) platzsparender.

Code:
   for(int j=0;j<20;j++)
   {
      str[j]='\0';
   }
Das ist überflüssig. Verschwendet nur Platz ohne irgendeinen Vorteil zu bringen.

Und zuletzt noch eine eher ästhetische Anmerkung: die if-else-if-Wurst finde ich unschön und unübersichtlich. Mein Gegenvorschlag:
Code:
char* ReadString ( void ) {

   static unsigned char str[20];
   unsigned int zeichen;
   unsigned char i = 0;

   while (i < 19) {

      // warte auf nächstes Zeichen
      do
         zeichen = uart_getc();
      while (zeichen & UART_NO_DATA);

      // Fehler?
      if (zeichen & 0xff00) {
         lcd_clrscr();
         if (zeichen & UART_FRAME_ERROR)
            lcd_puts("Frame ERROR");
         else if (zeichen & UART_OVERRUN_ERROR)
            lcd_puts("Overrun ERROR");
         else if (zeichen & UART_BUFFER_OVERFLOW)
            lcd_puts("Buffer OVERFLOW");
         waitms(500);
         continue;
      }

      //Abbruch wenn ','
      if (zeichen == ',')
         break;

      // Zeichen eintragen
      str[i] = zeichen;
      i++;
   }

   // terminieren
   str[i] = '\0';
 
   return str;
}