[TUT] [SOFT] Using the USART - Serial communications

Go To Last Post
490 posts / 0 new

Pages

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

ah i see, so if i can't find the MAX232, is there any other way that i can turn the signals "upside down"? cause i'm not that confident of finding the MAX232 over here.. is there another name for it? if i knew the voltages i could most probably hook it up to a few resistors in between the serial port and the AVR? i think i'll be using AVRdude to program the avr chip.. but is the idea there though? to program the chip i pin 3 and 4 of the serial port to pin 2 and pin3 of the atmega88 PDIP?

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

Just to be clear, what is at the "other end" of the wire that the mega88 is connecting to? Is it a PC? You will need level conversion and signal inversion if this is the case and, to be honest, while other solutions are possible, handling the -12V is going to be easiest with a MAX232 (or one of that family - see the Maxim/Dallas web site). If however you are connecting to something with "TTL level UART" then you don't need to worry about the massive negative voltages and you can do the inversion with a transistor alone. In fact some "cheap" AVR development boards do this rather than use a proper MAX232. If you search for "AVR development board schematic" at Google you may find some circuits where this has been done.

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

hm, the "other end" of the wire that the mega88 is connecting to would be a usb<->serial port. My laptop does not have a serial port and i don't have enough cash to invest in a proper chip programmer, so i was reading up on the internet and i found stuff on creating a serial port programmer, so i was thinking maybe i could try creating a usb<->serial port programmer..

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

One does not absoulutely need an max232 for level conversion. There are other similar chips, some require an extra +-12 V or so. There is also the option to uses simple transistors or optocouplers to do the inversion and level conversion.
Nearly all PCs don't actually need the negative voltage and a 0/5 V signal is ok for most PCs. This can make the circuit much simpler allthough not following the standards. One example circuit can be found in the Atmel application note for the AVR911 programmer.

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

Hi,

I need to transmit 8 -bit pseudo random number using the USART port. How do I do this?

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

Quote:

I need to transmit 8 -bit pseudo random number using the USART port. How do I do this?

You can implement a 8-bit LFSR, then output the result.

http://en.wikipedia.org/wiki/Lin...

Q: what did the emitter say to the collector?
A: All your base are belong to us.

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

Quote:

Nearly all PCs don't actually need the negative voltage and a 0/5 V signal is ok for most PCs.

Just a thought: could you merely buffer your signal through an inverter on a supply of, say, 6V. Then use a resistor divider to supply "GND" on pin 5 of the DB9?

This would essentially be +/- 3V signals.

Q: what did the emitter say to the collector?
A: All your base are belong to us.

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

I've tried to connect my ATMega 32 to my mobile (siemens A50 with doesn't nedd RS232) but something don't work.

My phone uses the following config:
19200 bits per second.
8 data bits.
None parity.
1 stop bit.

Using fuses I've choosen "Int. RC Osc. 8 MHz; Start-up time: 6 CK + 64 ms"

I have the following code:

#include  

#define USART_BAUDRATE 19200
#define F_CPU 7372800
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) 

int baud = BAUD_PRESCALE;

void USART_Init( unsigned int baud )
{
	/* Set baud rate */
	UBRRH = (unsigned char)(baud>>8);
	UBRRL = (unsigned char)baud;
	/* Enable receiver and transmitter */
	UCSRB = (1<<RXEN)|(1<<TXEN);
	/* Set frame format: 8data, 2stop bit */
	UCSRC = (1<<URSEL)|(0<<USBS)|(3<<UCSZ0);//1 solo bit de parada
}

void USART_Transmit( unsigned char data )
{
	/* Wait for empty transmit buffer */
	while ( !( UCSRA & (1<<UDRE)) )
		;
	/* Put data into buffer, sends the data */
	UDR = data;
}


void USART_Putstring(char * str)
{ 
	while(*str)
	{ 
		USART_Transmit(*str++); 
 	} 
}

unsigned char USART_Receive( void )
{
	/* Wait for data to be received */
	while ( !(UCSRA & (1<<RXC)) )
		;
	/* Get and return received data from buffer */
	return UDR;
}

int main (void) 
{ 
	USART_Init(baud);

	int x;
	DDRA=0xff;
	PORTA=0xff;//Encendido
	USART_Putstring("ATD 636725862");
	PORTA=0x00;//Apagado
}

Anyone can help me???
THANKS!!!

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

Quote:

