A luta continua... e está para durar eheheh.
Uma breve noção de SPI: SPI é um método de comunicação síncrona que utiliza SDI, SDO, SCK e mais 1 ou 2 pinos que neste caso não interessa.
Configurado tudo isto, chego ao primeiro problema: o PAN3101 utiliza um pino para SDIO e outro para SCK,  mas no meu MCU tenho 2 pinos a fazer o trabalho de 1 (SDI + SDO = SDIO).
Resolvi a questão da seguinte forma: liguei ambos os pinos, SDI + SDO, e como o pino de SDI está sempre configurado como input, posso trabalhar normalmente com o SDO. Quando quiser receber alguma coisa, coloco o SDO também como input, para que não force a comunicação a ir para Low ou para High.
Resolvido isto, tenho apenas um problema, quando estou a fazer a transmissão o registo SSPBUF fica cheio  com o que acabei de transmitir e a flag SSPIF deixa de ter efeito, então faço o clear do registo primeiro.
Como se pode ver na página 4 do datasheet, se eu pedir a leitura do endereço 0x14 (enderesso para teste de comunicação), a resposta deveria ser 0x10, ou 16 em decimal, ou 10000 em binário.
Excerto do código:

PIR1bits.SSPIF=0;
SSPBUF=0x14;
while(!PIR1bits.SSPIF);
SSPBUF=0;
PIR1bits.SSPIF=0;
TRISB2=1; //tri-state
while(!PIR1bits.SSPIF); //espera resposta
A[2]=SSPBUF;
TRISB2=0; //output again
A[2]=16, então a comunicação está a ser bem feita.

O problema até agora é quando peço a leitura do endereço 0x02 ou 0x03, que me deveria dar o deslocamento, o resultado ou é 0 (0b00000000), ou é -1 (0b11111111).

A investigação continua.....

4 Responses so far.

  1. Amigão, parabens pelo blog, achei muita coisa util, isso que ainda não olhei tudo.
    faz alguns dias que ando pesquisando sobre fluxo optico para eu poder colocar no meu hexcopter... e hoje resolvi depenar meu mouse e tentar ver se funcina. Eu me baseei em alguns codigos encontrados na net, e me baseie em algumas informações que voce passou ai no blog.
    Bom... não sei se voce ja conseguiu fazer funcionar, mas de repente posso te ajudar. fiz alguns testes e parece ter funcionado.... se eu seto a resolução para 400, ele le como 400, e para 800 também funciona. os deltas X e Y também estão variando. Não coloquei lente apropriada ainda mas...
    me manda um email.... tenta com esse sketch abaixo... boa sorte...
    não da bola que tem muito registrador que não se usa e que está com o endereço errado, peguei de um outro codigo fonte... abraço
    #define SCLK 5
    #define SDIO 6
    #define NCS 4

    #define PRODUCT_ID1 0x01 // should be 0x12
    #define PRODUCTID2 0x3e//
    #define REVISION_ID 0x01//
    #define MOTION_REG 0x16
    #define DELTA_Y_REG 0x02
    #define DELTA_X_REG 0x03
    #define SQUAL_REG 0x05
    #define MAXIMUM_PIXEL_REG 0x08
    #define MINIMUM_PIXEL_REG 0x0a
    #define PIXEL_SUM_REG 0x09
    #define PIXEL_DATA_REG 0x0b
    #define SHUTTER_UPPER_REG 0x06
    #define SHUTTER_LOWER_REG 0x07
    #define RESET 0x3a
    #define CPI500v 0x00
    #define CPI1000v 0x01

    #define NUM_PIXELS 361

    byte pix[361];

    void setup()
    {
    Serial.begin(115200);

    pinMode(SDIO, OUTPUT);
    pinMode(SCLK, OUTPUT);
    pinMode(NCS, OUTPUT);

    sync();

    //ADNS_write(RESET, 0x5a);
    ADNS_write(0x00, 0x81); //Full Reset
    ADNS_write(0x00, 0x01); //Disable Sleep Mode
    //ADNS_write(0x1B, 0x80); //SET 400 RESOLUTION
    delay(1); // From NRESET pull high to valid motion, assuming VDD and motion is present.

    }

    void loop()
    {
    char MR = ADNS_read(0x16); // Freezes DX and DY until they are read or MOTION is read again.
    char dx = ADNS_read(DELTA_X_REG);
    char dy = ADNS_read(DELTA_Y_REG);
    Serial.print("MOTION REG:");
    Serial.print(MR, DEC);
    Serial.print("DELTA:");
    Serial.print(dx, DEC);
    Serial.print(" ");
    Serial.println(dy, DEC);
    delay(200);
    }

    void sync() {
    digitalWrite(NCS, LOW);
    delayMicroseconds(2);
    digitalWrite(NCS, HIGH);
    }

    byte ADNS_read(byte address) {
    digitalWrite(NCS, LOW);// select the chip
    pinMode (SDIO, OUTPUT);

    for (byte i=128; i >0 ; i >>= 1) {
    digitalWrite (SCLK, LOW);
    digitalWrite (SDIO, (address & i) != 0 ? HIGH : LOW);
    delayMicroseconds(3); // tSWR = 20us min.
    digitalWrite (SCLK, HIGH);
    }

    pinMode (SDIO, INPUT);

    delayMicroseconds(20); // tSWR = 20us min.

    byte res = 0;
    for (byte i=128; i >0 ; i >>= 1) {
    delayMicroseconds(3); // tSWR = 20us min.
    digitalWrite (SCLK, LOW);
    digitalWrite (SCLK, HIGH);
    if( digitalRead (SDIO) == HIGH )
    res |= i;
    }

    digitalWrite(NCS, HIGH);// de-select the chip
    return res;
    }

    void ADNS_write(byte address, byte data) {
    digitalWrite(NCS, LOW);// select the chip
    pinMode (SDIO, OUTPUT);
    address |= 128;
    for (byte i = 128; i > 0 ; i >>= 1) {
    digitalWrite (SCLK, LOW);
    digitalWrite (SDIO, (address & i) != 0 ? HIGH : LOW);
    delayMicroseconds(3); // tSWR = 20us min.
    digitalWrite (SCLK, HIGH);
    }

    delayMicroseconds(30); // tSWW = 30us min.

    for (byte i = 128; i > 0 ; i >>= 1) {
    digitalWrite (SCLK, LOW);
    digitalWrite (SDIO, (data & i) != 0 ? HIGH : LOW);
    delayMicroseconds(3); // tSWR = 20us min.
    digitalWrite (SCLK, HIGH);
    }

    digitalWrite(NCS, HIGH);// de-select the chip
    }

  2. esse codigo foi feito para o ADNS..alguma coisa
    o NCS não foi usado

  3. outra coisa....
    o Serial.begin(115200); ta sendo usado só para mostrar as coisas no serial monitor do Arduino

  4. Olá.

    Bom comentário!

    Vou ler com um pouco mais de atenção e fazer mais umas experiências.

    Qualquer novidade, coloco por cá.

    Obrigado ;).


    Abração

Enviar um comentário