STK500,M48 and USART

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

Hi Freaks,
I am trying to make the USART on my M48 work with the STK500. I have already tried this with the M16 with STK500 and it has worked. However, it has been a while and do not remember the clock settings.

I am using Dean's basic code to make it work with the STK500. Here it is:

#include 
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((8000000/ (USART_BAUDRATE * 16UL))) - 1) //value to load into UBRR

void USART0_init()
  {

      UCSR0B |= (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and reception circuitry 
      UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); //Set to 8 bit no parity, 1 stop bit
      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

   }

int main (void)
   {

     char ReceivedByte;
     USART0_init();

        for(;;)
          {

             while((UCSR0A & (1 << RXC0)) == 0) {};
             ReceivedByte = UDR0;

             while((UCSR0A & (1 << UDRE0)) == 0){};
             UDR0 = ReceivedByte;

           }

    } 

I am pretty sure it is a clock selection issue on the STK500. Now when I connect my STK500 from the RS232 CTRL port to AVRStudio, I get the following options:


Ext Clock
Internal RC Osc. 8MHz
Internal RC osc. 128kHz
External low freq.Crystal
External full swing crystal
External crystal oscillator 0.4 - 0.9 MHz
External crystal oscillator 0.4 - 3 MHz
External crystal oscillator 3.0 - 8.0 MHz
External crystal oscillator 8.0 - MHz

Also the CLKDIV8 fuse in my AVRStudio programmer settings is checked.

Reading the STK500 manual tells me:

When the XTAL1 jumper is mounted, the STK500 internal clock system is used as main clock to the target AVR. The internal clock system can either use a crystal in the on-board crystal socket, or a software generated clock from the master MCU. The frequency of the software generated clock can be set from 0 to 3.68Mhz. The default value is 3.68Mhz. Section "Oscillator" explains how to set the clock frequency from AVR Studio.

When using the STK500 software generated clock system as main clock, the target AVR microcontroller fuses should be configured for "external clock" as clock source. This gives shortest start-up time for the microcontroller. For details of start-up time, see the datasheet for the AVR microcontroller. Explanation of clock source fuses configuration, see "Fuse settings". Not all AVR devices have fuses for selection between using a crystal or oscillator as clock source.

So can I insert my 8MHz crystal into the crystal socket on the STK500 and select the "External crystal oscillator 3.0 - 8.0 MHz" in AVRStudio?

Thanks.

edit: What I can't understand is how this worked with an M16. I did not use any external crystal, I had the default settings on my STK500.

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

Just start with the default jumper settings on the STK500. This gives a software controlled clock that you can set via Studio.

Make sure that your mega48 fuses are set for ANY clock other than the internal RC clock settings.

Then play with a blinky program, varying the STK500 clock speed. Follow with a UART program. You may have to change the Hyperterminal baud-rate if you choose some of the slower clock values. For example if your program is written for 9600 baud at 3.68MHz clock, if you slow the clock to 1.832MHz you will be at 4800 baud. Or if you have the CKDIV8 fuse set, you need to listen at 1200 baud instead of 9600.

After these experiments, you need to think of using crystals or moving your mega48 to an external board. Change the STK500 jumpers for your crystal.
Set the clock fuses correctly before you move the AVR. You will need "external high speed crystal" or "internal RC" for the external board.

NEVER "external clock".

But on the STK500, you will find the AVR will work with any clock fuse settings. So you can experiment as much as you like. You can always recover.

David.

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

Thanks, David.

Quote:

Or if you have the CKDIV8 fuse set, you need to listen at 1200 baud instead of 9600.

That did the trick. I am now using a 3MHz external clock with the default jumper settings on the STK500.

This 3MHz external clock should still be more accurate than the internal RC oscillator of the M48 right?

Eventually I would like to move to an external crystal. I want to make my own board with Serial interface to the AVR so that I can control it from my PC.
So what are the settings on the STK500 with an external crystal?
Here is what I gathered from the datasheet for external crystal:

1. Remove the xtal1 jumper.
2. Keep the OSCSEL jumper at default position?
3. Connect the crystal to port E pins Xt1 and Xt2.
4. Select external high speed crystal in AVRStudio.

Is this correct?

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

Just read the STK500 manual. Do what it says, instead of making up some different rules.

As I said earlier, you can experiment as much as you like. You cannot go wrong with a STK500.

Try everything and see for yourself.