I've choosen "Int. RC Osc. 8 MHz;

Quote:

#define F_CPU 7372800


In the words of Sesame street - "one of these things is not like the other" ;)

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

clawson wrote:
In the words of Sesame street - "one of these things is not like the other" ;)

I change F_CPU in mi code an it neither works, any other idea??? thank you

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

It'll most likely be the standard problem then.

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

Any other can help me???

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

I already said - usual problem - as your search no doubt confirmed (if you didn't spot FAQ#3 in my sig) that is that the AVR isn't running at the speed you think. It's probably about 1MHz rather than either 8MHz or 7.3MHz

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

I'm not undertanding you (my english is'nt the best).

If I choose 8 MHz in fuses and my Vcc is 5V, my AVR sould be working with 8MHz, doesn't it???

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

Yes IF you have set the fuses correctly and attached an 8MHz crystal and cleared the CKDIV8 fuse (if there is one) then the AVR will be running at 8MHz and your UBRRL calculation based on F_CPU 8000000UL will work correctly. But my assertion is that you may have not succeeded with one of these things and the CPU maybe itn't running at the 8MHz you think. Try writing a program to flash an LED at a known rate. If it flashes at that rate (based on an F_CPU assumption) then the problem lies elsewhere but if it flashes at some other rate it maybe indicates that you haven't yet succeeded in getting the AVR running at 8MHz. This is usually the problem when people aren't getting UART comms working as expected.

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

I don't have attached any external crystal I tougth that if I choose fuse internal clock works at selected one.

Can I use USART with my internal clock??

I'll try to program LED trying to find mi actual frecuency. Do you know any other metod more exact???

Thanks for all!

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

n00b here , and this is my first post...

Anyways , i picked up ATmega 32 for interfacing motors to MATLAB , so that I can control PWM , etc using my computer.

The problem i'm facing is that in hyperterminal , i can receive characters from the microcontroller , but i can't send anything to it.

I set F_CPU to 1Mhz (1000000UL) , and baud as 2400.
Int. Osc 1mhz 6clk+64ms is selected in the fuse bits.

I'm using the exact same code given in the tutorial with minor modifications.

#include 

#define USART_BAUDRATE 2400
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

int main (void)
{
   char ReceivedByte;
   int i=0; 
   UCSRB |= (1 << RXEN) | (1 << TXEN);   // Turn on the transmission and reception circuitry
   UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes

   UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
   UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register

  for (;i<10;1++) // Loop for printing chars
   {
      
      while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
      UDR = 'a'+i; // print chars from a.
   }

 

  for (;;) // Loop forever
   {
      while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been recieved and is ready to be read from UDR
      ReceivedByte = UDR; // Fetch the recieved byte value into the variable "ByteReceived"

      while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
      UDR = ReceivedByte; // Echo back the received byte back to the computer
   }   
}

in hyperterminal , I get the output abcdefghi , but after that , any characters that I type are ignored and are not echoed back.

I've tested loopback using a wire , and it works fine for all baud rates , databits,parity , etc.

I've been trying to solve this for the last 2 days , and i'm at my wits end now .. :(

hope you could guide me in the right direction.

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

Hi there,

all is fine so far but how can one write texts of strings of characters and display them on a screen.
is it?
Output the following please:
"Hello world"
or is it
printf "hello world"
etc.?
I tried this recipe:

#include
#include
#include
#include
#define F 4000000 /* oscillator-frequency
in Hz */
#define UART_BAUD_RATE 9600
#define UART_BAUD_CALC(UART_BAUD_RATE,FC) (F/(UART_BAUD_RATE*16l)-1)

size_t strlen (const char*);
void usart_putc(unsigned char c) {
// wait until UDR ready
while(!(UCSRA & (1 << UDRE)));
UDR = c; // send character
}

void uart_puts (char *s) {
// loop until *s != NULL
while (*s) {
usart_putc(*s);
s++;
}
}
char *str1 = "Hallo World!";

char s [7];
int16_t i=0x40;

void init(void) {
// set baud rate
UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F)>>8);
UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F);

// Enable receiver and transmitter; enable RX interrupt
UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
//UCSRB = (1<<
//asynchronous 8N1
UCSRC = (1 << URSEL) | (3 << UCSZ0);
}

int main(void) {
init(); // init USART
//sei(); // enable interrupts

// send initial character

while (!(UCSRA & (1 << UDRE)));
itoa(i,s,10);
uart_puts(s);

return 0;
}

