0
\$\begingroup\$

I want to send some string to PC via serial port. In cute com (software) its displaying the string but with some chars missing. Also some hex numbers are appended at the start and end of the string. What could be the problem? Can anyone please help to solve this issue. My code is here.

#include <avr/io.h>  
#include <string.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#include <util/delay.h>    
#define USART_BAUDRATE 9600    // Baud Rate value
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
void usart_init() {

//Enable communication in duplex mode
UCSR1A = (1 << U2X1);
UCSR1B |= (1 << RXEN1) | (1 << TXEN1);// Turn on the transmission and   reception circuitry
UCSR1C &= ~(1 << UMSEL1);
UCSR1C |= (1<<USBS1) | (1 << UCSZ10) | (1 << UCSZ11);

 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.. 
 }

 void serial_write(unsigned char data) {

  while(!(UCSR1A & (1<<UDRE1)))
  ;
  UDR1 = data;
  _delay_ms(10);
 }

 void transmitString(unsigned char *str) {

 int i;
 for(i=0;i<strlen(str);i++) {
  serial_write(str[i]);
  _delay_ms(1);
 }
 }

 int main() {
    cli();
    usart_init();
    unsigned char buffer[20];
    strcpy(buffer, "Walk Alone");
    while(1) {  
    transmitString(buffer);
    //_delay_ms(250);
  }
   return 0;
  }
\$\endgroup\$
  • \$\begingroup\$ I changed all unsigned char to char when troubleshooting. still same problem exists. Please help. \$\endgroup\$ – Sanju Feb 22 '13 at 6:49
  • \$\begingroup\$ I would have expected your baud rate to be out by a factor of two, because you have U2X1 enabled and are using 16 as the baud rate divisor. Try commenting out the line UCSR1A = ... But that would give total junk, can you post a sample output and how the PC serial terminal is setup (speed, parity, stop bits). \$\endgroup\$ – PeterJ Feb 22 '13 at 7:35
  • \$\begingroup\$ Can you append your question with the string you expect and the string you actually receive? What OS patform are you using? I think it may be a synchronization problem. I personally like to add couple of extra bytes that I know can be discarded when I reecive them. Flushing the serial buffer before starting may help too. \$\endgroup\$ – jippie Feb 22 '13 at 7:57
  • \$\begingroup\$ @PeterJ : Hi thanks for your reply and yes i tried changing all possibilities like for 2X speed,changing baudrate for different values but not got expected in cutecom. Even I tried with commenting that UCSR1A but nouse. Tried for different baudrates too. I am using Linux with Port setup is 8 bit data 1 stop bit, parity none. \$\endgroup\$ – Sanju Feb 23 '13 at 9:39
  • \$\begingroup\$ @jippie: Thanks jippie sir. I am using Linux and I programmed in asynchronous mode know. How can I get junk data. The output something like this "\0xfd5E \0xca\0xcd\0xf6 (\0xcaM\0xf6 q\0xff\0x8a\0xf2 \0xfd5E \0xca\0xcd\0xf6 \0xe1\0xcaM\0xf6" To get my string on serial port what i may do please help. I have another doubt about Atmega128, Initially is A128 is selected the External Clock source or not. Please help in this also. \$\endgroup\$ – Sanju Feb 23 '13 at 9:50
1
\$\begingroup\$

According to my reading of your code and the datasheet there are two problems:

Two stop bits

The code here is probably not what you want:

UCSR1C |= (1<<USBS1) | (1 << UCSZ10) | (1 << UCSZ11);

This sets 2 stop bits (USBS1 value == 1). You probably want one stop bit. I would use a construct like this:

UCSR1C = (0<<USBS1) | (0 << UCSZ12) | (1 << UCSZ11) | (1 << UCSZ10);

just to make it very clear what you are doing.

Baud rate

According to my calculations, your BAUD_PRESCALE is 16000000/9600*16-1 = 26666. According to the datasheet, for 9600 with U2X1 set, the UBRR registers (L and H) need to be set to 207. So to my mind you are not setting the baud rate correctly.

A note on interrupts

In response to David Norman's comment about the interrupts (I think what is meant there is that interrupts would be easier), I beg to differ.

  • For me, anyway, polling is easier to implement
  • For many AVR tasks, (such as SPI sends), it has been found that polling is faster than interrupt-driven comms: probably due to the relative high-overhead of jumps (have to touch the stack), enabling/disabling the interrupt bits, etc.

As David Norman points out, if battery life is a concern, then interrupt-driven comms may be a better solution.

\$\endgroup\$
  • \$\begingroup\$ polling takes up CPU usage which in 'many' cases undesirable especially when you are using battery as Vcc. Also interrupts make the code concise and does not involve any many flags as polling does. But again, it comes down to personal choice and the quality of code. \$\endgroup\$ – David Norman Apr 7 '13 at 5:14
  • \$\begingroup\$ Hmm.. good point. I don't know about battery usage: I suppose if with interrupts you can sleep, with polling you can't. As far as which one is more battery draining: idle-looping or interrupting, I have no idea. Let me know if you test it! \$\endgroup\$ – angelatlarge Apr 7 '13 at 5:17
  • \$\begingroup\$ I have tested it, I have been programming embedded devices for over 2 years now. Mostly the devices are mobile and requires a battery, using interrupts your microprocessor can go to sleep which saves battery in the long run. For polling if you put your processor to sleep, you would need external interrupt to wake it up upon an event so why not just use interrupts in the first place, the code will be shorter in the end \$\endgroup\$ – David Norman Apr 7 '13 at 5:21
  • \$\begingroup\$ @DavidNorman Since the OP has not mentioned battery life I do not think it is incumbent upon us to assume that batter life is a concern. And I would disagree with the claim that using an ATmega device implies running off a battery, at least from my own experience. \$\endgroup\$ – angelatlarge Apr 22 '13 at 23:35
0
\$\begingroup\$

I would drop Cute Com straight away and switch to something like Termite. Usually when you're dropping characters (it has happened to me many times) it is because the terminal program uses the .NET SerialPort class which converts received data to ASCII then translates it back to whatever the user wants. Instead you should be using a program which uses the Win32API directly (i.e. Termite). You can choose to display in binary, ASCII or hexadecimal without worry at all. I switched last year and would never go back (after spending 2 weeks debugging something that wasn't broken).

\$\endgroup\$
  • \$\begingroup\$ Ragarding the .NET SerialPort class and ASCII encoding: This only applies, if you write/read to/from a string type and use the default encoding. Its totally possible to either read/write data as byte[] or just change the default encoding. So its not a limitation of the SerialPort class but wrong usage. \$\endgroup\$ – Rev1.0 Jun 22 '13 at 9:02
-1
\$\begingroup\$

I was facing the same problem when I was trying to send a string to my LCD display serially using mega128. The problem was that the system clock was too fast compared to the speed at which bytes are transferred.

Firstly comment your baud rate in your program code.

Secondly, do not use delays in your function where serial communication is concerned.

Thirdly, to troubleshoot use break points where your code sends data which would be UDR1 = data;. Observe on the other side if you are receiving each character. This is to ensure that your serial driver is working correctly.

Fourth, since you are not using interrupts (which will be much easier to go about), check when the buffer is empty for a new byte as well as check if the flag is cleared (I reckon you have done that, I'm not checking the data sheet).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.