Serial communication failure for ATMEGA328PB-XMINI.

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

I tried serial communication between Atmega328PB-XMINI and the PC by configuring USART0 and related registers, this partially worked. The problem that faced was - if I set 9600 as Baud-rate in the code then every in PC terminal (TeraTerm) settings baud-rate needs to be changed to 19200, plus serial comm. is not possible with any other baud-rates.

Following is the code that I used:

#include <avr/io.h>
#include <string.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL
#include <util/delay.h>

#define FOSC 8000000 //Clock speed
#define BAUD 9600 //28800    //9600  //2400  //19200 
void usart_init(void)
{
        
        /* Initializing for USART0 and USART1 */
        
    UCSR0B |= (1<<TXEN0);   //(1<<RXEN0)|
    UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);   /* Set frame format: data=8, stop bit=1 */
    UBRR0H = 0x00;
    UBRR0L = 0x33;
    UCSR0A |= (1<<TXC0);      //Clear the left-out transmissions

}

void usart_send (unsigned char ch)
{    
                           
    /* Wait for empty transmit buffer */   
    while ( !( UCSR0A & (1<<UDRE0)) );
    /* Put data into buffer, sends the data */
    UCSR0A |= (1<<TXC0);      //Clear the left-out transmissions
    UDR0 = ch;
}

unsigned char usart_recv (void)
{
    while (!(UCSR0A & (1<<RXC0)));
    return UDR0;
}

int main(void)
{
    unsigned char str[40] = "AT+GSN\r\n";
    unsigned char strLenght = 40;
    unsigned char i = 0;
    usart_init();

            while (1)
            {
                    usart_send(str[i++]);
                    if (i >= strLenght)
                    {
                        i = 0;
                    }
            }
    return 0;
}
 

I am not able to figure the problem please help

 

Also tried it by using printf/scanf commands, here serial communication just does not work at all. Following was the code that I used:

#include <avr/io.h>
#include <stdio.h>

int main(void)
{
    int i;
    char a;
    /* Communication Parameters: 8 Data, 1 Stop, No Parity
       USART Receiver and Transmitter: On
       USART Mode: Asynchronous */
    
    UCSR0B = 0x18;
    UCSR0C = 0x86;
    UBRR0H = 0x00;
    UBRR0L = 0x33;            // USART Baud Rate: 9600
    UCSR0A = (1<<TXC0);         //Clear pending Transmissions
    
    while ( !( UCSR0A & (1<<UDRE0)) ) {};
    
    printf ("Arago Electric");
    scanf ("%d", &i);
    if(i==1)
    {
        printf ("one is entered");
    }
    while (1) 
    {
        scanf ("%c", &a);
        switch(a)
        {
            case 'a':
            printf ("A is entered");
            break;
            
            case 'b':
            printf ("B is entered");
            break;    
        }
    }
    return 0;
}

 

 

Please give suggestions, finally I am supposed to set up a communication between Atmega328PB and a GSM module.

 

Also please suggest on how can I make use of both USART '0' and '1' for a single application, I tried testing USART1 individually but it didnt work.

Thank you.

 

 

This topic has a solution.

dviz

Last Edited: Mon. Oct 15, 2018 - 12:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My guess is that the board is 16MHz (most are) not 8MHz as this implies:

#define F_CPU 8000000UL
#include <util/delay.h>

#define FOSC 8000000 //Clock speed

BTW I wonder why you would have two different symbols (F_CPU and FOSC) defined to be the same thing? The usual method is to always use "F_CPU" because that is what things like <util/delay.h> will be looking for.

 

EDIT: I'm not familiar with this board but this:

 

Seems to suggest that the 32U4 (EDBG) varies the speed of the 328PB according to the operating voltage which presumably defaults to 5V (hence 16MHz)

Last Edited: Mon. Oct 15, 2018 - 09:04 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay. Thank you Sir. I tried the way that you suggested but I faced the same problem. But if I do this change the register's value UBRR0L=103 (the decimal value used for U2X0=1) as given the component datasheet, then serial transmission works fine, here I am still trying to figure out why so. But the program with printf/scanf still won't work.

dviz

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well what made you pick 0x33 in the original code? 0x33 is 51. The datasheet shows:

 

 

 

So if it works for you at 19200 baud then clearly F_CPU is 16MHz

 

As I say the manual for the Xplained seems to suggest that at 3.3V operation the 328PB is clocked at 8MHz and at 5.0V operation it is clocked at 16MHz. As all this seems to have proved that it is running at 16MHz then clearly you must be operating it at 5.0V

 

The only surprise here would be if you say it is 3.3V. Then 8MHz would be expected and so 51 in UBRR would be expected to deliver 9600 baud not 19200 baud.

 

EDIT: just to be clear this is what the 328PB Xplained manual says about power:

 

 

So unless you have changed jumpers that it talks about here is IS working at 5.0V and the chip IS running at 16MHz. There is no mystery here - it is all as per the user manual.

Last Edited: Mon. Oct 15, 2018 - 12:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes Sir. Got your point. Thank you so much Sir for clearing my doubt. Will make changes accordingly.

dviz

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

DVIZ wrote:
But the program with printf/scanf still won't work.
But I don't see where you do the FDEV_SETUP_STREAM() ??

 

You need to read this:

 

https://www.nongnu.org/avr-libc/...

 

As you'll learn there you need uart send/receive routines with this interface:

int	uart_putchar(char c, FILE *stream);
int	uart_getchar(FILE *stream);

You then do this:

FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);

and finally you do this:

int
main(void)
{

  ioinit();

  stdout = stdin = &uart_str;

That then connects you uart_putchar() and uart_getchar() routines to the stdin (scanf) and stdout (printf) streams so the standard <stdio.h> functions can then be used.

 

By default stdin/stdout are not connected to anything - it's left as your choice what you want to connect them to - you might, for example, have preferred printf() to go to an LCD in which case you would have provided an LCD_putchar() routine then done an FDEV_SETUP_STREAM to create a stream with that as its output function and then you might connect stdout to that stream instead. Now the printf() output would go to LCD instead.

 

But if you don'd do any of this then scanf/printf will appear to do nothing. (but at least they don't crash! ;-)