But i get the number 64 on the screen.

How, what, where should I write to get "hello world"?

Thanks

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

hallo body.

I am not the best avr freak there is I am just a newbee.

but when I read you code I wonder about the for loop.

for (;i<10;1++)

and you get.

I get the output abcdefghi 

a-i char total 9 and you ask i to be smaller than 10

I would try to change (;i<10;1++)to maybe (;i<20;1++)

goog luck

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

Hey , got another atmega16 , and the code works perfect on it , doesn't work with my old microcontroller , kinda weird , right ??

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

Quote:

But i get the number 64 on the screen.

That's exactly what that program, as you have written it above, should do. You set i to be 0x40 (which is 64 in decimal). You then itoa() it with a radix of 10 (so will get it converted to "64" and then you uart_puts() the generated string.

If you want "Hallo world" then given the components you have written simply use either:

uart_puts(str1);

or

uart_puts("Hallo world");

If you wanted to wire up the output for printf() to your putc() routine so you could use:

printf("Hallo world");

you need to look at the way this is done in the avr-libc manual and specifically the stdio demo program

Cliff

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

Hi all,
I got Following AVR Tutorial on " I copy the code given in tutorial-Using the USART with AVR-GCC " and paste it in AVR Studio 4.

I comipled it & I got these Errors:-
1)../UARTtry1.c:11: error: 'UCSRC' undeclared (first use in this function)
2)../UARTtry1.c:11: error: 'URSEL' undeclared (first use in this function)
3) ../UARTtry1.c:13: error: 'UBRRL' undeclared (first use in this function)
4)../UARTtry1.c:13: error: 'F_CPU' undeclared (first use in this function)
5)../UARTtry1.c:14: error: 'UBRRH' undeclared (first use in this function)
6)../UARTtry1.c:18: error: 'UCSRA' undeclared (first use in this function)
7)../UARTtry1.c:19: error: 'UDR' undeclared (first use in this function).

I have installed- "WinAVR-20080610-install".
I am new AVR.
Please tell me how to remove these errors.

Pra_kod

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

What are you doing about defining F_CPU? Do you intend to use a #define or are you going to set it under Project Configuration (which would be better)? That would get rid of (4) above

As for all the other errors, which AVR is this? Do you #include at the top of the code? Have you set the right device type under Project Configuation?

If it's one of the AVRs with numbered UARTs (e.g. mega48/88/168/162/128/etc./etc.) then what are you doing about porting the register and bit name nomenclature? They don't have UDR (for example) they have UDR0 (and possibly UDR1)

Cliff

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

Hi Cliff,
Thanks for your Hints. Now i am able to remove all the errors. But the program is not working.
I want to transmit 'a' on UART0. I am using ATmega128 & AVR Studio4. I don't get pulses at TXD0 pin on C.R.O.
Program control is remaining in -- " while (!(UCSR0A & (1 << UDRE0)) ) {}; " loop continuously.
What could be the problem?


#define F_CPU 8000000UL
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

#include
#include
#include

int main (void)
{
char ReceivedByte;
ReceivedByte='A';

UBRR0L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UBRR0H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register

UCSR0B |= (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and reception circuitry
UCSR0C |= (1 << UMSEL0) | (1 << UCSZ00) | (1 << UCSZ01); // Use 8-bit character sizes

for (;;) // Loop forever
{
while (!(UCSR0A & (1 << UDRE0)) ) {}; // Do nothing until UDR is ready for more data to be written to it

UDR0 = ReceivedByte; // Echo back the received byte back to the computer
}
}

clawson wrote:
What are you doing about defining F_CPU? Do you intend to use a #define or are you going to set it under Project Configuration (which would be better)? That would get rid of (4) above

As for all the other errors, which AVR is this? Do you #include at the top of the code? Have you set the right device type under Project Configuation?

If it's one of the AVRs with numbered UARTs (e.g. mega48/88/168/162/128/etc./etc.) then what are you doing about porting the register and bit name nomenclature? They don't have UDR (for example) they have UDR0 (and possibly UDR1)

Cliff

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

Quote:

#include
#include
#include
#include
#include

#define FOSC 18432000// Clock Speed
#define BAUD 115200
#define MYUBRR FOSC/16/BAUD-1

//unsigned char buf[];

void usart_init(void);
void usart_Tx(unsigned char data);
unsigned char usart_Rx(void);

int main( void )
{

unsigned char *data,ptr[]="string to send",c;

data=ptr;
usart_init();
while(*data){
c=*data;
usart_Tx(c);
data++;}

while(1){
c =usart_Rx();
usart_Tx(c);}

return 0;

}

void usart_init( void )
{
unsigned int ubrr=MYUBRR;
printf("%d",ubrr);

UBRR0H = (unsigned char)(ubrr>>8); /* Set baud rate */
UBRR0L = (unsigned char)ubrr;

/* Enable receiver and transmitter */

UCSR0B |= (1<<RXEN0)|(1<<TXEN0);

/* Set frame format: 8data, 2stop bit */
UCSR0C = 0x06;

/*Disabling the interrrupts*/

}

void usart_Tx( unsigned char data )
{

/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE)) );
/* Put data into buffer, sends the data */

