Software UART

Hi, I’m trying to create a software usart for a project and to learn how it works. I’ve looked up some timing diagrams on the net and coded a little routine. I use WinAVR C, Mega168 at 8Mhz. Here’s what I have:

void DebugTransmit2( unsigned char Data )
{
	int i;
	unsigned char Byte;
	
	setBit( PORTB, 0 );
	_delay_us( 104 );
	clearBit( PORTB, 0 );
	_delay_us( 104 );
	
	Byte = Data;
	
	for ( i = 0; i < 8; i++ )						//Shift out the data
	{
		if ( Byte & 1 )								//Shift out the LSB
			setBit( PORTB, 0 );
		else	
			clearBit( PORTB, 0 );
	
		Byte = Byte >> 1;							//Shift down the data for the next bit
		_delay_us( 104 );							//Delay to the next bit
	}

	setBit( PORTB, 0 );
	_delay_us( 104 );
	_delay_us( 104 );
}

I get this out of it:

FF 11111111

FF 11111111

81 10000001

82 10000010

80 10000000

84 10000100

88 10001000

90 10010000

A0 10100000

When I call DebugTransmit2 with these values:

0xFF, 0xFF, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40

I got 104uSec from 8e6/9600 cycles at 1/8e6 per cycle = 104usec

I’m not sure what I’m doing wrong.

Brainwav.

Ok, I got it to work. I had to clear the bit right after the for loop and delay for one bit and insert a line into the for loop which doesn’t make much sense to me. The line is: if (i == 3) _delay_us(104);

so after 4 bits, I delay a dummy bit and go another 4 bits. Must be a timing problem somewhere.

For asynchronous UARTs, you need 1.5 or more bit times for the stop bit.

Each byte in a real UART is one start bit, 8 data bits, and 1.5 or 2 stop bits, or more. At least that’s what 8N1 is.

So check out marking/spacing for start/stop bits.

Your code to add a mid-byte delay isn’t correct.

8N1 is one stop bit!

Leon

Hi, I added the one stop bit (8N1 is one stop bit, verified already), but I still had to add the one bit delay after 4 bits. I tested it with a couple serial terminals that come with boot loaders and it works there, but not in HyperTerminal.

I got the transmit function to work too and had to add the bit delay there also. Strange eh?

That’s right. 8N1=1 start, 8 data, 1 stop. all same duration.

Beware this: If you do a constant transmission of back to back bytes in 8N1 and enable a receiving UART anywhere in this, it will likely not be able to find the start bit and get the correct frame synch. Solution: don’t do that. Or put in a 10 bit “marking” delay or so every now and then for the receiver to re-synch on the start bit.

http://en.wikipedia.org/wiki/Asynchronous_start-stop