USI as SPI - Master&从站通信 - 仅发生7次转换

时间:2016-01-12 04:11:50

标签: microcontroller avr spi atmega attiny

寻找这个问题的一些帮助我已经坚持了一段时间。

问题:

当从从机接收一个字节时,发生错误的转换次数,通常是7但不总是。

SETUP:

Atmega328P作为主人和& ATtiny85作为奴隶。使用AVR-GCC在Atmel Studio 6中编译。

的尝试:

我很确定这是一个时间问题,即使我在代码中找不到任何错误,但我仍尝试USICS1USICS0USICLK&的所有组合。 SPI模式0& 1只是为了排除它们(AVR319数据表说USI因为SPI与模式0和1兼容,但我也试过3)。现在,当我等待回复时,我将尝试使用轮询方法而不是中断驱动,并希望继续阅读数据表。我不认为这会解决它,但我没有想法。

MASTER CODE:

// Master - ATmega 328P

#ifndef F_CPU
#define F_CPU 16000000UL
#endif

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "uart.h"

#define CTRL_PORT   DDRB
#define DATA_PORT   PORTB
#define SS_PIN      PORTB2
#define CLK_PIN     PORTB5
#define MOSI_PIN    PORTB3
#define MISO_PIN    PORTB4

#define UART_BAUD_RATE 9600

volatile char res;
volatile char val = 0x4D;

/*
    Initialize SPI and UART
*/
void init()
{
    //Set MOSI, clock pin and SS pin as output.
    CTRL_PORT = _BV(MOSI_PIN) | _BV(CLK_PIN) | _BV(SS_PIN);

    //Enable SPI mode, master and F_CPU/128.
    SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0) | _BV(SPR1);

    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

    sei();
}

/*
    Transmit char to, and receive char from, the slave.
*/
void Transmit(char data)
{
    SPDR = data;

    while(!(SPSR & (1<<SPIF))) {}

    res = SPDR;
}

/*
   Transmit char 'M', for Master, to slave and receive 
   slaves number, in this case '2'. Print char from slave to serial
*/
int main()
{
    init();

    while(1)
    {
        Transmit(val);
        uart_putc(res);

        _delay_ms(1000);
    }
    return 0;
}

SLAVE CODE:

#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define CTRL_PORT   DDRB
#define DATA_PORT   PORTB
#define SS_PIN      PB4
#define CLK_PIN     PB2
#define DI_PIN      PB0
#define DO_PIN      PB1

/*
    Initialize USI as slave
*/
void init()
{
    //DO pin is configured for output
    CTRL_PORT |= _BV(DO_PIN);

    //All other pins as input
    CTRL_PORT &= ~(_BV(DI_PIN) | _BV(CLK_PIN) | _BV(SS_PIN));


    DATA_PORT |= _BV(DI_PIN) | _BV(CLK_PIN);

    //Enable USI overflow interrupt, set three wire mode and set
    //  clock to External, positive edge.
    USICR = _BV(USIOIE) | _BV(USIWM0) | _BV(USICS0) | _BV(USICS1);

    //Clear overflow flag
    USISR = _BV(USIOIF);    

    sei();
}

/*
    USI overflow interrupt - triggered when transfer complete
*/
ISR(USI_OVF_vect)
{
    USISR = _BV(USIOIF);

    USIDR = 0x32;
}

int main()
{
    init();

    while(1) {}

    return 0;
}

非常感谢您提供的任何帮助,谢谢。

1 个答案:

答案 0 :(得分:2)

我将时钟和振荡器关系从fosc / 128更改为fosc / 4,我得到了预期的字符。