UDR0 = data;
printf("%c",data);

}

unsigned char usart_Rx( void )
{

/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) );
/* Get and return received data from buffer */

return UDR0;
}

i have written a program for send info from atmega 64 to hyper terminal and from hyperterminal to atmega64. but it is displying junk values even i have selected 115200,8,none,1,flow control also none.wt is the proble could u tell me please.

Quote:

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

Stealing Proteus doesn't make you an engineer.

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

Hello! I want to know how to send a ADC result to the UART and see the result of the ADC conversion on the PC. Thanks

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

Quote:

Hello! I want to know how to send a ADC result to the UART and see the result of the ADC conversion on the PC.

Yeah? So what have you got so far?

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

mustang'a wrote:
Hello! I want to know how to send a ADC result to the UART and see the result of the ADC conversion on the PC. Thanks
Stop hijacking threads. You have posted the same question now at least four times.

Stealing Proteus doesn't make you an engineer.

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

Thanks very much on the tutorial, I have been trying to get my MavricIB(atmega128), to communicate for days now, and just got it. I ordered it assembled and didn't realize they set the fuses in the factory to make it work at 16mhz by default, duh. Anyways, great tutorial, I learned A LOT, very appreciated!!! :lol:

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

Hi. I'm using an ATMega8 with a 16 MHz external crystal. I set the SUT_CKSEL to Ext. Crystal/Resonator High Freq. and I can get the tutorial code to work. It echos back the keys I hit. Now, I'm trying to get the value of OCR1A sent to the terminal. All I get though, is a repeating ZZZZZZZZZZZZZZZ. Any ideas?

#include 
#define F_CPU 16000000
#include 
#include 

void sendStream(char c[], int length) {

int i;

for (i = 0; i < length; i++) {
  while ((UCSRA & (1 << UDRE)) == 0) {};
  UDR = c[i];
}

}

int main (void)
{

char buff[4];

DDRB |= (1 << PB1);
ICR1 = 40000;

TCCR1A |= (1<<COM1A1) | (1<<WGM11);
TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS11);
UCSRB |= (1 << RXEN) | (1 << TXEN);
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
UBRRL = 103;


