Why can't I successfully send messages over RS232?
You have missed a major detail of RS232. Logic levels are as follows:
Figure 1. RS232 signal levels. Source: Wikimedia Commons.
- Logic 1 = -3 to -12 V.
- Logic 0 = +3 to +12 V.
- Between -3 and +3 the logic level is undefined.
- The RS232 start bit is a logic 0.
To convert from TTL (5 V) logic to RS232 a driver is required. Chips such as the MAX232 do the logic level inversion and voltage boost for you.
It is possible to "cheat" sometimes and feed a TTL signal into an RS232 input provided the logic level is inverted. The reliability of this method depends on the chip used on the RS232 input.
Figure 2. The transmitted waveform. On top is the bit pattern of the'Q' that you transmitted. On the bottom is how the RS232 input read it.
Note that the RS232 input is looking for a positive edge to indicate the start bit. This doesn't happen until the second bit of your data so everything thereafter is one bit to the right and inverted as the receiver sees it. As luck has it your MSB is the correct logic level for the stop bit so the receiver interpreted it as a valid frame, decoded it and displayed a 'W'.
For test purposes you can invert your TTL output. This will probably work as it is "working" at the moment.
Figure 3. The MAX232 chip uses capacitors in charge pump circuits to boost the 5 V supply for RS232 levels.
For reliability add a MAX232 chip to transmit and receive a proper RS232 level signal.
Considering the short haul and low bit rate of 9600, TTL and CMOS levels work fine. The problem eloquently detailed by @Transistor is that UART data is negative logic 0~5V and RS-232 is positive logic +/-V f between +/-3 and +/-15V (?)
Therefore as *he also suggests, an inverter will work.
The problem is not a bit error rate (BER) issue or signal integrity, but inverted logic.
Also, the "grey zone" is for long-haul noise margin It is not <+/-3V for you because your cable is short. The actual logic threshold of RS-232 Rx is exactly the same as old TTL ( two Vbe drops) or 1.4V +/-20%(?) tolerance.
They call it a grey zone in order to meet all the distance and baud rate specs due to noise glitches and edge ringing.
For longer cables get any MAX232. Variations may depend on voltage speed and features.