Has baud rate converter been done?

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

A friend would like to come up with a device that has a high baud rate on one side, and 9600 on the other. Flow control on the fast side is a must; although the buffer can be fairly small.

This is a straightforward project, but if someone has done it, it would save me a few hours :P

If I were starting from scratch, I would use a small part with one UART, and then use a "software UART" for the 9600 baud.

-Mike

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would use a Mega162, with two UARTS and 1K of internal RAM for buffering. The code would only be about 200 words.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the thought. Since sending 9600 in software is a no-brainer I think I'm gonna stick with a software UART for the slow side. Although the Mega162 is physically smaller (in MLF) I'm not ready for it yet. I'd rather not use a 40-pin dip and hook up only 8 pins. This makes the 90S2313 and Tiny2313 very strong choices.

I don't actually know yet if and when the slow side needs to talk back, (distinguishing simplex, half duplex, or full duplex).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you can get away with the internal 8 mhz oscillator you can save even more space avoiding extra components!

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sxpilot450 wrote:
If you can get away with the internal 8 mhz oscillator you can save even more space avoiding extra components!

I intend to..... anyone seen such an application? I'm about to start writing one... :o

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's a receive side softy. It was originally based on an Atmel appnote, as you'll see from some left-over comments. It runs on a Tiny12 using the internal oscillator at 1.2MHz and is set for 9600 baud. I've also used it without problems at 19,200. I only needed a receiver so I don't have any transmit code, but the timer runs continually so it shouldn't be hard to add tx. However, note that if you get an incoming character the timer is changed for one cycle to 1.5 bit times, and this will screw up any tx that happens to be running at the time, so it's really only useful for half duplex.

; soft UART Registers
.def	i_sr		=r13		;Int flag store
.def	u_buffer	=r14		;Serial buffer
.def	t_sr		=r15		;Timer flag store
.def	u_tmp		=r16		;Scratchregister
.def	u_bit_cnt	=r17		;Bit counter
.def	u_status	=r18		;Status buffer
.def	u_reload	=r19		;Reload-register

.def	millisec	=r25


; soft UART BAUD-rate settings @ nominal 1.2MHz clock (1.2M/9600)
.equ	N=123			; actually 125 but trim for low voltage

; Bit positions in the Status-register
.equ	RDR=0			;Receive data ready bit
.equ	BUSY=7			;Busy-flag (read-only)




; uart_init - Subroutine for UART initialization
; This routine initializes the UART. It sets the timer and enables the
; external interrupt (receiving). To enable the UART the global interrupt
; flag must be set (with SEI).
	ldi	u_reload,256+8-N	; 8=cycles used before reload
	out	TCNT0,u_reload		; load timer
	ldi	u_tmp,0x01		; 1x clock (1.2MHz)
	out	TCCR0,u_tmp		; Start timer and set clock source
	ldi	u_tmp,0x42		; (disable pullups)
	out	MCUCR,u_tmp		; int on falling edges
	ldi	u_tmp,0x02
	out	TIMSK,u_tmp		; enable timer int
	ldi	u_tmp,0x40		; INT0
	out	GIMSK,u_tmp		; Enable external interrupt 0
	clr	u_status		; Erase status-byte



; EXT_INT0 - External Interrupt Routine 0
; This routine is executed when a negative edge on the incoming serial
; signal is detected. It disables further external interrupts and the
; remainder of the serial word is handled by the timer interrupt.
ext_int0:
	in	i_sr,SREG		;Store Status Register
	ldi	u_tmp,256+29-(N+N/2)	;Set timer to 1.5 bits
	out	TCNT0,u_tmp		;  29 = clock cycles that
					;  have already been used in this
					;  interrupt plus the cycles
					;  that will be used by the time
					;  delay between timer interrupt request
					;  and the actual sampling of the first
					;  data bit.
	ldi	u_tmp,0x02		;Set bit 1 in u_tmp
	out	TIFR,u_tmp		;to clear T/C0 overflow flag
	clr	u_bit_cnt		;Clear bit counter
	ldi	u_status,0x80		;Set busy-flag $80 to trip uart
	out	GIMSK,u_bit_cnt		;Disable ExtInt0
	out	SREG,i_sr		;Restore SREG
	reti

; TIM0_OVF - Timer/Counter 0 Overflow Interrupt
; The timer must be allowed to run constantly for other functions.
; We have to handle a parity bit as well as a stop bit.
; When the RDR flag is set, the (new) data can be read from u_buffer.
tim0_ovf:
	in	t_sr,SREG		; Store status register
	out	TCNT0,u_reload		; Reload timer
	in	u_tmp,PINB		; read the port immediately
	sbrs	u_status,7		; if (BUSY) is clear,
	rjmp	tim0_more		; do not process UART
