Add a debug trap as the first thing in your LCD_WriteRAM routine. Check the passed argument against the bounds. Output a message over your serial port when it is out of bounds. If it isn't the argument that is the problem then dig deeper and debug each string or array in the same way. 100% of the hard faults I've had are caused by variables accessing out of bounds. Looking past the end of a string is easy to do.
Hmm, I've already tried this, not with the serial port though, but with a debugging tool. Then I can just read the counting integer fx.
But I can't find the thing which makes the hard fault!
Also, the thing that keeps irretating me is, that the code works on the STM32F103RET6 without any problems, but on the STM32F103ZET6 the hard fault appears!