Code:
/* ATmega16 */
int uart_putc(unsigned char c)
{
while (!(UCSRA & (1<<UDRE)))                   /* warten bis Senden moeglich */
{
}

UDR = c;                         /* sende Zeichen */
return 0;
}
Was tut das!?
Es wird gewartet bis das UDRE Bit im UCSRA Register 1 ist.
Wenn ich mich recht entsinne bedeutet das, das das Senderegister leer ist.
while(!(UCSRA&(1<<UDRE)));
Dann wird das UDR mit dem gewünschten Zeichen beschrieben: UDR=c;
Die Routine stammt aus Deinem Code! - Eigentlich solltest Du dann schon wissen, was die Routine tut!
Die Routine gibt noch einen int Wert zurück, damit die aufrufende Routine weiß, das sie ausgeführt wurde.
Das wurde in meinem Codeschnipsel nicht berücksichtigt und macht hier auch keinen Sinn, weil ja keine anderen Werte als 0 zurück gegeben werden können.
Es würde Sinn machen, wenn da noch ein Timeout oder sonst eine Fehlererkennung drin wäre, die andere return Werte als 0 generieren kann.
Der aufruf müsste dann lauten:
status=uart_putc(uc_string[i]);

Der Wert 0, den die Routine dann zurück gibt wäre dann in der int Variable status zu finden.
Da dort aber nur der Wert 0 auftauchen kann, kann man sich die rückgabe des wertes gleich schenken also aus:
int uart_putc(unsigned char c)
wird
void uart_putc(unsigned char c)

das
return 0;
entfällt ersatzlos.



Diese Senderoutine verschwendet aber eine Menge Rechenzeit - das ist Dir hoffentlich klar!
Der Controller wartet ja so lange, bis 8Bit + Start und Stoppbit, also 10 Bits, eines Zeichens komplett über die TxD Leitung versendet ist.

Das dauert bei 9600bit/sek ca. 1ms. In dieser Zeit hätte der Controller bei 8MHz 8000Befehle abarbeiten können!
Das ist auch der Grund, warum man solche Funktionen über Interrupts erledigt.

Auch der USART kann Interruptgetriggert arbeiten!

Man schreibt dazu die zu sendenden Daten in einen Ringpuffer und eine Sendeinteruptroutine holt sich diese Daten dann ab und versentet sie dann ohne weiteres zutun des Hauptprogrammes im Transmit Interrupt des USART.

Aber arbeite erstmal mit Deiner Methode weiter.
Das kann man dann bei mehr Programmiererfahrung immer noch mal umbasteln.