; no need to enable ints again here, as ext int can't happen
; during uart receive
	inc	u_bit_cnt		; Increment bit_counter
	cpi	u_bit_cnt,0x09		; if u_bit_cnt = 9
	breq	tim0_parity		; do parity
	brcc	tim0_stop		; if >9 do stop
	ror	u_tmp			; shift input bit (1)
	ror	u_tmp			; into carry
	ror	u_buffer		; Shift carry into data
	rjmp	tim0_more
; We can process byte on bit 9 while parity and stop are coming in
tim0_parity:
	sbr	u_status,0x01		; Set ready bit
	rjmp	tim0_more
tim0_stop:				; on stop bit
	cbr	u_status,0x80		; clear busy bit
	ldi	u_tmp,0x40
	out	GIFR,u_tmp		; clear ext int flag
	out	GIMSK,u_tmp		; Enable for next start
tim0_more:
	tst	millisec		; If millisec is 0
	breq	tim0_ret		; leave it alone
	dec	millisec		; else decrement
tim0_ret:
	out	SREG,t_sr		; Restore status register
	reti
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mneary wrote:
sxpilot450 wrote:
If you can get away with the internal 8 mhz oscillator you can save even more space avoiding extra components!

I intend to..... anyone seen such an application? I'm about to start writing one... :o

Be careful, the maximum acceptable baud rate error is typically +/- 3% but may be as low as +/- 2%. You'll probably need to calibrate the internal RC oscillator at the temperature you intend to operate at. If you need to operate over a wide temperature range, the internal RC oscillator may not be accurate enough.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll definitely be watching baud rate; and a resonator isn't a high price to pay. This is probably no more than one or two units.

I'm tempted to try something clever like measuring the baud rate of my hosts and tweeking the RC clock to match them. (if they agree). But that's a lot of work to save one part.

Now I'm searching for transceivers. I don't want that fake RS232 that so many ciircuits use (plus 3v for "0" and plus 0.4v for "1".) I want to drive as close to the voltages shown to me by the hosts. So far, the best transmitter I can find is LM324; it'll drive within 1V of each rail and is probably fast enough for the interfaces (still awaiting detailed requirements). Receiver is looking like LM339. It gives me an open-collector signal just right for an AVR input. But together they'll typically draw 2.6 mA (a max of 5 mA) which I intend to steal from the hosts' RS232s. That's sort of on the edge.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there any sort of user control or menu? Is it on the fast side or the slow side? What's the highest baud? How many bauds? xonxoff or rtscts? Inquiring minds want to know!! Does it work both ways (fast to slow and slow to fast), or only one way?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Does it work both ways

Yes, inquiring minds do want to know. Turns out my friend is asking in behalf of another friend of his. Hopefully we'll know in a day or so whether it's full duplex, half duplex, or simplex.

I don't envision any user menu; 9600 fixed on one side and either autobaud or fixed (high) rate on the other.

The more I think about it, the more it feels like packet radio.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mneary wrote:

Now I'm searching for transceivers. I don't want that fake RS232 that so many ciircuits use (plus 3v for "0" and plus 0.4v for "1".) I want to drive as close to the voltages shown to me by the hosts. So far, the best transmitter I can find is LM324; it'll drive within 1V of each rail and is probably fast enough for the interfaces (still awaiting detailed requirements). Receiver is looking like LM339. It gives me an open-collector signal just right for an AVR input. But together they'll typically draw 2.6 mA (a max of 5 mA) which I intend to steal from the hosts' RS232s. That's sort of on the edge.

It seems to me that two chip just for a RS232 transceiver are a bit of overkill (but I am not sure I understood correctly).
If you have enough RAM buffer, you can use software handshaking XON/XOFF, so you need only one RS232 Receiver, and one RS232 Transmitter.
You can do the job with two digital BJT, some passives and power stealed from host RS232: there should be a lot of schematic around the Web.

Regards,
Pedro

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I hope nobody minds the topic drift... :oops:

If I have all of TXD, RTS, CTS, and RXD on both ports, it would fully utilize both quad chips (If they are fast enough).. On the other hand if I only have one or two each RXD and TXD, then it's serous overkill (and I wouldn't have enough supply current).

I'm still waiting for that info. :?

On the net, I've seen a lot of RS232 "drivers" using BJTs. However all I've seen so far are single-ended (they drive the true state to -V or 0V and have the false state pulled up weakly to +V.) I have Rohm EMH6 and UMC4N digital transistor arrays (I'd like this to be tiny) :shock: The best I've done (on paper) is three transistors plus one diode for each channel. The 4 necessary resistors are inside the digital transistor.

To save current, I could use LT1030 for drivers instead of the op amp.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just a thought-

If this turns out to really be full-duplex, you might want to consider a CPLD for the project.

My $0.02

Regards