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

Go To Last Post
490 posts / 0 new

Pages

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

thanks for the reply.
i saw the table for 16mhz. can i use a more bitrate for more speed, i mean the error is very less at those speeds.

Attachment(s): 

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

The entries you have cricled there all show 0.2% error which is well within the bounds of -2%<=err%<=+2%

In fact in that table the only baud rates that are "suspicious" are 57K6 without U2X (though 2.1% is probaly OK in fact). 115K2 is not achievable (-3.5%) without using U2X which brings it back to the borderline 2.1%. 230K4 is not achieveable whatever you do.

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

i will try and let u know what are the results. thanks for the suggestions.
i think i will go for 38.4kbps baudrate.

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

hi,

nice nice tutorial well writen.
I have tried it on a AT90USB162. I have to change most stuff to include an 1 so the "right" uart is selected i assume, e.x UCSRC changed to UCSR1C BUT i can not get the line that sets 8n1 to work, keep getting errors on that one, anyone who can tell me how it should look on my avr ?

thanks

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

You don't need to do ANYTHING to select 8n1 - it's the default in all(*) the AVRs

To get the UART going in it's very most baic form it really shouldn't take anything more than setting UBRR and the TXEN bit in fact.

Cliff

(* unless anyone knows of one where it isn't?)

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

#include
#include

#ifndef F_CPU
#define F_CPU 8000000
#endif

#define BAUDRATE 9600
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)