while(1)
{
for(OCR1A=2000;OCR1A<=4000;OCR1A++){
_delay_ms(1);
itoa(OCR1A,buff,10);
sendStream(buff,4);
}
for(OCR1A=4000;OCR1A>=2000;OCR1A--){
_delay_ms(1);
itoa(OCR1A,buff,10);
sendStream(buff,4);
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For one thing, your buff[] is not big enough to hold the largest possible integer + null terminator. Try making it larger (you're probably clobbering your stack).

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

Thanks for the idea. I changed buff[4] to buff[10]. Now the output is changed, but still not what I would expect. I get output that constantly changes. For example, at one point it looked pretty close to this (some letters are extended ascii with tilde, umlaut and other symbols):

rTA/db!T"Pahl(34:&@1"
                     O&&
$'
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sounds like you need to back up and try something simpler to figure out if your sendStream actually works. Try feeding it some known data (ie. "hello",5).

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

Good call. I like it. Here's what I get.

helloT@        
       helloT@
              helloT@

I got this output by changing two lines of sendStream code to

(sendStream("hello",10);

I used 10 to make sure I didn't "clobber my stack" as suggested above.

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

You're printing out a fixed number of characters, but the size of the data is variable -- in your "Test" example, the length of the string is 5 characters (four letters plus the NULL terminator) but you are forcing your sendStream function to send 10 characters. Five of those characters will be garbage, which is what you are seeing.

As all strings are NULL terminated, ommit the length parameter in your sendStream function and have it print the characters in the string until a 0x00 terminator byte is reached. That way, it will automatically always print the entire string so long as the data in the string buffer is shorter than the buffer length.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Ok, it looks like you've validated your sendStream (of course you told it to print more characters than you gave it, but that's ok). Now try to validate the itoa() part, by passing a known integer, ie. 1234. You're getting closer...

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

Can anyone suggest me the code with hardware flow control (using RTS and CTS)???

Thank you!

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

Quote:
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR = ReceivedByte; // Echo back the received byte back to the computer

What is the advantage of checking UDRE instead of checking TXC if data can be sent?

Shouldnt the result be the same even if TXC is checked?

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

TXC indicates that the transmission is complete, and is set once the UDR buffer is empty. However, the UDR register is double buffered, so that you can stuff a new byte in while the previous byte is still being sent.

Checking UDRE allows you to take advantage of the double buffer (as it triggers when there is space in the UDR buffer) while the TXC flag does not as it only triggers when all pending bytes have been sent.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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



#define F_CPU 1000000UL
#define USART_BAUDRATE 4800
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) 



int main(void)

{

char recieveddata;

/* Enable Rx and Tx */

UCSRB |= (1<<RXEN) | (1<<TXEN);



/* Set no of bits to be Transmitted/recieved = 8 */

UCSRC |= (1<<UCSZ1) | (1<<UCSZ0);


/* Set the Baud Rate in UBRR Registers */

UBRRL = BAUD_PRESCALE;		/* Load the Lower Bits of BAUD_PRESCALE */

UBRRH = (BAUD_PRESCALE >> 8); /* Load the Upper 8 Bits of BAUD_PRESCALE */






while (1);{




/* Recieve Data and Store in variable called "recieveddata"  */

While ( (UCSRA & (1<<RXC)) == 0 ) ;{}

recieveddata = UDR;


/* Add 1 to the last recieved byte and transmit it back  */

While ( (UCSRA & (1<<TXC)) == 0 ) ;{}

UDR = recieveddata +1;


}




}

I'm using a Parallel Programmer made by following the instructions here to program a attiny2313.

I have so far tried basic I/O operations on the tiny2313 with great success.
I'm interested in trying USART communication between a PC and a tiny2313.

If i take the above code , put it in WinAvr , use this makefile , will it be possible for me to do USART communication?

I am only interested in transferring a few bytes of data for proof of concept.
I'm running my tiny2313's as they are bought without any fuse changes or anything. I just plug in the parallel port cable and transfer the program.

So , based on what i've read , my tiny2313 will be operating at 8MHz/8 = 1MHz with the RC Oscillator.

So , i've chosen a baud rate of 4800 as to get the UBRR value as ~12.0

I read in your tutorial that RC oscillators cannot be used for USART communication.
which of the two do you actually mean?
1) It works , but the chances of error are high
2) it doesnt work at all.

Please do tell me if i can procceed trying with the RC Oscillator and if anything is wrong with my code...

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

(1)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

What happens if the function results in a non-integer?
Will the non integer be loaded into UBRR?

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

Quote:

What happens if the function results in a non-integer?
Will the non integer be loaded into UBRR?

Exactly. And when you read the Error% column in the UART baud tables in the datasheet it's a direct consequence of this. That's why the "magic crystals" are so good for use with UART as they have frequencies that are integer divisible by 300 exactly so all the 1200,2400,4800,9600,19200... and so on are always achievable with no rounding error and no Error% - hence their Error% column is full of 0.0%

Cliff

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

Thanks for the tutorial Dean :)

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

Hello,

Does anyone knows how many devices could be connected on one UART Bus?

One device is the master, and the others are slaves.

Please advise!

Thanks in advance

Walid

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

Hi there, I thought people here should much be familiar with HyperTerminal stuff that's why I am posting my question here. Sorry if I got the wrong place.

I am doing a project that interfaces an ADS1252, ATmega644p. I would like to see/validate the data I have got from ADC on the computer. ADC is read using USART_set in_SPI mode. Another USART is connected to ICL232 chip and RS232 cable.

Data can be seen on oscilloscope but I am not sure if the data is accurate. So can you please tell me how to see it on HyperTerminal or even better on Excel?