David.

p.s. the STK500 clock setting will be more accurate than the internal RC. But in practice, the RC is not that bad really.

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

Thanks again, David. I will certainly stick to the STK500 manual.

With my working code, I am trying to control some LED's on port B through the hyperterminal. Here is what I have so far:


#include 
#include 
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((3000000/ (USART_BAUDRATE * 16UL))) - 1) //value to load into UBRR

void USART0_init()
{


   UCSR0B |= (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and reception circuitry 
   UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); //Set to 8 bit no parity, 1 stop bit
   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

}


void USART_putchar(char c)
     {

        while ((UCSR0A & (1 << UDRE0)) == 0) {};     
        UDR0 = c;
       _delay_ms(100);
      }

void USART_putstring(char *s)
  {
    while (*s)
        USART_putchar(*s++);
  }


int main (void)
    {

       DDRB = 0x01;
       char ReceivedByte;
       USART0_init();
       USART_putstring("Hello!!");

          for(;;)
            {
              			  
	      while((UCSR0A & (1 << RXC0)) == 0) {};
              ReceivedByte = UDR0;
		  
              if (ReceivedByte == 'A')//BYTE RECEIVED FROM PC
                {
 
                 _delay_ms(100);
                  PORTB &= ~(1 << PB0);
                 _delay_ms(100);
                 }	  

           }
     } 

When I open up hyperterminal, I get a garbage string and not "Hello". Is this because of the baud rate? Should I add a delay?

Also I cannot see the LED on Port B0 toggling when I press 'A' on the keyboard. What could be wrong?

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

Ok I changed the following from:

PORTB &= ~(1 << PB0); 

to:

PORTB ^= ~(1 << PB0); 

and I still don't see the LED toggling. Any ideas what could be missing?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 
                 _delay_ms(100); 
                  PORTB &= ~(1 << PB0); 
                 _delay_ms(100); 

You only need 1 delay, maybe at 200ms??

Quote:
get a garbage string and not "Hello". Is this because of the baud rate?
Most likely
Quote:
Also I cannot see the LED on Port B0 toggling when I press 'A' on the keyboard
Beacuse you NEVER get A as you don't communicate correctly with the PC as shown above.

Where are you getting the strange 3MHz clock from?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

If you set the STK500 clock to 3.00MHz then your UART should work fine. However it is a very strange value for a clock.

As John said, you will never receive the 'A' if the baud-rate is garbage. You would have to try every key on the keyboard until you found one that mapped a garbage to 'A'.

You want your loop to c = getchar() from the UART, and putchar(c) it back to Hyperterminal.

char uart_getchar(void)
{
    while((UCSR0A & (1 << RXC0)) == 0) {};
    return UDR0;
}

    ...
    c = uart_getchar();
    uart_putchar(c);
    ...

David.

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

When you said you were using "3MHz" I thought you just meant this as short-hand for the STK500 oscillators default 3.6864MHz but if it is that value then instead of:

#define BAUD_PRESCALE (((3000000/ (USART_BAUDRATE * 16UL))) - 1) //value to load into UBRR

use:

#define BAUD_PRESCALE (((3686400/ (USART_BAUDRATE * 16UL))) - 1) //value to load into UBRR

If it really is 3.0000MHz this seems like an extraordinarily odd value to choose!

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

Thanks, guys.

I changed the frequency to 3.686MHz. Here is my code now:

#include 
#include 
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((3686400/ (USART_BAUDRATE * 16UL))) - 1) //value to load into UBRR

//select external oscillator (3.0M - 8.0MHz) 
//in programming settings; leave the DEFAULT 
//jumper settings for OSCSEL on the STK500 board
unsigned char ReceivedByte;
unsigned char BytetoPC;

void USART0_init()
{


   UCSR0B |= (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and reception circuitry 
   UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); //Set to 8 bit no parity, 1 stop bit
   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

}

