UART RS232 Problems

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

I have a project with an atmega using the serial port. I have a max3232 logic level converter for RS232. I communictate fine with some PC software I am using and have used a few different PCs without difficulty. I tried connecting it to a PDA serial port and the PDA recieves the status packets once per second like expected, but when I open and close the serial port on the pda it causes the microcontroller to go into some unknown state. I can't even communicate with it when I reconnect the device to a PC. Once the device is reset it performs as expected again with the PC. This problem is repeatable. It's as if the PDA is causing some glitches and screwing up the firmware. It is wierd because the firmware checks packets using a crc and packet headers.

Any ideas?

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

...

Last Edited: Wed. Feb 17, 2010 - 11:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have designed a passthrough program on the PC and all the data gets forwarded each way.
So,
PDA > crossover > PC com1 > PC com2 > ST serial cable > device
and vice versa.

Everything seems to work okay.

PDA > device

Works for 5 - 60 seconds, then uC messes up.

I just tried disconnecting the TX from the PDA to the device and it looks like the PDA recieves data without any problem. So something with the TX line.

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

...

Last Edited: Wed. Feb 17, 2010 - 11:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Atmega1280, 16MHz

	//configure UART0
	UCSR0A = 0x02;
	UCSR0B = 0xB8;
	UCSR0C = 0x06;
	UBRR0 = 16;

void txchar0(unsigned char inchar)
{
	int tempc;
    
	if (tx_counter0 < TX_BUFFER_SIZE0)
	{
		UCSR0B &= ~(1<<UDRIE0); // disable uart empty interrupt

		tempc = tx_wr_index0 + tx_counter0;
		if (tempc >= TX_BUFFER_SIZE0)
			tx_buffer0[tempc - TX_BUFFER_SIZE0] = inchar;
		else
			tx_buffer0[tempc] = inchar;
		tx_counter0++;  //new byte added

		UCSR0B |= 1<<UDRIE0;  // enable interrupt again
	}
}


ISR(USART0_UDRE_vect)
{
	if (tx_counter0 != 0)
	{
		UDR0 = tx_buffer0[tx_wr_index0++];	//tx next byte
		tx_counter0--;						//one less byte to send

		if(tx_wr_index0 >= TX_BUFFER_SIZE0) //Reset Write index
			tx_wr_index0 = 0;
	}
	else
	{
		UCSR0B &= ~(1<<UDRIE0); // disable UDR empty interrupt, all done with tx buffer
	}
}

ISR(USART0_RX_vect)
{
	if((UCSR0A & 0x1C) == 0) // Byte okay
	{
		if (rx_bytes0 < RX_BUFFER_SIZE0) // Space in buffer
		{
			rx_bytes0++;				//New Byte
			rx_buffer0[rx_wr_index0] = UDR0;	//Store in buffer

			if(++rx_wr_index0 >= RX_BUFFER_SIZE0)	//reset write index
				rx_wr_index0 = 0;
		}
	}
}

I have an interrupt driven communication, with buffering and packet incompletion timeout. I take a byte at a time out of the buffer in the main loop and build a packet if a header is found, I also have a CRC check I do on the packet. I have used this method for a few years now without a problem.

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

I checked on the TX from the PDA to the RS232 level converter to the uC. I found that when the PDA was connected, the RS232 line was -6V or idle. When the PDA com port was disconnected(in software) the PDA caused the line to go to +6V as if a byte was being sent (start bytes) but it was stuck high. I'm guessing the interrupt for the RX recv. is being hammered. Anyone else ever have this problem? I think I may be able to solve it in firmware by disabling the interrupt for a second if detect an invalid stop bit.

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

So I believe I solved the problem by disabling the rx input and rx interrupt. I then re-enable it using a pin change on the rx pin (when the PDA reconnects) interrupt. Seems to be working so far.