My ADC has 24bits resolution, thus I am now receiving 3 bytes of data on UDR0 (data register of usart 0) and saved as Data[0..2]. I now transfer this data to UDR1 (data register of usart 1) to be transmitted through RS232 to be read on HyperTerminal.

The setting on my HyperTerminal is : Baud 57600, Data Length 8bits, Parity NONE, Stopbit ONE, and the last one (I don't remember what) as NONE. My uC has Fcpu of 2Mhz and according to the datasheet, the %error is 8.5%. I am not sure if this will much affect whatever I should be seeing on the HyperTerminal but at the moment, I am seeing NOTHING.

Do you know what problem I am facing now? Can anyone please advice if possible?

I am assuming that by firing up the ADC and uC, the data will "automatically" be displayed on the HyperTerminal window but I am pretty sure that my concept is wrong here. Can you tell me the proper procedure? Do I have to convert my data into ASCII or HEX as what I have read on forums? HOW? Do I convert it first before transmitting or the HyperTerminal will do it for me? Also, by streaming the data directly into HyperTerminal as what I am doing now, why don't I see anything like corrupted data or something like that?

Sorry if my questions sounds stupid but I really couldn't find any tutorials or information about interfacing uC, RS232 with HyperTerminal. Many thanks in advanced!!

p/s: also, a pseudo/ list of procedures of setting up HyperTerminal will be very much helpful :) (I don't even know which key to press to get it working a.k.a NOOB).

Mien

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

Quote:

%error is 8.5%. I am not sure if this will much affect whatever I should be seeing on the HyperTerminal but at the moment, I am seeing NOTHING

Well there's your problem right there - UART requires on both ends having clocks running at almost exactly the same rate (the A in UART stands for Asynchronous after all). The clocks can drift out a little bit but once they get any more than about -2%..+2% they are then too far apart for communications to work. An error of 8.5% is fatal.

On a 2MHz CPU (assuming that is accurate) the baud rates you can use are 2400 (0.2%), 4800 (0.2%), 9600 (0.2%), 14400 (2.1% if U2X used), 19200 (0.2% if U2X used)

Even the 14400 in that is going to be "iffy".

You didn't say whether your 2MHz was quartz or RC. If quartz then those ARE the error rates you'll get. If it's the internal RC you can "tweak" it by adjusting OSCCAL (Oscillator Calibration) to get rid of those errors all together and possibly even bring other baud rates (such as 57600) into error% range. But to calibrate it you need some form of known timing signal to calibrate against. One possibility for that is actually the width of a UART bit which you could measure by running the RXD signal to an INT0 or ICP pin.

Your problem clearly isn't with Hyperterminal - it should "just work" - the only "gotcha" is to ensure that the setup includes having hardware flow control switched off.

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

Hi Cliff, thanks for having the patience to reply to my basic newbie questions!

I have tried 9600 but I received nothing on HyperT as well(with everything on HyperT setup correctly, flow control-NONE).

Well, I am using a prescalar to get 2Mhz but the OSCCAL option that you suggested is a bit too complicated for me to understand so I think I would like to opt that out.

I am not sure if it is the problem with my code. I tried using synchonise mode before but I couldn’t see any waveforms coming out on the oscilloscope. So I modified my code to make it async. I don’t know if there’s something I missed out during this modification – I changed the register, added in SREG |=(1<<7) to enable interrupt as told on the datasheet so that I can use Rx, Tx, Empty enables/flag enables. I am not sure if I need any XCK clock settings for this so I omitted that. Can you spot any mistakes in doing this?

] //setup usart in spi mode for adc interfacing
void Setup_USART_As_SPI(void)
{
    UCSR0B =
            USART_CSR_B_Receive_Interrupt_EN |
            USART_CSR_B_Transmit_Interrupt_EN |
            USART_CSR_B_Data_Register_Empty_EN |
            0;

    //ensure transmitter and reciever disabled
    UCSR0B &= ~(
                        USART_CSR_B_Receiver_EN |
                        USART_CSR_B_Transmitter_EN
                    );


    //run usart at max baud rate
    UBRR0 = 0;

    UCSR0C =
        USART_CSR_C_Master_SPI |
        USART_CSR_C_CLK_Phase_Falling |
        0;
        //USART_CSR_C_CLK_Polarity_High |
        //USART_CSR_C_MSB_Last |


    //ensure transmitter and receiver ensabled
    UCSR0B |= (
                        USART_CSR_B_Receiver_EN |
                        USART_CSR_B_Transmitter_EN
                    );
};
//setup usart for rs232
void Setup_Usart(void)
{
    //setup global interrupt in SREG
    //requirement for Rx and Tx Enable
    SREG |= (1 << 7);


	//disable the reciever and transmitter
	UCSR1B &=
		~(
			USART_CSR_B_Receiver_EN |
			USART_CSR_B_Transmitter_EN
		);

	//set the Control status register B
	UCSR1B =
		0;


	//set the Control status register C
	UCSR1C =
		USART_CSR_C_USART_NumStopBits(1) |
		USART_CSR_C_USART_Parity_None |
		USART_CSR_C_USART_ModeSelect_ASync |
		USART_CSR_C_USART_CharSize_Max8(8) |
		0;
	

	//set the baud rate register Sync
	UBRR1L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
	UBRR1H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register


	//enable the reciever and transmitter
	UCSR1B |=
		(
			USART_CSR_B_Receiver_EN |
			USART_CSR_B_Transmitter_EN |
            USART_CSR_B_Data_Register_Interrupt_Empty_EN
		);

};