void UART_putchar(char BytetoPC)
     {

	   while ((UCSR0A & (1 << UDRE0)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
       UDR0 = BytetoPC;
	   _delay_ms(100);
     }




void USART_putstring(char *s)
  {
    while (*s)
        UART_putchar(*s++);
  }


char UART_getchar()
  {
   while((UCSR0A & (1 << RXC0)) == 0) {};
   return UDR0;
  }




int main (void)
    {

       DDRB = 0x01;
	  
       USART0_init();

          for(;;)
            {
			  
			  
			  UART_putchar('H');
			  //USART_putstring("Hello!");
			  ReceivedByte = UART_getchar();
			  UART_putchar(ReceivedByte);

              if (ReceivedByte == 'A')//BYTE RECEIVED FROM PC
			
                {
 
                 
                  PORTB ^= ~(1 << PB0);
                  _delay_ms(200);          
	        }

          }
     } 

Now with this code, when I open my hyperterminal, I get nothing to start with, when I turn the power OFF/ON on my STK500, I get an 'H' on my hyperterminal. I also get an 'H' when I type something on my keyboard. I am getting the echo of what I am typing on the hyperterminal.

However, I want to display a "Hello" message before I start. How can I do this? When I used the USART_putstring() function, I get a frame error on my hyperterminal.

Also the LED is still not being controlled by 'A'. I added a single 200 ms delay and still nothing. Should I change my baud rate?

edit: Right after I posted this, I tried it and it worked. I had to add delays big time:

#include 
#include 
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((3686400/ (USART_BAUDRATE * 16UL))) - 1) //value to load into UBRR

//select external oscillator (3.0M - 8.0MHz) 
//in programming settings; leave the DEFAULT 
//jumper settings for OSCSEL on the STK500 board
unsigned char ReceivedByte;
unsigned char BytetoPC;

void USART0_init()
{


   UCSR0B |= (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and reception circuitry 
   UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); //Set to 8 bit no parity, 1 stop bit
   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

}

void UART_putchar(char BytetoPC)
     {

	   while ((UCSR0A & (1 << UDRE0)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
       UDR0 = BytetoPC;
	   _delay_ms(100);
     }




void USART_putstring(char *s)
  {
    while (*s)
        UART_putchar(*s++);
  }


char UART_getchar()
  {
   while((UCSR0A & (1 << RXC0)) == 0) {};
   return UDR0;
  }




int main (void)
    {

       DDRB = 0x01;
	  
	  
       USART0_init();

          for(;;)
            {
			  
			  
			  UART_putchar('H');
			  _delay_ms(100);
			  //USART_putstring("Hello!");
			  ReceivedByte = UART_getchar();
			  _delay_ms(100);
			  UART_putchar(ReceivedByte);

              if (ReceivedByte == 'A')//BYTE RECEIVED FROM PC
			  
                {
 
                 
                  PORTB = 0x01;
                          
		}
			 

           }
     } 

Now the only thing is I would like to display the "Hello" message when I open my hyperterminal. Do I have to add it outside the for(;;)?

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

I can assure you that your code works ok. If you get garbage then this is because you are lying about the clock frequency.

As I suggested earlier, you can experiment as much as you like with the STK500. After you change the software clock, you must WRITE the new value back.

#include 
#include 
#define USART_BAUDRATE 9600
//#define BAUD_PRESCALE (((3686400/ (USART_BAUDRATE * 16UL))) - 1) //value to load into UBRR
#define BAUD_PRESCALE (((F_CPU/ (USART_BAUDRATE * 16UL))) - 1)       //value to load into UBRR

//select external oscillator (3.0M - 8.0MHz)
//in programming settings; leave the DEFAULT
//jumper settings for OSCSEL on the STK500 board
unsigned char ReceivedByte;
unsigned char BytetoPC;

void USART0_init()
{
    UCSR0B |= (1 << RXEN0) | (1 << TXEN0);      // Turn on the transmission and reception circuitry
    UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);    //Set to 8 bit no parity, 1 stop bit
    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
}

void UART_putchar(char BytetoPC)
{

    while ((UCSR0A & (1 << UDRE0)) == 0) {
    };                          // Do nothing until UDR is ready for more data to be written to it
    UDR0 = BytetoPC;
//    _delay_ms(100);
}

void USART_putstring(char *s)
{
    while (*s)
        UART_putchar(*s++);
}

char UART_getchar()
{
    while ((UCSR0A & (1 << RXC0)) == 0) {
    };
    return UDR0;
}

int main(void)
{

    DDRB = 0x01;

    USART0_init();
    USART_putstring("Hello!");

    for (;;) {
        ReceivedByte = UART_getchar();
        UART_putchar(ReceivedByte);

        if (ReceivedByte == 'A')        //BYTE RECEIVED FROM PC
        {
            PORTB ^= ~(1 << PB0);
            _delay_ms(200);
        }
    }
}