ATMega328P frequency changed from 16MHz to 1MHz while coding SPI

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

Hi guys,

 

Good day.  Now I am trying to learn SPI coding using Arduino Uno based board using the ATMega 328P.  I am trying to connect the Uno to the ATMega 2560 board.

While programming the ATMega328P I got some message in the Atmel Studio: "Would you like this fuse to be changed back?"  I ignored this but somehow from 16MHz the ATMega328P clock turned to 1MHz.  Can someone tell me what happened?

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

ryan2019 wrote:

Can someone tell me what happened?

 

You changed the fuses so that now you are running on the internal 8MHz RC oscillator with the 'div8' (divide by 8) option. ie 1MHz.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

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

So, very likely,  SEVERAL fuses got involved.

 

One or more of the CKSEL bits got changed to use the internal RC oscillator (that makes 8MHz). 

 

Very likely the CKDIV8 fuse got changed (that makes 8MHz into 1MHz. This MIGHT have alternatively happened by changing the CLKPS bits in the CLKPR register (this COULD change 16MHz to 1MHz or 8MHz to 1MHz).   

 

So,  there are three ways that could have happened: (1)  change CKSEL fuse bits to use internal RC oscillator plus CKDIV8 fuse bit; (2) change CKSEL fuse bits to use internal RC oscillator plus change CLKPS bits in CLKPR register; (16) change only CLKPS bits in CLKPR register (which keeps 16MHz crystal oscillator running). 

 

Given the message that you got, I would bet that it was (1).

 

Jim

 

 

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Sun. Jan 26, 2020 - 08:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

So, very likely,  SEVERAL fuses got involved.

 

One or more of the CKSEL bits got changed to use the internal RC oscillator (that makes 8MHz). 

 

Very likely the CKDIV8 fuse got changed (that makes 8MHz into 1MHz. This MIGHT have alternatively happened by changing the CLKPS bits in the CLKPR register (this COULD change 16MHz to 1MHz or 8MHz to 1MHz).   

 

So,  there are three ways that could have happened: (1)  change CKSEL fuse bits to use internal RC oscillator plus CKDIV8 fuse bit; (2) change CKSEL fuse bits to use internal RC oscillator plus change CLKPS bits in CLKPR register; (16) change only CLKPS bits in CLKPR register (which keeps 16MHz crystal oscillator running). 

 

Given the message that you got, I would bet that it was (1).

 

Jim

 

 

 

 

Not sure in what way it was changed.  This is my code and this is not working.  What is the problem here.

#include <avr/io.h>

void SPIinit()
{
	SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
}

void SPI_Tx(uint8_t data)
{
	while(!(SPSR&(1<<SPIF)));
	SPDR=data;
}

int main(void)
{
	DDRB=0x28;					//set MOSI, SCK and SS as output 
	PORTB=(1<<2);					//set SS High	
   
	SPIinit();
	   
    while (1) 
    {
		if(PINB&(1<<0))
		{
			SPI_Tx(0xFF);
		}
		else
		{
			SPI_Tx(0x00);
		}
    }
}

 

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

You do not say exactly what "is not working"! We cannot help you without some help from you in the first place.

 

If you don't know what has changed, then read the fuses and check the contents of CLKPR, for  starters. It may be a bit of a challenge to find in the IDE Help, but it is there.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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


ryan2019 wrote:

DDRB=0x28;					//set MOSI, SCK and SS as output
	PORTB=(1<<2);					//set SS High
   

Something is wrong with this picture.  Now I need to pull up the datasheet for that model, but 0x28 is only two bits set not three signals, and 1<<2 is neither of those.

 

For Mega88 family,

so then it would be 0x2C, right?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Mon. Jan 27, 2020 - 01:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

ryan2019 wrote:

DDRB=0x28;					//set MOSI, SCK and SS as output
	PORTB=(1<<2);					//set SS High
   

Something is wrong with this picture.  Now I need to pull up the datasheet for that model, but 0x28 is only two bits set not three signals, and 1<<2 is neither of those.

 

For Mega88 family,

so then it would be 0x2C, right?

 

Thank you for the correction sir.  The output are not responding when I toggle the switch.  I connected the slave SS to GND.

I have the code for the Master and Slave below.  Kindly check if you see some problems.  Appreciate your help.

Thank you.

//Master Code

#include <avr/io.h>

void SPIinit()
{
	SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_Tx(uint8_t data)
{
	while(!(SPSR&(1<<SPIF)));
	SPDR=data;
}

int main(void)
{
	DDRB=0x2C;					//set MOSI, SCK and SS as output (1<<3)|(1<<5)|(1<<2)
	PORTB=(1<<2);					//set SS High	

	SPIinit();

    while (1)
    {
		if(PINB&(1<<0))
		{
			SPI_Tx(0xFF);
		}
		else
		{
			SPI_Tx(0x00);
		}
    }
}

//Slave Code

#include <avr/io.h>

void SPIinit()
{
	SPCR=(1<<SPE);
}

unsigned char SPI_Rx()
{
	while(!(SPSR&(1<<SPIF)));
	return SPDR;
}

int main(void)
{
    DDRB=0xFF;
    SPIinit();

    while (1)
    {
		if (SPDR==(0xFF))
		{
			PORTB|=(1<<6);
			PORTB&=~(1<<7);
		}
		else if (SPDR==(0x00))
		{
			PORTB&=~(1<<6);
			PORTB|=(1<<7);
		}
    }
}

 

Last Edited: Mon. Jan 27, 2020 - 02:50 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Slave:

 

int main(void)
{
    DDRB=0xFF;   // ??

You set all spi pins output.

I think it should be

 

   DDRB |= (1<<MISO);                          // Set MISO output, all others input
   DDRB &= ~((1<<SS) | (1<<MOSI) | (1<<CLCK));

 

Edit:

I notice you need output PB6, PB7 so do

DDRB |=  (1<<MISO)|(1<<PB6)|(1<<PB7);        // outputs
DDRB &= ~((1<<SS)|(1<<MOSI)| 1<<CLCK));      // inputs

 

Last Edited: Mon. Jan 27, 2020 - 07:43 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Visovian wrote:

Slave:

 

int main(void)
{
    DDRB=0xFF;   // ??

You set all spi pins output.

I think it should be

 

   DDRB |= (1<<MISO);                          // Set MISO output, all others input
   DDRB &= ~((1<<SS) | (1<<MOSI) | (1<<CLCK));

 

Edit:

I notice you need output PB6, PB7 so do

DDRB |=  (1<<MISO)|(1<<PB6)|(1<<PB7);        // outputs
DDRB &= ~((1<<SS)|(1<<MOSI)| 1<<CLCK));      // inputs

 

 

Thank you for the corrections Sir.  Now they are working with some rearrangement on the lines.

void SPI_Tx(uint8_t data)
{
	
	SPDR=data;
	while(!(SPSR&(1<<SPIF)));
	
}

 

Last Edited: Mon. Jan 27, 2020 - 02:47 PM