That was for setup. Now this is the functions I called.

//function for reading data from adc using usart spi
void USARTSPI_ReadADS1252(void)
{
            //declare 8bit WatchDRDY to detect DRDY mode
            unsigned char WatchDRDy;

    			//Watch for Data ready
            WatchDRDy = (PINC & 0x02 );
			//if Data ready occurs, do nothing
			while (WatchDRDy == (PINC & 0x02 ))
			{
                //do nothing
			};


            // make the whole delay to 22us to pass through the DRDY mode
            _delay_us ( 4);

			//PORTC0 = 0
			PORTC ^= (1);

            //Write to data register to initiate data transfer
            //flush adc
            UDR0= 0;
            //Wait till you've received 8 bits
            //Do nothing  when Receive Complete Flag is ZERO (  means when it has not yet completely received data)
            while ((USART_CSR_A_Receive_Flag  & UCSR0A) == 0)
            {
            }
            //Read the data
            //UDR0 is the 8- bit USART Data Register
            Data[2] = UDR0;

            //flush register
            UDR0 = 0;
            while ((USART_CSR_A_Receive_Flag  & UCSR0A) == 0)
            {
            }
            Data[1] = UDR0;

            //flush register
            UDR0 = 0;
            while ((USART_CSR_A_Receive_Flag & UCSR0A) == 0)
            {
            }
            Data[0] = UDR0;
//interfacing with rs232
void USART_RS232_Interfacing(void)
{

	//formula to mask and count 8 times
	int Loop = (Loop + 1) & 7;

	//at the 8th count, Loop will give 0
	if ( Loop == 0 )
	{
		//get Data[] into another variable ToUsart1[]
		ToUsart1[0] = Data[0];
		ToUsart1[1] = Data[1];
		ToUsart1[2] = Data[2];
	}

	//stream location counter initialisation
	int streamLoc = 0;

	//stream out data from  ToUsart1[0..2]
	while (streamLoc < 3)
	{
		// Do nothing until UDR is ready for more data to be written to it by checking register empty flag
		while ((UCSR1A & USART_CSR_A_Data_Register_Empty_Flag ) == 0) {};

		// Send out the byte value in the variable ToUsart[0..2] to data register of Usart_RS232
		UDR1 = ToUsart1[streamLoc];

		// increment stream location counter 0..2
		streamLoc++;

	}
};

Can you see any mistakes in the data sending flow?

I have just received a 1.8432MHz oscillator (Analog Electronics) this morning and I am wondering if I should try that one. If I were to be using external oscillator, do you think it will solve the problem or was it mistakes in my code?

Many many thanks!

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

Quote:

I am wondering if I should try that one

Exactly - the options with UART are (a) spend ages fiddling about trying to get the calibration of the internal oscillator right or (b) use quartz and you are finished.

The only "gotchas" when you start using a crystal are (a) are CKSEL fuses set to enable it, (b) is CKDIV8 disabled (to prevent it being divided by 8), (c) have you got a MAX232 (or other signal inverter) between the AVR and the PC

But as you may know 1.8432MHz is one of the so called "magic crystal" because a property of its frequency is that it can be divided down to all the commonly used UART baud rates with a 0% error. Which is nice.

Pages

Topic locked