Serial Port trouble, only get spaces

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

I've spent the last few hours trying to solve this but just can't understand what's happening. I have a simple program sending a character through the serial port every 1000ms. On the test board I have a led flipping every time the character is sent. The led is flipping allright and the little led on my USB-serial adapter is blinking every sec as well, so I guess the data is being sent. Problem is, I can't seem to receive anything on the computer. Hyperterminal just sits there doing nothing. If I use terminal (http://tariff.dcslab.net/download/) the cursor in the terminal window moves everytime something is sent, but no character appears, just blank spaces. Any help would be appreciated ;) Thanks!

Here's my code (yes, it's crappy and highly unoptimized but I'm just testing stuff out ;)):

#define FOSC 14745600 				// Frequência do Cristal
#define BAUDRATE 19200				// Baudrate pretendida
#define UBRR_SCALER FOSC/16/BAUDRATE -1	// UBRR a definir (U2X=0, assíncrono)

void init_serial(unsigned int ubrr) {
		
	//Baudrate
	UBRRL = (unsigned char) ubrr;
	UBRRH = (unsigned char) (ubrr>>8);
		
	//Desactivar interrupts
	bit_clear(UCSRB,BIT(7));	//RXIE
	bit_clear(UCSRB,BIT(6));	//TXIE
	bit_clear(UCSRB,BIT(5));	//UDRIE

	//Desactiva parity check
	UCSRC |= (1<<URSEL); // Escrever em UCSRC em vez de UBRRH	
	bit_clear(UCSRC,BIT(5));
	bit_clear(UCSRC,BIT(4));

	//2 stop bits
	bit_set(UCSRC,BIT(3));

	// 8bits por character (UCSZ2:0=011)
	UCSRC &= 0b11111001;
	UCSRC |= 0b00000110;
	bit_clear(UCSRB,BIT(2));

	//Modo assíncrono
	bit_clear(UCSRC,BIT(6));

	//Activar recepção e transmissão
	UCSRB |= (1 << RXEN) | (1 << TXEN);


}

void main() {

	DDRB=0xFF;

	init_serial(UBRR_SCALER);
	unsigned char meh = 'w';
	
	wwhile(1){

		UDR = meh;
		while ((UCSRA & (1 << TXC)) == 0) {};
		bit_flip(PORTB,BIT(0));
		delay_ms(1000);

}
}

[/code]

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

Try it with an L after 14745600.... this will force the expression to be evaluated using longs instead of ints.

Imagecraft compiler user

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

Hum, I didn't quite understand what you mean. For that frequency and baudrate the UBRR should be 47, and during simulation in AVRstudio it's correctly evaluated to that value. You think it might be an incorrectly sed baudrate?

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

What is the result of the baudrate divisor calculation? 47? Does it appear in the map file? Seems like its real easy to edit, add one letter 'L', save, recompile, run, see if it works differently.

Imagecraft compiler user

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

Tried it, same thing keeps happening ;)

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

Quote:

#define FOSC 14745600

Are you sure that your AVR is really running at this speed? If you output 'U' characters repeatedly, what bit width do you measure on a 'scope?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Check the clk/8 fuse - for some reason I find it keeps getting set!

C. H.
-------------------------------------------------------------------
It's only waste if you don't use it!

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

Quote:
UCSRC |= (1<<URSEL);
You do realize you are not doing the URSEL thing correctly? (I'm assuming by the code comments that the unnamed avr you use needs to set URSEL to access UCSRC).

You are ending up messing with UBRRH instead of UCSRC.

Figure out how to change UCSRC correctly and you may get the correct baud rate set.

Quote:
yes, it's crappy
and next time fix it so we can read it and compile it (I gave up right away as you didn't provide your macros, and all that bit clearing/setting got me confused).

Also-

Quote:
while ((UCSRA & (1 << TXC)) == 0) {};
even if you removed the delay in the loop (and actually needed this), this would only be of any use the first time through, as you are not clearing TXC, and it will remain set after the first character is transmitted.

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

curtvm wrote:
Quote:
UCSRC |= (1<<URSEL);
You do realize you are not doing the URSEL thing correctly? (I'm assuming by the code comments that the unnamed avr you use needs to set URSEL to access UCSRC).

You are ending up messing with UBRRH instead of UCSRC.

Figure out how to change UCSRC correctly and you may get the correct baud rate set.

Also-

Quote:
while ((UCSRA & (1 << TXC)) == 0) {};
even if you removed the delay in the loop (and actually needed this), this would only be of any use the first time through, as you are not clearing TXC, and it will remain set after the first character is transmitted.

Sorry, I'm using an ATmega8. I thought that, whenever the URSEL bit is set I'm writing to UCSRC. Do I have to set it whenever I want to write to that register?
Also, as for clearing the TXC bit, I thought that it was set to 0 whenever I sent something through the buffer and then set back to 1 when the transmission was finished. It only clears automaticly when running it's interrupt routine?

Quote:

and next time fix it so we can read it and compile it (I gave up right away as you didn't provide your macros, and all that bit clearing/setting got me confused).

Sorry, will do. The bit_set(), bit_flip(), bit_clear() are just macros to operate directly on BIT(x) of each register.

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

You also might want to try another terminal program - I've used Realterm forever and it works very well. I know that Hyperterminal only lets you view data in either ASCII or ANSI. Realterm lets you view the hex characters that are coming through - works great when you're sending non-printable characters. With Realterm you'll be able to see what is actually coming through. That might help you determine what's going wrong.

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

Quote:
Do I have to set it whenever I want to write to that register?
You have to write URSEL at the same time as you write the other bits. You also don't want to do UCSRC |= because in order to read UCSRC, it has to read twice (first read gets UBRRH). Which also means your macros won't work on UCSRC either.

So, for 2 stop bits, just set UCSRC all at once-

void init_serial(unsigned int ubrr) {
   //Baudrate
   UBRRL = (unsigned char) ubrr;
   UBRRH = (unsigned char) (ubrr>>8);
    
   //2 stop bits  
   //8 data bits    
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);

   //Activar recepção e transmissão
   UCSRB = (1 << RXEN) | (1 << TXEN);
} 

If you read the datasheet for TXC, you will see that the only two ways to clear it, are by using the transmit complete interrupt or clearing it yourself by writing a 1 to TXC. You could use UDRE instead, which just shows if the buffer is empty or not.

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

Aye, that was the problem, it's working just fine now.
Thanks mate!

Last Edited: Mon. Apr 14, 2008 - 09:12 PM