int main (void)
{
char ReceivedByte;

DDRD = 0b01111111; //7 0
PORTD = 0b00000000;

UCSR1B |= (1 << RXEN1) | (1 << TXEN1); // Turn on the transmission and reception circuitry

UBRR1L=UBRRVAL; //low byte
UBRR1H=(UBRRVAL>>8); //high byte

// sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed

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

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

/*
ISR(USART_RXC_vect)
{
char ReceivedByte;
ReceivedByte = UDR1; // Fetch the recieved byte value into the variable "ByteReceived"

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

thatsthe code used atm, the reason i loop a 'U' out is simpel, clawson sugested use a 'U' becouse that will measure 2,5volt avg on the avrs TXD. Useing no codeline to set bits parity stopbits, im told skipping this leavs the default 8n1

i have connected the avrs TXD to a max232 pin 10, wich is TTL input, still measure 2.5volt
onmax 232 pin 7 i measure 0,14 volt wich is correct, its the avg of rs232 signal low and high (-9 and +9)

so it all seems to work, still when i connect it to my PCs serialport pin ground and RXD my hyperterminal set to 8n1 do not output 'U' endlesly, nutting att all happends

HELP!

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

ok, gues what ! the ground cable was broken inside the insulation! replaced it (the rs232 cable) and now something happends atleast, i get a wierd looking 'C' all the time, not a good looking 'U'

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

#ifndef F_CPU
#define F_CPU 8000000
#endif

#define BAUDRATE 9600
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)

UBRR1L=UBRRVAL; //low byte
UBRR1H=(UBRRVAL>>8); //high byte

seems to give 1200baud.....
well atleast my code works IF i set the hyperterm to 1200baud instead of 9600......

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

I didn't really delve into your code but I saw you are actually getting 1200 BAUD when you expect 9600 BAUD...is that right? Well 1200 is 8 times less than 9600. That tells me you might be actually running on the 1MHz Internal RC oscillator, which is the default fuse configuration for most AVR's. Time to read up on default clock source fusing.

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

my idea also, so i went back to the datasheet and checked the value for 9600baud @ 1MHz and put that in instead of 51 wich is 9600@8MHz

no luck tho! :(

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

hii
i am able to receive data on computer using usart(by hyper terminal)
can you tell me how to send data as it requires bin file in sending option.

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

Use "Send file" on Hyperterminal's "Transfer" menu. For this to work the AVR will need to implement one of the protocol transfers listed there (Xmodem, Ymodem, Zmodem, Kermit, etc.)

Hyperterminal does have a "Send text file" entry on that menu and this MAY work for what you want to do but be warned that any 0x1A bytes in your data may be interpreted as an Enf Of File (EOF) marker and teminate the transfer. If you are going to use simple text transfer you might be better off first converting the binary to some well known ASCII based format for binary transmission such as Motorola SRecords or Intel Hex. (or even things like UUencode)

I guess the first question is what kind of data are you talking about?

Cliff

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

i tried to send a text file but nothing happaned. in notepad, i write 'l'(without quote) and saved it as txt file and then send it but nothing.
i try to find a find a text file to hex file convertor but i dont find any.

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

Why bother putting an "l" into a file and then sending it? Why not simply type the L key at the terminal?

Anyway, what does your receiver code in the AVR look like? If TX from AVR to PC works then your clock/baud rate are correct so it should just be a matter of setting RXEN and then lifting bytes out of UDR when RXC says one has arrived.

Cliff

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

i have try what you have mentioned, but it was not working and now it is working. thanks clawson, thanks buddy.

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

Hi all!

10x a lot for the tutorial Dean-it is very well written, understandable and useful.

I try to implement your code to mega128(with some changes), but it isn't working like it suppose to.
Fuses are set to IntOsc-8MHz.Character Size-8 bit,1 stop bit.
With baud rate that i chose it generate 0.2% Error-acceptable error.
For seria comm from computer i'm using Tera Term Web 3.1(with adjustment of bps same as mega & Local Echo turned ON)
I'm using JTAG to debug it-add breakpoint after the first while.But the RXC0 is still 0 after i send some data with Tera Term.The program stay in the while.
Can somebody give me advice what might be wrong?
Should i try to change baud rate or Clock?
10x in advance.

Here is my code:

#include

#define BAUD 51//UBRR value taken from datasheet-9600 bps

int main (void)
{
char ReceivedByte;
/* Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);

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

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

while ((UCSR0A & (1 << UDRE0)) == 0) {}; // 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
}
}

Beware the barrenness of a busy life.
Socrates .

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

Start by confirming that the processor really is running at 8MHz. One way to do that is to put a scope on the TXD pin, write code that just puts a 'U' into UDR0 every time UDRE says it's OK to and see if you get 104us width bits on the scope. If you don't have a scope use routines to write a simple program (based on F_CPU 8000000UL) that flashes an LED on a pin. Does it flash at the expected rate?

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

I'm using AVR Studio -it read and verify fuses and it shows that current settings of the MCU is 8MHz.
Or you talk about +-10% IntOsc accuracy?

Beware the barrenness of a busy life.
Socrates .

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

Yup in part that (there's a clue in the FAQ at the bottom of this message!). What are you doing, for example, with the factory programmed OSCCAL value?

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

10x for the quick answer!

I program OSCCAL Register to 8Mhz-not by code (like "OSCCAL|=0xXX") but by AVR Studio features-it automaticly program OSCCAL Register with chosen frequency(0 for programmed bit and 1 for unprogrammed).

Beware the barrenness of a busy life.
Socrates .

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

Are we talking about the same thing? I quote the 128 datasheet:

Quote:
Writing the calibration byte to this address will trim the Internal Oscillator to remove process variations from the Oscillator frequency. During Reset, the 1 MHz calibration value which is located in the signature row high byte (address 0x00) is automatically loaded into the OSCCAL Register. If the internal RC is used at other frequencies, the calibration values must be loaded manually. This can be done by first reading the signature row by a programmer, and then store the calibration values in the Flash or EEPROM. Then the value can be read by software and loaded into the OSCCAL Register. When OSCCAL is zero, the lowest available frequency is chosen. Writing non-zero values to this register will increase the frequency of the Internal Oscillator. Writing $FF to the register gives the highest available frequency. The calibrated Oscillator is used to time EEPROM and Flash access. If EEPROM or Flash is written, do not calibrate to more than 10% above the nominal frequency. Otherwise, the EEPROM or Flash write may fail. Note that the Oscillator is intended for calibration to 1.0, 2.0, 4.0, or 8.0 MHz.

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

10x for Quote clawson.

I'll read a bit more, make some trials and will write what i've done(about 1h-3h from now) .
10x.

Beware the barrenness of a busy life.
Socrates .

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

Wow it took me more time than i expected(even though something else distract my attention).

I've check some app notes like "AVR053: Calibration of the internal RC oscillator" and "AVR054: Run-time calibration of the internal RC oscillator" just to find out(by chance) that RS 232 is connected to USART1 not to USART0!!!

Now USART is working properly and i know(eventually) how to calibrate IntOsc with External Oscillator.

10x for the replays clawson.
PS:The most significant thing is to be stubborn!

Beware the barrenness of a busy life.
Socrates .

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

I have used this tutorial successfully for Atmega8.Now I am trying with Atmega128 but it is not working properly.I have set the hfuse =99 and lfuse =E4 and I modified the code as below:


#include  
#include 

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


int main (void) 
{ 
   char ReceivedByte; 
   
   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 << USBS0) | (1 << UCSZ01) | (1 << UCSZ00); // Use 8-bit character sizes 

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

      while ((UCSR0A & (1 << UDRE0)) == 0) {}; // 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 
   }    
} 

But I am getting some garbage characters.What could be the problem?

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

What is your F_CPU and did you use the data sheet or AVRCalc to calculate the % transmission error?

Smiley

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

smileymicros wrote:
What is your F_CPU and did you use the data sheet or AVRCalc to calculate the % transmission error?

Smiley

F_CPU is 8 mhz,when I tried the previous code with Atmega8 the characters were echoed back to the hyperterminal without a single error.

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

bootstrap wrote:
I have used this tutorial successfully for Atmega8.Now I am trying with Atmega128 but it is not working properly.I have set the hfuse =99 and lfuse =E4 and I modified the code as below:


#include  
#include 

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


int main (void) 
{ 
   char ReceivedByte; 
   
   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 << USBS0) | (1 << UCSZ01) | (1 << UCSZ00); // Use 8-bit character sizes 

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

      while ((UCSR0A & (1 << UDRE0)) == 0) {}; // 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 
   }    
} 

But I am getting some garbage characters.What could be the problem?

Could any one please tell me what could be the problem.

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

Well all the signs are that you may think your F_CPU is 8Mhz but it isn't

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
      ReceivedByte = UDR1; // Fetch the recieved byte 

UDR1? UDR0 would make sense here.
/Lars

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

Hi Dean .....nice tutorial !!

I am using atmega16 with 8 MHz external crystal......seems error is 8.5% @9600. Even at other baud rates error is huge !! :-)

What can I do other that changing the external crystal :-) ?? Please suggest !!

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

Are you sure you are operating at the crystal frequency? Standard fuse configuration of most AVR's is to run off internal RC oscillator at 1MHz.

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

Yes....that is confirmed...I am using 8MHz.

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

Now here is the latest what I did...Let me go point wise..

1. I used the AVR atmega16 microcontroller with an external 8 MHz crystal.

2. I used a "Pololu USB to Serial adaptor" to get a serial port on my laptop.

3. Checked the serial port by "loop back test"...it worked fine...i.e. connected serial ports' Tx to its Rx & opened Hyperterminal ...what I typed is what returned to the terminal...so the serial port on my laptop was fine.

4. My atmega16 development board has a max232 ic connection done & a female serial port provided.

5. Then I burnt the following code on the the atmega16.
-----------------------------------------------------
#include
#include

void main(void)
{
CLI(); //disable interrupts
UCSRB = 0b00000000;
UCSRA = 0b00100000;
UCSRC = 0b10000110;
UBRR = 51;
UCSRB = 0b00011000;
SEI();//enable interrupts
while(1)
{
while(!UDRE);
UDR='a';
}
}
-----------------------------------------------------

6. Connected the Tx of the atmega16 development board to Rx of Pololu USB to Serial adaptor fitted to my laptop. And also connected both the grounds.

7. Made a connection thru Hyperterminal at 9600 bauds / Hardware Control : None / Parity : None / Databits : 8 / Stop Bits : 1.

8. I was expecting "aaaaaaaaaaaaaa......" on the Hyperterminal screen...but nothing happened.

9. Referring to Table no. 70 on page 170 of Atmega16's datasheet I also tried with UBRR = 0 (i.e. at 0.5 M bauds) so that error = 0, but that too did not work.

Please advise !!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
while(!UDRE);

I bet that line doesn't do what you think it does!

(hint UDRE==5 on the mega16)

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

What about using serial communication to write to a Robot like the Boe-Bot from Parallax?

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

Hello! first time poster.. so please be nice :D

I currently have an ATmega88p. And it has one USART 0 which is directly connected to PORT D. It is, however, also connected to the databus and therefore should be accessible through other ports as well.

I've been looking online for awhile, and I don't see indication that it actually is available on other ports. So I figured I'd ask here.

Can i use USART 0 with other PORTS other than PORT D? If so, can this be done through C? This might be a stupid question... but I just wanted to be 100% sure....

Any code examples would be appreciated.

Thank you in advance!

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

AVRs do not allow the internal peripherals to be mapped to other pins. In a mega88P TXD is on pin 3 (PD1) and RXD is on pin 2 (PD0) and there's nothing you can do to change this.

If you have laid out a PCB and mapped the signals incorrectly the only other solution might be to ignore the hardware USART and simply implement a "soft UART" that bit-bangs another couple of pins.

Cliff

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

Nice tut. :)
Silly question. I have seen some rs232 pinouts for DB9 connector, e.g. here:
http://www.interfacebus.com/RS232_Pinout.html
or here
http://www.youritronics.com/wp-content/uploads/2008/05/avr-butterfly-with-pin-headers-soldered1.jpg My deduction is that when I see a picture of a DB9 connector it shows the view on the side of soldering pins, right?

I am asking because in the link from that tut. it is opposite http://www.coolcircuit.com/circuit/rs232_driver/max232.gif

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

The first two are correct, and yes - they show the connector from the soldering side. Pins start from pin 1 located at the top-left of the connector.

Many connectors actually have the pins numbered in very faint writing in the moulded plastic above the soldering point.

- Dean :twisted:

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

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

I am trying to figure out why me RS transmission is not working. I though it was written so much about it, that is should be easy.

I have connected pins correctly, iam running atmega32 with 10MHz crystal and the test code is like:

#define BAUDRATE 64  // 9600 at 10MHz
#define LED 0
#define LED2 6					 
#define F_CPU 10000000
//tranmission led
#define LED_ON()  PORTC |= (1<<LED)
#define LED_OFF()  PORTC &= ~(1<<LED) 

//power led
#define LED2_ON() PORTD |= (1<<LED2)		
#define LED2_OFF() PORTD &= ~(1<<LED2) 


#include 
#include 

void rsInit(unsigned char baud) {
  //UBRRH = 0;
  UBRRL = baud;
  UCSRC = (1<<UCSZ0) | (1<<UCSZ1);  // 8N1
  UCSRB = (1<<RXEN) | (1<<TXEN);    // enable tx and rx
}

void rsSend(unsigned char data) {
  while( !(UCSRA & (1<<UDRE)));
  UDR = data;
}

unsigned char rsRecv() {
  while( !(UCSRA & (1<<RXC)));
  return UDR;
}

void portInit() {
  
  
  //DDRD = (1 << LED); 
 // PORTC = 0xFF;
  DDRC = 0xFF;
  DDRD = (1 << LED2); 
}

volatile unsigned char bytes[16];
 

int main(void){

	unsigned int i=0;
	asm("cli");
	portInit();
	_delay_ms(100);
	rsInit(BAUDRATE);
	LED2_ON();
	bytes[0]=0x30;
	bytes[2]=0x40;
	bytes[3]=0x42;
	bytes[4]=0xFF;
	bytes[5]=0x48;
	bytes[6]=0x40;
	bytes[7]=0x60;
	bytes[8]=0x70;
	bytes[9]=0x80;
	bytes[10]=0xF0;
	bytes[11]=0xF0;
	bytes[12]=0xF0;
	bytes[13]=0xFA;
	bytes[14]=0xFA;
	bytes[15]=0xFA;
	while(1){
	
		for(i=0;i<16;i++){
		     rsSend(bytes[i]);
		}
		LED_ON();
		_delay_ms(250);
		LED_OFF();
		_delay_ms(250);
		_delay_ms(250);
		_delay_ms(250);

	}
	return 0;
}

I am setting in Putty at the PC side 8bits,no parity,1 stop, no flow control, checked also with Xon/Xoff. Sometimes it throws on my screen series of ' and |.

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

Did you change the AVR's default fuses so that it really does use your external crystal, rather than its internal 1MHz RC oscillator?

- Dean :twisted:

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

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

My fuse settings for low byte are 0xFF (so external RC/crystal) and high byte 0xC9 to have CKOPT=0 (for more than 8MHz, full rail swing). When I use _delay_ms(250) function 4 times to see if the diode lights on for 1 seconds, it does so. According to the datasheet atmega32-16pu can be clocked from a crystal oscillator >8MHz.

My error rating is 1.7%.

My pogramm should send strings of 16 hex values to the PCs hyperterminal. When I should launch hyperterminal/putty? Does it matters?

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

I tried this code on my atmega16 for connecting it to my pc with one visual basic aplication. But I find that the valued is 128 bigger than the expected.If I deduct 128, I solve the problem, but I really dont know why and what I am doing.Also if I send a number bigger than 128 produces failures.
Any idea??

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

plesase help me, about Multi-processor communication .
I can't find where slave's address is located when avr is a slave in multi-processor communication.

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

Read the section "Using MPCM" in the datasheet. The numbered steps there tell you how a slave should recognise it's being addressed - there's no "slave address register" (like with TWI/I2C), it just checks the UDR after the address byte arrives.

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

Hi all interested in robotics, please visit to know more on robotis and contribute to http://robots4all.blogspot.com/
.Lot of cool stuff on robotics. Happy learninig & posting !!

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

Hallo All.

It is great that you spent time to make this great tutorial........thanks alot.

I want to make the mega16 responde to a command I will send from a program made i C# from the pc over a serial rs232 line and use the modbus protocol.

but right now I trying to send a string to the pc. I only works in JTAG mode and is printing some strange charters like(!,,\)

in runtime mode it prints (X on pc if I enter a (0xE1). I checked the hex value and it is A8F8

I dont understand why it do not print at least 5 charters.

can anybody help me???. and a sample code with the modbus implemented would be perfect. see code below

#include 			
#include "stdlib.h"
#include "string.h"
#include "stdio.h"

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


int main () 
{ 
   int ReceivedByte; 

   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 (;;) // 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 
     	
		if ( ReceivedByte==0xED) 
		{UDR = 0xEC;
		}

		
		if ( ReceivedByte==0xE1)
		{USART_TxString("hallo");// send hallo to pc
		
			
		}
		else UDR = ReceivedByte; // Echo back the received byte back to the computer 
	 
	 
	  
}

 }

void USART_Tx(char data)
{   
	 UDR = data; // Send data to the computer 
	while (!(UCSRA & (1<<UDRE)));{} // wait till transmit Data register is empty
  
}

void USART_TxString(const char StringPtr[]) 
{ 
   while (*StringPtr != 0x00) 
   { 
	  USART_Tx(*StringPtr); 
      StringPtr++; 
   } 
}




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

hey, that's a nice article. i was just wondering if i tried to create my own serial programmer, do i need to have the MAX232 in between my serial port and my microchip? or could i just connect jumper wires between pin 3 and 4 of the serial port pins straight to the Rx and Tx ports of the microchip that i'm trying to program?(in my case, a atmega88 PDIP so it should be pin 2 and pin3 ? sorry but i'm quite new to this :D)

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

A Max232 is used for two reasons:

(1) -12V may be headed down the line towards the AVR - it won't like this. MAX232 level converts this to 0..5V. So in this case you have no such worries if both devices are already at TTL level

(2) a MAX232 inverts the TXD/RXD signals so they are the "right way up" as far as a standard UART device such as a PC is concerned. If it's two AVRs you are talking about then they are both "upside down" so should be able to chat amicably with nothing in-between.

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

Yes, you need a MAX232 when connecting the AVR to the computer's serial port. That is because the AVR uses 0V-VCC voltage levels, while the PC uses -10V-10V for signalling. Connecting the AVR directly to the PC at proper RS-232 levels will kill the AVR.

If you are connecting the AVR directly to another AVR using the same voltage levels, you do not need the MAX232 as both AVRs will be speaking serial data at the same logic levels.

- Dean :twisted:

EDIT: Darn, beaten by Cliff.

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

Pages

Topic locked