I decided to rip the plastic off the DB9 and discovered a really tiny PCB. I removed the DB9, and decided to pass this little PCB to a scope session. How the hell do they manage to do a USB to RS232 with only a couple of external components ? They is no big capacitor for level shifter (remember RS232 is a +12/-12v ) ? The answer is simple, they don’t !!
This device isn’t RS232 compliant at all, the signals on the DB9 are TTL compliant, but not RS232. The ouput is between 0/5V and the input can handle -12/+12V but works great with a 0/5V too. I simply removed used pads on one side and added a couple on pins.
Please note that RX pin is missing on this pix but needed of course. The next step : How can I use this with an AVR Atmega (I used a Atmega8 but any will do the trick). Serial connection on a micro is TTL like this board, but the TTL signal is just inverted. A “1″ on the RS232 side is a -12V and +5V on a TTL, and a 0 on the RS232 side is a + 12V and a 0v on the TTL. You can find all the information here.
In fact MAX232 do both level shitting and inverting, but as I’m to lazy to wire a MAX232 (and will destroy the cheap aspect of this hack), I decided to handle this by software. This mean, I won’t be able to use the Atmega serial builtin port but need to write some additional code, to do the RS232 encoding/decoding by hand.
I simply put this on a verroboard, connect VCC to USB Vcc, GND, RX and TX to random pins on the AVR and let’s go to RS232 software serial. This can be done easily in fact, and I managed to handle 19200bauds with the internal 8Mhz clock of the Atmega. Above you will find the popular uart_putc() and uart_getc() ..
1 #define UART_TX D,1
2 #define UART_RX D,2
3 #define UART_DELAY 52 // 1/9600 = 104uS : 1/19200 = 52uS
4
5
6 void uart_putc(char c)
7 {
8 uchar i;
9 uchar temp;
10
11 // start
12 set_output(UART_TX);
13 _delay_us(UART_DELAY);
14 clr_output(UART_TX);
15
16 for(i=0;i<8;i++)
17 {
18 temp = c&1;
19 if (temp==0)
20 set_output(UART_TX);
21 else
22 clr_output(UART_TX);
23 _delay_us(UART_DELAY);
24
25 c = c >>1;
26 }
27
28 // stop
29 set_output(UART_TX);
30 _delay_us(UART_DELAY);
31 clr_output(UART_TX);
32
33 _delay_us(UART_DELAY);
34 }
35
36 uchar uart_getc()
37 {
38 uchar i;
39 uchar ib = 0;
40 uchar currentChar=0;
41
42 while (ib != 1)
43 ib = get_input(UART_RX);
44
45 _delay_us(UART_DELAY/2); // middle of the start bit
46 for(i=0;i<8;i++)
47 {
48 _delay_us(UART_DELAY);
49 ib = get_input(UART_RX);
50
51 if (ib ==0)
52 currentChar |= 1<
53 }
54 return currentChar;
55 }
Nothing more to say, this hack works really great, and I can now build a bunch of USB board without paying so much. The only drawback of this approach is that you can’t use an interrupt for the uart_getc() so you have deal with that in your code. Another approach would use a single transistor for the RX pin to make the RX compliant w/ the AVR serial built-in routine.
Buy Low Cost USB to TTL Adapter