SPI Slave Works When Clock Is 1MHz, But Not At 8MHz - ATMEGA16

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

I had left my fuses alone from the start, especially when programming my AVR via SPI (using at STM32 and my own code) wasn't producing consistently clean return values.


Once I got that all sorted out, I was able to program my AVR and blink an LED (thanks to a previous thread)... Yayyy!


So I move onto getting USART working... not so "yayyy". For some strange reason, even at 2400 baud, my echo code wasn't returning what I was sending.


After a ton of varying attempts, I thought I might just try to change my fuse to clock at 8MHz instead of the factory-set 1MHz (to give my more baud options to try).

I didn't think it'd be a big deal since I know earlier I had tested switching the fuse to 2MHz and then back to 1MHz. I don't remember if I tried 4MHz at that time.


Now that I set the fuse for 8MHz, ALL the SPI data I send returns 0xFF. (eg. Sending programming mode 0xAC530000, returns 0xFFFFFFFF from my AVR)

I changed my STM32 code so I could change my SPI speeds on-the-fly (instead of having to re-flash my ST for every test).


I originally had my SPI speed set at 15625, but I also tested at the max 250000 (1/4 of 1MHz). For the most part, 250KHz worked, but there were random error returns and I wouldn't trust flashing anything at that speed. But 15625 produced zero errors.


I have another ATMEGA16 that is bare/untouched and my SPI code still works with that.


Are there any thoughts why it works flawlessly (seemingly) at 1MHz and an SPI speed of 15625, but not when it's at 8MHz? I tried several other SPI speeds including the max 2MHz (1/4 8MHz), 1MHz, 250KHz as well as 15625Hz and they all give me MISO returns of 0xFF.


My master is:

Polarity = Low

Phase = First edge

Data Size = 8 bit

First Bit = MSB


GPIO is:

Speed = Very High (50MHz - 200MHz //whatever this does. I'm guessing slew.)

SCK, MOSI = SPI Function/Mode & No pullup

MISO = SPI Function/Mode & Pullup at the start, then no pullup once the AVR enters programming mode

Reset = Push/Pull & Pullup


And this all works fine when my AVR is at 1MHz.


Frankly, when the datasheet says "When reading data from the ATmega16, data is clocked on the falling edge of SCK", that would make me think my ST would want the phase to be the second edge when the polarity is low. But when I tried that with my 1MHz clocked AVR, I got a lot more error returns.

The ST comment for "phase" is described as "Specifies the clock active edge for the bit capture". "Bit capture" = "reading data from the ATMega16" to me. "Falling edge" means the second edge when the polarity is low.

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

vindicator wrote:
Are there any thoughts why it works flawlessly (seemingly) at 1MHz and an SPI speed of 15625, but not when it's at 8MHz? I tried several other SPI speeds including the max 2MHz (1/4 8MHz), 1MHz, 250KHz as well as 15625Hz and they all give me MISO returns of 0xFF.
Show your code. SPI is synchronous so it simply goes at whatever speed the master pulses the SCK. I suppose the only danger might be line capacitance or something changing the data signal shape from well defined square wave. What does it look like on a scope?

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

Ugh, there's that "scope" mention again. It may very well be time I turned my ST into a scope, among it's many other functions. It seems like it would've been the "cure" for a bunch of my issues (including UART).

What code are you looking to see? Again, this is all being done via my ST board, so you'd only be seeing ST library stuff like:

    USBD_CDC_SPI_HandleTypeDef.Init.BaudRatePrescaler = USBD_CDC_SPI_Prescaler;
    USBD_CDC_SPI_HandleTypeDef.Init.Direction = SPI_DIRECTION_2LINES;
    USBD_CDC_SPI_HandleTypeDef.Init.CLKPhase = SPI_PHASE_1EDGE;
    USBD_CDC_SPI_HandleTypeDef.Init.CLKPolarity = SPI_POLARITY_LOW;
    USBD_CDC_SPI_HandleTypeDef.Init.CRCPolynomial = 10;
    USBD_CDC_SPI_HandleTypeDef.Init.DataSize = SPI_DATASIZE_8BIT;
    USBD_CDC_SPI_HandleTypeDef.Init.FirstBit = SPI_FIRSTBIT_MSB;
    USBD_CDC_SPI_HandleTypeDef.Init.Mode = SPI_MODE_MASTER;
    USBD_CDC_SPI_HandleTypeDef.Init.NSS = SPI_NSS_SOFT;

    if (HAL_SPI_Init(&USBD_CDC_SPI_HandleTypeDef) != HAL_OK)

    while (HAL_SPI_GetState(&USBD_CDC_SPI_HandleTypeDef) != HAL_SPI_STATE_READY)


if (hspi->Instance == SPI1)
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

    /* SPI SCK GPIO pin configuration  */
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* SPI MISO GPIO pin configuration  */
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Pull = GPIO_PULLUP; //Change to no-pull AFTER 0xAC53
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* SPI MOSI GPIO pin configuration  */
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(SPI1_IRQn, 6, 0);

    /* RESET */
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate = 0;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

I doubt anyone would be interested in unrelated code like:

static void USBD_CDC_Error_Handler(void)
    /* User may add here some code to deal with this error */
    while (1)

Someone else mentioned adding a capacitor on VCC/GND even though stuff worked and the AVR was being powered by my ST. But I went ahead and added 22uF, though it didn't make any difference with my issues.


I'll start exploring with making my ST a scope now. I know I saw references of really neat projects that already did it.