SPI with Atmega32 and At42QT2100

I have a communication problem with an Atmega3216PU with an at42qt2100.

Data tables: Atmega32PU16 and AT42QT2100

This is my code:

#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#define F_CPU  16000000
#define UART_BAUD_RATE  9600
#define UART_BAUD_REGISTERS  (((F_CPU / (UART_BAUD_RATE * 16UL))) - 1)

int printCHAR(char character, FILE *stream)
{
    while ((UCSRA & (1 << UDRE)) == 0) {};
    UDR = character;
    return 0;
}
FILE uart_str = FDEV_SETUP_STREAM(printCHAR, NULL, _FDEV_SETUP_RW);

void setup(){
    // Init SIO
    UCSRB |= (1 << RXEN) | (1 << TXEN);
    UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);

    UBRRL = UART_BAUD_REGISTERS;

    fprintf(&uart_str, "");
    stdout = &uart_str;
    printf("");

    //Init spi
    //set MOSI, SCK and SS output, all others input
    DDRB |= (1<<DDB7)|(1<<DDB5)|(1<<DDB4);
    SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0)|(1<<CPHA)|(1<<CPOL);

}

void loop(){

    uint8_t data = 0b01000000; //Sending this sequence should return device id
    printf("Sending: %d \n",data);
    _delay_ms(10000);
    PORTB &= 0b11101111; // SS auf LOW!! (Pin4)
    SPDR = data;
    while(!(SPSR & (1<<SPIF)));
    PORTB |= (1<<PB4); // SS auf HIGH!! (Pin4)
    printf("Receiving: %d \n",SPDR);
    _delay_ms(10000);
}

void main(){
    setup();
    while(1){
        loop();
    }
}

      

I should get a response from at42qt2100 with device id 108, but I always get 0. This ist output: Sending: 64 Receiving: 0

Does anyone see the wrong configuration?

+3


source to share


1 answer


I took a quick look at the AT42QT2100 table you link and I immediately see a couple of problems:

  • After SS is set low, the host must wait> 2us (in free-run mode) before starting SCK. You start transmitting SPI immediately, and if you are using 16 MHz, that means you can start transmitting as soon as 62.5ns after setting SS low.
  • The datasheet also states that the host must send 3 bytes of data within 10ms, or the transaction will be treated as an error and the exchange will be reset. You send 1 byte and then wait 20 seconds before sending the next byte.
  • The datasheet indicates that the device settings become active after 3 bytes are sent. This means that 3 more bytes must be sent to receive a response to your command.

You should be doing something more in line with this:



#define NUM_DATA_BYTES   3
void loop(){
    uint8_t sendData[NUM_DATA_BYTES] =
    {
        0b01000000, /* Device Version Command and default values. */
        0b00000000, /* Default Value for Byte 2. */
        0b11000000, /* Default Value for Byte 3. */
    };
    uint8_t receiveData[NUM_DATA_BYTES] = { 0 };
    uint8_t i;

    PORTB &= 0b11101111; // SS auf LOW!! (Pin4)

     /* Ensure that >2us delay requirement is met.  Although, the 
        for() loop below will probably introduce enough delay. */
    _delay_ms(1);

    /* Send command data. */
    for (i = 0; i < NUM_DATA_BYTES; i++)
    {
            SPDR = sendData[i];
            while(!(SPSR & (1<<SPIF)));
    }
    PORTB |= (1<<PB4); // SS auf HIGH!! (Pin4)

    /* Delay here may be unnecessary, but it ensures that timing
       issues do not occur. */
    _delay_ms(1);
    PORTB &= 0b11101111; // SS auf LOW!! (Pin4)
    _delay_ms(1);

    /* Receive device response data. */
    for (i = 0; i < NUM_DATA_BYTES; i++)
    {
            SPDR = sendData[i];
            while(!(SPSR & (1<<SPIF)));
            receiveData[i] = SPDR;

            printf("Receiving byte %d: %d \n", (i + 1), receiveData[i]);
    }
    PORTB |= (1<<PB4); // SS auf HIGH!! (Pin4)

    _delay_ms(10000);
}

      

I'm sure this code isn't perfect, but it should get you on the right track. Good luck!

0


source







All Articles